[PATCH 1/5] PCI: Add disconnected device checks to user config reads

From: Matthew Wood

Date: Sat Oct 24 2026 - 20:10:07 EST


Since commit 4b1038834739 ("PCI: Don't attempt config access to
disconnected devices") the kernel config read accessors skip devices
marked disconnected, returning PCIBIOS_DEVICE_NOT_FOUND and ~0 data.
The user config read accessors still issue the read, and if the host
bridge completes it with ~0 data and no error, they report success.

Check pci_dev_is_disconnected() in pci_user_read_config_*() as well,
failing with -ENODEV and ~0 data. Do the check after waiting for any
pci_cfg_access_lock() holder so a reader blocked behind a reset also
sees a device that was disconnected while it waited.

This prepares for converting sysfs attributes from the kernel
accessors to the user accessors so they keep skipping disconnected
devices.

On a disconnected device, existing callers of the user read accessors
now behave as follows:

- The sysfs "config" file and /proc/bus/pci ignore the return value
and return the same ~0 data as before
- pciconfig_read() fails with -EIO
- VPD reads and VFIO config reads fail with -ENODEV instead of
returning ~0 data
- VPD writes fail with -ENODEV instead of timing out with a
"firmware bug" warning
- VFIO writes to PCI_COMMAND fail with -ENODEV, since VFIO reads the
current value first

Signed-off-by: Matthew Wood <thepacketgeek@xxxxxxxxx>
Tested-by: Nikita Vetoshkin <nekto0n@xxxxxxxx>
---
drivers/pci/access.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index b123da16b63b..18a206bb2a94 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -237,8 +237,11 @@ int pci_user_read_config_##size \
raw_spin_lock_irq(&pci_lock); \
if (unlikely(dev->block_cfg_access)) \
pci_wait_cfg(dev); \
- ret = dev->bus->ops->read(dev->bus, dev->devfn, \
- pos, sizeof(type), &data); \
+ if (pci_dev_is_disconnected(dev)) \
+ ret = PCIBIOS_DEVICE_NOT_FOUND; \
+ else \
+ ret = dev->bus->ops->read(dev->bus, dev->devfn, \
+ pos, sizeof(type), &data); \
raw_spin_unlock_irq(&pci_lock); \
if (ret) \
PCI_SET_ERROR_RESPONSE(val); \
--
2.53.0-Meta