From: Paul M. <le...@li...> - 2007-08-06 09:48:05
|
On Mon, Aug 06, 2007 at 06:33:10PM +0900, Magnus Damm wrote: > I understand that you want to setup your priorities somehow, but I > think there must exist better and cleaner ways to do it. I know Paul > was thinking about adding some function to set interrupt priority > similar to set_irq_type(), but I wonder if it may be better to allow > the user to select the priorities from sysfs or something. Probably > not, at least not as a first step. > > So if some generic function like set_irq_type() could be used that > would be great - otherwise I think just adding some intc specific > function is good enough. So this is what I would prefer something like > this: > > void board_irq_setup() > { > /* first register the board specific interrupts */ > register_intc_controller(&intc_desc); > > /* then setup interrupt priorities for this board */ > set_irq_priority(STNIC_IRQ, 12); > set_irq_priority(CF_IRQ, 3); > } > > Does that solve what you are want to do? > > Speaking about interrupt priorities, the irq code in > arch/sh/boards/se/770x/irq.c seem to set a priority that is very > similar to the IRQ value. Do you know anything about this? Is this > priority value similar by pure coincidence, or is this related to the > IRL interrupt number? > Yes, I was thinking of something like the following. This does restrict the range of allowable priorities at request_irq() time, but if someone has a use case for an explicit priority, set_irq_prio() can be used for kicking that down to the chip handler. I would wager that 99.99999% of all use cases will fit in with default/high/low priorities, though. If someone has a non-academic use case that won't fit in this model, I'd be interested in hearing it. -- diff --git a/include/linux/irq.h b/include/linux/irq.h index 1695054..1f7578e 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -45,6 +45,11 @@ typedef void fastcall (*irq_flow_handler_t)(unsigned int irq, #define IRQ_TYPE_SENSE_MASK 0x0000000f /* Mask of the above */ #define IRQ_TYPE_PROBE 0x00000010 /* Probing in progress */ +/* IRQ priorities */ +#define IRQ_PRIO_NONE 0x00000000 /* Default priority */ +#define IRQ_PRIO_HIGH 0x00000001 /* High priority */ +#define IRQ_PRIO_LOW 0x00000002 /* Low priority */ + /* Internal flags */ #define IRQ_INPROGRESS 0x00000100 /* IRQ handler active - do not enter! */ #define IRQ_DISABLED 0x00000200 /* IRQ disabled - do not enter! */ @@ -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 @@ -379,6 +386,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) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 615ce97..fa7df4d 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -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/irq.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 |