patch-2.1.36 linux/arch/sparc/kernel/irq.c
Next file: linux/arch/sparc/kernel/ptrace.c
Previous file: linux/arch/sparc/kernel/head.S
Back to the patch index
Back to the overall index
- Lines: 385
- Date:
Tue Apr 22 22:39:12 1997
- Orig file:
v2.1.35/linux/arch/sparc/kernel/irq.c
- Orig date:
Mon Apr 14 16:28:07 1997
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.66 1997/04/14 05:38:21 davem Exp $
+/* $Id: irq.c,v 1.72 1997/04/20 11:41:26 ecd Exp $
* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
* Sparc the IRQ's are basically 'cast in stone'
* and you are supposed to probe the prom's device
@@ -41,6 +41,10 @@
#include <asm/hardirq.h>
#include <asm/softirq.h>
+#ifdef __SMP_PROF__
+extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS];
+#endif
+
/*
* Dave Redman (djhr@tadpole.co.uk)
*
@@ -71,11 +75,11 @@
void (*disable_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
void (*enable_pil_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
void (*disable_pil_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
-void (*clear_clock_irq)( void ) = irq_panic;
-void (*clear_profile_irq)( void ) = irq_panic;
-void (*load_profile_irq)( unsigned int ) = (void (*)(unsigned int)) irq_panic;
-void (*init_timers)( void (*)(int, void *,struct pt_regs *)) =
- (void (*)( void (*)(int, void *,struct pt_regs *))) irq_panic;
+void (*clear_clock_irq)(void) = irq_panic;
+void (*clear_profile_irq)(int) = (void (*)(int)) irq_panic;
+void (*load_profile_irq)(int, unsigned int) = (void (*)(int, unsigned int)) irq_panic;
+void (*init_timers)(void (*)(int, void *,struct pt_regs *)) =
+ (void (*)(void (*)(int, void *,struct pt_regs *))) irq_panic;
#ifdef __SMP__
void (*set_cpu_int)(int, int);
@@ -128,6 +132,109 @@
return len;
}
+#ifdef __SMP_PROF__
+
+static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
+
+extern unsigned int prof_multiplier[NR_CPUS];
+extern unsigned int prof_counter[NR_CPUS];
+
+int get_smp_prof_list(char *buf) {
+ int i,j, len = 0;
+ struct irqaction * action;
+ unsigned long sum_spins = 0;
+ unsigned long sum_spins_syscall = 0;
+ unsigned long sum_spins_sys_idle = 0;
+ unsigned long sum_smp_idle_count = 0;
+ unsigned long sum_local_timer_ticks = 0;
+
+ for (i=0;i<smp_num_cpus;i++) {
+ int cpunum = cpu_logical_map[i];
+ sum_spins+=smp_spins[cpunum];
+ sum_spins_syscall+=smp_spins_syscall[cpunum];
+ sum_spins_sys_idle+=smp_spins_sys_idle[cpunum];
+ sum_smp_idle_count+=smp_idle_count[cpunum];
+ sum_local_timer_ticks+=smp_local_timer_ticks[cpunum];
+ }
+
+ len += sprintf(buf+len,"CPUS: %10i \n", smp_num_cpus);
+ len += sprintf(buf+len," SUM ");
+ for (i=0;i<smp_num_cpus;i++)
+ len += sprintf(buf+len," P%1d ",cpu_logical_map[i]);
+ len += sprintf(buf+len,"\n");
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ action = *(i + irq_action);
+ if (!action || !action->handler)
+ continue;
+ len += sprintf(buf+len, "%3d: %10d ",
+ i, kstat.interrupts[i]);
+ for (j=0;j<smp_num_cpus;j++)
+ len+=sprintf(buf+len, "%10d ",
+ int_count[cpu_logical_map[j]][i]);
+ len += sprintf(buf+len, "%c %s",
+ (action->flags & SA_INTERRUPT) ? '+' : ' ',
+ action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ",%s %s",
+ (action->flags & SA_INTERRUPT) ? " +" : "",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
+ }
+ len+=sprintf(buf+len, "LCK: %10lu",
+ sum_spins);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_spins[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," spins from int\n");
+
+ len+=sprintf(buf+len, "LCK: %10lu",
+ sum_spins_syscall);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_spins_syscall[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," spins from syscall\n");
+
+ len+=sprintf(buf+len, "LCK: %10lu",
+ sum_spins_sys_idle);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," spins from sysidle\n");
+ len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
+
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_idle_count[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," idle ticks\n");
+
+ len+=sprintf(buf+len,"TICK %10lu",sum_local_timer_ticks);
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10lu",smp_local_timer_ticks[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," local APIC timer ticks\n");
+
+ len+=sprintf(buf+len,"MULT: ");
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10u",prof_multiplier[cpu_logical_map[i]]);
+ len +=sprintf(buf+len," profiling multiplier\n");
+
+ len+=sprintf(buf+len,"COUNT: ");
+ for (i=0;i<smp_num_cpus;i++)
+ len+=sprintf(buf+len," %10u",prof_counter[cpu_logical_map[i]]);
+
+ len +=sprintf(buf+len," profiling counter\n");
+
+ len+=sprintf(buf+len, "IPI: %10lu received\n",
+ ipi_count);
+
+ return len;
+}
+#endif
+
void free_irq(unsigned int irq, void *dev_id)
{
struct irqaction * action;
@@ -185,7 +292,11 @@
/* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */
unsigned int local_irq_count[NR_CPUS];
-atomic_t __sparc_bh_counter;
+#ifdef __SMP__
+atomic_t __sparc_bh_counter = ATOMIC_INIT(0);
+#else
+int __sparc_bh_counter = 0;
+#endif
#ifdef __SMP__
/* SMP interrupt locking on Sparc. */
@@ -200,49 +311,10 @@
spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
/* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT;
-
-#define irq_active(cpu) \
- (atomic_read(&global_irq_count) != local_irq_count[cpu])
-
-static unsigned long previous_irqholder;
-
-#define INIT_STUCK 10000000
-
-#define STUCK \
-if (!--stuck) { \
- printk("wait_on_irq CPU#%d stuck at %08lx, waiting for [%08lx:%x] " \
- "(local=[%d(%x:%x:%x:%x)], global=[%d:%x]) ", \
- cpu, where, previous_irqholder, global_irq_holder, \
- local_count, local_irq_count[0], local_irq_count[1], \
- local_irq_count[2], local_irq_count[3], \
- atomic_read(&global_irq_count), global_irq_lock); \
- printk("g[%d:%x]\n", atomic_read(&global_irq_count), global_irq_lock); \
- stuck = INIT_STUCK; \
-}
-
-static inline void wait_on_irq(int cpu, unsigned long where)
-{
- int stuck = INIT_STUCK;
- int local_count = local_irq_count[cpu];
-
- while(local_count != atomic_read(&global_irq_count)) {
- atomic_sub(local_count, &global_irq_count);
- spin_unlock(&global_irq_lock);
- while(1) {
- STUCK;
- if(atomic_read(&global_irq_count))
- continue;
- if(global_irq_lock)
- continue;
- if(spin_trylock(&global_irq_lock))
- break;
- }
- atomic_add(local_count, &global_irq_count);
- }
-}
+atomic_t global_irq_count = ATOMIC_INIT(0);
/* There has to be a better way. */
+/* XXX Must write faster version in irqlock.S -DaveM */
void synchronize_irq(void)
{
int cpu = smp_processor_id();
@@ -259,123 +331,6 @@
}
}
-#undef INIT_STUCK
-#define INIT_STUCK 10000000
-
-#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;}
-
-static inline void get_irqlock(int cpu, unsigned long where)
-{
- int stuck = INIT_STUCK;
-
- if(!spin_trylock(&global_irq_lock)) {
- if((unsigned char) cpu == global_irq_holder)
- return;
- do {
- do {
- STUCK;
- barrier();
- } while(global_irq_lock);
- } while(!spin_trylock(&global_irq_lock));
- }
- wait_on_irq(cpu, where);
- global_irq_holder = cpu;
- previous_irqholder = where;
-}
-
-void __global_cli(void)
-{
- int cpu = smp_processor_id();
- unsigned long where;
-
- __asm__ __volatile__("mov %%i7, %0\n\t" : "=r" (where));
- __cli();
- get_irqlock(cpu, where);
-}
-
-void __global_sti(void)
-{
- release_irqlock(smp_processor_id());
- __sti();
-}
-
-/* Yes, I know this is broken, but for the time being...
- *
- * On Sparc we must differentiate between real local processor
- * interrupts being disabled and global interrupt locking, this
- * is so that interrupt handlers which call this stuff don't get
- * interrupts turned back on when restore_flags() runs because
- * our current drivers will be very surprised about this, yes I
- * know they need to be fixed... -DaveM
- */
-unsigned long __global_save_flags(void)
-{
- unsigned long flags, retval = 0;
-
- __save_flags(flags);
- if(global_irq_holder == (unsigned char) smp_processor_id())
- retval |= 1;
- if(flags & PSR_PIL)
- retval |= 2;
- return retval;
-}
-
-void __global_restore_flags(unsigned long flags)
-{
- if(flags & 1) {
- __global_cli();
- } else {
- release_irqlock(smp_processor_id());
-
- if(flags & 2)
- __cli();
- else
- __sti();
- }
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 200000000
-
-#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; \
-}
-
-static void irq_enter(int cpu, int irq)
-{
- extern void smp_irq_rotate(int cpu);
- int stuck = INIT_STUCK;
-
- smp_irq_rotate(cpu);
- hardirq_enter(cpu);
- while(global_irq_lock) {
- if((unsigned char) cpu == global_irq_holder) {
- printk("YEEEE Local interrupts enabled, global disabled\n");
- break;
- }
- STUCK;
- barrier();
- }
-}
-
-static void irq_exit(int cpu, int irq)
-{
- __cli();
- hardirq_exit(cpu);
- release_irqlock(cpu);
-}
-
-#else /* !__SMP__ */
-
-#define irq_enter(cpu, irq) (local_irq_count[cpu]++)
-#define irq_exit(cpu, irq) (local_irq_count[cpu]--)
-
#endif /* __SMP__ */
void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
@@ -406,9 +361,17 @@
struct irqaction * action;
unsigned int cpu_irq = irq & NR_IRQS;
int cpu = smp_processor_id();
+#ifdef __SMP__
+ extern void smp_irq_rotate(int cpu);
+#endif
disable_pil_irq(cpu_irq);
- irq_enter(cpu, irq);
+#ifdef __SMP__
+ /* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */
+ if(irq < 10)
+ smp_irq_rotate(cpu);
+#endif
+ irq_enter(cpu, cpu_irq);
action = *(cpu_irq + irq_action);
kstat.interrupts[cpu_irq]++;
do {
@@ -417,7 +380,7 @@
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
- irq_exit(cpu, irq);
+ irq_exit(cpu, cpu_irq);
enable_pil_irq(cpu_irq);
}
@@ -432,7 +395,7 @@
irq_enter(cpu, irq);
floppy_interrupt(irq, dev_id, regs);
irq_exit(cpu, irq);
- disable_pil_irq(irq);
+ enable_pil_irq(irq);
}
#endif
@@ -596,12 +559,12 @@
*/
unsigned long probe_irq_on(void)
{
- return 0;
+ return 0;
}
int probe_irq_off(unsigned long mask)
{
- return 0;
+ return 0;
}
/* djhr
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov