Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Commit

Permalink
PCI: pciehp: Fix infinite loop in IRQ handler upon power fault
Browse files Browse the repository at this point in the history
commit 23584c1ed3e15a6f4bfab8dc5a88d94ab929ee12 upstream.

The Power Fault Detected bit in the Slot Status register differs from
all other hotplug events in that it is sticky:  It can only be cleared
after turning off slot power.  Per PCIe r5.0, sec. 6.7.1.8:

  If a power controller detects a main power fault on the hot-plug slot,
  it must automatically set its internal main power fault latch [...].
  The main power fault latch is cleared when software turns off power to
  the hot-plug slot.

The stickiness used to cause interrupt storms and infinite loops which
were fixed in 2009 by commits 5651c48 ("PCI pciehp: fix power fault
interrupt storm problem") and 99f0169 ("PCI: pciehp: enable
software notification on empty slots").

Unfortunately in 2020 the infinite loop issue was inadvertently
reintroduced by commit 8edf5332c393 ("PCI: pciehp: Fix MSI interrupt
race"):  The hardirq handler pciehp_isr() clears the PFD bit until
pciehp's power_fault_detected flag is set.  That happens in the IRQ
thread pciehp_ist(), which never learns of the event because the hardirq
handler is stuck in an infinite loop.  Fix by setting the
power_fault_detected flag already in the hardirq handler.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=214989
Link: https://lore.kernel.org/linux-pci/DM8PR11MB5702255A6A92F735D90A4446868B9@DM8PR11MB5702.namprd11.prod.outlook.com
Fixes: 8edf5332c393 ("PCI: pciehp: Fix MSI interrupt race")
Link: https://lore.kernel.org/r/66eaeef31d4997ceea357ad93259f290ededecfd.1637187226.git.lukas@wunner.de
Reported-by: Joseph Bao <[email protected]>
Tested-by: Joseph Bao <[email protected]>
Signed-off-by: Lukas Wunner <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
Cc: [email protected] # v4.19+
Cc: Stuart Hayes <[email protected]>
[sudip: adjust context]
Signed-off-by: Sudip Mukherjee <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
l1k authored and Blackmanx committed Dec 21, 2022
1 parent 6e1c9af commit 46428d6
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions drivers/pci/hotplug/pciehp_hpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,8 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
*/
if (ctrl->power_fault_detected)
status &= ~PCI_EXP_SLTSTA_PFD;
else if (status & PCI_EXP_SLTSTA_PFD)
ctrl->power_fault_detected = true;

events |= status;
if (!events) {
Expand All @@ -585,7 +587,7 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
}

if (status) {
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events);
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, status);

/*
* In MSI mode, all event bits must be zero before the port
Expand Down Expand Up @@ -660,8 +662,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id)
}

/* Check Power Fault Detected */
if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
ctrl->power_fault_detected = 1;
if (events & PCI_EXP_SLTSTA_PFD) {
ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(slot));
pciehp_set_attention_status(slot, 1);
pciehp_green_led_off(slot);
Expand Down

0 comments on commit 46428d6

Please sign in to comment.