Commit 4b103883 authored by Keith Busch's avatar Keith Busch Committed by Bjorn Helgaas

PCI: Don't attempt config access to disconnected devices

If we've  detected the PCI device is disconnected, there is no need to
attempt to access its config space since we know the operation will fail.
Make all the config reads and writes return -ENODEV error immediately when
in such a state.

If a caller requests a config read to a disconnected device, return a data
value of all 1's.  This is the same as what hardware is expected to return
when accessing a removed device, but software can do this faster without
relying on hardware.
Tested-by: default avatarKrishna Dhulipala <krishnad@fb.com>
Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarWei Zhang <wzhang@fb.com>
parent 89ee9f76
...@@ -893,12 +893,20 @@ EXPORT_SYMBOL(pcie_capability_clear_and_set_dword); ...@@ -893,12 +893,20 @@ EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);
int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val) int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
{ {
if (pci_dev_is_disconnected(dev)) {
*val = ~0;
return -ENODEV;
}
return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val); return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
} }
EXPORT_SYMBOL(pci_read_config_byte); EXPORT_SYMBOL(pci_read_config_byte);
int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val) int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
{ {
if (pci_dev_is_disconnected(dev)) {
*val = ~0;
return -ENODEV;
}
return pci_bus_read_config_word(dev->bus, dev->devfn, where, val); return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
} }
EXPORT_SYMBOL(pci_read_config_word); EXPORT_SYMBOL(pci_read_config_word);
...@@ -906,18 +914,26 @@ EXPORT_SYMBOL(pci_read_config_word); ...@@ -906,18 +914,26 @@ EXPORT_SYMBOL(pci_read_config_word);
int pci_read_config_dword(const struct pci_dev *dev, int where, int pci_read_config_dword(const struct pci_dev *dev, int where,
u32 *val) u32 *val)
{ {
if (pci_dev_is_disconnected(dev)) {
*val = ~0;
return -ENODEV;
}
return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val); return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
} }
EXPORT_SYMBOL(pci_read_config_dword); EXPORT_SYMBOL(pci_read_config_dword);
int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val) int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
{ {
if (pci_dev_is_disconnected(dev))
return -ENODEV;
return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val); return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
} }
EXPORT_SYMBOL(pci_write_config_byte); EXPORT_SYMBOL(pci_write_config_byte);
int pci_write_config_word(const struct pci_dev *dev, int where, u16 val) int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
{ {
if (pci_dev_is_disconnected(dev))
return -ENODEV;
return pci_bus_write_config_word(dev->bus, dev->devfn, where, val); return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
} }
EXPORT_SYMBOL(pci_write_config_word); EXPORT_SYMBOL(pci_write_config_word);
...@@ -925,6 +941,8 @@ EXPORT_SYMBOL(pci_write_config_word); ...@@ -925,6 +941,8 @@ EXPORT_SYMBOL(pci_write_config_word);
int pci_write_config_dword(const struct pci_dev *dev, int where, int pci_write_config_dword(const struct pci_dev *dev, int where,
u32 val) u32 val)
{ {
if (pci_dev_is_disconnected(dev))
return -ENODEV;
return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
} }
EXPORT_SYMBOL(pci_write_config_dword); EXPORT_SYMBOL(pci_write_config_dword);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment