diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2012-06-18 12:10:39 -0600 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-06-18 12:10:39 -0600 |
commit | 47fcb6da65e9e74f71f4ec68f1245fc600bec711 (patch) | |
tree | 6ef869c8f5768d8804ace7c36bbd6d493f995ad1 /drivers/pci/pci.c | |
parent | cc2fa3fa320d5f40a12713c104bbe5d3da4636e4 (diff) | |
parent | 9cb604ed45a31419bab3877472691a5da15a3c47 (diff) | |
download | linux-3.10-47fcb6da65e9e74f71f4ec68f1245fc600bec711.tar.gz linux-3.10-47fcb6da65e9e74f71f4ec68f1245fc600bec711.tar.bz2 linux-3.10-47fcb6da65e9e74f71f4ec68f1245fc600bec711.zip |
Merge branch 'topic/stowe-cap-cleanup' into next
* topic/stowe-cap-cleanup:
PCI: remove redundant capabilities checking in pci_{save, restore}_pcie_state
PCI: add pci_pcie_cap2() check for PCIe feature capabilities >= v2
PCI: remove redundant checking in PCI Express capability routines
PCI: make pci_ltr_supported() static
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 115 |
1 files changed, 67 insertions, 48 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b743a9afb4d..ae5d96ac2aa 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -254,6 +254,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) } /** + * 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 * @cap: capability code @@ -755,12 +787,6 @@ EXPORT_SYMBOL(pci_choose_state); ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ (type == PCI_EXP_TYPE_ROOT_PORT || \ type == PCI_EXP_TYPE_RC_EC)) -#define pcie_cap_has_devctl2(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1) -#define pcie_cap_has_lnkctl2(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1) -#define pcie_cap_has_sltctl2(type, flags) \ - ((flags & PCI_EXP_FLAGS_VERS) > 1) static struct pci_cap_saved_state *pci_find_saved_cap( struct pci_dev *pci_dev, char cap) @@ -803,13 +829,14 @@ static int pci_save_pcie_state(struct pci_dev *dev) pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); if (pcie_cap_has_rtctl(dev->pcie_type, flags)) pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); - if (pcie_cap_has_devctl2(dev->pcie_type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); - if (pcie_cap_has_lnkctl2(dev->pcie_type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); - if (pcie_cap_has_sltctl2(dev->pcie_type, flags)) - pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); + pos = pci_pcie_cap2(dev); + if (!pos) + return 0; + + 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; } @@ -836,12 +863,14 @@ static void pci_restore_pcie_state(struct pci_dev *dev) pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); if (pcie_cap_has_rtctl(dev->pcie_type, flags)) pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); - if (pcie_cap_has_devctl2(dev->pcie_type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); - if (pcie_cap_has_lnkctl2(dev->pcie_type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); - if (pcie_cap_has_sltctl2(dev->pcie_type, flags)) - pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); + + pos = pci_pcie_cap2(dev); + if (!pos) + 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++]); } @@ -1916,7 +1945,7 @@ void pci_enable_ari(struct pci_dev *dev) { int pos; u32 cap; - u16 flags, ctrl; + u16 ctrl; struct pci_dev *bridge; if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) @@ -1927,18 +1956,14 @@ void pci_enable_ari(struct pci_dev *dev) return; bridge = dev->bus->self; - if (!bridge || !pci_is_pcie(bridge)) + if (!bridge) return; - pos = pci_pcie_cap(bridge); + /* ARI is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(bridge); if (!pos) return; - /* ARI is a PCIe v2 feature */ - pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags); - if ((flags & PCI_EXP_FLAGS_VERS) < 2) - return; - pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap); if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; @@ -1951,7 +1976,7 @@ void pci_enable_ari(struct pci_dev *dev) } /** - * pci_enable_ido - enable ID-based ordering on a device + * pci_enable_ido - enable ID-based Ordering on a device * @dev: the PCI device * @type: which types of IDO to enable * @@ -1964,7 +1989,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type) int pos; u16 ctrl; - pos = pci_pcie_cap(dev); + /* ID-based Ordering is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; @@ -1987,10 +2013,8 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type) int pos; u16 ctrl; - if (!pci_is_pcie(dev)) - return; - - pos = pci_pcie_cap(dev); + /* ID-based Ordering is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; @@ -2029,10 +2053,8 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) u16 ctrl; int ret; - if (!pci_is_pcie(dev)) - return -ENOTSUPP; - - pos = pci_pcie_cap(dev); + /* OBFF is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return -ENOTSUPP; @@ -2082,10 +2104,8 @@ void pci_disable_obff(struct pci_dev *dev) int pos; u16 ctrl; - if (!pci_is_pcie(dev)) - return; - - pos = pci_pcie_cap(dev); + /* OBFF is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; @@ -2102,15 +2122,13 @@ EXPORT_SYMBOL(pci_disable_obff); * RETURNS: * True if @dev supports latency tolerance reporting, false otherwise. */ -bool pci_ltr_supported(struct pci_dev *dev) +static bool pci_ltr_supported(struct pci_dev *dev) { int pos; u32 cap; - if (!pci_is_pcie(dev)) - return false; - - pos = pci_pcie_cap(dev); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return false; @@ -2118,7 +2136,6 @@ bool pci_ltr_supported(struct pci_dev *dev) return cap & PCI_EXP_DEVCAP2_LTR; } -EXPORT_SYMBOL(pci_ltr_supported); /** * pci_enable_ltr - enable latency tolerance reporting @@ -2139,7 +2156,8 @@ int pci_enable_ltr(struct pci_dev *dev) if (!pci_ltr_supported(dev)) return -ENOTSUPP; - pos = pci_pcie_cap(dev); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return -ENOTSUPP; @@ -2174,7 +2192,8 @@ void pci_disable_ltr(struct pci_dev *dev) if (!pci_ltr_supported(dev)) return; - pos = pci_pcie_cap(dev); + /* LTR is a PCIe cap v2 feature */ + pos = pci_pcie_cap2(dev); if (!pos) return; |