On s390 systems, which use a machine level hypervisor, PCI devices are always accessed through a form of PCI pass-through which fundamentally operates on a per PCI function granularity. This is also reflected in the s390 PCI hotplug driver which creates hotplug slots for individual PCI functions. Its reset_slot() function, which is a wrapper for zpci_hot_reset_device(), thus also resets individual functions. Currently, the pci_create_slot() assigns the same pci_slot object to multifunction devices. This approach worked fine on s390 systems that only exposed virtual functions as individual PCI domains to the operating system. Since commit 44510d6fa0c0 ("s390/pci: Handling multifunctions") s390 supports exposing the topology of multifunction PCI devices by grouping them in a shared PCI domain. This creates a problem when resetting a function through the hotplug driver's slot_reset() interface. When attempting to reset a function through the hotplug driver, the shared slot assignment causes the wrong function to be reset instead of the intended one. It also leaks memory as we do create a pci_slot object for the function, but don't correctly free it in pci_slot_release(). Add a flag for struct pci_slot to allow per function PCI slots for functions managed through a hypervisor, which exposes individual PCI functions while retaining the topology. Since we can use all 8 bits for slot 'number' (for ARI devices), change slot 'number' u16 to account for special values PCI_SLOT_PLACEHOLDER and PCI_SLOT_ALL_DEVICES.
Unified · Split
| @@ -4897,8 +4897,9 @@ static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, bool probe) · 4896 unmodified lines | |||
| 4897 | 4897 | ||
| 4898 | static int pci_dev_reset_slot_function(struct pci_dev *dev, bool probe) | 4898 | static int pci_dev_reset_slot_function(struct pci_dev *dev, bool probe) |
| 4899 | { | 4899 | { |
| 4900 | if (dev->multifunction || dev->subordinate || !dev->slot || | 4900 | if (dev->subordinate || !dev->slot || |
| 4901 | dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) | 4901 | dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || |
| 4902 | (dev->multifunction && !dev->slot->per_func_slot)) | ||
| 4902 | return -ENOTTY; | 4903 | return -ENOTTY; |
| 4903 | 4904 | ||
| 4904 | return pci_reset_hotplug_slot(dev->slot->hotplug, probe); | 4905 | return pci_reset_hotplug_slot(dev->slot->hotplug, probe); |
| @@ -72,6 +72,23 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf) · 71 unmodified lines | |||
| 72 | return bus_speed_read(slot->bus->cur_bus_speed, buf); | 72 | return bus_speed_read(slot->bus->cur_bus_speed, buf); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | static bool pci_dev_matches_slot(struct pci_dev *dev, struct pci_slot *slot) | ||
| 76 | { | ||
| 77 | if (slot->per_func_slot) | ||
| 78 | return dev->devfn == slot->number; | ||
| 79 | |||
| 80 | return slot->number == PCI_SLOT_ALL_DEVICES || | ||
| 81 | PCI_SLOT(dev->devfn) == slot->number; | ||
| 82 | } | ||
| 83 | |||
| 84 | static bool pci_slot_enabled_per_func(void) | ||
| 85 | { | ||
| 86 | if (IS_ENABLED(CONFIG_S390)) | ||
| 87 | return true; | ||
| 88 | |||
| 89 | return false; | ||
| 90 | } | ||
| 91 | |||
| 75 | static void pci_slot_release(struct kobject *kobj) | 92 | static void pci_slot_release(struct kobject *kobj) |
| 76 | { | 93 | { |
| 77 | struct pci_dev *dev; | 94 | struct pci_dev *dev; |
| @@ -82,8 +99,7 @@ static void pci_slot_release(struct kobject *kobj) · 4 unmodified lines | |||
| 82 | 99 | ||
| 83 | down_read(&pci_bus_sem); | 100 | down_read(&pci_bus_sem); |
| 84 | list_for_each_entry(dev, &slot->bus->devices, bus_list) | 101 | list_for_each_entry(dev, &slot->bus->devices, bus_list) |
| 85 | if (slot->number == PCI_SLOT_ALL_DEVICES || | 102 | if (pci_dev_matches_slot(dev, slot)) |
| 86 | PCI_SLOT(dev->devfn) == slot->number) | ||
| 87 | dev->slot = NULL; | 103 | dev->slot = NULL; |
| 88 | up_read(&pci_bus_sem); | 104 | up_read(&pci_bus_sem); |
| 89 | 105 | ||
| @@ -187,8 +203,7 @@ void pci_dev_assign_slot(struct pci_dev *dev) · 97 unmodified lines | |||
| 187 | 203 | ||
| 188 | mutex_lock(&pci_slot_mutex); | 204 | mutex_lock(&pci_slot_mutex); |
| 189 | list_for_each_entry(slot, &dev->bus->slots, list) | 205 | list_for_each_entry(slot, &dev->bus->slots, list) |
| 190 | if (slot->number == PCI_SLOT_ALL_DEVICES || | 206 | if (pci_dev_matches_slot(dev, slot)) |
| 191 | PCI_SLOT(dev->devfn) == slot->number) | ||
| 192 | dev->slot = slot; | 207 | dev->slot = slot; |
| 193 | mutex_unlock(&pci_slot_mutex); | 208 | mutex_unlock(&pci_slot_mutex); |
| 194 | } | 209 | } |
| @@ -299,6 +314,9 @@ placeholder: · 104 unmodified lines | |||
| 299 | slot->bus = pci_bus_get(parent); | 314 | slot->bus = pci_bus_get(parent); |
| 300 | slot->number = slot_nr; | 315 | slot->number = slot_nr; |
| 301 | 316 | ||
| 317 | if (pci_slot_enabled_per_func()) | ||
| 318 | slot->per_func_slot = 1; | ||
| 319 | |||
| 302 | slot->kobj.kset = pci_slots_kset; | 320 | slot->kobj.kset = pci_slots_kset; |
| 303 | 321 | ||
| 304 | slot_name = make_slot_name(name); | 322 | slot_name = make_slot_name(name); |
| @@ -319,8 +337,7 @@ placeholder: · 14 unmodified lines | |||
| 319 | 337 | ||
| 320 | down_read(&pci_bus_sem); | 338 | down_read(&pci_bus_sem); |
| 321 | list_for_each_entry(dev, &parent->devices, bus_list) | 339 | list_for_each_entry(dev, &parent->devices, bus_list) |
| 322 | if (slot_nr == PCI_SLOT_ALL_DEVICES || | 340 | if (pci_dev_matches_slot(dev, slot)) |
| 323 | PCI_SLOT(dev->devfn) == slot_nr) | ||
| 324 | dev->slot = slot; | 341 | dev->slot = slot; |
| 325 | up_read(&pci_bus_sem); | 342 | up_read(&pci_bus_sem); |
| 326 | 343 | ||
| @@ -79,17 +79,18 @@ · 78 unmodified lines | |||
| 79 | * and, if ARI Forwarding is enabled, functions may appear to be on multiple | 79 | * and, if ARI Forwarding is enabled, functions may appear to be on multiple |
| 80 | * devices. | 80 | * devices. |
| 81 | */ | 81 | */ |
| 82 | #define PCI_SLOT_ALL_DEVICES 0xfe | 82 | #define PCI_SLOT_ALL_DEVICES 0xfeff |
| 83 | 83 | ||
| 84 | /* Used to identify a slot as a placeholder */ | 84 | /* Used to identify a slot as a placeholder */ |
| 85 | #define PCI_SLOT_PLACEHOLDER 0xff | 85 | #define PCI_SLOT_PLACEHOLDER 0xffff |
| 86 | 86 | ||
| 87 | /* pci_slot represents a physical slot */ | 87 | /* pci_slot represents a physical slot */ |
| 88 | struct pci_slot { | 88 | struct pci_slot { |
| 89 | struct pci_bus *bus; /* Bus this slot is on */ | 89 | struct pci_bus *bus; /* Bus this slot is on */ |
| 90 | struct list_head list; /* Node in list of slots */ | 90 | struct list_head list; /* Node in list of slots */ |
| 91 | struct hotplug_slot *hotplug; /* Hotplug info (move here) */ | 91 | struct hotplug_slot *hotplug; /* Hotplug info (move here) */ |
| 92 | unsigned char number; /* Device nr, or PCI_SLOT_ALL_DEVICES */ | 92 | u16 number; /* Device nr, or PCI_SLOT_ALL_DEVICES */ |
| 93 | unsigned int per_func_slot:1; /* Allow per function slot */ | ||
| 93 | struct kobject kobj; | 94 | struct kobject kobj; |
| 94 | }; | 95 | }; |
| 95 | 96 | ||