aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2017-02-20 10:57:47 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-02-22 16:51:17 +1100
commit9e3c7ee4086fc9123134209aebcecd0c1f95e2ca (patch)
treef0532c35324e498772153fc4ede7eb44d9ce3fe3
parentb03d75da4a7f1211e59166115ec66d1dd674fbad (diff)
downloadskiboot-9e3c7ee4086fc9123134209aebcecd0c1f95e2ca.zip
skiboot-9e3c7ee4086fc9123134209aebcecd0c1f95e2ca.tar.gz
skiboot-9e3c7ee4086fc9123134209aebcecd0c1f95e2ca.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>
-rw-r--r--core/pcie-slot.c4
-rw-r--r--include/pci-slot.h1
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;