Commit 27c1ce8b authored by Keith Busch's avatar Keith Busch Committed by Bjorn Helgaas

PCI/AER: Use kfifo for tracking events instead of reimplementing it

The kernel provides a generic FIFO implementation, so no need to reinvent
that capability in a driver.  Replace the AER-specific implementation with
the kernel-provided kfifo.  Since the interrupt handler producer and work
queue consumer run single threaded, there is no need for additional
locking, so remove that lock, too.
Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent fcd4d369
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "../pci.h" #include "../pci.h"
#include "portdrv.h" #include "portdrv.h"
#define AER_ERROR_SOURCES_MAX 100 #define AER_ERROR_SOURCES_MAX 128
#define AER_MAX_TYPEOF_COR_ERRS 16 /* as per PCI_ERR_COR_STATUS */ #define AER_MAX_TYPEOF_COR_ERRS 16 /* as per PCI_ERR_COR_STATUS */
#define AER_MAX_TYPEOF_UNCOR_ERRS 26 /* as per PCI_ERR_UNCOR_STATUS*/ #define AER_MAX_TYPEOF_UNCOR_ERRS 26 /* as per PCI_ERR_UNCOR_STATUS*/
...@@ -43,14 +43,8 @@ struct aer_err_source { ...@@ -43,14 +43,8 @@ struct aer_err_source {
struct aer_rpc { struct aer_rpc {
struct pci_dev *rpd; /* Root Port device */ struct pci_dev *rpd; /* Root Port device */
struct work_struct dpc_handler; struct work_struct dpc_handler;
struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX]; DECLARE_KFIFO(aer_fifo, struct aer_err_source, AER_ERROR_SOURCES_MAX);
unsigned short prod_idx; /* Error Producer Index */
unsigned short cons_idx; /* Error Consumer Index */
int isr; int isr;
spinlock_t e_lock; /*
* Lock access to Error Status/ID Regs
* and error producer/consumer index
*/
struct mutex rpc_mutex; /* struct mutex rpc_mutex; /*
* only one thread could do * only one thread could do
* recovery on the same * recovery on the same
...@@ -1217,35 +1211,6 @@ static void aer_isr_one_error(struct aer_rpc *rpc, ...@@ -1217,35 +1211,6 @@ static void aer_isr_one_error(struct aer_rpc *rpc,
} }
} }
/**
* get_e_source - retrieve an error source
* @rpc: pointer to the root port which holds an error
* @e_src: pointer to store retrieved error source
*
* Return 1 if an error source is retrieved, otherwise 0.
*
* Invoked by DPC handler to consume an error.
*/
static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
{
unsigned long flags;
/* Lock access to Root error producer/consumer index */
spin_lock_irqsave(&rpc->e_lock, flags);
if (rpc->prod_idx == rpc->cons_idx) {
spin_unlock_irqrestore(&rpc->e_lock, flags);
return 0;
}
*e_src = rpc->e_sources[rpc->cons_idx];
rpc->cons_idx++;
if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
rpc->cons_idx = 0;
spin_unlock_irqrestore(&rpc->e_lock, flags);
return 1;
}
/** /**
* aer_isr - consume errors detected by root port * aer_isr - consume errors detected by root port
* @work: definition of this work item * @work: definition of this work item
...@@ -1258,7 +1223,7 @@ static void aer_isr(struct work_struct *work) ...@@ -1258,7 +1223,7 @@ static void aer_isr(struct work_struct *work)
struct aer_err_source uninitialized_var(e_src); struct aer_err_source uninitialized_var(e_src);
mutex_lock(&rpc->rpc_mutex); mutex_lock(&rpc->rpc_mutex);
while (get_e_source(rpc, &e_src)) while (kfifo_get(&rpc->aer_fifo, &e_src))
aer_isr_one_error(rpc, &e_src); aer_isr_one_error(rpc, &e_src);
mutex_unlock(&rpc->rpc_mutex); mutex_unlock(&rpc->rpc_mutex);
} }
...@@ -1272,51 +1237,23 @@ static void aer_isr(struct work_struct *work) ...@@ -1272,51 +1237,23 @@ static void aer_isr(struct work_struct *work)
*/ */
irqreturn_t aer_irq(int irq, void *context) irqreturn_t aer_irq(int irq, void *context)
{ {
unsigned int status, id;
struct pcie_device *pdev = (struct pcie_device *)context; struct pcie_device *pdev = (struct pcie_device *)context;
struct aer_rpc *rpc = get_service_data(pdev); struct aer_rpc *rpc = get_service_data(pdev);
int next_prod_idx; struct pci_dev *rp = rpc->rpd;
unsigned long flags; struct aer_err_source e_src = {};
int pos; int pos = rp->aer_cap;
pos = pdev->port->aer_cap;
/*
* Must lock access to Root Error Status Reg, Root Error ID Reg,
* and Root error producer/consumer index
*/
spin_lock_irqsave(&rpc->e_lock, flags);
/* Read error status */ pci_read_config_dword(rp, pos + PCI_ERR_ROOT_STATUS, &e_src.status);
pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status); if (!(e_src.status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV)))
if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
spin_unlock_irqrestore(&rpc->e_lock, flags);
return IRQ_NONE; return IRQ_NONE;
}
/* Read error source and clear error status */ pci_read_config_dword(rp, pos + PCI_ERR_ROOT_ERR_SRC, &e_src.id);
pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id); pci_write_config_dword(rp, pos + PCI_ERR_ROOT_STATUS, e_src.status);
pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
/* Store error source for later DPC handler */ if (!kfifo_put(&rpc->aer_fifo, e_src))
next_prod_idx = rpc->prod_idx + 1;
if (next_prod_idx == AER_ERROR_SOURCES_MAX)
next_prod_idx = 0;
if (next_prod_idx == rpc->cons_idx) {
/*
* Error Storm Condition - possibly the same error occurred.
* Drop the error.
*/
spin_unlock_irqrestore(&rpc->e_lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
}
rpc->e_sources[rpc->prod_idx].status = status;
rpc->e_sources[rpc->prod_idx].id = id;
rpc->prod_idx = next_prod_idx;
spin_unlock_irqrestore(&rpc->e_lock, flags);
/* Invoke DPC handler */
schedule_work(&rpc->dpc_handler); schedule_work(&rpc->dpc_handler);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
EXPORT_SYMBOL_GPL(aer_irq); EXPORT_SYMBOL_GPL(aer_irq);
...@@ -1441,9 +1378,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) ...@@ -1441,9 +1378,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
if (!rpc) if (!rpc)
return NULL; return NULL;
/* Initialize Root lock access, e_lock, to Root Error Status Reg */
spin_lock_init(&rpc->e_lock);
rpc->rpd = dev->port; rpc->rpd = dev->port;
INIT_WORK(&rpc->dpc_handler, aer_isr); INIT_WORK(&rpc->dpc_handler, aer_isr);
mutex_init(&rpc->rpc_mutex); mutex_init(&rpc->rpc_mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment