Messages in this thread Patch in this message | | | Subject | [5/7] Xen VMM patch set : split free_irq into teardown_irq | Date | Fri, 19 Nov 2004 23:23:37 +0000 | From | Ian Pratt <> |
| |
This patch moves the `unregister the irqaction' part of free_irq into a new function teardown_irq, leaving only the mapping from dev_id to irqaction and freeing the irqaction in free_irq. free_irq calls teardown_irq to unregister the irqaction. This is similar to how setup_irq and request_irq work for registering irq's. We need teardown_irq to allow us to unregister irq's which were registered early during boot when memory management wasn't ready yet, i.e. irq's which were registered using setup_irq and use a static irqaction which cannot be kfree'd.
Signed-off-by: ian.pratt@cl.cam.ac.uk
--- diff -Nurp pristine-linux-2.6.10-rc2/include/linux/irq.h tmp-linux-2.6.10-rc2-xen.patch/include/linux/irq.h --- pristine-linux-2.6.10-rc2/include/linux/irq.h 2004-11-15 01:28:57.000000000 +0000 +++ tmp-linux-2.6.10-rc2-xen.patch/include/linux/irq.h 2004-11-19 14:00:39.000000000 +0000 @@ -73,6 +73,7 @@ extern irq_desc_t irq_desc [NR_IRQS]; #include <asm/hw_irq.h> /* the arch dependent stuff */ extern int setup_irq(unsigned int irq, struct irqaction * new); +extern int teardown_irq(unsigned int irq, struct irqaction * old); #ifdef CONFIG_GENERIC_HARDIRQS extern cpumask_t irq_affinity[NR_IRQS]; diff -Nurp pristine-linux-2.6.10-rc2/kernel/irq/manage.c tmp-linux-2.6.10-rc2-xen.patch/kernel/irq/manage.c --- pristine-linux-2.6.10-rc2/kernel/irq/manage.c 2004-11-15 01:27:20.000000000 +0000 +++ tmp-linux-2.6.10-rc2-xen.patch/kernel/irq/manage.c 2004-11-19 14:00:30.000000000 +0000 @@ -215,28 +215,18 @@ int setup_irq(unsigned int irq, struct i return 0; } -/** - * free_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. The function - * does not return until any executing interrupts for this IRQ - * have completed. - * - * This function must not be called from interrupt context. +/* + * Internal function to unregister an irqaction - typically used to + * deallocate special interrupts that are part of the architecture. */ -void free_irq(unsigned int irq, void *dev_id) +int teardown_irq(unsigned int irq, struct irqaction * old) { struct irq_desc *desc; struct irqaction **p; unsigned long flags; if (irq >= NR_IRQS) - return; + return -ENOENT; desc = irq_desc + irq; spin_lock_irqsave(&desc->lock,flags); @@ -248,7 +238,7 @@ void free_irq(unsigned int irq, void *de struct irqaction **pp = p; p = &action->next; - if (action->dev_id != dev_id) + if (action != old) continue; /* Found it - now remove it from the list of entries */ @@ -265,13 +255,52 @@ void free_irq(unsigned int irq, void *de /* Make sure it's not being used on another CPU */ synchronize_irq(irq); - kfree(action); - return; + return 0; } - printk(KERN_ERR "Trying to free free IRQ%d\n",irq); + printk(KERN_ERR "Trying to teardown free IRQ%d\n",irq); spin_unlock_irqrestore(&desc->lock,flags); + return -ENOENT; + } +} + +/** + * free_irq - free an interrupt + * @irq: Interrupt line to free + * @dev_id: Device identity to free + * + * Remove an interrupt handler. The handler is removed and if the + * interrupt line is no longer in use by any driver it is disabled. + * On a shared IRQ the caller must ensure the interrupt is disabled + * on the card it drives before calling this function. The function + * does not return until any executing interrupts for this IRQ + * have completed. + * + * This function must not be called from interrupt context. + */ +void free_irq(unsigned int irq, void *dev_id) +{ + struct irq_desc *desc; + struct irqaction *action; + unsigned long flags; + + if (irq >= NR_IRQS) + return; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + for (action = desc->action; action != NULL; action = action->next) { + if (action->dev_id != dev_id) + continue; + + spin_unlock_irqrestore(&desc->lock,flags); + + if (teardown_irq(irq, action) == 0) + kfree(action); return; } + printk(KERN_ERR "Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + return; } EXPORT_SYMBOL(free_irq); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |