diff options
author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2015-09-11 14:36:34 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-09-15 16:15:41 +1000 |
commit | c34905c558bfd0773da0adf8b7f7d8bedea480a8 (patch) | |
tree | cdf2ed4aa9a169c7a6fe22c9c71609e363098b01 /core/pci.c | |
parent | ef186c6ce6c9e730a91263aac38153e4257fb354 (diff) | |
download | skiboot-c34905c558bfd0773da0adf8b7f7d8bedea480a8.zip skiboot-c34905c558bfd0773da0adf8b7f7d8bedea480a8.tar.gz skiboot-c34905c558bfd0773da0adf8b7f7d8bedea480a8.tar.bz2 |
PCI: Clear error bits after changing MPS
Chaning MPS on PCI upstream bridge might cause error bits set on
downstream endpoints when system boots into Linux as below case
shows:
host# lspci -vvs 0001:06:00.0
0001:06:00.0 Ethernet controller: Broadcom Corporation \
NetXtreme II BCM57810 10 Gigabit Ethernet (rev 10)
:
DevSta: CorrErr+ UncorrErr- FatalErr- UnsuppReq+ AuxPwr- TransPend-
:
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+
This clears those error bits in AER and PCIe capability after MPS
is changed. With the patch applied, no more error bits are seen.
Reported-by: John Walthour <jwalthour@us.ibm.com>
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/pci.c')
-rw-r--r-- | core/pci.c | 22 |
1 files changed, 19 insertions, 3 deletions
@@ -609,20 +609,23 @@ static int pci_configure_mps(struct phb *phb, struct pci_device *pd, void *userdata __unused) { - uint32_t ecap, mps; + uint32_t ecap, aercap, mps; uint16_t val; assert(phb); assert(pd); - mps = phb->mps; /* If the MPS isn't acceptable one, bail immediately */ + mps = phb->mps; if (mps < 128 || mps > 4096) return 1; + /* Retrieve PCIe and AER capability */ + ecap = pci_cap(pd, PCI_CFG_CAP_ID_EXP, false); + aercap = pci_cap(pd, PCIECAP_ID_AER, true); + /* PCIe device always has MPS capacity */ if (pd->mps) { - ecap = pci_cap(pd, PCI_CFG_CAP_ID_EXP, false); mps = ilog2(mps) - 7; pci_cfg_read16(phb, pd->bdfn, ecap + PCICAP_EXP_DEVCTL, &val); @@ -630,6 +633,19 @@ static int pci_configure_mps(struct phb *phb, pci_cfg_write16(phb, pd->bdfn, ecap + PCICAP_EXP_DEVCTL, val); } + /* Changing MPS on upstream PCI bridge might cause some error + * bits in PCIe and AER capability. To clear them to avoid + * confusion. + */ + if (aercap) { + pci_cfg_write32(phb, pd->bdfn, aercap + PCIECAP_AER_UE_STATUS, + 0xffffffff); + pci_cfg_write32(phb, pd->bdfn, aercap + PCIECAP_AER_CE_STATUS, + 0xffffffff); + } + if (ecap) + pci_cfg_write16(phb, pd->bdfn, ecap + PCICAP_EXP_DEVSTAT, 0xf); + return 0; } |