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
- Lines: 291
- Date:
Mon Dec 6 17:15:53 1999
- Orig file:
v2.3.29/linux/arch/alpha/kernel/irq.c
- Orig date:
Tue Aug 31 17:29:12 1999
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)