Skip to content

Commit 388c8c1

Browse files
James Bottomleyjbarnes993
James Bottomley
authored andcommittedOct 23, 2008
PCI: add routines for debugging and handling lost interrupts
We're getting a lot of storage drivers blamed for interrupt misrouting issues. This patch provides a standard way of reporting the problem ... and, if possible, correcting it. Signed-off-by: James Bottomley <[email protected]> Signed-off-by: Jesse Barnes <[email protected]>
1 parent 18b341b commit 388c8c1

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed
 

‎drivers/pci/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
#
44

55
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
6-
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o
6+
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
7+
irq.o
78
obj-$(CONFIG_PROC_FS) += proc.o
89

910
# Build PCI Express stuff if needed

‎drivers/pci/irq.c

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* PCI IRQ failure handing code
3+
*
4+
* Copyright (c) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
5+
*/
6+
7+
#include <linux/acpi.h>
8+
#include <linux/device.h>
9+
#include <linux/kernel.h>
10+
#include <linux/pci.h>
11+
12+
static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
13+
{
14+
struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
15+
16+
dev_printk(KERN_ERR, &pdev->dev,
17+
"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
18+
parent->dev.bus_id, parent->vendor, parent->device);
19+
dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
20+
dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
21+
WARN_ON(1);
22+
}
23+
24+
/**
25+
* pci_lost_interrupt - reports a lost PCI interrupt
26+
* @pdev: device whose interrupt is lost
27+
*
28+
* The primary function of this routine is to report a lost interrupt
29+
* in a standard way which users can recognise (instead of blaming the
30+
* driver).
31+
*
32+
* Returns:
33+
* a suggestion for fixing it (although the driver is not required to
34+
* act on this).
35+
*/
36+
enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *pdev)
37+
{
38+
if (pdev->msi_enabled || pdev->msix_enabled) {
39+
enum pci_lost_interrupt_reason ret;
40+
41+
if (pdev->msix_enabled) {
42+
pci_note_irq_problem(pdev, "MSIX routing failure");
43+
ret = PCI_LOST_IRQ_DISABLE_MSIX;
44+
} else {
45+
pci_note_irq_problem(pdev, "MSI routing failure");
46+
ret = PCI_LOST_IRQ_DISABLE_MSI;
47+
}
48+
return ret;
49+
}
50+
#ifdef CONFIG_ACPI
51+
if (!(acpi_disabled || acpi_noirq)) {
52+
pci_note_irq_problem(pdev, "Potential ACPI misrouting please reboot with acpi=noirq");
53+
/* currently no way to fix acpi on the fly */
54+
return PCI_LOST_IRQ_DISABLE_ACPI;
55+
}
56+
#endif
57+
pci_note_irq_problem(pdev, "unknown cause (not MSI or ACPI)");
58+
return PCI_LOST_IRQ_NO_INFORMATION;
59+
}
60+
EXPORT_SYMBOL(pci_lost_interrupt);

‎include/linux/pci.h

+7
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,13 @@ struct pci_dev __deprecated *pci_find_slot(unsigned int bus,
546546
unsigned int devfn);
547547
#endif /* CONFIG_PCI_LEGACY */
548548

549+
enum pci_lost_interrupt_reason {
550+
PCI_LOST_IRQ_NO_INFORMATION = 0,
551+
PCI_LOST_IRQ_DISABLE_MSI,
552+
PCI_LOST_IRQ_DISABLE_MSIX,
553+
PCI_LOST_IRQ_DISABLE_ACPI,
554+
};
555+
enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev);
549556
int pci_find_capability(struct pci_dev *dev, int cap);
550557
int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
551558
int pci_find_ext_capability(struct pci_dev *dev, int cap);

0 commit comments

Comments
 (0)
Please sign in to comment.