[Skiboot] [PATCH] core/pci: Fix PCIe slot's presence

Gavin Shan gwshan at linux.vnet.ibm.com
Mon Nov 21 11:45:18 AEDT 2016


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's and
its link capability.

Cc: stable # 5.3.0+
Fixes: bc66fb67aee ("core/pci: Support PCI slot")
Signed-off-by: Gavin Shan <gwhsan at linux.vnet.ibm.com>
---
 core/pcie-slot.c   | 4 +++-
 include/pci-slot.h | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/core/pcie-slot.c b/core/pcie-slot.c
index b877cec..4308d0b 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;
 	}
@@ -436,6 +436,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;
-- 
2.1.0



More information about the Skiboot mailing list