Skip to content

Commit 7fd1fe4

Browse files
oohalmpe
authored andcommitted
pci-hotplug/pnv_php: Add a reset_slot() callback
When performing EEH recovery of devices in a hotplug slot we need to use the slot driver's ->reset_slot() callback to prevent spurious hotplug events due to spurious DLActive and PresDet change interrupts. Add a reset_slot() callback to pnv_php so we can handle recovery of devices in pnv_php managed slots. Signed-off-by: Oliver O'Halloran <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 98fd32c commit 7fd1fe4

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

drivers/pci/hotplug/pnv_php.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,37 @@ static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan)
511511
return 0;
512512
}
513513

514+
static int pnv_php_reset_slot(struct hotplug_slot *slot, int probe)
515+
{
516+
struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
517+
struct pci_dev *bridge = php_slot->pdev;
518+
uint16_t sts;
519+
520+
/*
521+
* The CAPI folks want pnv_php to drive OpenCAPI slots
522+
* which don't have a bridge. Only claim to support
523+
* reset_slot() if we have a bridge device (for now...)
524+
*/
525+
if (probe)
526+
return !bridge;
527+
528+
/* mask our interrupt while resetting the bridge */
529+
if (php_slot->irq > 0)
530+
disable_irq(php_slot->irq);
531+
532+
pci_bridge_secondary_bus_reset(bridge);
533+
534+
/* clear any state changes that happened due to the reset */
535+
pcie_capability_read_word(php_slot->pdev, PCI_EXP_SLTSTA, &sts);
536+
sts &= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
537+
pcie_capability_write_word(php_slot->pdev, PCI_EXP_SLTSTA, sts);
538+
539+
if (php_slot->irq > 0)
540+
enable_irq(php_slot->irq);
541+
542+
return 0;
543+
}
544+
514545
static int pnv_php_enable_slot(struct hotplug_slot *slot)
515546
{
516547
struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
@@ -548,6 +579,7 @@ static const struct hotplug_slot_ops php_slot_ops = {
548579
.set_attention_status = pnv_php_set_attention_state,
549580
.enable_slot = pnv_php_enable_slot,
550581
.disable_slot = pnv_php_disable_slot,
582+
.reset_slot = pnv_php_reset_slot,
551583
};
552584

553585
static void pnv_php_release(struct pnv_php_slot *php_slot)
@@ -721,6 +753,12 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
721753
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
722754
sts &= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
723755
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
756+
757+
pci_dbg(pdev, "PCI slot [%s]: HP int! DLAct: %d, PresDet: %d\n",
758+
php_slot->name,
759+
!!(sts & PCI_EXP_SLTSTA_DLLSC),
760+
!!(sts & PCI_EXP_SLTSTA_PDC));
761+
724762
if (sts & PCI_EXP_SLTSTA_DLLSC) {
725763
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts);
726764
added = !!(lsts & PCI_EXP_LNKSTA_DLLLA);
@@ -735,6 +773,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
735773

736774
added = !!(presence == OPAL_PCI_SLOT_PRESENT);
737775
} else {
776+
pci_dbg(pdev, "PCI slot [%s]: Spurious IRQ?\n", php_slot->name);
738777
return IRQ_NONE;
739778
}
740779

0 commit comments

Comments
 (0)