Commit 56abbf8a authored by Oza Pawandeep's avatar Oza Pawandeep Committed by Bjorn Helgaas

PCI/DPC: Clear interrupt status in interrupt handler top half

The generic IRQ handling code ensures that an interrupt handler runs with
its interrupt masked or disabled.  If the interrupt is level-triggered, the
interrupt handler must tell its device to stop asserting the interrupt
before returning.  If it doesn't, we will immediately take the interrupt
again when the handler returns and the generic code unmasks the interrupt.

The driver doesn't know whether its interrupt is edge- or level-triggered,
so it must clear its interrupt source directly in its interrupt handler.

Previously we cleared the DPC interrupt status in the bottom half, i.e., in
deferred work, which can cause an interrupt storm if the DPC interrupt
happens to be level-triggered, e.g., if we're using INTx instead of MSI.

Clear the DPC interrupt status bit in the interrupt handler, not in the
deferred work.
Signed-off-by: default avatarOza Pawandeep <poza@codeaurora.org>
[bhelgaas: changelog]
Signed-off-by: default avatarBjorn Helgaas <helgaas@kernel.org>
Reviewed-by: default avatarKeith Busch <keith.busch@intel.com>
parent 60cc43fc
...@@ -113,7 +113,7 @@ static void dpc_work(struct work_struct *work) ...@@ -113,7 +113,7 @@ static void dpc_work(struct work_struct *work)
} }
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
PCI_EXP_DPC_STATUS_TRIGGER | PCI_EXP_DPC_STATUS_INTERRUPT); PCI_EXP_DPC_STATUS_TRIGGER);
pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl); pci_read_config_word(pdev, cap + PCI_EXP_DPC_CTL, &ctl);
pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL, pci_write_config_word(pdev, cap + PCI_EXP_DPC_CTL,
...@@ -223,6 +223,9 @@ static irqreturn_t dpc_irq(int irq, void *context) ...@@ -223,6 +223,9 @@ static irqreturn_t dpc_irq(int irq, void *context)
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);
pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS,
PCI_EXP_DPC_STATUS_INTERRUPT);
schedule_work(&dpc->work); schedule_work(&dpc->work);
return IRQ_HANDLED; return IRQ_HANDLED;
......
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