diff options
author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2017-02-20 10:57:47 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-02-22 17:05:14 +1100 |
commit | 5889ef66d7b574c2dc1abf7230c7d6edd07a73c4 (patch) | |
tree | cacf5d5737109f1f7ea88c1f12beadac8cf37de0 | |
parent | af4f68a34484e50857d7bfbe6f9c2141839dd4fb (diff) | |
download | skiboot-5889ef66d7b574c2dc1abf7230c7d6edd07a73c4.zip skiboot-5889ef66d7b574c2dc1abf7230c7d6edd07a73c4.tar.gz skiboot-5889ef66d7b574c2dc1abf7230c7d6edd07a73c4.tar.bz2 |
core/pci: Fix PCIe slot's presence
According to PCIe spec, the presence bit is hardcoded to 1 if PCIe
switch downstream port doesn't support slot capability. The register
used for the check in pcie_slot_get_presence_state() is wrong. It
should be PCIe capability register instead of PCIe slot capability
register. Otherwise, we always have present bit on the PCI topology.
The issue is found on Supermicro's p8dtu2u machine:
# lspci -t
-+-[0022:00]---00.0-[01-08]----00.0-[02-08]--+-01.0-[03]----00.0
| \-02.0-[04-08]--
# cat /sys/bus/pci/slots/S002204/adapter
1
# lspci -vvs 0022:02:02.0
# lspci -vvs 0022:02:02.0
0022:02:02.0 PCI bridge: PLX Technology, Inc. PEX 8718 16-Lane, \
5-Port PCI Express Gen 3 (8.0 GT/s) Switch (rev ab) (prog-if 00 [Normal decode])
:
Capabilities: [68] Express (v2) Downstream Port (Slot+), MSI 00
:
SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet- Interlock-
Changed: MRL- PresDet- LinkState-
This fixes the issue by checking the correct register (PCIe capability).
Also, the register's value is cached in advance as we did for slot and
link capability.
Fixes: bc66fb67aee ("core/pci: Support PCI slot")
Cc: stable # 5.3.0+
Signed-off-by: Gavin Shan <gwhsan@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
(cherry picked from commit 9e3c7ee4086fc9123134209aebcecd0c1f95e2ca)
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | core/pcie-slot.c | 4 | ||||
-rw-r--r-- | include/pci-slot.h | 1 |
2 files changed, 4 insertions, 1 deletions
diff --git a/core/pcie-slot.c b/core/pcie-slot.c index eb8a02c..defb66a 100644 --- a/core/pcie-slot.c +++ b/core/pcie-slot.c @@ -43,7 +43,7 @@ static int64_t pcie_slot_get_presence_state(struct pci_slot *slot, uint8_t *val) * doesn't support slot capability according to PCIE spec. */ if (pd->dev_type == PCIE_TYPE_SWITCH_DNPORT && - !(slot->slot_cap & PCICAP_EXP_CAP_SLOT)) { + !(slot->pcie_cap & PCICAP_EXP_CAP_SLOT)) { *val = OPAL_PCI_SLOT_PRESENT; return OPAL_SUCCESS; } @@ -437,6 +437,8 @@ struct pci_slot *pcie_slot_create(struct phb *phb, struct pci_device *pd) /* Cache the link and slot capabilities */ if (pd) { ecap = pci_cap(pd, PCI_CFG_CAP_ID_EXP, false); + pci_cfg_read16(phb, pd->bdfn, ecap + PCICAP_EXP_CAPABILITY_REG, + &slot->pcie_cap); pci_cfg_read32(phb, pd->bdfn, ecap + PCICAP_EXP_LCAP, &slot->link_cap); pci_cfg_read32(phb, pd->bdfn, ecap + PCICAP_EXP_SLOTCAP, diff --git a/include/pci-slot.h b/include/pci-slot.h index 81a61c3..ce3e8dd 100644 --- a/include/pci-slot.h +++ b/include/pci-slot.h @@ -176,6 +176,7 @@ struct pci_slot { */ uint32_t state; uint32_t retry_state; + uint16_t pcie_cap; uint32_t link_cap; uint32_t slot_cap; uint64_t delay_tgt_tb; |