diff options
| author | Ralf Baechle <ralf@linux-mips.org> | 2005-03-21 18:59:38 +0000 | 
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 19:30:59 +0100 | 
| commit | 4f12bfe5a498747a9a66f135a67aa8e1caa819dc (patch) | |
| tree | f358bd77f56b4014c1e5a9b5804995fd521c7853 /arch/mips/sgi-ip27/ip27-irq.c | |
| parent | 6cbe0631591ca45177d52364dec81cdfba19fec0 (diff) | |
| download | linux-4f12bfe5a498747a9a66f135a67aa8e1caa819dc.tar.bz2 | |
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[];  static inline int alloc_level(int cpu, int irq)  { +	struct hub_data *hub = hub_data(cpu_to_node(cpu));  	struct slice_data *si = cpu_data[cpu].data; -	int level;				/* pre-allocated entries */ +	int level; -	level = find_first_zero_bit(si->irq_alloc_mask, LEVELS_PER_SLICE); +	level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE);  	if (level >= LEVELS_PER_SLICE)  		panic("Cpu %d flooded with devices\n", cpu); -	__set_bit(level, si->irq_alloc_mask); +	__set_bit(level, hub->irq_alloc_mask);  	si->level_to_irq[level] = irq;  	return level; @@ -216,9 +217,11 @@ static int intr_connect_level(int cpu, int bit)  {  	nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));  	struct slice_data *si = cpu_data[cpu].data; +	unsigned long flags; -	__set_bit(bit, si->irq_enable_mask); +	set_bit(bit, si->irq_enable_mask); +	local_irq_save(flags);  	if (!cputoslice(cpu)) {  		REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]);  		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)  		REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]);  		REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]);  	} +	local_irq_restore(flags);  	return 0;  } @@ -235,7 +239,7 @@ static int intr_disconnect_level(int cpu, int bit)  	nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));  	struct slice_data *si = cpu_data[cpu].data; -	__clear_bit(bit, si->irq_enable_mask); +	clear_bit(bit, si->irq_enable_mask);  	if (!cputoslice(cpu)) {  		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)  static void shutdown_bridge_irq(unsigned int irq)  {  	struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); +	struct hub_data *hub = hub_data(cpu_to_node(bc->irq_cpu));  	bridge_t *bridge = bc->base;  	struct slice_data *si = cpu_data[bc->irq_cpu].data;  	int pin, swlevel; @@ -313,7 +318,7 @@ static void shutdown_bridge_irq(unsigned int irq)  	swlevel = find_level(&cpu, irq);  	intr_disconnect_level(cpu, swlevel); -	__clear_bit(swlevel, si->irq_alloc_mask); +	__clear_bit(swlevel, hub->irq_alloc_mask);  	si->level_to_irq[swlevel] = -1;  	bridge->b_int_enable &= ~(1 << pin); @@ -433,25 +438,24 @@ void install_ipi(void)  	int slice = LOCAL_HUB_L(PI_CPU_NUM);  	int cpu = smp_processor_id();  	struct slice_data *si = cpu_data[cpu].data; -	hubreg_t mask, set; +	struct hub_data *hub = hub_data(cpu_to_node(cpu)); +	int resched, call; + +	resched = CPU_RESCHED_A_IRQ + slice; +	__set_bit(resched, hub->irq_alloc_mask); +	__set_bit(resched, si->irq_enable_mask); +	LOCAL_HUB_CLR_INTR(resched); + +	call = CPU_CALL_A_IRQ + slice; +	__set_bit(call, hub->irq_alloc_mask); +	__set_bit(call, si->irq_enable_mask); +	LOCAL_HUB_CLR_INTR(call);  	if (slice == 0) { -		LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); -		LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); -		mask = LOCAL_HUB_L(PI_INT_MASK0_A);	/* Slice A */ -		set = (1UL << CPU_RESCHED_A_IRQ) | (1UL << CPU_CALL_A_IRQ); -		mask |= set; -		si->irq_enable_mask[0] |= set; -		si->irq_alloc_mask[0] |= set; -		LOCAL_HUB_S(PI_INT_MASK0_A, mask); +		LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]); +		LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]);  	} else { -		LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); -		LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); -		mask = LOCAL_HUB_L(PI_INT_MASK0_B);	/* Slice B */ -		set = (1UL << CPU_RESCHED_B_IRQ) | (1UL << CPU_CALL_B_IRQ); -		mask |= set; -		si->irq_enable_mask[1] |= set; -		si->irq_alloc_mask[1] |= set; -		LOCAL_HUB_S(PI_INT_MASK0_B, mask); +		LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]); +		LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]);  	}  } |