aboutsummaryrefslogtreecommitdiff
path: root/core/pci.c
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2017-02-10 12:19:58 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-02-16 16:50:53 +1100
commitaf23374372850b69cb1351523c2a5cf34db4a968 (patch)
treef5d938707ceb9a4c4cc86cb52fc89cda9d68654a /core/pci.c
parenteeed7e762030c6df704da7dd92f650ebdf412ebf (diff)
downloadskiboot-af23374372850b69cb1351523c2a5cf34db4a968.zip
skiboot-af23374372850b69cb1351523c2a5cf34db4a968.tar.gz
skiboot-af23374372850b69cb1351523c2a5cf34db4a968.tar.bz2
core/pci: Introduce separate function to initialize PCIe capability
The logic initializing device's PCIe capability is resident in the function pci_scan_one() from day one. It's because information (e.g. vendor/device IDs) aren't stored into PCI device instance in old days. Now, the PCI device instance contains all information required to initialize its PCIe capability and others. This moves the logic initializing PCIe capability from pci_scan_one() to separate functions, pci_init_capabilities() and pci_init_pcie_cap(). pci_scan_one() is simplified to make code maintaining a bit easier. Also, it will allow us to intorduce separate functions to initialize other capabilities as we're doing for PCIe capability. This also exports pci_init_capabilities() so that it can be reused by SRIOV VFs in future. No logical changes introduced by this. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Reviewed-by: Russell Currey <ruscur@russell.cc> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/pci.c')
-rw-r--r--core/pci.c119
1 files changed, 66 insertions, 53 deletions
diff --git a/core/pci.c b/core/pci.c
index 0a9f8cd..5f6e259 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -130,14 +130,76 @@ int64_t pci_find_ecap(struct phb *phb, uint16_t bdfn, uint16_t want,
return OPAL_UNSUPPORTED;
}
+static void pci_init_pcie_cap(struct phb *phb, struct pci_device *pd)
+{
+ int64_t ecap = 0;
+ uint16_t reg;
+ uint32_t val;
+
+ /* On the upstream port of PLX bridge 8724 (rev ba), PCI_STATUS
+ * register doesn't have capability indicator though it support
+ * various PCI capabilities. So we need ignore that bit when
+ * looking for PCI capabilities on the upstream port, which is
+ * limited to one that seats directly under root port.
+ */
+ if (pd->vdid == 0x872410b5 && pd->parent && !pd->parent->parent) {
+ uint8_t rev;
+
+ pci_cfg_read8(phb, pd->bdfn, PCI_CFG_REV_ID, &rev);
+ if (rev == 0xba)
+ ecap = __pci_find_cap(phb, pd->bdfn,
+ PCI_CFG_CAP_ID_EXP, false);
+ else
+ ecap = pci_find_cap(phb, pd->bdfn, PCI_CFG_CAP_ID_EXP);
+ } else {
+ ecap = pci_find_cap(phb, pd->bdfn, PCI_CFG_CAP_ID_EXP);
+ }
+
+ if (ecap <= 0) {
+ pd->dev_type = PCIE_TYPE_LEGACY;
+ return;
+ }
+
+ pci_set_cap(pd, PCI_CFG_CAP_ID_EXP, ecap, false);
+
+ /*
+ * XXX We observe a problem on some PLX switches where one
+ * of the downstream ports appears as an upstream port, we
+ * fix that up here otherwise, other code will misbehave
+ */
+ pci_cfg_read16(phb, pd->bdfn, ecap + PCICAP_EXP_CAPABILITY_REG, &reg);
+ pd->dev_type = GETFIELD(PCICAP_EXP_CAP_TYPE, reg);
+ if (pd->parent && pd->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
+ pd->parent->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
+ pd->vdid == 0x874810b5) {
+ PCIDBG(phb, pd->bdfn, "Fixing up bad PLX downstream port !\n");
+ pd->dev_type = PCIE_TYPE_SWITCH_DNPORT;
+ }
+
+ /* XXX Handle ARI */
+ if (pd->dev_type == PCIE_TYPE_SWITCH_DNPORT ||
+ pd->dev_type == PCIE_TYPE_ROOT_PORT)
+ pd->scan_map = 0x1;
+
+ /* Read MPS capability, whose maximal size is 4096 */
+ pci_cfg_read32(phb, pd->bdfn, ecap + PCICAP_EXP_DEVCAP, &val);
+ pd->mps = (128 << GETFIELD(PCICAP_EXP_DEVCAP_MPSS, val));
+ if (pd->mps > 4096)
+ pd->mps = 4096;
+}
+
+void pci_init_capabilities(struct phb *phb, struct pci_device *pd)
+{
+ pci_init_pcie_cap(phb, pd);
+}
+
static struct pci_device *pci_scan_one(struct phb *phb, struct pci_device *parent,
uint16_t bdfn)
{
struct pci_device *pd = NULL;
- uint32_t retries, vdid, val;
- int64_t rc, ecap;
+ uint32_t retries, vdid;
+ int64_t rc;
uint8_t htype;
- uint16_t capreg;
bool had_crs = false;
for (retries = 0; retries < 40; retries++) {
@@ -188,56 +250,7 @@ static struct pci_device *pci_scan_one(struct phb *phb, struct pci_device *paren
pd->scan_map = 0xffffffff; /* Default */
pd->primary_bus = (bdfn >> 8);
- /* On the upstream port of PLX bridge 8724 (rev ba), PCI_STATUS
- * register doesn't have capability indicator though it support
- * various PCI capabilities. So we need ignore that bit when
- * looking for PCI capabilities on the upstream port, which is
- * limited to one that seats directly under root port.
- */
- if (vdid == 0x872410b5 && parent && !parent->parent) {
- uint8_t rev;
-
- pci_cfg_read8(phb, bdfn, PCI_CFG_REV_ID, &rev);
- if (rev == 0xba)
- ecap = __pci_find_cap(phb, bdfn,
- PCI_CFG_CAP_ID_EXP, false);
- else
- ecap = pci_find_cap(phb, bdfn, PCI_CFG_CAP_ID_EXP);
- } else {
- ecap = pci_find_cap(phb, bdfn, PCI_CFG_CAP_ID_EXP);
- }
- if (ecap > 0) {
- pci_set_cap(pd, PCI_CFG_CAP_ID_EXP, ecap, false);
- pci_cfg_read16(phb, bdfn, ecap + PCICAP_EXP_CAPABILITY_REG,
- &capreg);
- pd->dev_type = GETFIELD(PCICAP_EXP_CAP_TYPE, capreg);
-
- /*
- * XXX We observe a problem on some PLX switches where one
- * of the downstream ports appears as an upstream port, we
- * fix that up here otherwise, other code will misbehave
- */
- if (pd->parent && pd->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
- pd->parent->dev_type == PCIE_TYPE_SWITCH_UPPORT &&
- vdid == 0x874810b5) {
- PCIDBG(phb, bdfn,
- "Fixing up bad PLX downstream port !\n");
- pd->dev_type = PCIE_TYPE_SWITCH_DNPORT;
- }
-
- /* XXX Handle ARI */
- if (pd->dev_type == PCIE_TYPE_SWITCH_DNPORT ||
- pd->dev_type == PCIE_TYPE_ROOT_PORT)
- pd->scan_map = 0x1;
-
- /* Read MPS capability, whose maximal size is 4096 */
- pci_cfg_read32(phb, bdfn, ecap + PCICAP_EXP_DEVCAP, &val);
- pd->mps = (128 << GETFIELD(PCICAP_EXP_DEVCAP_MPSS, val));
- if (pd->mps > 4096)
- pd->mps = 4096;
- } else {
- pd->dev_type = PCIE_TYPE_LEGACY;
- }
+ pci_init_capabilities(phb, pd);
/* If it's a bridge, sanitize the bus numbers to avoid forwarding
*