On Sun, Aug 3, 2008 at 10:54 AM, Yinghai Lu <yhlu.kernel@gmail.com> wrote:how about this one? diff --git a/include/linux/irq.h b/include/linux/irq.h index bd69d90..9d87f6a 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -154,6 +154,8 @@ struct irq_chip { * @name: flow handler name for /proc/interrupts output */ struct irq_desc { + unsigned int irq; + struct irq_desc *next; irq_flow_handler_t handle_irq; struct irq_chip *chip; struct msi_desc *msi_desc; @@ -181,7 +183,7 @@ struct irq_desc { const char *name; } ____cacheline_internodealigned_in_smp; -extern struct irq_desc irq_desc[NR_IRQS]; +extern struct irq_desc *get_irq_desc(unsigned int irq); /* * Migration helpers for obsolete names, they will go away: diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index e9d022c..347edb8 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -48,7 +48,90 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc) * Controller mappings for all interrupt sources: */ int nr_irqs = NR_IRQS; -struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { + +#ifdef CONFIG_HAVE_DYN_ARRAY +static struct irq_desc irq_desc_init __initdata = { + .irq = -1U; + .status = IRQ_DISABLED, + .chip = &no_irq_chip, + .handle_irq = handle_bad_irq, + .depth = 1, + .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), +#ifdef CONFIG_SMP + .affinity = CPU_MASK_ALL +#endif +}; + +static int nr_irq_desc = NR_VECTORS; + +static int __init parse_nr_irq_desc(char *arg) +{ + if (arg) + nr_irq_desc = simple_strtoul(arg, NULL, 0); + return 0; +} + +early_param("nr_irq_desc", parse_nr_irq_desc); + +static void __init init_work(void *data) +{ + struct dyn_array *da = data; + int i; + struct irq_desc *desc; + + desc = *da->name; + + for (i = 0; i < *da->nr; i++) + memcpy(&desc[i], &irq_desc_init, sizeof(struct irq_desc)); + + for (i = 1; i < *da->nr; i++) + desc[i-1].next = &desc[i]; +} + +static struct irq_desc *irq_desc; +DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irq_desc, PAGE_SIZE, init_work); + +struct irq_desc *get_irq_desc(unsigned int irq) +{ + struct irq_desc *desc, *desc_pri; + + BUG_ON(irq == -1U); + + desc = &irq_desc[0]; + while (desc) { + if (desc->irq == irq) + return desc; + + if (desc->irq == -1U) { + desc->irq = irq; + return desc; + } + desc_pri = desc; + desc = desc->next; + } + + /* + * we run out of pre-allocate ones + * and __alloc_bootmem or kzalloc could be used + */ + + if (after_bootmem) + desc = (struct irq_desc *) get_zeroed_page(GFP_ATOMIC); + else + desc = alloc_bootmem_pages(PAGE_SIZE); + + if (!desc || ((unsigned long)desc & ~PAGE_MASK)) + panic("please boot with nr_irq_desc= %d\n", nr_irq_desc * 2); + + desc_pri->next = desc; + desc->irq = irq; + + return desc; +} + +#else + +static struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ... NR_IRQS-1] = { .status = IRQ_DISABLED, .chip = &no_irq_chip, @@ -61,6 +144,16 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { } }; +struct irq_desc *get_irq_desc(unsigned int irq) +{ + if (irq < nr_irqs) + return &irq_desc[irq]; + + return NULL; +} + +#endif + /* * What should we do if we get a hw irq event on an illegal vector? * Each architecture has to answer this themself. do we need to lock to avoid racing in get_irq_desc? YH --
| Washington Odhiambo | Weird Problem with NAT - more details |
| Greg Kroah-Hartman | [PATCH 001/196] Chinese: Add the known_regression URI to the HOWTO |
| Tarkan Erimer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Andrew Morton | -mm merge plans for 2.6.23 |
git: | |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Gerrit Renker | [PATCH 0/37] dccp: Feature negotiation - last call for comments |
| David Miller | Re: [GIT]: Networking |
| Denys Fedoryshchenko | thousands of classes, e1000 TX unit hang |
