mirror of https://gitee.com/openkylin/linux.git
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 <oohall@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20190903101605.2890-9-oohall@gmail.com
This commit is contained in:
parent
98fd32cde5
commit
7fd1fe4e48
|
@ -511,6 +511,37 @@ static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pnv_php_reset_slot(struct hotplug_slot *slot, int probe)
|
||||
{
|
||||
struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
|
||||
struct pci_dev *bridge = php_slot->pdev;
|
||||
uint16_t sts;
|
||||
|
||||
/*
|
||||
* The CAPI folks want pnv_php to drive OpenCAPI slots
|
||||
* which don't have a bridge. Only claim to support
|
||||
* reset_slot() if we have a bridge device (for now...)
|
||||
*/
|
||||
if (probe)
|
||||
return !bridge;
|
||||
|
||||
/* mask our interrupt while resetting the bridge */
|
||||
if (php_slot->irq > 0)
|
||||
disable_irq(php_slot->irq);
|
||||
|
||||
pci_bridge_secondary_bus_reset(bridge);
|
||||
|
||||
/* clear any state changes that happened due to the reset */
|
||||
pcie_capability_read_word(php_slot->pdev, PCI_EXP_SLTSTA, &sts);
|
||||
sts &= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
|
||||
pcie_capability_write_word(php_slot->pdev, PCI_EXP_SLTSTA, sts);
|
||||
|
||||
if (php_slot->irq > 0)
|
||||
enable_irq(php_slot->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pnv_php_enable_slot(struct hotplug_slot *slot)
|
||||
{
|
||||
struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
|
||||
|
@ -548,6 +579,7 @@ static const struct hotplug_slot_ops php_slot_ops = {
|
|||
.set_attention_status = pnv_php_set_attention_state,
|
||||
.enable_slot = pnv_php_enable_slot,
|
||||
.disable_slot = pnv_php_disable_slot,
|
||||
.reset_slot = pnv_php_reset_slot,
|
||||
};
|
||||
|
||||
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)
|
|||
pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts);
|
||||
sts &= (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC);
|
||||
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts);
|
||||
|
||||
pci_dbg(pdev, "PCI slot [%s]: HP int! DLAct: %d, PresDet: %d\n",
|
||||
php_slot->name,
|
||||
!!(sts & PCI_EXP_SLTSTA_DLLSC),
|
||||
!!(sts & PCI_EXP_SLTSTA_PDC));
|
||||
|
||||
if (sts & PCI_EXP_SLTSTA_DLLSC) {
|
||||
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lsts);
|
||||
added = !!(lsts & PCI_EXP_LNKSTA_DLLLA);
|
||||
|
@ -735,6 +773,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data)
|
|||
|
||||
added = !!(presence == OPAL_PCI_SLOT_PRESENT);
|
||||
} else {
|
||||
pci_dbg(pdev, "PCI slot [%s]: Spurious IRQ?\n", php_slot->name);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue