Skip to content

Commit 80f9fc2

Browse files
madscientist159maddy-kerneldev
authored andcommitted
PCI: pnv_php: Work around switches with broken presence detection
The Microsemi Switchtec PM8533 PFX 48xG3 [11f8:8533] PCIe switch system was observed to incorrectly assert the Presence Detect Set bit in its capabilities when tested on a Raptor Computing Systems Blackbird system, resulting in the hot insert path never attempting a rescan of the bus and any downstream devices not being re-detected. Work around this by additionally checking whether the PCIe data link is active or not when performing presence detection on downstream switches' ports, similar to the pciehp_hpc.c driver. Signed-off-by: Shawn Anastasio <[email protected]> Signed-off-by: Timothy Pearson <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Signed-off-by: Madhavan Srinivasan <[email protected]> Link: https://patch.msgid.link/505981576.1359853.1752615415117.JavaMail.zimbra@raptorengineeringinc.com
1 parent 4668619 commit 80f9fc2

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

drivers/pci/hotplug/pnv_php.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,20 @@ static int pnv_php_get_power_state(struct hotplug_slot *slot, u8 *state)
391391
return 0;
392392
}
393393

394+
static int pcie_check_link_active(struct pci_dev *pdev)
395+
{
396+
u16 lnk_status;
397+
int ret;
398+
399+
ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
400+
if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status))
401+
return -ENODEV;
402+
403+
ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
404+
405+
return ret;
406+
}
407+
394408
static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
395409
{
396410
struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
@@ -403,6 +417,19 @@ static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state)
403417
*/
404418
ret = pnv_pci_get_presence_state(php_slot->id, &presence);
405419
if (ret >= 0) {
420+
if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM &&
421+
presence == OPAL_PCI_SLOT_EMPTY) {
422+
/*
423+
* Similar to pciehp_hpc, check whether the Link Active
424+
* bit is set to account for broken downstream bridges
425+
* that don't properly assert Presence Detect State, as
426+
* was observed on the Microsemi Switchtec PM8533 PFX
427+
* [11f8:8533].
428+
*/
429+
if (pcie_check_link_active(php_slot->pdev) > 0)
430+
presence = OPAL_PCI_SLOT_PRESENT;
431+
}
432+
406433
*state = presence;
407434
ret = 0;
408435
} else {

0 commit comments

Comments
 (0)