aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2018-09-18 19:58:46 -0400
committerBjorn Helgaas <bhelgaas@google.com>2018-10-08 13:18:14 -0400
commit6200cc5ee2baa573e7ac4dbcfca750e0b777c37d (patch)
tree4dbb000d46ec1f506182c295398f4f0497150092
parentecae65e133f2e0647e6364d691130ff551382d91 (diff)
PCI/AER: Use threaded IRQ for bottom half
The threaded IRQ is naturally single threaded as desired, so use that to simplify the AER bottom half handler. Since the root port structure has much less to do now, remove the rpc construction helper routine. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/pcie/aer.c60
1 files changed, 13 insertions, 47 deletions
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index f70ee6dfb79e..638d0cbc704e 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -42,14 +42,7 @@ struct aer_err_source {
42 42
43struct aer_rpc { 43struct aer_rpc {
44 struct pci_dev *rpd; /* Root Port device */ 44 struct pci_dev *rpd; /* Root Port device */
45 struct work_struct dpc_handler;
46 DECLARE_KFIFO(aer_fifo, struct aer_err_source, AER_ERROR_SOURCES_MAX); 45 DECLARE_KFIFO(aer_fifo, struct aer_err_source, AER_ERROR_SOURCES_MAX);
47 int isr;
48 struct mutex rpc_mutex; /*
49 * only one thread could do
50 * recovery on the same
51 * root port hierarchy
52 */
53}; 46};
54 47
55/* AER stats for the device */ 48/* AER stats for the device */
@@ -1215,15 +1208,18 @@ static void aer_isr_one_error(struct aer_rpc *rpc,
1215 * 1208 *
1216 * Invoked, as DPC, when root port records new detected error 1209 * Invoked, as DPC, when root port records new detected error
1217 */ 1210 */
1218static void aer_isr(struct work_struct *work) 1211static irqreturn_t aer_isr(int irq, void *context)
1219{ 1212{
1220 struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); 1213 struct pcie_device *dev = (struct pcie_device *)context;
1214 struct aer_rpc *rpc = get_service_data(dev);
1221 struct aer_err_source uninitialized_var(e_src); 1215 struct aer_err_source uninitialized_var(e_src);
1222 1216
1223 mutex_lock(&rpc->rpc_mutex); 1217 if (kfifo_is_empty(&rpc->aer_fifo))
1218 return IRQ_NONE;
1219
1224 while (kfifo_get(&rpc->aer_fifo, &e_src)) 1220 while (kfifo_get(&rpc->aer_fifo, &e_src))
1225 aer_isr_one_error(rpc, &e_src); 1221 aer_isr_one_error(rpc, &e_src);
1226 mutex_unlock(&rpc->rpc_mutex); 1222 return IRQ_HANDLED;
1227} 1223}
1228 1224
1229/** 1225/**
@@ -1251,8 +1247,7 @@ irqreturn_t aer_irq(int irq, void *context)
1251 if (!kfifo_put(&rpc->aer_fifo, e_src)) 1247 if (!kfifo_put(&rpc->aer_fifo, e_src))
1252 return IRQ_HANDLED; 1248 return IRQ_HANDLED;
1253 1249
1254 schedule_work(&rpc->dpc_handler); 1250 return IRQ_WAKE_THREAD;
1255 return IRQ_HANDLED;
1256} 1251}
1257EXPORT_SYMBOL_GPL(aer_irq); 1252EXPORT_SYMBOL_GPL(aer_irq);
1258 1253
@@ -1363,30 +1358,6 @@ static void aer_disable_rootport(struct aer_rpc *rpc)
1363} 1358}
1364 1359
1365/** 1360/**
1366 * aer_alloc_rpc - allocate Root Port data structure
1367 * @dev: pointer to the pcie_dev data structure
1368 *
1369 * Invoked when Root Port's AER service is loaded.
1370 */
1371static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
1372{
1373 struct aer_rpc *rpc;
1374
1375 rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
1376 if (!rpc)
1377 return NULL;
1378
1379 rpc->rpd = dev->port;
1380 INIT_WORK(&rpc->dpc_handler, aer_isr);
1381 mutex_init(&rpc->rpc_mutex);
1382
1383 /* Use PCIe bus function to store rpc into PCIe device */
1384 set_service_data(dev, rpc);
1385
1386 return rpc;
1387}
1388
1389/**
1390 * aer_remove - clean up resources 1361 * aer_remove - clean up resources
1391 * @dev: pointer to the pcie_dev data structure 1362 * @dev: pointer to the pcie_dev data structure
1392 * 1363 *
@@ -1397,11 +1368,6 @@ static void aer_remove(struct pcie_device *dev)
1397 struct aer_rpc *rpc = get_service_data(dev); 1368 struct aer_rpc *rpc = get_service_data(dev);
1398 1369
1399 if (rpc) { 1370 if (rpc) {
1400 /* If register interrupt service, it must be free. */
1401 if (rpc->isr)
1402 free_irq(dev->irq, dev);
1403
1404 flush_work(&rpc->dpc_handler);
1405 aer_disable_rootport(rpc); 1371 aer_disable_rootport(rpc);
1406 kfree(rpc); 1372 kfree(rpc);
1407 set_service_data(dev, NULL); 1373 set_service_data(dev, NULL);
@@ -1421,15 +1387,17 @@ static int aer_probe(struct pcie_device *dev)
1421 struct device *device = &dev->port->dev; 1387 struct device *device = &dev->port->dev;
1422 1388
1423 /* Alloc rpc data structure */ 1389 /* Alloc rpc data structure */
1424 rpc = aer_alloc_rpc(dev); 1390 rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
1425 if (!rpc) { 1391 if (!rpc) {
1426 dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n"); 1392 dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
1427 aer_remove(dev);
1428 return -ENOMEM; 1393 return -ENOMEM;
1429 } 1394 }
1395 rpc->rpd = dev->port;
1396 set_service_data(dev, rpc);
1430 1397
1431 /* Request IRQ ISR */ 1398 /* Request IRQ ISR */
1432 status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev); 1399 status = request_threaded_irq(dev->irq, aer_irq, aer_isr,
1400 IRQF_SHARED, "aerdrv", dev);
1433 if (status) { 1401 if (status) {
1434 dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n", 1402 dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
1435 dev->irq); 1403 dev->irq);
@@ -1437,8 +1405,6 @@ static int aer_probe(struct pcie_device *dev)
1437 return status; 1405 return status;
1438 } 1406 }
1439 1407
1440 rpc->isr = 1;
1441
1442 aer_enable_rootport(rpc); 1408 aer_enable_rootport(rpc);
1443 dev_info(device, "AER enabled with IRQ %d\n", dev->irq); 1409 dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
1444 return 0; 1410 return 0;