genirq: support multiple interrupt priorities
RFC PATCH 1/1 genirq: support multiple interrupt priorities
This is a simple patch for adding trivial interrupt priority support.
I've added a ->set_prio() to the irq_chip which is implemented effectively the same way as ->set_type(), it's an optional component for those that really care about it.
This follows the rationale that PICs that do support multiple priorities are going to support a fairly wide range, which is not something that can easily be represented generically. Given that, the only IRQF_PRIO_* flags that are introduced are for generic priorities that we assume all priority-capable PICs can support -- namely, high, low, and default (or none). In addition to this there is also a set_irq_prio() modelled after set_irq_type() which platform-specific code can set to more specific values that aren't suitable for generic abstraction.
My primary use case for this is for making sure we have high priorities where we want them in the platform code, especially chained handlers, timers, things of that nature. Going the genirq route is certainly much cleaner than trying to hack up my own arch-specific API for this. I imagine other people will have similar use cases for this.
Comments? Flames?
--
include/linux/interrupt.h | 5 +++++ include/linux/irq.h | 3 +++ kernel/irq/chip.c | 26 ++++++++++++++++++++++++++ kernel/irq/manage.c | 16 ++++++++++++++++ 4 files changed, 50 insertions(+)
include/linux/interrupt.h +5 -0
@@ -45,6 +45,8 @@* IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is * registered first in an shared interrupt is considered for * performance reasons) +* IRQF_PRIO_HIGH - Give IRQ a high priority +* IRQF_PRIO_LOW - Give IRQ a low priority */ #define IRQF_DISABLED 0x00000020#define IRQF_SAMPLE_RANDOM 0x00000040
@@ -54,6 +56,9 @@#define IRQF_PERCPU 0x00000400#define IRQF_NOBALANCING 0x00000800#define IRQF_IRQPOLL 0x00001000 +#define IRQF_PRIO_HIGH 0x00002000 +#define IRQF_PRIO_LOW 0x00004000 +#define IRQF_PRIO_MASK (IRQF_PRIO_HIGH | IRQF_PRIO_LOW)/* * Migration helpers. Scheduled for removal in 9/2007
include/linux/irq.h +3 -0
@@ -91,6 +96,7 @@ struct msi_desc;* @retrigger: resend an IRQ to the CPU * @set_type: set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ * @set_wake: enable/disable power-management wake-on of an IRQ +* @set_prio: set the priority of an IRQ * * @release: release function solely used by UML * @typename: obsoleted by name, kept as migration helper
@@ -113,6 +119,7 @@ struct irq_chip {int (*retrigger)(unsigned int irq);int (*set_type)(unsigned int irq,unsigned int flow_type);int (*set_wake)(unsigned int irq,unsigned int on); +int (*set_prio)(unsigned int irq,unsigned int prio);/* Currently used only by UML, might disappear one day.*/ #ifdef CONFIG_IRQ_RELEASE_METHOD
@@ -381,6 +388,7 @@ extern int set_irq_data(unsigned int irq, void *data);extern int set_irq_chip_data (unsigned int irq,void *data);extern int set_irq_type (unsigned int irq,unsigned int type);extern int set_irq_msi (unsigned int irq,struct msi_desc *entry); +extern int set_irq_prio (unsigned int irq,unsigned int prio);#define get_irq_chip (irq) (irq_desc[irq].chip)#define get_irq_chip_data (irq) (irq_desc[irq].chip_data)
kernel/irq/chip.c +26 -0
@@ -141,6 +141,32 @@ int set_irq_type(unsigned int irq, unsigned int type)EXPORT_SYMBOL (set_irq_type);/** +* set_irq_prio - set the irq priority for an irq +* @irq: irq number +* @prio: interrupt priority - see include/linux/interrupt.h +*/ +int set_irq_prio (unsigned int irq,unsigned int prio) +{ +struct irq_desc *desc; +unsigned long flags; +int ret = -ENXIO ; + +if (irq >=NR_IRQS ) { +printk (KERN_ERR "Trying to set irq priority for IRQ%d\n" , irq); +return -ENODEV ; + } + + desc = irq_desc + irq; +if (desc->chip->set_prio) { +spin_lock_irqsave (&desc->lock, flags); + ret = desc->chip->set_prio (irq, prio); +spin_unlock_irqrestore (&desc->lock, flags); + } +return ret; +} +EXPORT_SYMBOL (set_irq_prio); + +/** * set_irq_data - set irq type data for an irq * @irq: Interrupt number * @data: Pointer to interrupt specific data
kernel/irq/manage.c +16 -0
@@ -347,6 +353,22 @@ int setup_irq(unsigned int irq, struct irqaction *new) }else compat_irq_chip_set_default_handler (desc); +/* Setup the priority if configured: */ +if (new->flags &IRQF_PRIO_MASK ) { +if (desc->chip && desc->chip->set_prio) + desc->chip->set_prio (irq, + new->flags &IRQF_PRIO_MASK ); +else +/* +* IRQF_PRIO_* but the PIC does not support +* multiple priorities? +*/ +printk (KERN_WARNING "No IRQF_PRIO set_prio " +"function for IRQ %d (%s)\n" , irq, + desc->chip ? desc->chip->name : +"unknown" ); + } + desc->status &= ~(IRQ_AUTODETECT |IRQ_WAITING |IRQ_INPROGRESS );
Quoted 5 lines · Paul Mundt
This is a simple patch for adding trivial interrupt priority support.
I've added a ->set_prio() to the
irq_chipwhich is implemented effectively the same way as ->set_type(), it's an optional component for those that really care about it.
i have no fundamental objections but it would be nice to actually prototype this by implementing real priority support in the hardware:
both the i8259A and the IO-APIC/local-apic has such IRQ prioritization features.
Quoted 2 lines
+ *
IRQF_PRIO_HIGH- Give IRQ a high priority
+ *IRQF_PRIO_LOW- Give IRQ a low priority
this should be a numeric scale. (Preferably in the 1-99 range (the hardware can then do a lower-resolution thing out of it), so that we can directly map this to IRQ threads and SCHED_FIFO priorities in -rt.)
Ingo
Quoted 12 lines · Ingo Molnar
Quoted 5 lines · Paul Mundt
This is a simple patch for adding trivial interrupt priority support.
I've added a ->set_prio() to the
irq_chipwhich is implemented effectively the same way as ->set_type(), it's an optional component for those that really care about it.i have no fundamental objections but it would be nice to actually prototype this by implementing real priority support in the hardware:
both the i8259A and the IO-APIC/local-apic has such IRQ prioritization features.
I would not have written the patch if I did not have hardware that supported it. I suppose I can start with interfacing the x86 PICs if that makes it easier to swallow, though ;-)
Quoted 7 lines
Quoted 2 lines
+ *
IRQF_PRIO_HIGH- Give IRQ a high priority
+ *IRQF_PRIO_LOW- Give IRQ a low prioritythis should be a numeric scale. (Preferably in the 1-99 range (the hardware can then do a lower-resolution thing out of it), so that we can directly map this to IRQ threads and
SCHED_FIFOpriorities in -rt.)
I don't disagree with that, but that makes it a little hard to pass in a priority at request_irq() time. These IRQF_PRIO_HIGH/LOW are only for such usage, the intent is to have a numeric value that's more meaningful to the underlying hardware passed on to set_irq_prio() otherwise.
In any event, there's no problem with doing that anyways, both IRQF_PRIO_HIGH and IRQF_PRIO_LOW are substantially above the 1-99 range that the mask can be tested for if the underlying controller isn't interested in mapping the 1-99 range to its own view of priorities. Presumably you want this numeric range also reflected in the irq_desc for -rt? If so, I'll start hacking something up.