PCI/DPC: Defer event handling to work queue
Move all event handling to the existing work queue, which will make it simpler to pass event information to the 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>
This commit is contained in:
parent
f8d46c89c8
commit
0c27e28f77
@ -108,14 +108,6 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev)
|
|||||||
return PCI_ERS_RESULT_RECOVERED;
|
return PCI_ERS_RESULT_RECOVERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dpc_work(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct dpc_dev *dpc = container_of(work, struct dpc_dev, work);
|
|
||||||
struct pci_dev *pdev = dpc->dev->port;
|
|
||||||
|
|
||||||
/* We configure DPC so it only triggers on ERR_FATAL */
|
|
||||||
pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
|
static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
|
||||||
{
|
{
|
||||||
@ -174,33 +166,21 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t dpc_irq(int irq, void *context)
|
static void dpc_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct dpc_dev *dpc = (struct dpc_dev *)context;
|
struct dpc_dev *dpc = container_of(work, struct dpc_dev, work);
|
||||||
struct pci_dev *pdev = dpc->dev->port;
|
struct pci_dev *pdev = dpc->dev->port;
|
||||||
struct device *dev = &dpc->dev->device;
|
struct device *dev = &dpc->dev->device;
|
||||||
u16 cap = dpc->cap_pos, status, source, reason, ext_reason;
|
u16 cap = dpc->cap_pos, status, source, reason, ext_reason;
|
||||||
|
|
||||||
pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status);
|
pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status);
|
||||||
|
pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, &source);
|
||||||
if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0))
|
|
||||||
return IRQ_NONE;
|
|
||||||
|
|
||||||
if (!(status & PCI_EXP_DPC_STATUS_TRIGGER)) {
|
|
||||||
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
|
|
||||||
PCI_EXP_DPC_STATUS_INTERRUPT);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID,
|
|
||||||
&source);
|
|
||||||
|
|
||||||
dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n",
|
dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n",
|
||||||
status, source);
|
status, source);
|
||||||
|
|
||||||
reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1;
|
reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1;
|
||||||
ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5;
|
ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5;
|
||||||
|
|
||||||
dev_warn(dev, "DPC %s detected, remove downstream devices\n",
|
dev_warn(dev, "DPC %s detected, remove downstream devices\n",
|
||||||
(reason == 0) ? "unmasked uncorrectable error" :
|
(reason == 0) ? "unmasked uncorrectable error" :
|
||||||
(reason == 1) ? "ERR_NONFATAL" :
|
(reason == 1) ? "ERR_NONFATAL" :
|
||||||
@ -208,10 +188,26 @@ static irqreturn_t dpc_irq(int irq, void *context)
|
|||||||
(ext_reason == 0) ? "RP PIO error" :
|
(ext_reason == 0) ? "RP PIO error" :
|
||||||
(ext_reason == 1) ? "software trigger" :
|
(ext_reason == 1) ? "software trigger" :
|
||||||
"reserved error");
|
"reserved error");
|
||||||
|
|
||||||
/* show RP PIO error detail information */
|
/* show RP PIO error detail information */
|
||||||
if (dpc->rp_extensions && reason == 3 && ext_reason == 0)
|
if (dpc->rp_extensions && reason == 3 && ext_reason == 0)
|
||||||
dpc_process_rp_pio_error(dpc);
|
dpc_process_rp_pio_error(dpc);
|
||||||
|
|
||||||
|
/* We configure DPC so it only triggers on ERR_FATAL */
|
||||||
|
pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t dpc_irq(int irq, void *context)
|
||||||
|
{
|
||||||
|
struct dpc_dev *dpc = (struct dpc_dev *)context;
|
||||||
|
struct pci_dev *pdev = dpc->dev->port;
|
||||||
|
u16 cap = dpc->cap_pos, status;
|
||||||
|
|
||||||
|
pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status);
|
||||||
|
|
||||||
|
if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0))
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
|
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
|
||||||
PCI_EXP_DPC_STATUS_INTERRUPT);
|
PCI_EXP_DPC_STATUS_INTERRUPT);
|
||||||
if (status & PCI_EXP_DPC_STATUS_TRIGGER)
|
if (status & PCI_EXP_DPC_STATUS_TRIGGER)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user