提交 b3623f8e 编写于 作者: K Keith Busch 提交者: Caspar Zhang

PCI/AER: Use threaded IRQ for bottom half

task #29600094

commit 6200cc5ee2baa573e7ac4dbcfca750e0b777c37d upstream.
Backport summary: for 4.19 kernel ICX PCIe Gen4 support.

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: NKeith Busch <keith.busch@intel.com>
Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
(cherry picked from commit 6200cc5ee2baa573e7ac4dbcfca750e0b777c37d)
Signed-off-by: NEthan Zhao <haifeng.zhao@intel.com>
Signed-off-by: NArtie Ding <artie.ding@linux.alibaba.com>
Acked-by: NCaspar Zhang <caspar@linux.alibaba.com>
上级 e45c2531
......@@ -42,14 +42,7 @@ struct aer_err_source {
struct aer_rpc {
struct pci_dev *rpd; /* Root Port device */
struct work_struct dpc_handler;
DECLARE_KFIFO(aer_fifo, struct aer_err_source, AER_ERROR_SOURCES_MAX);
int isr;
struct mutex rpc_mutex; /*
* only one thread could do
* recovery on the same
* root port hierarchy
*/
};
/* AER stats for the device */
......@@ -1215,15 +1208,18 @@ static void aer_isr_one_error(struct aer_rpc *rpc,
*
* Invoked, as DPC, when root port records new detected error
*/
static void aer_isr(struct work_struct *work)
static irqreturn_t aer_isr(int irq, void *context)
{
struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
struct pcie_device *dev = (struct pcie_device *)context;
struct aer_rpc *rpc = get_service_data(dev);
struct aer_err_source uninitialized_var(e_src);
mutex_lock(&rpc->rpc_mutex);
if (kfifo_is_empty(&rpc->aer_fifo))
return IRQ_NONE;
while (kfifo_get(&rpc->aer_fifo, &e_src))
aer_isr_one_error(rpc, &e_src);
mutex_unlock(&rpc->rpc_mutex);
return IRQ_HANDLED;
}
/**
......@@ -1251,8 +1247,7 @@ irqreturn_t aer_irq(int irq, void *context)
if (!kfifo_put(&rpc->aer_fifo, e_src))
return IRQ_HANDLED;
schedule_work(&rpc->dpc_handler);
return IRQ_HANDLED;
return IRQ_WAKE_THREAD;
}
EXPORT_SYMBOL_GPL(aer_irq);
......@@ -1362,30 +1357,6 @@ static void aer_disable_rootport(struct aer_rpc *rpc)
pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
}
/**
* aer_alloc_rpc - allocate Root Port data structure
* @dev: pointer to the pcie_dev data structure
*
* Invoked when Root Port's AER service is loaded.
*/
static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
{
struct aer_rpc *rpc;
rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
if (!rpc)
return NULL;
rpc->rpd = dev->port;
INIT_WORK(&rpc->dpc_handler, aer_isr);
mutex_init(&rpc->rpc_mutex);
/* Use PCIe bus function to store rpc into PCIe device */
set_service_data(dev, rpc);
return rpc;
}
/**
* aer_remove - clean up resources
* @dev: pointer to the pcie_dev data structure
......@@ -1397,11 +1368,6 @@ static void aer_remove(struct pcie_device *dev)
struct aer_rpc *rpc = get_service_data(dev);
if (rpc) {
/* If register interrupt service, it must be free. */
if (rpc->isr)
free_irq(dev->irq, dev);
flush_work(&rpc->dpc_handler);
aer_disable_rootport(rpc);
kfree(rpc);
set_service_data(dev, NULL);
......@@ -1421,15 +1387,17 @@ static int aer_probe(struct pcie_device *dev)
struct device *device = &dev->port->dev;
/* Alloc rpc data structure */
rpc = aer_alloc_rpc(dev);
rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
if (!rpc) {
dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
aer_remove(dev);
return -ENOMEM;
}
rpc->rpd = dev->port;
set_service_data(dev, rpc);
/* Request IRQ ISR */
status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
status = request_threaded_irq(dev->irq, aer_irq, aer_isr,
IRQF_SHARED, "aerdrv", dev);
if (status) {
dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
dev->irq);
......@@ -1437,8 +1405,6 @@ static int aer_probe(struct pcie_device *dev)
return status;
}
rpc->isr = 1;
aer_enable_rootport(rpc);
dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册