aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-04-19 19:41:21 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-21 18:31:29 -0400
commitd61a38b2ced149c00898833ccd3ea0433db8ae7d (patch)
treea1bbd0305469af7d5006b2eb85f6c34dfaccb9a8 /arch
parent6baa9b20a68a88c2fd751cbe8d7652009379351b (diff)
sparc32, leon: must protect IRQ controller register with spinlock
The LEON interrupt controller has one single mask register for all IRQs per CPU, even though the genirq layer protects us from accessing the same IRQ at the same time other IRQs share the same mask register and may thus interfere. Some other IRQ controllers has a mask register or similar per IRQ instead which makes spinlocks unncessary. Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/kernel/leon_kernel.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index 8591cf124ec..390e4696276 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -31,6 +31,7 @@ int leondebug_irq_disable;
31int leon_debug_irqout; 31int leon_debug_irqout;
32static int dummy_master_l10_counter; 32static int dummy_master_l10_counter;
33unsigned long amba_system_id; 33unsigned long amba_system_id;
34static DEFINE_SPINLOCK(leon_irq_lock);
34 35
35unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ 36unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
36unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ 37unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
@@ -88,10 +89,10 @@ static void leon_unmask_irq(struct irq_data *data)
88 unsigned long mask, flags; 89 unsigned long mask, flags;
89 90
90 mask = (unsigned long)data->chip_data; 91 mask = (unsigned long)data->chip_data;
91 local_irq_save(flags); 92 spin_lock_irqsave(&leon_irq_lock, flags);
92 LEON3_BYPASS_STORE_PA(LEON_IMASK, 93 LEON3_BYPASS_STORE_PA(LEON_IMASK,
93 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask))); 94 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) | (mask)));
94 local_irq_restore(flags); 95 spin_unlock_irqrestore(&leon_irq_lock, flags);
95} 96}
96 97
97static void leon_mask_irq(struct irq_data *data) 98static void leon_mask_irq(struct irq_data *data)
@@ -99,11 +100,10 @@ static void leon_mask_irq(struct irq_data *data)
99 unsigned long mask, flags; 100 unsigned long mask, flags;
100 101
101 mask = (unsigned long)data->chip_data; 102 mask = (unsigned long)data->chip_data;
102 local_irq_save(flags); 103 spin_lock_irqsave(&leon_irq_lock, flags);
103 LEON3_BYPASS_STORE_PA(LEON_IMASK, 104 LEON3_BYPASS_STORE_PA(LEON_IMASK,
104 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask))); 105 (LEON3_BYPASS_LOAD_PA(LEON_IMASK) & ~(mask)));
105 local_irq_restore(flags); 106 spin_unlock_irqrestore(&leon_irq_lock, flags);
106
107} 107}
108 108
109static unsigned int leon_startup_irq(struct irq_data *data) 109static unsigned int leon_startup_irq(struct irq_data *data)
@@ -383,10 +383,10 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
383{ 383{
384 unsigned long mask, flags, *addr; 384 unsigned long mask, flags, *addr;
385 mask = get_irqmask(irq_nr); 385 mask = get_irqmask(irq_nr);
386 local_irq_save(flags); 386 spin_lock_irqsave(&leon_irq_lock, flags);
387 addr = (unsigned long *)&(leon3_irqctrl_regs->mask[cpu]); 387 addr = (unsigned long *)&(leon3_irqctrl_regs->mask[cpu]);
388 LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | (mask))); 388 LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | (mask)));
389 local_irq_restore(flags); 389 spin_unlock_irqrestore(&leon_irq_lock, flags);
390} 390}
391 391
392#endif 392#endif