aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2018-10-11 14:34:11 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-10-18 20:43:09 -0400
commit390e2db8248075ae2f31a7046a88eda0f9784310 (patch)
treef99fd4dd81976702e38e7d7b0261f907a3a84d50
parent0e98db259fd8760fde556e640b447dadeceefc96 (diff)
PCI/AER: Abstract AER interrupt handling
The aer_inject module was directly calling aer_irq(). This required the AER driver export its private IRQ handler for no other reason than to support error injection. A driver should not have to expose its private interfaces, so use the IRQ subsystem to route injection to the AER driver, and make aer_irq() a private interface. This provides additional benefits: First, directly calling the IRQ handler bypassed the IRQ subsytem so the injection wasn't really synthesizing what happens if a shared AER interrupt occurs. The error injection had to provide the callback data directly, which may be racing with a removal that is freeing that structure. The IRQ subsystem can handle that race. Finally, using the IRQ subsystem automatically reacts to threaded IRQs, keeping the error injection abstracted from that implementation detail. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/pcie/aer.c3
-rw-r--r--drivers/pci/pcie/aer_inject.c5
-rw-r--r--drivers/pci/pcie/portdrv.h4
3 files changed, 5 insertions, 7 deletions
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 90b53abf621d..a90a9194ac4a 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -1229,7 +1229,7 @@ static irqreturn_t aer_isr(int irq, void *context)
1229 * 1229 *
1230 * Invoked when Root Port detects AER messages. 1230 * Invoked when Root Port detects AER messages.
1231 */ 1231 */
1232irqreturn_t aer_irq(int irq, void *context) 1232static irqreturn_t aer_irq(int irq, void *context)
1233{ 1233{
1234 struct pcie_device *pdev = (struct pcie_device *)context; 1234 struct pcie_device *pdev = (struct pcie_device *)context;
1235 struct aer_rpc *rpc = get_service_data(pdev); 1235 struct aer_rpc *rpc = get_service_data(pdev);
@@ -1249,7 +1249,6 @@ irqreturn_t aer_irq(int irq, void *context)
1249 1249
1250 return IRQ_WAKE_THREAD; 1250 return IRQ_WAKE_THREAD;
1251} 1251}
1252EXPORT_SYMBOL_GPL(aer_irq);
1253 1252
1254static int set_device_error_reporting(struct pci_dev *dev, void *data) 1253static int set_device_error_reporting(struct pci_dev *dev, void *data)
1255{ 1254{
diff --git a/drivers/pci/pcie/aer_inject.c b/drivers/pci/pcie/aer_inject.c
index f40ed5867c89..726987f8d53c 100644
--- a/drivers/pci/pcie/aer_inject.c
+++ b/drivers/pci/pcie/aer_inject.c
@@ -14,6 +14,7 @@
14 14
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/irq.h>
17#include <linux/miscdevice.h> 18#include <linux/miscdevice.h>
18#include <linux/pci.h> 19#include <linux/pci.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
@@ -457,7 +458,9 @@ static int aer_inject(struct aer_error_inj *einj)
457 dev_info(&edev->device, 458 dev_info(&edev->device,
458 "aer_inject: Injecting errors %08x/%08x into device %s\n", 459 "aer_inject: Injecting errors %08x/%08x into device %s\n",
459 einj->cor_status, einj->uncor_status, pci_name(dev)); 460 einj->cor_status, einj->uncor_status, pci_name(dev));
460 aer_irq(-1, edev); 461 local_irq_disable();
462 generic_handle_irq(edev->irq);
463 local_irq_enable();
461 } else { 464 } else {
462 pci_err(rpdev, "aer_inject: AER device not found\n"); 465 pci_err(rpdev, "aer_inject: AER device not found\n");
463 ret = -ENODEV; 466 ret = -ENODEV;
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index abfdc2ae7979..e495f04394d0 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -151,10 +151,6 @@ static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
151} 151}
152#endif 152#endif
153 153
154#ifdef CONFIG_PCIEAER
155irqreturn_t aer_irq(int irq, void *context);
156#endif
157
158struct pcie_port_service_driver *pcie_port_find_service(struct pci_dev *dev, 154struct pcie_port_service_driver *pcie_port_find_service(struct pci_dev *dev,
159 u32 service); 155 u32 service);
160struct device *pcie_port_find_device(struct pci_dev *dev, u32 service); 156struct device *pcie_port_find_device(struct pci_dev *dev, u32 service);