diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2005-03-21 13:59:38 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 14:30:59 -0400 |
commit | 4f12bfe5a498747a9a66f135a67aa8e1caa819dc (patch) | |
tree | f358bd77f56b4014c1e5a9b5804995fd521c7853 /arch/mips/sgi-ip27/ip27-irq.c | |
parent | 6cbe0631591ca45177d52364dec81cdfba19fec0 (diff) |
HUB interrupts are allocated per node, not per slice. Make manipulation
of the interrupt mask register atomic by disabling interrupts.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/sgi-ip27/ip27-irq.c')
-rw-r--r-- | arch/mips/sgi-ip27/ip27-irq.c | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 61817a18aed2..5d374e6ce63d 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c | |||
@@ -74,14 +74,15 @@ extern int irq_to_slot[]; | |||
74 | 74 | ||
75 | static inline int alloc_level(int cpu, int irq) | 75 | static inline int alloc_level(int cpu, int irq) |
76 | { | 76 | { |
77 | struct hub_data *hub = hub_data(cpu_to_node(cpu)); | ||
77 | struct slice_data *si = cpu_data[cpu].data; | 78 | struct slice_data *si = cpu_data[cpu].data; |
78 | int level; /* pre-allocated entries */ | 79 | int level; |
79 | 80 | ||
80 | level = find_first_zero_bit(si->irq_alloc_mask, LEVELS_PER_SLICE); | 81 | level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); |
81 | if (level >= LEVELS_PER_SLICE) | 82 | if (level >= LEVELS_PER_SLICE) |
82 | panic("Cpu %d flooded with devices\n", cpu); | 83 | panic("Cpu %d flooded with devices\n", cpu); |
83 | 84 | ||
84 | __set_bit(level, si->irq_alloc_mask); | 85 | __set_bit(level, hub->irq_alloc_mask); |
85 | si->level_to_irq[level] = irq; | 86 | si->level_to_irq[level] = irq; |
86 | 87 | ||
87 | return level; | 88 | return level; |
@@ -216,9 +217,11 @@ static int intr_connect_level(int cpu, int bit) | |||
216 | { | 217 | { |
217 | nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); | 218 | nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); |
218 | struct slice_data *si = cpu_data[cpu].data; | 219 | struct slice_data *si = cpu_data[cpu].data; |
220 | unsigned long flags; | ||
219 | 221 | ||
220 | __set_bit(bit, si->irq_enable_mask); | 222 | set_bit(bit, si->irq_enable_mask); |
221 | 223 | ||
224 | local_irq_save(flags); | ||
222 | if (!cputoslice(cpu)) { | 225 | if (!cputoslice(cpu)) { |
223 | REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); | 226 | REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); |
224 | REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); | 227 | REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); |
@@ -226,6 +229,7 @@ static int intr_connect_level(int cpu, int bit) | |||
226 | REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); | 229 | REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); |
227 | REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); | 230 | REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); |
228 | } | 231 | } |
232 | local_irq_restore(flags); | ||
229 | 233 | ||
230 | return 0; | 234 | return 0; |
231 | } | 235 | } |
@@ -235,7 +239,7 @@ static int intr_disconnect_level(int cpu, int bit) | |||
235 | nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); | 239 | nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); |
236 | struct slice_data *si = cpu_data[cpu].data; | 240 | struct slice_data *si = cpu_data[cpu].data; |
237 | 241 | ||
238 | __clear_bit(bit, si->irq_enable_mask); | 242 | clear_bit(bit, si->irq_enable_mask); |
239 | 243 | ||
240 | if (!cputoslice(cpu)) { | 244 | if (!cputoslice(cpu)) { |
241 | REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); | 245 | REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); |
@@ -298,6 +302,7 @@ static unsigned int startup_bridge_irq(unsigned int irq) | |||
298 | static void shutdown_bridge_irq(unsigned int irq) | 302 | static void shutdown_bridge_irq(unsigned int irq) |
299 | { | 303 | { |
300 | struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); | 304 | struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); |
305 | struct hub_data *hub = hub_data(cpu_to_node(bc->irq_cpu)); | ||
301 | bridge_t *bridge = bc->base; | 306 | bridge_t *bridge = bc->base; |
302 | struct slice_data *si = cpu_data[bc->irq_cpu].data; | 307 | struct slice_data *si = cpu_data[bc->irq_cpu].data; |
303 | int pin, swlevel; | 308 | int pin, swlevel; |
@@ -313,7 +318,7 @@ static void shutdown_bridge_irq(unsigned int irq) | |||
313 | swlevel = find_level(&cpu, irq); | 318 | swlevel = find_level(&cpu, irq); |
314 | intr_disconnect_level(cpu, swlevel); | 319 | intr_disconnect_level(cpu, swlevel); |
315 | 320 | ||
316 | __clear_bit(swlevel, si->irq_alloc_mask); | 321 | __clear_bit(swlevel, hub->irq_alloc_mask); |
317 | si->level_to_irq[swlevel] = -1; | 322 | si->level_to_irq[swlevel] = -1; |
318 | 323 | ||
319 | bridge->b_int_enable &= ~(1 << pin); | 324 | bridge->b_int_enable &= ~(1 << pin); |
@@ -433,25 +438,24 @@ void install_ipi(void) | |||
433 | int slice = LOCAL_HUB_L(PI_CPU_NUM); | 438 | int slice = LOCAL_HUB_L(PI_CPU_NUM); |
434 | int cpu = smp_processor_id(); | 439 | int cpu = smp_processor_id(); |
435 | struct slice_data *si = cpu_data[cpu].data; | 440 | struct slice_data *si = cpu_data[cpu].data; |
436 | hubreg_t mask, set; | 441 | struct hub_data *hub = hub_data(cpu_to_node(cpu)); |
442 | int resched, call; | ||
443 | |||
444 | resched = CPU_RESCHED_A_IRQ + slice; | ||
445 | __set_bit(resched, hub->irq_alloc_mask); | ||
446 | __set_bit(resched, si->irq_enable_mask); | ||
447 | LOCAL_HUB_CLR_INTR(resched); | ||
448 | |||
449 | call = CPU_CALL_A_IRQ + slice; | ||
450 | __set_bit(call, hub->irq_alloc_mask); | ||
451 | __set_bit(call, si->irq_enable_mask); | ||
452 | LOCAL_HUB_CLR_INTR(call); | ||
437 | 453 | ||
438 | if (slice == 0) { | 454 | if (slice == 0) { |
439 | LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); | 455 | LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]); |
440 | LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); | 456 | LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]); |
441 | mask = LOCAL_HUB_L(PI_INT_MASK0_A); /* Slice A */ | ||
442 | set = (1UL << CPU_RESCHED_A_IRQ) | (1UL << CPU_CALL_A_IRQ); | ||
443 | mask |= set; | ||
444 | si->irq_enable_mask[0] |= set; | ||
445 | si->irq_alloc_mask[0] |= set; | ||
446 | LOCAL_HUB_S(PI_INT_MASK0_A, mask); | ||
447 | } else { | 457 | } else { |
448 | LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); | 458 | LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]); |
449 | LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); | 459 | LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]); |
450 | mask = LOCAL_HUB_L(PI_INT_MASK0_B); /* Slice B */ | ||
451 | set = (1UL << CPU_RESCHED_B_IRQ) | (1UL << CPU_CALL_B_IRQ); | ||
452 | mask |= set; | ||
453 | si->irq_enable_mask[1] |= set; | ||
454 | si->irq_alloc_mask[1] |= set; | ||
455 | LOCAL_HUB_S(PI_INT_MASK0_B, mask); | ||
456 | } | 460 | } |
457 | } | 461 | } |