diff options
Diffstat (limited to 'arch/tile/kernel/irq.c')
| -rw-r--r-- | arch/tile/kernel/irq.c | 135 | 
1 files changed, 41 insertions, 94 deletions
diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c index 128805ef8f2..637f2ffaa5f 100644 --- a/arch/tile/kernel/irq.c +++ b/arch/tile/kernel/irq.c @@ -21,6 +21,7 @@  #include <hv/drv_pcie_rc_intf.h>  #include <arch/spr_def.h>  #include <asm/traps.h> +#include <linux/perf_event.h>  /* Bit-flag stored in irq_desc->chip_data to indicate HW-cleared irqs. */  #define IS_HW_CLEARED 1 @@ -53,12 +54,6 @@ static DEFINE_PER_CPU(unsigned long, irq_disable_mask)   */  static DEFINE_PER_CPU(int, irq_depth); -/* State for allocating IRQs on Gx. */ -#if CHIP_HAS_IPI() -static unsigned long available_irqs = ~(1UL << IRQ_RESCHEDULE); -static DEFINE_SPINLOCK(available_irqs_lock); -#endif -  #if CHIP_HAS_IPI()  /* Use SPRs to manipulate device interrupts. */  #define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_K, irq_mask) @@ -73,7 +68,8 @@ static DEFINE_SPINLOCK(available_irqs_lock);  /*   * The interrupt handling path, implemented in terms of HV interrupt - * emulation on TILE64 and TILEPro, and IPI hardware on TILE-Gx. + * emulation on TILEPro, and IPI hardware on TILE-Gx. + * Entered with interrupts disabled.   */  void tile_dev_intr(struct pt_regs *regs, int intnum)  { @@ -152,14 +148,13 @@ void tile_dev_intr(struct pt_regs *regs, int intnum)   * Remove an irq from the disabled mask.  If we're in an interrupt   * context, defer enabling the HW interrupt until we leave.   */ -void enable_percpu_irq(unsigned int irq) +static void tile_irq_chip_enable(struct irq_data *d)  { -	get_cpu_var(irq_disable_mask) &= ~(1UL << irq); +	get_cpu_var(irq_disable_mask) &= ~(1UL << d->irq);  	if (__get_cpu_var(irq_depth) == 0) -		unmask_irqs(1UL << irq); +		unmask_irqs(1UL << d->irq);  	put_cpu_var(irq_disable_mask);  } -EXPORT_SYMBOL(enable_percpu_irq);  /*   * Add an irq to the disabled mask.  We disable the HW interrupt @@ -167,52 +162,53 @@ EXPORT_SYMBOL(enable_percpu_irq);   * in an interrupt context, the return path is careful to avoid   * unmasking a newly disabled interrupt.   */ -void disable_percpu_irq(unsigned int irq) +static void tile_irq_chip_disable(struct irq_data *d)  { -	get_cpu_var(irq_disable_mask) |= (1UL << irq); -	mask_irqs(1UL << irq); +	get_cpu_var(irq_disable_mask) |= (1UL << d->irq); +	mask_irqs(1UL << d->irq);  	put_cpu_var(irq_disable_mask);  } -EXPORT_SYMBOL(disable_percpu_irq);  /* Mask an interrupt. */ -static void tile_irq_chip_mask(unsigned int irq) +static void tile_irq_chip_mask(struct irq_data *d)  { -	mask_irqs(1UL << irq); +	mask_irqs(1UL << d->irq);  }  /* Unmask an interrupt. */ -static void tile_irq_chip_unmask(unsigned int irq) +static void tile_irq_chip_unmask(struct irq_data *d)  { -	unmask_irqs(1UL << irq); +	unmask_irqs(1UL << d->irq);  }  /*   * Clear an interrupt before processing it so that any new assertions   * will trigger another irq.   */ -static void tile_irq_chip_ack(unsigned int irq) +static void tile_irq_chip_ack(struct irq_data *d)  { -	if ((unsigned long)get_irq_chip_data(irq) != IS_HW_CLEARED) -		clear_irqs(1UL << irq); +	if ((unsigned long)irq_data_get_irq_chip_data(d) != IS_HW_CLEARED) +		clear_irqs(1UL << d->irq);  }  /*   * For per-cpu interrupts, we need to avoid unmasking any interrupts   * that we disabled via disable_percpu_irq().   */ -static void tile_irq_chip_eoi(unsigned int irq) +static void tile_irq_chip_eoi(struct irq_data *d)  { -	if (!(__get_cpu_var(irq_disable_mask) & (1UL << irq))) -		unmask_irqs(1UL << irq); +	if (!(__get_cpu_var(irq_disable_mask) & (1UL << d->irq))) +		unmask_irqs(1UL << d->irq);  }  static struct irq_chip tile_irq_chip = {  	.name = "tile_irq_chip", -	.ack = tile_irq_chip_ack, -	.eoi = tile_irq_chip_eoi, -	.mask = tile_irq_chip_mask, -	.unmask = tile_irq_chip_unmask, +	.irq_enable = tile_irq_chip_enable, +	.irq_disable = tile_irq_chip_disable, +	.irq_ack = tile_irq_chip_ack, +	.irq_eoi = tile_irq_chip_eoi, +	.irq_mask = tile_irq_chip_mask, +	.irq_unmask = tile_irq_chip_unmask,  };  void __init init_IRQ(void) @@ -220,7 +216,7 @@ void __init init_IRQ(void)  	ipi_init();  } -void __cpuinit setup_irq_regs(void) +void setup_irq_regs(void)  {  	/* Enable interrupt delivery. */  	unmask_irqs(~0UL); @@ -233,7 +229,7 @@ void tile_irq_activate(unsigned int irq, int tile_irq_type)  {  	/*  	 * We use handle_level_irq() by default because the pending -	 * interrupt vector (whether modeled by the HV on TILE64 and +	 * interrupt vector (whether modeled by the HV on  	 * TILEPro or implemented in hardware on TILE-Gx) has  	 * level-style semantics for each bit.  An interrupt fires  	 * whenever a bit is high, not just at edges. @@ -241,14 +237,14 @@ void tile_irq_activate(unsigned int irq, int tile_irq_type)  	irq_flow_handler_t handle = handle_level_irq;  	if (tile_irq_type == TILE_IRQ_PERCPU)  		handle = handle_percpu_irq; -	set_irq_chip_and_handler(irq, &tile_irq_chip, handle); +	irq_set_chip_and_handler(irq, &tile_irq_chip, handle);  	/*  	 * Flag interrupts that are hardware-cleared so that ack()  	 * won't clear them.  	 */  	if (tile_irq_type == TILE_IRQ_HW_CLEAR) -		set_irq_chip_data(irq, (void *)IS_HW_CLEARED); +		irq_set_chip_data(irq, (void *)IS_HW_CLEARED);  }  EXPORT_SYMBOL(tile_irq_activate); @@ -259,76 +255,27 @@ void ack_bad_irq(unsigned int irq)  }  /* - * Generic, controller-independent functions: + * /proc/interrupts printing:   */ - -int show_interrupts(struct seq_file *p, void *v) +int arch_show_interrupts(struct seq_file *p, int prec)  { -	int i = *(loff_t *) v, j; -	struct irqaction *action; -	unsigned long flags; - -	if (i == 0) { -		seq_printf(p, "           "); -		for (j = 0; j < NR_CPUS; j++) -			if (cpu_online(j)) -				seq_printf(p, "CPU%-8d", j); -		seq_putc(p, '\n'); -	} - -	if (i < NR_IRQS) { -		raw_spin_lock_irqsave(&irq_desc[i].lock, flags); -		action = irq_desc[i].action; -		if (!action) -			goto skip; -		seq_printf(p, "%3d: ", i); -#ifndef CONFIG_SMP -		seq_printf(p, "%10u ", kstat_irqs(i)); -#else -		for_each_online_cpu(j) -			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); -#endif -		seq_printf(p, " %14s", irq_desc[i].chip->name); -		seq_printf(p, "  %s", action->name); +#ifdef CONFIG_PERF_EVENTS +	int i; -		for (action = action->next; action; action = action->next) -			seq_printf(p, ", %s", action->name); +	seq_printf(p, "%*s: ", prec, "PMI"); -		seq_putc(p, '\n'); -skip: -		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); -	} +	for_each_online_cpu(i) +		seq_printf(p, "%10llu ", per_cpu(perf_irqs, i)); +	seq_puts(p, "  perf_events\n"); +#endif  	return 0;  }  #if CHIP_HAS_IPI() -int create_irq(void) +int arch_setup_hwirq(unsigned int irq, int node)  { -	unsigned long flags; -	int result; - -	spin_lock_irqsave(&available_irqs_lock, flags); -	if (available_irqs == 0) -		result = -ENOMEM; -	else { -		result = __ffs(available_irqs); -		available_irqs &= ~(1UL << result); -		dynamic_irq_init(result); -	} -	spin_unlock_irqrestore(&available_irqs_lock, flags); - -	return result; +	return irq >= NR_IRQS ? -EINVAL : 0;  } -EXPORT_SYMBOL(create_irq); -void destroy_irq(unsigned int irq) -{ -	unsigned long flags; - -	spin_lock_irqsave(&available_irqs_lock, flags); -	available_irqs |= (1UL << irq); -	dynamic_irq_cleanup(irq); -	spin_unlock_irqrestore(&available_irqs_lock, flags); -} -EXPORT_SYMBOL(destroy_irq); +void arch_teardown_hwirq(unsigned int irq) { }  #endif  | 
