sparse irq_desc[] array: core kernel and x86 changes

Impact: new feature

Problem on distro kernels: irq_desc[NR_IRQS] takes megabytes of RAM with
NR_CPUS set to large values. The goal is to be able to scale up to much
larger NR_IRQS value without impacting the (important) common case.

To solve this, we generalize irq_desc[NR_IRQS] to an (optional) array of
irq_desc pointers.

When CONFIG_SPARSE_IRQ=y is used, we use kzalloc_node to get irq_desc,
this also makes the IRQ descriptors NUMA-local (to the site that calls
request_irq()).

This gets rid of the irq_cfg[] static array on x86 as well: irq_cfg now
uses desc->chip_data for x86 to store irq_cfg.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Yinghai Lu 2008-12-05 18:58:31 -08:00 committed by Ingo Molnar
parent 218d11a8b0
commit 0b8f1efad3
23 changed files with 659 additions and 173 deletions

View file

@ -44,6 +44,57 @@ struct rand_pool_info {
extern void rand_initialize_irq(int irq);
struct timer_rand_state;
#ifndef CONFIG_SPARSE_IRQ
extern struct timer_rand_state *irq_timer_state[];
extern int nr_irqs;
static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
{
if (irq >= nr_irqs)
return NULL;
return irq_timer_state[irq];
}
static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
{
if (irq >= nr_irqs)
return;
irq_timer_state[irq] = state;
}
#else
#include <linux/irq.h>
static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
{
struct irq_desc *desc;
desc = irq_to_desc(irq);
if (!desc)
return NULL;
return desc->timer_rand_state;
}
static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
{
struct irq_desc *desc;
desc = irq_to_desc(irq);
if (!desc)
return;
desc->timer_rand_state = state;
}
#endif
extern void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value);
extern void add_interrupt_randomness(int irq);