Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 354e6f72 authored by eric miao's avatar eric miao Committed by Russell King
Browse files

ARM: 6197/2: preliminary support for sparse IRQ



So to allow NR_IRQS to be dynamic and platforms to specify the number
of IRQs really needed.

Acked-by: default avatarPaul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarEric Miao <eric.y.miao@gmail.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 309caa9c
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1289,6 +1289,18 @@ config HW_PERF_EVENTS
	  Enable hardware performance counter support for perf events. If
	  disabled, perf events will use software events only.

config SPARSE_IRQ
	bool "Support sparse irq numbering"
	depends on EXPERIMENTAL
	help
	  This enables support for sparse irqs. This is useful in general
	  as most CPUs have a fairly sparse array of IRQ vectors, which
	  the irq_desc then maps directly on to. Systems with a high
	  number of off-chip IRQs will want to treat this as
	  experimental until they have been independently verified.

	  If you don't know what to do here, say N.

source "mm/Kconfig"

config LEDS
+2 −0
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@
#define irq_canonicalize(i)	(i)
#endif

#define NR_IRQS_LEGACY	16

/*
 * Use this value to indicate lack of interrupt
 * capability
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ struct machine_desc {
	 * by assembler code in head.S, head-common.S
	 */
	unsigned int		nr;		/* architecture number	*/
	unsigned int		nr_irqs;	/* number of IRQs */
	unsigned int		phys_io;	/* start of physical io	*/
	unsigned int		io_pg_offst;	/* byte offset for io 
						 * page tabe entry	*/
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ struct seq_file;
/*
 * This is internal.  Do not use it.
 */
extern unsigned int arch_nr_irqs;
extern void (*init_arch_irq)(void);
extern void init_FIQ(void);
extern int show_fiq_list(struct seq_file *, void *);
+27 −14
Original line number Diff line number Diff line
@@ -47,12 +47,14 @@
#define irq_finish(irq) do { } while (0)
#endif

unsigned int arch_nr_irqs;
void (*init_arch_irq)(void) __initdata = NULL;
unsigned long irq_err_count;

int show_interrupts(struct seq_file *p, void *v)
{
	int i = *(loff_t *) v, cpu;
	struct irq_desc *desc;
	struct irqaction * action;
	unsigned long flags;

@@ -67,24 +69,25 @@ int show_interrupts(struct seq_file *p, void *v)
		seq_putc(p, '\n');
	}

	if (i < NR_IRQS) {
		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
		action = irq_desc[i].action;
	if (i < nr_irqs) {
		desc = irq_to_desc(i);
		raw_spin_lock_irqsave(&desc->lock, flags);
		action = desc->action;
		if (!action)
			goto unlock;

		seq_printf(p, "%3d: ", i);
		for_each_present_cpu(cpu)
			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
		seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
		seq_printf(p, " %10s", desc->chip->name ? : "-");
		seq_printf(p, "  %s", action->name);
		for (action = action->next; action; action = action->next)
			seq_printf(p, ", %s", action->name);

		seq_putc(p, '\n');
unlock:
		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
	} else if (i == NR_IRQS) {
		raw_spin_unlock_irqrestore(&desc->lock, flags);
	} else if (i == nr_irqs) {
#ifdef CONFIG_FIQ
		show_fiq_list(p, v);
#endif
@@ -112,7 +115,7 @@ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
	 * Some hardware gives randomly wrong interrupts.  Rather
	 * than crashing, do something sensible.
	 */
	if (unlikely(irq >= NR_IRQS)) {
	if (unlikely(irq >= nr_irqs)) {
		if (printk_ratelimit())
			printk(KERN_WARNING "Bad IRQ%u\n", irq);
		ack_bad_irq(irq);
@@ -132,12 +135,12 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
	struct irq_desc *desc;
	unsigned long flags;

	if (irq >= NR_IRQS) {
	if (irq >= nr_irqs) {
		printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
		return;
	}

	desc = irq_desc + irq;
	desc = irq_to_desc(irq);
	raw_spin_lock_irqsave(&desc->lock, flags);
	desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
	if (iflags & IRQF_VALID)
@@ -151,14 +154,25 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)

void __init init_IRQ(void)
{
	struct irq_desc *desc;
	int irq;

	for (irq = 0; irq < NR_IRQS; irq++)
		irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
	for (irq = 0; irq < nr_irqs; irq++) {
		desc = irq_to_desc_alloc_node(irq, 0);
		desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
	}

	init_arch_irq();
}

#ifdef CONFIG_SPARSE_IRQ
int __init arch_probe_nr_irqs(void)
{
	nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
	return 0;
}
#endif

#ifdef CONFIG_HOTPLUG_CPU

static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
@@ -178,10 +192,9 @@ static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
void migrate_irqs(void)
{
	unsigned int i, cpu = smp_processor_id();
	struct irq_desc *desc;

	for (i = 0; i < NR_IRQS; i++) {
		struct irq_desc *desc = irq_desc + i;

	for_each_irq_desc(i, desc) {
		if (desc->node == cpu) {
			unsigned int newcpu = cpumask_any_and(desc->affinity,
							      cpu_online_mask);
Loading