patch-2.3.30 linux/arch/alpha/kernel/irq.c

Next file: linux/arch/alpha/kernel/irq_impl.h
Previous file: linux/arch/alpha/kernel/fpreg.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.29/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
@@ -22,15 +22,15 @@
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/bitops.h>
 #include <asm/machvec.h>
+#include <asm/spinlock.h>
 
 #include "proto.h"
-#include "irq_impl.h"
 
 #define vulp	volatile unsigned long *
 #define vuip	volatile unsigned int *
@@ -42,8 +42,8 @@
 int __local_bh_count;
 #endif
 
-#if NR_IRQS > 64
-#  error Unable to handle more than 64 irq levels.
+#if NR_IRQS > 128
+#  error Unable to handle more than 128 irq levels.
 #endif
 
 #ifdef CONFIG_ALPHA_GENERIC
@@ -60,7 +60,8 @@
 /*
  * Shadow-copy of masked interrupts.
  */
-unsigned long alpha_irq_mask = ~0UL;
+
+unsigned long _alpha_irq_masks[2] = { ~0UL, ~0UL };
 
 /*
  * The ack_irq routine used by 80% of the systems.
@@ -110,6 +111,8 @@
 # define IACK_SC	TSUNAMI_IACK_SC
 #elif defined(CONFIG_ALPHA_POLARIS)
 # define IACK_SC	POLARIS_IACK_SC
+#elif defined(CONFIG_ALPHA_IRONGATE)
+# define IACK_SC        IRONGATE_IACK_SC
 #else
   /* This is bogus but necessary to get it to compile on all platforms. */
 # define IACK_SC	1L
@@ -179,19 +182,22 @@
  */
 
 static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction *irq_action[NR_IRQS];
+spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = {0,} };
 
 
 static inline void
 mask_irq(unsigned long irq)
 {
-	alpha_mv.update_irq_hw(irq, alpha_irq_mask |= 1UL << irq, 0);
+	set_bit(irq, _alpha_irq_masks);
+	alpha_mv.update_irq_hw(irq, alpha_irq_mask, 0);
 }
 
 static inline void
 unmask_irq(unsigned long irq)
 {
-	alpha_mv.update_irq_hw(irq, alpha_irq_mask &= ~(1UL << irq), 1);
+	clear_bit(irq, _alpha_irq_masks);
+	alpha_mv.update_irq_hw(irq, alpha_irq_mask, 1);
 }
 
 void
@@ -225,12 +231,7 @@
 int
 check_irq(unsigned int irq)
 {
-	struct irqaction **p;
-
-	p = irq_action + irq;
-	if (*p == NULL)
-		return 0;
-	return -EBUSY;
+	return irq_desc[irq].action ? -EBUSY : 0;
 }
 
 int
@@ -248,7 +249,7 @@
 	if (!handler)
 		return -EINVAL;
 
-	p = irq_action + irq;
+	p = &irq_desc[irq].action;
 	action = *p;
 	if (action) {
 		/* Can't share interrupts unless both agree to */
@@ -309,14 +310,14 @@
 		printk("Trying to free reserved IRQ %d\n", irq);
 		return;
 	}
-	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+	for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
 		if (action->dev_id != dev_id)
 			continue;
 
 		/* Found it - now free it */
 		save_and_cli(flags);
 		*p = action->next;
-		if (!irq[irq_action])
+		if (!irq_desc[irq].action)
 			mask_irq(irq);
 		restore_flags(flags);
 		kfree(action);
@@ -339,7 +340,7 @@
 #endif
 
 	for (i = 0; i < NR_IRQS; i++) {
-		action = irq_action[i];
+		action = irq_desc[i].action;
 		if (!action) 
 			continue;
 		p += sprintf(p, "%3d: ",i);
@@ -387,8 +388,6 @@
 
 static void show(char * str, void *where);
 
-#define SYNC_OTHER_CPUS(x)	udelay((x)+1);
-
 static inline void
 wait_on_irq(int cpu, void *where)
 {
@@ -409,7 +408,6 @@
 
 		/* Duh, we have to loop. Release the lock to avoid deadlocks */
 		spin_unlock(&global_irq_lock);
-		mb();
 
 		for (;;) {
 			if (!--count) {
@@ -417,7 +415,7 @@
 				count = MAXCOUNT;
 			}
 			__sti();
-			SYNC_OTHER_CPUS(cpu);
+			udelay(1); /* make sure to run pending irqs */
 			__cli();
 
 			if (atomic_read(&global_irq_count))
@@ -437,17 +435,13 @@
 get_irqlock(int cpu, void* where)
 {
 	if (!spin_trylock(&global_irq_lock)) {
-		/* do we already hold the lock? */
-		if (cpu == global_irq_holder) {
-#if 0
-			printk("get_irqlock: already held at %08lx\n",
-			       previous_irqholder);
-#endif
+		/* Do we already hold the lock?  */
+		if (cpu == global_irq_holder)
 			return;
-		}
-		/* Uhhuh.. Somebody else got it. Wait.. */
+		/* Uhhuh.. Somebody else got it.  Wait.  */
 		spin_lock(&global_irq_lock);
 	}
+
 	/*
 	 * Ok, we got the lock bit.
 	 * But that's actually just the easy part.. Now
@@ -543,63 +537,6 @@
         }
 }
 
-#undef INIT_STUCK
-#define INIT_STUCK (1<<26)
-
-#undef STUCK
-#define STUCK							\
-  if (!--stuck) {						\
-    printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",	\
-	   irq, cpu, global_irq_holder);			\
-    stuck = INIT_STUCK;						\
-  }
-
-#undef VERBOSE_IRQLOCK_DEBUGGING
-
-void
-irq_enter(int cpu, int irq)
-{
-#ifdef VERBOSE_IRQLOCK_DEBUGGING
-	extern void smp_show_backtrace_all_cpus(void);
-#endif
-	int stuck = INIT_STUCK;
-
-	hardirq_enter(cpu, irq);
-	barrier();
-	while (spin_is_locked(&global_irq_lock)) {
-		if (cpu == global_irq_holder) {
-			int globl_locked = spin_is_locked(&global_irq_lock);
-			int globl_icount = atomic_read(&global_irq_count);
-			int local_count = local_irq_count(cpu);
-
-			/* It is very important that we load the state
-			   variables before we do the first call to
-			   printk() as printk() could end up changing
-			   them...  */
-
-			printk("CPU[%d]: where [%p] glocked[%d] gicnt[%d]"
-			       " licnt[%d]\n",
-			       cpu, previous_irqholder, globl_locked,
-			       globl_icount, local_count);
-#ifdef VERBOSE_IRQLOCK_DEBUGGING
-			printk("Performing backtrace on all CPUs,"
-			       " write this down!\n");
-			smp_show_backtrace_all_cpus();
-#endif
-			break;
-		}
-		STUCK;
-		barrier();
-	}
-}
-
-void
-irq_exit(int cpu, int irq)
-{
-	hardirq_exit(cpu, irq);
-	release_irqlock(cpu);
-}
-
 static void
 show(char * str, void *where)
 {
@@ -700,12 +637,6 @@
 	}
 #endif
 }
-
-#else /* !__SMP__ */
-
-#define irq_enter(cpu, irq)	(++local_irq_count(cpu))
-#define irq_exit(cpu, irq)	(--local_irq_count(cpu))
-
 #endif /* __SMP__ */
 
 static void
@@ -722,7 +653,7 @@
 	printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
 	printk("Expecting: ");
 	for (i = 0; i < ACTUAL_NR_IRQS; i++)
-		if ((action = irq_action[i]))
+		if ((action = irq_desc[i].action))
 			while (action->handler) {
 				printk("[%s:%d] ", action->name, i);
 				action = action->next;
@@ -776,7 +707,7 @@
 
 	irq_enter(cpu, irq);
 	kstat.irqs[cpu][irq] += 1;
-	action = irq_action[irq];
+	action = irq_desc[irq].action;
 
 	/*
 	 * For normal interrupts, we mask it out, and then ACK it.
@@ -819,11 +750,13 @@
 	unsigned long delay;
 	unsigned int i;
 
-	for (i = ACTUAL_NR_IRQS - 1; i > 0; i--) {
+	/* Handle only the first 64 IRQs here.  This is enough for
+	   [E]ISA, which is the only thing that needs probing anyway.  */
+	for (i = (ACTUAL_NR_IRQS - 1) & 63; i > 0; i--) {
 		if (!(PROBE_MASK & (1UL << i))) {
 			continue;
 		}
-		action = irq_action[i];
+		action = irq_desc[i].action;
 		if (!action) {
 			enable_irq(i);
 			irqs |= (1UL << i);
@@ -852,6 +785,8 @@
 {
 	int i;
 	
+	/* Handle only the first 64 IRQs here.  This is enough for
+	   [E]ISA, which is the only thing that needs probing anyway.  */
         irqs &= alpha_irq_mask;
 	if (!irqs)
 		return 0;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)