From 786e22885d9959fda0473ace5a61cb11620fba9b Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Tue, 24 Jul 2012 17:20:02 +0800 Subject: PCI: Add pcie_flags_reg to cache PCIe capabilities register Since PCI Express Capabilities Register is read only, cache its value into struct pci_dev to avoid repeatedly calling pci_read_config_*(). Signed-off-by: Yijing Wang Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 3 ++- include/linux/pci.h | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6c143b4497ca..ba4d8550503c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -929,7 +929,8 @@ void set_pcie_port_type(struct pci_dev *pdev) pdev->is_pcie = 1; pdev->pcie_cap = pos; pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); - pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; + pdev->pcie_flags_reg = reg16; + pdev->pcie_type = pci_pcie_type(pdev); pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; } diff --git a/include/linux/pci.h b/include/linux/pci.h index 5faa8310eec9..95662b2f0c3d 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -258,6 +258,7 @@ struct pci_dev { u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */ u8 rom_base_reg; /* which config register controls the ROM */ u8 pin; /* which interrupt pin this device uses */ + u16 pcie_flags_reg; /* cached PCI-E Capabilities Register */ struct pci_driver *driver; /* which driver has allocated this device */ u64 dma_mask; /* Mask of the bits of bus address this @@ -1650,6 +1651,15 @@ static inline bool pci_is_pcie(struct pci_dev *dev) return !!pci_pcie_cap(dev); } +/** + * pci_pcie_type - get the PCIe device/port type + * @dev: PCI device + */ +static inline int pci_pcie_type(const struct pci_dev *dev) +{ + return (dev->pcie_flags_reg & PCI_EXP_FLAGS_TYPE) >> 4; +} + void pci_request_acs(void); bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags); bool pci_acs_path_enabled(struct pci_dev *start, -- cgit v1.2.3 From 62f87c0e31d646d5501edf4f7feb07d0ad689d80 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Tue, 24 Jul 2012 17:20:03 +0800 Subject: PCI: Introduce pci_pcie_type(dev) to replace pci_dev->pcie_type Introduce an inline function pci_pcie_type(dev) to extract PCIe device type from pci_dev->pcie_flags_reg field, and prepare for removing pci_dev->pcie_type. Signed-off-by: Yijing Wang Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- arch/powerpc/platforms/powernv/pci-ioda.c | 2 +- drivers/iommu/intel-iommu.c | 6 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- .../net/ethernet/qlogic/netxen/netxen_nic_main.c | 2 +- drivers/pci/iov.c | 6 ++-- drivers/pci/pci.c | 26 +++++++------- drivers/pci/pcie/aer/aer_inject.c | 2 +- drivers/pci/pcie/aer/aerdrv.c | 7 ++-- drivers/pci/pcie/aer/aerdrv_acpi.c | 2 +- drivers/pci/pcie/aer/aerdrv_core.c | 2 +- drivers/pci/pcie/aspm.c | 42 +++++++++++----------- drivers/pci/pcie/pme.c | 6 ++-- drivers/pci/pcie/portdrv_bus.c | 2 +- drivers/pci/pcie/portdrv_core.c | 4 +-- drivers/pci/pcie/portdrv_pci.c | 8 ++--- drivers/pci/probe.c | 9 ++--- drivers/pci/search.c | 2 +- 17 files changed, 67 insertions(+), 63 deletions(-) diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 9cda6a1ad0cf..b46e1dadc882 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -855,7 +855,7 @@ static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus) if (pe == NULL) continue; /* Leaving the PCIe domain ... single PE# */ - if (dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) + if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) pnv_ioda_setup_bus_PE(dev, pe); else if (dev->subordinate) pnv_ioda_setup_PEs(dev->subordinate); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 7469b5346643..8b5075d6dd5a 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2350,7 +2350,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) return 0; if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) return 0; - } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) + } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE) return 0; /* @@ -3545,10 +3545,10 @@ found: struct pci_dev *bridge = bus->self; if (!bridge || !pci_is_pcie(bridge) || - bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) + pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) return 0; - if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { + if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) { for (i = 0; i < atsru->devices_cnt; i++) if (atsru->devices[i] == bridge) return 1; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 4326f74f7137..976570d4c939 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7527,7 +7527,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev, goto skip_bad_vf_detection; bdev = pdev->bus->self; - while (bdev && (bdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT)) + while (bdev && (pci_pcie_type(bdev) != PCI_EXP_TYPE_ROOT_PORT)) bdev = bdev->bus->self; if (!bdev) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 342b3a79bd0f..01d6141cedd9 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1382,7 +1382,7 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP) return; - if (root->pcie_type != PCI_EXP_TYPE_ROOT_PORT) + if (pci_pcie_type(root) != PCI_EXP_TYPE_ROOT_PORT) return; aer_pos = pci_find_ext_capability(root, PCI_EXT_CAP_ID_ERR); diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 74bbaf82638d..aeccc911abb8 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -433,8 +433,8 @@ static int sriov_init(struct pci_dev *dev, int pos) struct resource *res; struct pci_dev *pdev; - if (dev->pcie_type != PCI_EXP_TYPE_RC_END && - dev->pcie_type != PCI_EXP_TYPE_ENDPOINT) + if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END && + pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT) return -ENODEV; pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl); @@ -503,7 +503,7 @@ found: iov->self = dev; pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); - if (dev->pcie_type == PCI_EXP_TYPE_RC_END) + if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) iov->link = PCI_DEVFN(PCI_SLOT(dev->devfn), iov->link); if (pdev) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f3ea977a5b1b..28eb55b77ee9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -885,7 +885,7 @@ static struct pci_cap_saved_state *pci_find_saved_cap( static int pci_save_pcie_state(struct pci_dev *dev) { - int pos, i = 0; + int type, pos, i = 0; struct pci_cap_saved_state *save_state; u16 *cap; u16 flags; @@ -903,13 +903,14 @@ static int pci_save_pcie_state(struct pci_dev *dev) pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); - if (pcie_cap_has_devctl(dev->pcie_type, flags)) + type = pci_pcie_type(dev); + if (pcie_cap_has_devctl(type, flags)) pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]); - if (pcie_cap_has_lnkctl(dev->pcie_type, flags)) + if (pcie_cap_has_lnkctl(type, flags)) pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); - if (pcie_cap_has_sltctl(dev->pcie_type, flags)) + if (pcie_cap_has_sltctl(type, flags)) pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); - if (pcie_cap_has_rtctl(dev->pcie_type, flags)) + if (pcie_cap_has_rtctl(type, flags)) pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); pos = pci_pcie_cap2(dev); @@ -924,7 +925,7 @@ static int pci_save_pcie_state(struct pci_dev *dev) static void pci_restore_pcie_state(struct pci_dev *dev) { - int i = 0, pos; + int i = 0, pos, type; struct pci_cap_saved_state *save_state; u16 *cap; u16 flags; @@ -937,13 +938,14 @@ static void pci_restore_pcie_state(struct pci_dev *dev) pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); - if (pcie_cap_has_devctl(dev->pcie_type, flags)) + type = pci_pcie_type(dev); + if (pcie_cap_has_devctl(type, flags)) pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]); - if (pcie_cap_has_lnkctl(dev->pcie_type, flags)) + if (pcie_cap_has_lnkctl(type, flags)) pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); - if (pcie_cap_has_sltctl(dev->pcie_type, flags)) + if (pcie_cap_has_sltctl(type, flags)) pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); - if (pcie_cap_has_rtctl(dev->pcie_type, flags)) + if (pcie_cap_has_rtctl(type, flags)) pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); pos = pci_pcie_cap2(dev); @@ -2459,8 +2461,8 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags) acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT); - if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM || - pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM || + pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || pdev->multifunction) { pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); if (!pos) diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 52229863e9fe..4e24cb8a94ae 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -288,7 +288,7 @@ static struct pci_dev *pcie_find_root_port(struct pci_dev *dev) while (1) { if (!pci_is_pcie(dev)) break; - if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) return dev; if (!dev->bus->self) break; diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 58ad7917553c..f7c62453ae00 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -81,10 +81,11 @@ bool pci_aer_available(void) static int set_device_error_reporting(struct pci_dev *dev, void *data) { bool enable = *((bool *)data); + int type = pci_pcie_type(dev); - if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) || - (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) || - (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) { + if ((type == PCI_EXP_TYPE_ROOT_PORT) || + (type == PCI_EXP_TYPE_UPSTREAM) || + (type == PCI_EXP_TYPE_DOWNSTREAM)) { if (enable) pci_enable_pcie_error_reporting(dev); else diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 124f20ff11b2..5194a7d41730 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -60,7 +60,7 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) p = (struct acpi_hest_aer_common *)(hest_hdr + 1); if (p->flags & ACPI_HEST_GLOBAL) { if ((pci_is_pcie(info->pci_dev) && - info->pci_dev->pcie_type == pcie_type) || bridge) + pci_pcie_type(info->pci_dev) == pcie_type) || bridge) ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); } else if (hest_match_pci(p, info->pci_dev)) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 0ca053538146..f55153489854 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -465,7 +465,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev) if (driver && driver->reset_link) { status = driver->reset_link(udev); - } else if (udev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) { + } else if (pci_pcie_type(udev) == PCI_EXP_TYPE_DOWNSTREAM) { status = default_downstream_reset_link(udev); } else { dev_printk(KERN_DEBUG, &dev->dev, diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b500840a143b..25916034c0ae 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -412,7 +412,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) * do ASPM for now. */ list_for_each_entry(child, &linkbus->devices, bus_list) { - if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { + if (pci_pcie_type(child) == PCI_EXP_TYPE_PCI_BRIDGE) { link->aspm_disable = ASPM_STATE_ALL; break; } @@ -425,8 +425,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) struct aspm_latency *acceptable = &link->acceptable[PCI_FUNC(child->devfn)]; - if (child->pcie_type != PCI_EXP_TYPE_ENDPOINT && - child->pcie_type != PCI_EXP_TYPE_LEG_END) + if (pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT && + pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END) continue; pos = pci_pcie_cap(child); @@ -552,7 +552,7 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev) INIT_LIST_HEAD(&link->children); INIT_LIST_HEAD(&link->link); link->pdev = pdev; - if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) { + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) { struct pcie_link_state *parent; parent = pdev->bus->parent->self->link_state; if (!parent) { @@ -585,12 +585,12 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) if (!pci_is_pcie(pdev) || pdev->link_state) return; - if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && + pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) return; /* VIA has a strange chipset, root port is under a bridge */ - if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT && pdev->bus->self) return; @@ -647,8 +647,8 @@ static void pcie_update_aspm_capable(struct pcie_link_state *root) if (link->root != root) continue; list_for_each_entry(child, &linkbus->devices, bus_list) { - if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT) && - (child->pcie_type != PCI_EXP_TYPE_LEG_END)) + if ((pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT) && + (pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END)) continue; pcie_aspm_check_latency(child); } @@ -663,8 +663,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) if (!pci_is_pcie(pdev) || !parent || !parent->link_state) return; - if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && - (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) + if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) && + (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM)) return; down_read(&pci_bus_sem); @@ -704,8 +704,8 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) if (aspm_disabled || !pci_is_pcie(pdev) || !link) return; - if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && - (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) + if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) && + (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)) return; /* * Devices changed PM state, we should recheck if latency @@ -729,8 +729,8 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) if (aspm_policy != POLICY_POWERSAVE) return; - if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && - (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) + if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) && + (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)) return; down_read(&pci_bus_sem); @@ -757,8 +757,8 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, if (!pci_is_pcie(pdev)) return; - if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || - pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || + pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) parent = pdev; if (!parent || !parent->link_state) return; @@ -933,8 +933,8 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) struct pcie_link_state *link_state = pdev->link_state; if (!pci_is_pcie(pdev) || - (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) + (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && + pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->aspm_support) @@ -950,8 +950,8 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) struct pcie_link_state *link_state = pdev->link_state; if (!pci_is_pcie(pdev) || - (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) + (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && + pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->aspm_support) diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 001f1b78f39c..30897bf05b58 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -120,7 +120,7 @@ static bool pcie_pme_from_pci_bridge(struct pci_bus *bus, u8 devfn) if (!dev) return false; - if (pci_is_pcie(dev) && dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { + if (pci_is_pcie(dev) && pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE) { down_read(&pci_bus_sem); if (pcie_pme_walk_bus(bus)) found = true; @@ -335,13 +335,13 @@ static void pcie_pme_mark_devices(struct pci_dev *port) struct pci_dev *dev; /* Check if this is a root port event collector. */ - if (port->pcie_type != PCI_EXP_TYPE_RC_EC || !bus) + if (pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC || !bus) return; down_read(&pci_bus_sem); list_for_each_entry(dev, &bus->devices, bus_list) if (pci_is_pcie(dev) - && dev->pcie_type == PCI_EXP_TYPE_RC_END) + && pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) pcie_pme_set_native(dev, NULL); up_read(&pci_bus_sem); } diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c index 18bf90f748f6..67be55a7f260 100644 --- a/drivers/pci/pcie/portdrv_bus.c +++ b/drivers/pci/pcie/portdrv_bus.c @@ -38,7 +38,7 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) return 0; if ((driver->port_type != PCIE_ANY_PORT) && - (driver->port_type != pciedev->port->pcie_type)) + (driver->port_type != pci_pcie_type(pciedev->port))) return 0; return 1; diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 75915b30ad19..bf320a9419f4 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -298,7 +298,7 @@ static int get_port_device_capability(struct pci_dev *dev) services |= PCIE_PORT_SERVICE_VC; /* Root ports are capable of generating PME too */ if ((cap_mask & PCIE_PORT_SERVICE_PME) - && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { + && pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) { services |= PCIE_PORT_SERVICE_PME; /* * Disable PME interrupt on this port in case it's been enabled @@ -336,7 +336,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq) device->release = release_pcie_device; /* callback to free pcie dev */ dev_set_name(device, "%s:pcie%02x", pci_name(pdev), - get_descriptor_id(pdev->pcie_type, service)); + get_descriptor_id(pci_pcie_type(pdev), service)); device->parent = &pdev->dev; device_enable_async_suspend(device); diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3a7eefcb270a..24d1463e688b 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -95,7 +95,7 @@ static int pcie_port_resume_noirq(struct device *dev) * which breaks ACPI-based runtime wakeup on PCI Express, so clear those * bits now just in case (shouldn't hurt). */ - if(pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) pcie_clear_root_pme_status(pdev); return 0; } @@ -186,9 +186,9 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, int status; if (!pci_is_pcie(dev) || - ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && - (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) && - (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) + ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) && + (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) && + (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM))) return -ENODEV; if (!dev->irq && dev->pin) { diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ba4d8550503c..1d52a43eb086 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1384,9 +1384,9 @@ static int only_one_child(struct pci_bus *bus) if (!parent || !pci_is_pcie(parent)) return 0; - if (parent->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT) return 1; - if (parent->pcie_type == PCI_EXP_TYPE_DOWNSTREAM && + if (pci_pcie_type(parent) == PCI_EXP_TYPE_DOWNSTREAM && !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) return 1; return 0; @@ -1463,7 +1463,7 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data) */ if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) || (dev->bus->self && - dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT))) + pci_pcie_type(dev->bus->self) != PCI_EXP_TYPE_ROOT_PORT))) *smpss = 0; if (*smpss > dev->pcie_mpss) @@ -1479,7 +1479,8 @@ static void pcie_write_mps(struct pci_dev *dev, int mps) if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { mps = 128 << dev->pcie_mpss; - if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && dev->bus->self) + if (pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT && + dev->bus->self) /* For "Performance", the assumption is made that * downstream communication will never be larger than * the MRRS. So, the MPS only needs to be configured diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 993d4a0a2469..621b162ceb69 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -41,7 +41,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) continue; } /* PCI device should connect to a PCIe bridge */ - if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) { + if (pci_pcie_type(pdev) != PCI_EXP_TYPE_PCI_BRIDGE) { /* Busted hardware? */ WARN_ON_ONCE(1); return NULL; -- cgit v1.2.3 From b2ef39be5744d4d3575474444345e71bd95013ba Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Tue, 24 Jul 2012 17:20:04 +0800 Subject: PCI: Remove unused field pcie_type from struct pci_dev With introduction of pci_pcie_type(), pci_dev->pcie_type field becomes redundant, so remove it. Signed-off-by: Yijing Wang Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 1 - include/linux/pci.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 1d52a43eb086..8bcc985faa16 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -930,7 +930,6 @@ void set_pcie_port_type(struct pci_dev *pdev) pdev->pcie_cap = pos; pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); pdev->pcie_flags_reg = reg16; - pdev->pcie_type = pci_pcie_type(pdev); pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; } diff --git a/include/linux/pci.h b/include/linux/pci.h index 95662b2f0c3d..9807da507e1f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -254,7 +254,6 @@ struct pci_dev { u8 revision; /* PCI revision, low byte of class word */ u8 hdr_type; /* PCI header type (`multi' flag masked out) */ u8 pcie_cap; /* PCI-E capability offset */ - u8 pcie_type:4; /* PCI-E device/port type */ u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */ u8 rom_base_reg; /* which config register controls the ROM */ u8 pin; /* which interrupt pin this device uses */ -- cgit v1.2.3 From 8c0d3a02c1309eb6112d2e7c8172e8ceb26ecfca Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 24 Jul 2012 17:20:05 +0800 Subject: PCI: Add accessors for PCI Express Capability The PCI Express Capability (PCIe spec r3.0, sec 7.8) comes in two versions, v1 and v2. In v1 Capability structures (PCIe spec r1.0 and r1.1), some fields are optional, so the structure size depends on the device type. This patch adds functions to access this capability so drivers don't have to be aware of the differences between v1 and v2. Note that these new functions apply only to the "PCI Express Capability," not to any of the other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.) Function pcie_capability_read_word/dword() reads the PCIe Capabilities register and returns the value in the reference parameter "val". If the PCIe Capabilities register is not implemented on the PCIe device, "val" is set to 0. Function pcie_capability_write_word/dword() writes the value to the specified PCIe Capability register. Function pcie_capability_clear_and_set_word/dword() sets and/or clears bits of a PCIe Capability register. [bhelgaas: changelog, drop "pci_" prefixes, don't export pcie_capability_reg_implemented()] Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/access.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 33 ++++++++ include/linux/pci_regs.h | 1 + 3 files changed, 236 insertions(+) diff --git a/drivers/pci/access.c b/drivers/pci/access.c index ba91a7e17519..3af0478c057b 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -469,3 +469,205 @@ void pci_cfg_access_unlock(struct pci_dev *dev) raw_spin_unlock_irqrestore(&pci_lock, flags); } EXPORT_SYMBOL_GPL(pci_cfg_access_unlock); + +static inline int pcie_cap_version(const struct pci_dev *dev) +{ + return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS; +} + +static inline bool pcie_cap_has_devctl(const struct pci_dev *dev) +{ + return true; +} + +static inline bool pcie_cap_has_lnkctl(const struct pci_dev *dev) +{ + int type = pci_pcie_type(dev); + + return pcie_cap_version(dev) > 1 || + type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_ENDPOINT || + type == PCI_EXP_TYPE_LEG_END; +} + +static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) +{ + int type = pci_pcie_type(dev); + + return pcie_cap_version(dev) > 1 || + type == PCI_EXP_TYPE_ROOT_PORT || + (type == PCI_EXP_TYPE_DOWNSTREAM && + dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT); +} + +static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev) +{ + int type = pci_pcie_type(dev); + + return pcie_cap_version(dev) > 1 || + type == PCI_EXP_TYPE_ROOT_PORT || + type == PCI_EXP_TYPE_RC_EC; +} + +static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) +{ + if (!pci_is_pcie(dev)) + return false; + + switch (pos) { + case PCI_EXP_FLAGS_TYPE: + return true; + case PCI_EXP_DEVCAP: + case PCI_EXP_DEVCTL: + case PCI_EXP_DEVSTA: + return pcie_cap_has_devctl(dev); + case PCI_EXP_LNKCAP: + case PCI_EXP_LNKCTL: + case PCI_EXP_LNKSTA: + return pcie_cap_has_lnkctl(dev); + case PCI_EXP_SLTCAP: + case PCI_EXP_SLTCTL: + case PCI_EXP_SLTSTA: + return pcie_cap_has_sltctl(dev); + case PCI_EXP_RTCTL: + case PCI_EXP_RTCAP: + case PCI_EXP_RTSTA: + return pcie_cap_has_rtctl(dev); + case PCI_EXP_DEVCAP2: + case PCI_EXP_DEVCTL2: + case PCI_EXP_LNKCAP2: + case PCI_EXP_LNKCTL2: + case PCI_EXP_LNKSTA2: + return pcie_cap_version(dev) > 1; + default: + return false; + } +} + +/* + * Note that these accessor functions are only for the "PCI Express + * Capability" (see PCIe spec r3.0, sec 7.8). They do not apply to the + * other "PCI Express Extended Capabilities" (AER, VC, ACS, MFVC, etc.) + */ +int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val) +{ + int ret; + + *val = 0; + if (pos & 1) + return -EINVAL; + + if (pcie_capability_reg_implemented(dev, pos)) { + ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val); + /* + * Reset *val to 0 if pci_read_config_word() fails, it may + * have been written as 0xFFFF if hardware error happens + * during pci_read_config_word(). + */ + if (ret) + *val = 0; + return ret; + } + + /* + * For Functions that do not implement the Slot Capabilities, + * Slot Status, and Slot Control registers, these spaces must + * be hardwired to 0b, with the exception of the Presence Detect + * State bit in the Slot Status register of Downstream Ports, + * which must be hardwired to 1b. (PCIe Base Spec 3.0, sec 7.8) + */ + if (pci_is_pcie(dev) && pos == PCI_EXP_SLTSTA && + pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { + *val = PCI_EXP_SLTSTA_PDS; + } + + return 0; +} +EXPORT_SYMBOL(pcie_capability_read_word); + +int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val) +{ + int ret; + + *val = 0; + if (pos & 3) + return -EINVAL; + + if (pcie_capability_reg_implemented(dev, pos)) { + ret = pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, val); + /* + * Reset *val to 0 if pci_read_config_dword() fails, it may + * have been written as 0xFFFFFFFF if hardware error happens + * during pci_read_config_dword(). + */ + if (ret) + *val = 0; + return ret; + } + + if (pci_is_pcie(dev) && pos == PCI_EXP_SLTCTL && + pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) { + *val = PCI_EXP_SLTSTA_PDS; + } + + return 0; +} +EXPORT_SYMBOL(pcie_capability_read_dword); + +int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) +{ + if (pos & 1) + return -EINVAL; + + if (!pcie_capability_reg_implemented(dev, pos)) + return 0; + + return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); +} +EXPORT_SYMBOL(pcie_capability_write_word); + +int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val) +{ + if (pos & 3) + return -EINVAL; + + if (!pcie_capability_reg_implemented(dev, pos)) + return 0; + + return pci_write_config_dword(dev, pci_pcie_cap(dev) + pos, val); +} +EXPORT_SYMBOL(pcie_capability_write_dword); + +int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, + u16 clear, u16 set) +{ + int ret; + u16 val; + + ret = pcie_capability_read_word(dev, pos, &val); + if (!ret) { + val &= ~clear; + val |= set; + ret = pcie_capability_write_word(dev, pos, val); + } + + return ret; +} +EXPORT_SYMBOL(pcie_capability_clear_and_set_word); + +int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, + u32 clear, u32 set) +{ + int ret; + u32 val; + + ret = pcie_capability_read_dword(dev, pos, &val); + if (!ret) { + val &= ~clear; + val |= set; + ret = pcie_capability_write_dword(dev, pos, val); + } + + return ret; +} +EXPORT_SYMBOL(pcie_capability_clear_and_set_dword); diff --git a/include/linux/pci.h b/include/linux/pci.h index 9807da507e1f..b8667e0548e0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -816,6 +816,39 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where, return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); } +int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val); +int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val); +int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val); +int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val); +int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, + u16 clear, u16 set); +int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, + u32 clear, u32 set); + +static inline int pcie_capability_set_word(struct pci_dev *dev, int pos, + u16 set) +{ + return pcie_capability_clear_and_set_word(dev, pos, 0, set); +} + +static inline int pcie_capability_set_dword(struct pci_dev *dev, int pos, + u32 set) +{ + return pcie_capability_clear_and_set_dword(dev, pos, 0, set); +} + +static inline int pcie_capability_clear_word(struct pci_dev *dev, int pos, + u16 clear) +{ + return pcie_capability_clear_and_set_word(dev, pos, clear, 0); +} + +static inline int pcie_capability_clear_dword(struct pci_dev *dev, int pos, + u32 clear) +{ + return pcie_capability_clear_and_set_dword(dev, pos, clear, 0); +} + /* user-space driven config access */ int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 7fb75b143755..3958f70f3202 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -549,6 +549,7 @@ #define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */ #define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */ #define PCI_EXP_LNKCTL2 48 /* Link Control 2 */ +#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */ #define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */ /* Extended Capabilities (PCI-X 2.0 and Express) */ -- cgit v1.2.3 From 59875ae489609b2267548dc85160c5f0f0c6f9d4 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 24 Jul 2012 17:20:06 +0800 Subject: PCI/core: Use PCI Express Capability accessors Use PCI Express Capability access functions to simplify core. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 314 ++++++++++----------------------------------------- drivers/pci/probe.c | 17 +-- drivers/pci/quirks.c | 9 +- 3 files changed, 66 insertions(+), 274 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 28eb55b77ee9..fac08f508d09 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -253,38 +253,6 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) return pos; } -/** - * pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure - * @dev: PCI device to check - * - * Like pci_pcie_cap() but also checks that the PCIe capability version is - * >= 2. Note that v1 capability structures could be sparse in that not - * all register fields were required. v2 requires the entire structure to - * be present size wise, while still allowing for non-implemented registers - * to exist but they must be hardwired to 0. - * - * Due to the differences in the versions of capability structures, one - * must be careful not to try and access non-existant registers that may - * exist in early versions - v1 - of Express devices. - * - * Returns the offset of the PCIe capability structure as long as the - * capability version is >= 2; otherwise 0 is returned. - */ -static int pci_pcie_cap2(struct pci_dev *dev) -{ - u16 flags; - int pos; - - pos = pci_pcie_cap(dev); - if (pos) { - pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); - if ((flags & PCI_EXP_FLAGS_VERS) < 2) - pos = 0; - } - - return pos; -} - /** * pci_find_ext_capability - Find an extended capability * @dev: PCI device to query @@ -854,21 +822,6 @@ EXPORT_SYMBOL(pci_choose_state); #define PCI_EXP_SAVE_REGS 7 -#define pcie_cap_has_devctl(type, flags) 1 -#define pcie_cap_has_lnkctl(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ - (type == PCI_EXP_TYPE_ROOT_PORT || \ - type == PCI_EXP_TYPE_ENDPOINT || \ - type == PCI_EXP_TYPE_LEG_END)) -#define pcie_cap_has_sltctl(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ - ((type == PCI_EXP_TYPE_ROOT_PORT) || \ - (type == PCI_EXP_TYPE_DOWNSTREAM && \ - (flags & PCI_EXP_FLAGS_SLOT)))) -#define pcie_cap_has_rtctl(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ - (type == PCI_EXP_TYPE_ROOT_PORT || \ - type == PCI_EXP_TYPE_RC_EC)) static struct pci_cap_saved_state *pci_find_saved_cap( struct pci_dev *pci_dev, char cap) @@ -885,13 +838,11 @@ static struct pci_cap_saved_state *pci_find_saved_cap( static int pci_save_pcie_state(struct pci_dev *dev) { - int type, pos, i = 0; + int i = 0; struct pci_cap_saved_state *save_state; u16 *cap; - u16 flags; - pos = pci_pcie_cap(dev); - if (!pos) + if (!pci_is_pcie(dev)) return 0; save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); @@ -899,62 +850,37 @@ static int pci_save_pcie_state(struct pci_dev *dev) dev_err(&dev->dev, "buffer not found in %s\n", __func__); return -ENOMEM; } - cap = (u16 *)&save_state->cap.data[0]; - - pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); - - type = pci_pcie_type(dev); - if (pcie_cap_has_devctl(type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]); - if (pcie_cap_has_lnkctl(type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); - if (pcie_cap_has_sltctl(type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); - if (pcie_cap_has_rtctl(type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); - pos = pci_pcie_cap2(dev); - if (!pos) - return 0; + cap = (u16 *)&save_state->cap.data[0]; + pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &cap[i++]); + pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &cap[i++]); + pcie_capability_read_word(dev, PCI_EXP_SLTCTL, &cap[i++]); + pcie_capability_read_word(dev, PCI_EXP_RTCTL, &cap[i++]); + pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &cap[i++]); + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &cap[i++]); + pcie_capability_read_word(dev, PCI_EXP_SLTCTL2, &cap[i++]); - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); - pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); - pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); return 0; } static void pci_restore_pcie_state(struct pci_dev *dev) { - int i = 0, pos, type; + int i = 0; struct pci_cap_saved_state *save_state; u16 *cap; - u16 flags; save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (!save_state || pos <= 0) - return; - cap = (u16 *)&save_state->cap.data[0]; - - pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); - - type = pci_pcie_type(dev); - if (pcie_cap_has_devctl(type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]); - if (pcie_cap_has_lnkctl(type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); - if (pcie_cap_has_sltctl(type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); - if (pcie_cap_has_rtctl(type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); - - pos = pci_pcie_cap2(dev); - if (!pos) + if (!save_state) return; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); - pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); - pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); + cap = (u16 *)&save_state->cap.data[0]; + pcie_capability_write_word(dev, PCI_EXP_DEVCTL, cap[i++]); + pcie_capability_write_word(dev, PCI_EXP_LNKCTL, cap[i++]); + pcie_capability_write_word(dev, PCI_EXP_SLTCTL, cap[i++]); + pcie_capability_write_word(dev, PCI_EXP_RTCTL, cap[i++]); + pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, cap[i++]); + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, cap[i++]); + pcie_capability_write_word(dev, PCI_EXP_SLTCTL2, cap[i++]); } @@ -2068,35 +1994,24 @@ void pci_free_cap_save_buffers(struct pci_dev *dev) */ void pci_enable_ari(struct pci_dev *dev) { - int pos; u32 cap; - u16 ctrl; struct pci_dev *bridge; if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) return; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); - if (!pos) + if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) return; bridge = dev->bus->self; if (!bridge) return; - /* ARI is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(bridge); - if (!pos) - return; - - pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap); + pcie_capability_read_dword(bridge, PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; - pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl); - ctrl |= PCI_EXP_DEVCTL2_ARI; - pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl); - + pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI); bridge->ari_enabled = 1; } @@ -2111,20 +2026,14 @@ void pci_enable_ari(struct pci_dev *dev) */ void pci_enable_ido(struct pci_dev *dev, unsigned long type) { - int pos; - u16 ctrl; + u16 ctrl = 0; - /* ID-based Ordering is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(dev); - if (!pos) - return; - - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); if (type & PCI_EXP_IDO_REQUEST) ctrl |= PCI_EXP_IDO_REQ_EN; if (type & PCI_EXP_IDO_COMPLETION) ctrl |= PCI_EXP_IDO_CMP_EN; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + if (ctrl) + pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, ctrl); } EXPORT_SYMBOL(pci_enable_ido); @@ -2135,20 +2044,14 @@ EXPORT_SYMBOL(pci_enable_ido); */ void pci_disable_ido(struct pci_dev *dev, unsigned long type) { - int pos; - u16 ctrl; + u16 ctrl = 0; - /* ID-based Ordering is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(dev); - if (!pos) - return; - - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); if (type & PCI_EXP_IDO_REQUEST) - ctrl &= ~PCI_EXP_IDO_REQ_EN; + ctrl |= PCI_EXP_IDO_REQ_EN; if (type & PCI_EXP_IDO_COMPLETION) - ctrl &= ~PCI_EXP_IDO_CMP_EN; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + ctrl |= PCI_EXP_IDO_CMP_EN; + if (ctrl) + pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, ctrl); } EXPORT_SYMBOL(pci_disable_ido); @@ -2173,17 +2076,11 @@ EXPORT_SYMBOL(pci_disable_ido); */ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) { - int pos; u32 cap; u16 ctrl; int ret; - /* OBFF is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(dev); - if (!pos) - return -ENOTSUPP; - - pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); + pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_OBFF_MASK)) return -ENOTSUPP; /* no OBFF support at all */ @@ -2194,7 +2091,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) return ret; } - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); + pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &ctrl); if (cap & PCI_EXP_OBFF_WAKE) ctrl |= PCI_EXP_OBFF_WAKE_EN; else { @@ -2212,7 +2109,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) return -ENOTSUPP; } } - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, ctrl); return 0; } @@ -2226,17 +2123,7 @@ EXPORT_SYMBOL(pci_enable_obff); */ void pci_disable_obff(struct pci_dev *dev) { - int pos; - u16 ctrl; - - /* OBFF is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(dev); - if (!pos) - return; - - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); - ctrl &= ~PCI_EXP_OBFF_WAKE_EN; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_OBFF_WAKE_EN); } EXPORT_SYMBOL(pci_disable_obff); @@ -2249,15 +2136,9 @@ EXPORT_SYMBOL(pci_disable_obff); */ static bool pci_ltr_supported(struct pci_dev *dev) { - int pos; u32 cap; - /* LTR is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(dev); - if (!pos) - return false; - - pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); + pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap); return cap & PCI_EXP_DEVCAP2_LTR; } @@ -2274,22 +2155,15 @@ static bool pci_ltr_supported(struct pci_dev *dev) */ int pci_enable_ltr(struct pci_dev *dev) { - int pos; - u16 ctrl; int ret; - if (!pci_ltr_supported(dev)) - return -ENOTSUPP; - - /* LTR is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(dev); - if (!pos) - return -ENOTSUPP; - /* Only primary function can enable/disable LTR */ if (PCI_FUNC(dev->devfn) != 0) return -EINVAL; + if (!pci_ltr_supported(dev)) + return -ENOTSUPP; + /* Enable upstream ports first */ if (dev->bus->self) { ret = pci_enable_ltr(dev->bus->self); @@ -2297,11 +2171,7 @@ int pci_enable_ltr(struct pci_dev *dev) return ret; } - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); - ctrl |= PCI_EXP_LTR_EN; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); - - return 0; + return pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_LTR_EN); } EXPORT_SYMBOL(pci_enable_ltr); @@ -2311,24 +2181,14 @@ EXPORT_SYMBOL(pci_enable_ltr); */ void pci_disable_ltr(struct pci_dev *dev) { - int pos; - u16 ctrl; - - if (!pci_ltr_supported(dev)) - return; - - /* LTR is a PCIe cap v2 feature */ - pos = pci_pcie_cap2(dev); - if (!pos) - return; - /* Only primary function can enable/disable LTR */ if (PCI_FUNC(dev->devfn) != 0) return; - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); - ctrl &= ~PCI_EXP_LTR_EN; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); + if (!pci_ltr_supported(dev)) + return; + + pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, PCI_EXP_LTR_EN); } EXPORT_SYMBOL(pci_disable_ltr); @@ -2411,9 +2271,6 @@ void pci_enable_acs(struct pci_dev *dev) if (!pci_acs_enable) return; - if (!pci_is_pcie(dev)) - return; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS); if (!pos) return; @@ -3178,15 +3035,10 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary); static int pcie_flr(struct pci_dev *dev, int probe) { int i; - int pos; u32 cap; - u16 status, control; - - pos = pci_pcie_cap(dev); - if (!pos) - return -ENOTTY; + u16 status; - pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap); + pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap); if (!(cap & PCI_EXP_DEVCAP_FLR)) return -ENOTTY; @@ -3198,7 +3050,7 @@ static int pcie_flr(struct pci_dev *dev, int probe) if (i) msleep((1 << (i - 1)) * 100); - pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status); + pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); if (!(status & PCI_EXP_DEVSTA_TRPND)) goto clear; } @@ -3207,9 +3059,7 @@ static int pcie_flr(struct pci_dev *dev, int probe) "proceeding with reset anyway\n"); clear: - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &control); - control |= PCI_EXP_DEVCTL_BCR_FLR; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, control); + pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); msleep(100); @@ -3577,18 +3427,11 @@ EXPORT_SYMBOL(pcix_set_mmrbc); */ int pcie_get_readrq(struct pci_dev *dev) { - int ret, cap; u16 ctl; - cap = pci_pcie_cap(dev); - if (!cap) - return -EINVAL; - - ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); - if (!ret) - ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12); + pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); - return ret; + return 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12); } EXPORT_SYMBOL(pcie_get_readrq); @@ -3602,19 +3445,11 @@ EXPORT_SYMBOL(pcie_get_readrq); */ int pcie_set_readrq(struct pci_dev *dev, int rq) { - int cap, err = -EINVAL; - u16 ctl, v; + u16 v; if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) - goto out; - - cap = pci_pcie_cap(dev); - if (!cap) - goto out; + return -EINVAL; - err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); - if (err) - goto out; /* * If using the "performance" PCIe config, we clamp the * read rq size to the max packet size to prevent the @@ -3632,14 +3467,8 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) v = (ffs(rq) - 8) << 12; - if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) { - ctl &= ~PCI_EXP_DEVCTL_READRQ; - ctl |= v; - err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl); - } - -out: - return err; + return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_READRQ, v); } EXPORT_SYMBOL(pcie_set_readrq); @@ -3652,18 +3481,11 @@ EXPORT_SYMBOL(pcie_set_readrq); */ int pcie_get_mps(struct pci_dev *dev) { - int ret, cap; u16 ctl; - cap = pci_pcie_cap(dev); - if (!cap) - return -EINVAL; - - ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); - if (!ret) - ret = 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); - return ret; + return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); } /** @@ -3676,32 +3498,18 @@ int pcie_get_mps(struct pci_dev *dev) */ int pcie_set_mps(struct pci_dev *dev, int mps) { - int cap, err = -EINVAL; - u16 ctl, v; + u16 v; if (mps < 128 || mps > 4096 || !is_power_of_2(mps)) - goto out; + return -EINVAL; v = ffs(mps) - 8; if (v > dev->pcie_mpss) - goto out; + return -EINVAL; v <<= 5; - cap = pci_pcie_cap(dev); - if (!cap) - goto out; - - err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); - if (err) - goto out; - - if ((ctl & PCI_EXP_DEVCTL_PAYLOAD) != v) { - ctl &= ~PCI_EXP_DEVCTL_PAYLOAD; - ctl |= v; - err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, ctl); - } -out: - return err; + return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_PAYLOAD, v); } /** diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 8bcc985faa16..d8f513bdf95c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -603,10 +603,10 @@ static void pci_set_bus_speed(struct pci_bus *bus) u32 linkcap; u16 linksta; - pci_read_config_dword(bridge, pos + PCI_EXP_LNKCAP, &linkcap); + pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap); bus->max_bus_speed = pcie_link_speed[linkcap & 0xf]; - pci_read_config_word(bridge, pos + PCI_EXP_LNKSTA, &linksta); + pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta); pcie_update_link_speed(bus, linksta); } } @@ -936,17 +936,9 @@ void set_pcie_port_type(struct pci_dev *pdev) void set_pcie_hotplug_bridge(struct pci_dev *pdev) { - int pos; - u16 reg16; u32 reg32; - pos = pci_pcie_cap(pdev); - if (!pos) - return; - pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); - if (!(reg16 & PCI_EXP_FLAGS_SLOT)) - return; - pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, ®32); + pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) pdev->is_hotplug_bridge = 1; } @@ -1160,8 +1152,7 @@ int pci_cfg_space_size(struct pci_dev *dev) if (class == PCI_CLASS_BRIDGE_HOST) return pci_cfg_space_size_ext(dev); - pos = pci_pcie_cap(dev); - if (!pos) { + if (!pci_is_pcie(dev)) { pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); if (!pos) goto fail; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 51553179e967..aa77538c50c7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3081,17 +3081,10 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe) static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) { - int pos; - - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); - if (!pos) - return -ENOTTY; - if (probe) return 0; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_BCR_FLR); + pcie_capability_write_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); msleep(100); return 0; -- cgit v1.2.3 From 76b57c6700e56d146938ca9dc1d553557e940d9f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 22 Aug 2012 09:41:27 -0600 Subject: PCI: Wait for pending transactions to complete before 82599 FLR Before initiating an FLR, we should wait for completion of any outstanding non-posted requests. See PCIe spec r3.0, sec 6.6.2. This makes reset_intel_82599_sfp_virtfn() very similar to the generic pcie_flr(). The only difference is that the 82599 doesn't report FLR support in the VF Device Capability register. Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index aa77538c50c7..7a451ff56ecc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3081,10 +3081,36 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe) static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) { + int i; + u16 status; + + /* + * http://www.intel.com/content/dam/doc/datasheet/82599-10-gbe-controller-datasheet.pdf + * + * The 82599 supports FLR on VFs, but FLR support is reported only + * in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5). + * Therefore, we can't use pcie_flr(), which checks the VF DEVCAP. + */ + if (probe) return 0; - pcie_capability_write_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); + /* Wait for Transaction Pending bit clean */ + for (i = 0; i < 4; i++) { + if (i) + msleep((1 << (i - 1)) * 100); + + pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); + if (!(status & PCI_EXP_DEVSTA_TRPND)) + goto clear; + } + + dev_err(&dev->dev, "transaction is not cleared; " + "proceeding with reset anyway\n"); + +clear: + pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR); + msleep(100); return 0; -- cgit v1.2.3 From 028fbad480edfc73157408f894a29385afc9689e Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 24 Jul 2012 17:20:07 +0800 Subject: PCI/hotplug: Use PCI Express Capability accessors Use PCI Express Capability access functions to simplify pcihp_slot.c. Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Reviewed-by: Kenji Kaneshige --- drivers/pci/hotplug/pcihp_slot.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index 8c05a18c9770..fec2d5b75440 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c @@ -96,17 +96,11 @@ static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp) static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) { int pos; - u16 reg16; u32 reg32; if (!hpp) return; - /* Find PCI Express capability */ - pos = pci_pcie_cap(dev); - if (!pos) - return; - if (hpp->revision > 1) { dev_warn(&dev->dev, "PCIe settings rev %d not supported\n", hpp->revision); @@ -114,17 +108,13 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) } /* Initialize Device Control Register */ - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); - reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); + pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, + ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or); /* Initialize Link Control Register */ - if (dev->subordinate) { - pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); - reg16 = (reg16 & hpp->pci_exp_lnkctl_and) - | hpp->pci_exp_lnkctl_or; - pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); - } + if (dev->subordinate) + pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL, + ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or); /* Find Advanced Error Reporting Enhanced Capability */ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); -- cgit v1.2.3 From 2dcfaf85cd0ced6dcfd4bf0012354b3fd2ed1f38 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 24 Jul 2012 17:20:08 +0800 Subject: PCI/portdrv: Use PCI Express Capability accessors Use PCI Express Capability access functions to simplify portdrv. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Kenji Kaneshige --- drivers/pci/pcie/portdrv_core.c | 15 +++++---------- drivers/pci/pcie/portdrv_pci.c | 9 +-------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index bf320a9419f4..aede99171e90 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -246,8 +246,7 @@ static void cleanup_service_irqs(struct pci_dev *dev) */ static int get_port_device_capability(struct pci_dev *dev) { - int services = 0, pos; - u16 reg16; + int services = 0; u32 reg32; int cap_mask = 0; int err; @@ -265,11 +264,9 @@ static int get_port_device_capability(struct pci_dev *dev) return 0; } - pos = pci_pcie_cap(dev); - pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); /* Hot-Plug Capable */ - if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) { - pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); + if (cap_mask & PCIE_PORT_SERVICE_HP) { + pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; /* @@ -277,10 +274,8 @@ static int get_port_device_capability(struct pci_dev *dev) * enabled by the BIOS and the hot-plug service driver * is not loaded. */ - pos += PCI_EXP_SLTCTL; - pci_read_config_word(dev, pos, ®16); - reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); - pci_write_config_word(dev, pos, reg16); + pcie_capability_clear_word(dev, PCI_EXP_SLTCTL, + PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); } } /* AER capable */ diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 24d1463e688b..2360330e48f1 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -64,14 +64,7 @@ __setup("pcie_ports=", pcie_port_setup); */ void pcie_clear_root_pme_status(struct pci_dev *dev) { - int rtsta_pos; - u32 rtsta; - - rtsta_pos = pci_pcie_cap(dev) + PCI_EXP_RTSTA; - - pci_read_config_dword(dev, rtsta_pos, &rtsta); - rtsta |= PCI_EXP_RTSTA_PME; - pci_write_config_dword(dev, rtsta_pos, rtsta); + pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME); } static int pcie_portdrv_restore_config(struct pci_dev *dev) -- cgit v1.2.3 From 537a77e65d2e971ff2688e285cc88283d4ce13b0 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 24 Jul 2012 17:20:09 +0800 Subject: PCI/pciehp: Use PCI Express Capability accessors Use PCI Express Capability access functions to simplify pciehp. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Kenji Kaneshige --- drivers/pci/hotplug/pciehp_acpi.c | 6 +----- drivers/pci/hotplug/pciehp_hpc.c | 12 ++++-------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 376d70d17176..24d709b7388c 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -81,16 +81,12 @@ static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots); /* Dummy driver for dumplicate name detection */ static int __init dummy_probe(struct pcie_device *dev) { - int pos; u32 slot_cap; acpi_handle handle; struct dummy_slot *slot, *tmp; struct pci_dev *pdev = dev->port; - pos = pci_pcie_cap(pdev); - if (!pos) - return -ENODEV; - pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); + pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 302451e8289d..13b2eaf7ba43 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -44,25 +44,25 @@ static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value); + return pcie_capability_read_word(dev, reg, value); } static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value); + return pcie_capability_read_dword(dev, reg, value); } static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value); + return pcie_capability_write_word(dev, reg, value); } static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) { struct pci_dev *dev = ctrl->pcie->port; - return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value); + return pcie_capability_write_dword(dev, reg, value); } /* Power Control Command */ @@ -855,10 +855,6 @@ struct controller *pcie_init(struct pcie_device *dev) goto abort; } ctrl->pcie = dev; - if (!pci_pcie_cap(pdev)) { - ctrl_err(ctrl, "Cannot find PCI Express capability\n"); - goto abort_ctrl; - } if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) { ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); goto abort_ctrl; -- cgit v1.2.3 From 263e54b99eb8f77be9b2144c5e466e95847c888c Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 24 Jul 2012 17:20:10 +0800 Subject: PCI/PME: Use PCI Express Capability accessors Use PCI Express Capability access functions to simplify PCIe PME. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/pme.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 30897bf05b58..9ca0dc9ffd84 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -57,17 +57,12 @@ struct pcie_pme_service_data { */ void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) { - int rtctl_pos; - u16 rtctl; - - rtctl_pos = pci_pcie_cap(dev) + PCI_EXP_RTCTL; - - pci_read_config_word(dev, rtctl_pos, &rtctl); if (enable) - rtctl |= PCI_EXP_RTCTL_PMEIE; + pcie_capability_set_word(dev, PCI_EXP_RTCTL, + PCI_EXP_RTCTL_PMEIE); else - rtctl &= ~PCI_EXP_RTCTL_PMEIE; - pci_write_config_word(dev, rtctl_pos, rtctl); + pcie_capability_clear_word(dev, PCI_EXP_RTCTL, + PCI_EXP_RTCTL_PMEIE); } /** @@ -226,18 +221,15 @@ static void pcie_pme_work_fn(struct work_struct *work) struct pcie_pme_service_data *data = container_of(work, struct pcie_pme_service_data, work); struct pci_dev *port = data->srv->port; - int rtsta_pos; u32 rtsta; - rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; - spin_lock_irq(&data->lock); for (;;) { if (data->noirq) break; - pci_read_config_dword(port, rtsta_pos, &rtsta); + pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta); if (rtsta & PCI_EXP_RTSTA_PME) { /* * Clear PME status of the port. If there are other @@ -276,17 +268,14 @@ static irqreturn_t pcie_pme_irq(int irq, void *context) { struct pci_dev *port; struct pcie_pme_service_data *data; - int rtsta_pos; u32 rtsta; unsigned long flags; port = ((struct pcie_device *)context)->port; data = get_service_data((struct pcie_device *)context); - rtsta_pos = pci_pcie_cap(port) + PCI_EXP_RTSTA; - spin_lock_irqsave(&data->lock, flags); - pci_read_config_dword(port, rtsta_pos, &rtsta); + pcie_capability_read_dword(port, PCI_EXP_RTSTA, &rtsta); if (!(rtsta & PCI_EXP_RTSTA_PME)) { spin_unlock_irqrestore(&data->lock, flags); -- cgit v1.2.3 From 43bd4ee89f748111d2a0443e6ef58f08ceb359aa Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 24 Jul 2012 17:20:11 +0800 Subject: PCI/AER: Use PCI Express Capability accessors Use PCI Express Capability access functions to simplify PCIe AER. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aerdrv.c | 17 ++++++------- drivers/pci/pcie/aer/aerdrv_core.c | 51 ++++++++------------------------------ 2 files changed, 17 insertions(+), 51 deletions(-) diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index f7c62453ae00..c78778fc0cba 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -1