Re: [PATCH v23 2/5] PCI: Allow per function PCI slots to fix slot reset on s390

[email protected] Wed, 05 Aug 2026 17:12:56 +0000
Newsgroups org.kernel.vger.linux-pci,org.kernel.vger.linux-s390
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [High] Unconditionally enabling per_func_slot on S390 breaks standard PCIe hotplug (e.g., pciehp), PCI_SLOT_ALL_DEVICES assignment, and physical slot matching.

Pre-existing issues:
- [High] Lockless access to `dev->slot` allows a Use-After-Free if a hotplug slot is concurrently destroyed.
--

--- Patch [2]: [PATCH v23 2/5] PCI: Allow per function PCI slots to fix slot reset on s390 ---
commit 5800507f8f4f03803f3a4540f211363e22c66b48
Author: Farhan Ali <[email protected]>

PCI: Allow per function PCI slots to fix slot reset on s390

This patch introduces a per_func_slot flag for struct pci_slot to allow
per-function PCI slots on s390. It modifies slot matching logic and changes
the slot number field to a u16 to accommodate special values.

> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 77b17b13ee615..350bae907ebf8 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4897,8 +4897,9 @@ static int pci_reset_hotplug_slot(struct hotplug_slot *hotplug, bool probe)
>  
>  static int pci_dev_reset_slot_function(struct pci_dev *dev, bool probe)
>  {
> -	if (dev->multifunction || dev->subordinate || !dev->slot ||
> -	    dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
> +	if (dev->subordinate || !dev->slot ||
> +	    dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
> +	    (dev->multifunction && !dev->slot->per_func_slot))

[Severity: High]
This is a pre-existing issue, but does reading dev->slot here and accessing
dev->slot->per_func_slot allow a use-after-free?

__pci_reset_function_locked() acquires device_lock(&dev->dev) but calls
pci_dev_reset_slot_function(), which reads dev->slot locklessly.

Concurrently, if a hotplug driver is removed, pci_destroy_slot() drops
the kobject refcount and triggers pci_slot_release().

pci_slot_release() frees the slot and sets dev->slot = NULL:

pci_slot_release() {
	...
	list_for_each_entry(dev, &slot->bus->devices, bus_list)
		if (pci_dev_matches_slot(dev, slot))
			dev->slot = NULL;
	...
	kfree(slot);
}

If the reset thread is preempted after checking dev->slot but before
dereferencing dev->slot->per_func_slot, could it dereference the freed
pointer?

>  		return -ENOTTY;
>  
>  	return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
> diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
> index 42ff66461f74a..897223f01f6ac 100644
> --- a/drivers/pci/slot.c
> +++ b/drivers/pci/slot.c
> @@ -72,6 +72,23 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
>  	return bus_speed_read(slot->bus->cur_bus_speed, buf);
>  }
>  
> +static bool pci_dev_matches_slot(struct pci_dev *dev, struct pci_slot *slot)
> +{
> +	if (slot->per_func_slot)
> +		return dev->devfn == slot->number;
> +
> +	return slot->number == PCI_SLOT_ALL_DEVICES ||
> +		PCI_SLOT(dev->devfn) == slot->number;
> +}
> +
> +static bool pci_slot_enabled_per_func(void)
> +{
> +	if (IS_ENABLED(CONFIG_S390))
> +		return true;
> +
> +	return false;
> +}
> +

[ ... ]

> @@ -299,6 +314,9 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
>  	slot->bus = pci_bus_get(parent);
>  	slot->number = slot_nr;
>  
> +	if (pci_slot_enabled_per_func())
> +		slot->per_func_slot = 1;
> +

[Severity: High]
Does unconditionally setting per_func_slot for all slots on S390 break
standard PCIe hotplug topologies?

When generic PCIe hotplug drivers like pciehp create a bus-wide slot, they
pass PCI_SLOT_ALL_DEVICES (now 0xfeff). Because pci_slot_enabled_per_func()
globally forces per_func_slot = 1 on S390, pci_dev_matches_slot() will
evaluate:

	dev->devfn == 0xfeff

Since devfn is an 8-bit value (0-255), this will never match, leaving
dev->slot unassigned for all devices on those buses.

Similarly, if a generic driver specifies a physical slot number (like 2),
it will evaluate dev->devfn == 2, which incorrectly matches Function 2 of
Device 0 rather than matching all functions of Device 2.

Will this cause generic hotplug slots to fail matching on S390, breaking
sysfs linkages and PCI resets?

>  	slot->kobj.kset = pci_slots_kset;
>

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=2