Commit d924c951 authored by Linus Torvalds's avatar Linus Torvalds

Add support for checking before-the-fact whether an IRQ is

already registered or not. The x86 PCI layer wants this for
its availability testing.

Doing a request_irq()/free_irq() pair to check this condition
like we used to do can lock the machine if the irq happens to
be screaming.
parent fe6705c3
...@@ -505,6 +505,20 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs) ...@@ -505,6 +505,20 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
return 1; return 1;
} }
int can_request_irq(unsigned int irq, unsigned long irqflags)
{
struct irqaction *action;
if (irq >= NR_IRQS)
return 0;
action = irq_desc[irq].action;
if (action) {
if (irqflags & action->flags & SA_SHIRQ)
action = NULL;
}
return !action;
}
/** /**
* request_irq - allocate an interrupt line * request_irq - allocate an interrupt line
* @irq: Interrupt line to allocate * @irq: Interrupt line to allocate
......
...@@ -695,11 +695,6 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev) ...@@ -695,11 +695,6 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
return NULL; return NULL;
} }
static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
return IRQ_NONE;
}
static int pcibios_lookup_irq(struct pci_dev *dev, int assign) static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
{ {
u8 pin; u8 pin;
...@@ -761,11 +756,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) ...@@ -761,11 +756,8 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
if (!(mask & (1 << i))) if (!(mask & (1 << i)))
continue; continue;
if (pirq_penalty[i] < pirq_penalty[newirq] && if (pirq_penalty[i] < pirq_penalty[newirq] && can_request_irq(i, SA_SHIRQ))
!request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
free_irq(i, dev);
newirq = i; newirq = i;
}
} }
} }
DBG(" -> newirq=%d", newirq); DBG(" -> newirq=%d", newirq);
......
...@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int); ...@@ -24,6 +24,7 @@ extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int); extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int); extern void enable_irq(unsigned int);
extern void release_x86_irqs(struct task_struct *); extern void release_x86_irqs(struct task_struct *);
extern int can_request_irq(unsigned int, unsigned long flags);
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */ #define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
......
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