diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2021-07-06 10:56:23 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2021-07-06 10:56:23 -0500 |
commit | 56d2731cb27e17ff8d2228ad4f78e9c0e8d13420 (patch) | |
tree | ab84a2ec715cab9981a73a8bf73d4be38efb3651 /drivers/pci/hotplug/pciehp_hpc.c | |
parent | 5f2554cc0ae202db743dc1155e55b7111409e822 (diff) | |
parent | 6d71cc4c91d856f05d9f175fba866616dd1a7d1f (diff) |
Merge branch 'pci/hotplug'
- Ignore pciehp Link Down/Up caused by DPC so device remains bound to
driver (Lukas Wunner)
- Declare global cpci_debug in header file (Krzysztof WilczyĆski)
* pci/hotplug:
PCI: cpcihp: Declare cpci_debug in header file
PCI: pciehp: Ignore Link Down/Up caused by DPC
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index fb3840e222ad..9d06939736c0 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -563,6 +563,32 @@ void pciehp_power_off_slot(struct controller *ctrl) PCI_EXP_SLTCTL_PWR_OFF); } +static void pciehp_ignore_dpc_link_change(struct controller *ctrl, + struct pci_dev *pdev, int irq) +{ + /* + * Ignore link changes which occurred while waiting for DPC recovery. + * Could be several if DPC triggered multiple times consecutively. + */ + synchronize_hardirq(irq); + atomic_and(~PCI_EXP_SLTSTA_DLLSC, &ctrl->pending_events); + if (pciehp_poll_mode) + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_DLLSC); + ctrl_info(ctrl, "Slot(%s): Link Down/Up ignored (recovered by DPC)\n", + slot_name(ctrl)); + + /* + * If the link is unexpectedly down after successful recovery, + * the corresponding link change may have been ignored above. + * Synthesize it to ensure that it is acted on. + */ + down_read(&ctrl->reset_lock); + if (!pciehp_check_link_active(ctrl)) + pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); + up_read(&ctrl->reset_lock); +} + static irqreturn_t pciehp_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; @@ -707,6 +733,16 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) } /* + * Ignore Link Down/Up events caused by Downstream Port Containment + * if recovery from the error succeeded. + */ + if ((events & PCI_EXP_SLTSTA_DLLSC) && pci_dpc_recovered(pdev) && + ctrl->state == ON_STATE) { + events &= ~PCI_EXP_SLTSTA_DLLSC; + pciehp_ignore_dpc_link_change(ctrl, pdev, irq); + } + + /* * Disable requests have higher priority than Presence Detect Changed * or Data Link Layer State Changed events. */ |