aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/pci_irq.c29
-rw-r--r--include/linux/interrupt.h10
-rw-r--r--kernel/irq/manage.c9
3 files changed, 43 insertions, 5 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index c8e169e46673..2c45dd3acc17 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -33,6 +33,7 @@
33#include <linux/pci.h> 33#include <linux/pci.h>
34#include <linux/acpi.h> 34#include <linux/acpi.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/interrupt.h>
36 37
37#define PREFIX "ACPI: " 38#define PREFIX "ACPI: "
38 39
@@ -387,6 +388,23 @@ static inline int acpi_isa_register_gsi(struct pci_dev *dev)
387} 388}
388#endif 389#endif
389 390
391static inline bool acpi_pci_irq_valid(struct pci_dev *dev, u8 pin)
392{
393#ifdef CONFIG_X86
394 /*
395 * On x86 irq line 0xff means "unknown" or "no connection"
396 * (PCI 3.0, Section 6.2.4, footnote on page 223).
397 */
398 if (dev->irq == 0xff) {
399 dev->irq = IRQ_NOTCONNECTED;
400 dev_warn(&dev->dev, "PCI INT %c: not connected\n",
401 pin_name(pin));
402 return false;
403 }
404#endif
405 return true;
406}
407
390int acpi_pci_irq_enable(struct pci_dev *dev) 408int acpi_pci_irq_enable(struct pci_dev *dev)
391{ 409{
392 struct acpi_prt_entry *entry; 410 struct acpi_prt_entry *entry;
@@ -431,11 +449,14 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
431 } else 449 } else
432 gsi = -1; 450 gsi = -1;
433 451
434 /*
435 * No IRQ known to the ACPI subsystem - maybe the BIOS /
436 * driver reported one, then use it. Exit in any case.
437 */
438 if (gsi < 0) { 452 if (gsi < 0) {
453 /*
454 * No IRQ known to the ACPI subsystem - maybe the BIOS /
455 * driver reported one, then use it. Exit in any case.
456 */
457 if (!acpi_pci_irq_valid(dev, pin))
458 return 0;
459
439 if (acpi_isa_register_gsi(dev)) 460 if (acpi_isa_register_gsi(dev))
440 dev_warn(&dev->dev, "PCI INT %c: no GSI\n", 461 dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
441 pin_name(pin)); 462 pin_name(pin));
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 0e95fcc75b2a..358076eda364 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -125,6 +125,16 @@ struct irqaction {
125 125
126extern irqreturn_t no_action(int cpl, void *dev_id); 126extern irqreturn_t no_action(int cpl, void *dev_id);
127 127
128/*
129 * If a (PCI) device interrupt is not connected we set dev->irq to
130 * IRQ_NOTCONNECTED. This causes request_irq() to fail with -ENOTCONN, so we
131 * can distingiush that case from other error returns.
132 *
133 * 0x80000000 is guaranteed to be outside the available range of interrupts
134 * and easy to distinguish from other possible incorrect values.
135 */
136#define IRQ_NOTCONNECTED (1U << 31)
137
128extern int __must_check 138extern int __must_check
129request_threaded_irq(unsigned int irq, irq_handler_t handler, 139request_threaded_irq(unsigned int irq, irq_handler_t handler,
130 irq_handler_t thread_fn, 140 irq_handler_t thread_fn,
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 841187239adc..e79e60f50bce 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1609,6 +1609,9 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
1609 struct irq_desc *desc; 1609 struct irq_desc *desc;
1610 int retval; 1610 int retval;
1611 1611
1612 if (irq == IRQ_NOTCONNECTED)
1613 return -ENOTCONN;
1614
1612 /* 1615 /*
1613 * Sanity-check: shared interrupts must pass in a real dev-ID, 1616 * Sanity-check: shared interrupts must pass in a real dev-ID,
1614 * otherwise we'll have trouble later trying to figure out 1617 * otherwise we'll have trouble later trying to figure out
@@ -1699,9 +1702,13 @@ EXPORT_SYMBOL(request_threaded_irq);
1699int request_any_context_irq(unsigned int irq, irq_handler_t handler, 1702int request_any_context_irq(unsigned int irq, irq_handler_t handler,
1700 unsigned long flags, const char *name, void *dev_id) 1703 unsigned long flags, const char *name, void *dev_id)
1701{ 1704{
1702 struct irq_desc *desc = irq_to_desc(irq); 1705 struct irq_desc *desc;
1703 int ret; 1706 int ret;
1704 1707
1708 if (irq == IRQ_NOTCONNECTED)
1709 return -ENOTCONN;
1710
1711 desc = irq_to_desc(irq);
1705 if (!desc) 1712 if (!desc)
1706 return -EINVAL; 1713 return -EINVAL;
1707 1714