From f8d46c89c86fa11c60c05e101a3a4c7458623103 Mon Sep 17 00:00:00 2001
From: Keith Busch <keith.busch@intel.com>
Date: Wed, 20 Jun 2018 15:38:27 -0600
Subject: [PATCH] PCI/DPC: Leave interrupts enabled while handling event
Git-commit: f8d46c89c86fa11c60c05e101a3a4c7458623103
Patch-mainline: v4.19-rc1
References: FATE#326277
Now that the DPC driver clears the interrupt status before exiting the
IRQ handler, we don't need to abuse the DPC control register to know if
a shared interrupt is for a new DPC event: a DPC port can not trigger
a second interrupt until the host clears the trigger status later in the
work queue handler.
Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Sinan Kaya <okaya@kernel.org>
Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
Acked-by: Takashi Iwai <tiwai@suse.de>
---
drivers/pci/pcie/dpc.c | 23 +++++------------------
1 file changed, 5 insertions(+), 18 deletions(-)
diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c
index 921ed979109d..972aac892846 100644
--- a/drivers/pci/pcie/dpc.c
+++ b/drivers/pci/pcie/dpc.c
@@ -77,7 +77,7 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev)
struct dpc_dev *dpc;
struct pcie_device *pciedev;
struct device *devdpc;
- u16 cap, ctl;
+ u16 cap;
/*
* DPC disables the Link automatically in hardware, so it has
@@ -105,10 +105,6 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev)
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
PCI_EXP_DPC_STATUS_TRIGGER);
- pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl);
- pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL,
- ctl | PCI_EXP_DPC_CTL_INT_EN);
-
return PCI_ERS_RESULT_RECOVERED;
}
@@ -183,16 +179,11 @@ static irqreturn_t dpc_irq(int irq, void *context)
struct dpc_dev *dpc = (struct dpc_dev *)context;
struct pci_dev *pdev = dpc->dev->port;
struct device *dev = &dpc->dev->device;
- u16 cap = dpc->cap_pos, ctl, status, source, reason, ext_reason;
-
- pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl);
-
- if (!(ctl & PCI_EXP_DPC_CTL_INT_EN) || ctl == (u16)(~0))
- return IRQ_NONE;
+ u16 cap = dpc->cap_pos, status, source, reason, ext_reason;
pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status);
- if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT))
+ if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0))
return IRQ_NONE;
if (!(status & PCI_EXP_DPC_STATUS_TRIGGER)) {
@@ -201,9 +192,6 @@ static irqreturn_t dpc_irq(int irq, void *context)
return IRQ_HANDLED;
}
- pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL,
- ctl & ~PCI_EXP_DPC_CTL_INT_EN);
-
pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID,
&source);
@@ -226,9 +214,8 @@ static irqreturn_t dpc_irq(int irq, void *context)
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
PCI_EXP_DPC_STATUS_INTERRUPT);
-
- schedule_work(&dpc->work);
-
+ if (status & PCI_EXP_DPC_STATUS_TRIGGER)
+ schedule_work(&dpc->work);
return IRQ_HANDLED;
}
--
2.19.2