From d3881e5015421a578bc328136471fcf1d02ac389 Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Tue, 7 Feb 2017 14:32:33 -0500 Subject: PCI: Export PCI device config accessors Replace the inline PCI device config read and write accessors with exported functions. This is preparing for these functions to make use of private data. Tested-by: Krishna Dhulipala Signed-off-by: Keith Busch Signed-off-by: Bjorn Helgaas Reviewed-by: Christoph Hellwig Reviewed-by: Wei Zhang --- drivers/pci/access.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/pci/access.c') diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 8b7382705bf2..c70e3113df7a 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -890,3 +890,41 @@ int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, return ret; } EXPORT_SYMBOL(pcie_capability_clear_and_set_dword); + +int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val) +{ + return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val); +} +EXPORT_SYMBOL(pci_read_config_byte); + +int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val) +{ + return pci_bus_read_config_word(dev->bus, dev->devfn, where, val); +} +EXPORT_SYMBOL(pci_read_config_word); + +int pci_read_config_dword(const struct pci_dev *dev, int where, + u32 *val) +{ + return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val); +} +EXPORT_SYMBOL(pci_read_config_dword); + +int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val) +{ + return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val); +} +EXPORT_SYMBOL(pci_write_config_byte); + +int pci_write_config_word(const struct pci_dev *dev, int where, u16 val) +{ + return pci_bus_write_config_word(dev->bus, dev->devfn, where, val); +} +EXPORT_SYMBOL(pci_write_config_word); + +int pci_write_config_dword(const struct pci_dev *dev, int where, + u32 val) +{ + return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); +} +EXPORT_SYMBOL(pci_write_config_dword); -- cgit v1.2.3 From 4b103883473964bbb7b0b6934999b283ee234a8a Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Wed, 29 Mar 2017 22:49:06 -0500 Subject: 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: Krishna Dhulipala Signed-off-by: Keith Busch Signed-off-by: Bjorn Helgaas Reviewed-by: Christoph Hellwig Reviewed-by: Wei Zhang --- drivers/pci/access.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/pci/access.c') diff --git a/drivers/pci/access.c b/drivers/pci/access.c index c70e3113df7a..1c8051003e67 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -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) { + if (pci_dev_is_disconnected(dev)) { + *val = ~0; + return -ENODEV; + } return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val); } EXPORT_SYMBOL(pci_read_config_byte); 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); } 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, u32 *val) { + if (pci_dev_is_disconnected(dev)) { + *val = ~0; + return -ENODEV; + } return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val); } EXPORT_SYMBOL(pci_read_config_dword); 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); } EXPORT_SYMBOL(pci_write_config_byte); 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); } 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, u32 val) { + if (pci_dev_is_disconnected(dev)) + return -ENODEV; return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); } EXPORT_SYMBOL(pci_write_config_dword); -- cgit v1.2.3 From 0b131b139467db844874f31b46bb638b541d9d3f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 27 Mar 2017 17:46:14 -0700 Subject: PCI: Fix typo pci_cfg_access_lock() comment There is no pci_cfg_access_unlocked(). I think the author meant pci_cfg_access_unlock(). Signed-off-by: Brian Norris Signed-off-by: Bjorn Helgaas --- drivers/pci/access.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/pci/access.c') diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 8b7382705bf2..5b7842b03571 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -629,7 +629,7 @@ void pci_vpd_release(struct pci_dev *dev) * * When access is locked, any userspace reads or writes to config * space and concurrent lock requests will sleep until access is - * allowed via pci_cfg_access_unlocked again. + * allowed via pci_cfg_access_unlock() again. */ void pci_cfg_access_lock(struct pci_dev *dev) { -- cgit v1.2.3 From 9b70ae4951746146838b474c3a90722666edf4c1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 19 Apr 2017 07:44:51 -0500 Subject: PCI: Include PCI-to-PCIe bridges as "Downstream Ports" A PCI/PCI-X to PCI Express bridge, sometimes referred to as a "reverse bridge", is a bridge with conventional PCI or PCI-X on its primary side and a PCI Express Port on its secondary (downstream) side. That PCIe Port is a Downstream Port and could be connected to a slot, just like a Root Port or a Switch Downstream Port. Make pcie_downstream_port() return true for them, so we can access the Slot registers in the PCIe capability. Signed-off-by: Bjorn Helgaas --- drivers/pci/access.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/pci/access.c') diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 1c8051003e67..9b09cd31158c 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -700,7 +700,8 @@ static bool pcie_downstream_port(const struct pci_dev *dev) int type = pci_pcie_type(dev); return type == PCI_EXP_TYPE_ROOT_PORT || - type == PCI_EXP_TYPE_DOWNSTREAM; + type == PCI_EXP_TYPE_DOWNSTREAM || + type == PCI_EXP_TYPE_PCIE_BRIDGE; } bool pcie_cap_has_lnkctl(const struct pci_dev *dev) -- cgit v1.2.3