irq.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * arch/ppc/kernel/irq.c
  3. *
  4. * Derived from arch/i386/kernel/irq.c
  5. * Copyright (C) 1992 Linus Torvalds
  6. * Adapted from arch/i386 by Gary Thomas
  7. * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  8. * Updated and modified by Cort Dougan <cort@fsmlabs.com>
  9. * Copyright (C) 1996-2001 Cort Dougan
  10. * Adapted for Power Macintosh by Paul Mackerras
  11. * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
  12. * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
  13. *
  14. * This file contains the code used by various IRQ handling routines:
  15. * asking for different IRQ's should be done through these routines
  16. * instead of just grabbing them. Thus setups with different IRQ numbers
  17. * shouldn't result in any weird surprises, and installing new handlers
  18. * should be easier.
  19. *
  20. * The MPC8xx has an interrupt mask in the SIU. If a bit is set, the
  21. * interrupt is _enabled_. As expected, IRQ0 is bit 0 in the 32-bit
  22. * mask register (of which only 16 are defined), hence the weird shifting
  23. * and complement of the cached_irq_mask. I want to be able to stuff
  24. * this right into the SIU SMASK register.
  25. * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx
  26. * to reduce code space and undefined function references.
  27. */
  28. #include <linux/errno.h>
  29. #include <linux/module.h>
  30. #include <linux/threads.h>
  31. #include <linux/kernel_stat.h>
  32. #include <linux/signal.h>
  33. #include <linux/sched.h>
  34. #include <linux/ptrace.h>
  35. #include <linux/ioport.h>
  36. #include <linux/interrupt.h>
  37. #include <linux/timex.h>
  38. #include <linux/config.h>
  39. #include <linux/init.h>
  40. #include <linux/slab.h>
  41. #include <linux/pci.h>
  42. #include <linux/delay.h>
  43. #include <linux/irq.h>
  44. #include <linux/proc_fs.h>
  45. #include <linux/random.h>
  46. #include <linux/seq_file.h>
  47. #include <linux/cpumask.h>
  48. #include <linux/profile.h>
  49. #include <linux/bitops.h>
  50. #include <asm/uaccess.h>
  51. #include <asm/system.h>
  52. #include <asm/io.h>
  53. #include <asm/pgtable.h>
  54. #include <asm/irq.h>
  55. #include <asm/cache.h>
  56. #include <asm/prom.h>
  57. #include <asm/ptrace.h>
  58. #define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
  59. extern atomic_t ipi_recv;
  60. extern atomic_t ipi_sent;
  61. #define MAXCOUNT 10000000
  62. int ppc_spurious_interrupts = 0;
  63. struct irqaction *ppc_irq_action[NR_IRQS];
  64. unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
  65. unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
  66. atomic_t ppc_n_lost_interrupts;
  67. #ifdef CONFIG_TAU_INT
  68. extern int tau_initialized;
  69. extern int tau_interrupts(int);
  70. #endif
  71. int show_interrupts(struct seq_file *p, void *v)
  72. {
  73. int i = *(loff_t *) v, j;
  74. struct irqaction * action;
  75. unsigned long flags;
  76. if (i == 0) {
  77. seq_puts(p, " ");
  78. for (j=0; j<NR_CPUS; j++)
  79. if (cpu_online(j))
  80. seq_printf(p, "CPU%d ", j);
  81. seq_putc(p, '\n');
  82. }
  83. if (i < NR_IRQS) {
  84. spin_lock_irqsave(&irq_desc[i].lock, flags);
  85. action = irq_desc[i].action;
  86. if ( !action || !action->handler )
  87. goto skip;
  88. seq_printf(p, "%3d: ", i);
  89. #ifdef CONFIG_SMP
  90. for (j = 0; j < NR_CPUS; j++)
  91. if (cpu_online(j))
  92. seq_printf(p, "%10u ",
  93. kstat_cpu(j).irqs[i]);
  94. #else
  95. seq_printf(p, "%10u ", kstat_irqs(i));
  96. #endif /* CONFIG_SMP */
  97. if (irq_desc[i].handler)
  98. seq_printf(p, " %s ", irq_desc[i].handler->typename);
  99. else
  100. seq_puts(p, " None ");
  101. seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge ");
  102. seq_printf(p, " %s", action->name);
  103. for (action = action->next; action; action = action->next)
  104. seq_printf(p, ", %s", action->name);
  105. seq_putc(p, '\n');
  106. skip:
  107. spin_unlock_irqrestore(&irq_desc[i].lock, flags);
  108. } else if (i == NR_IRQS) {
  109. #ifdef CONFIG_TAU_INT
  110. if (tau_initialized){
  111. seq_puts(p, "TAU: ");
  112. for (j = 0; j < NR_CPUS; j++)
  113. if (cpu_online(j))
  114. seq_printf(p, "%10u ", tau_interrupts(j));
  115. seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n");
  116. }
  117. #endif
  118. #ifdef CONFIG_SMP
  119. /* should this be per processor send/receive? */
  120. seq_printf(p, "IPI (recv/sent): %10u/%u\n",
  121. atomic_read(&ipi_recv), atomic_read(&ipi_sent));
  122. #endif
  123. seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
  124. }
  125. return 0;
  126. }
  127. void do_IRQ(struct pt_regs *regs)
  128. {
  129. int irq, first = 1;
  130. irq_enter();
  131. /*
  132. * Every platform is required to implement ppc_md.get_irq.
  133. * This function will either return an irq number or -1 to
  134. * indicate there are no more pending. But the first time
  135. * through the loop this means there wasn't and IRQ pending.
  136. * The value -2 is for buggy hardware and means that this IRQ
  137. * has already been handled. -- Tom
  138. */
  139. while ((irq = ppc_md.get_irq(regs)) >= 0) {
  140. __do_IRQ(irq, regs);
  141. first = 0;
  142. }
  143. if (irq != -2 && first)
  144. /* That's not SMP safe ... but who cares ? */
  145. ppc_spurious_interrupts++;
  146. irq_exit();
  147. }
  148. void __init init_IRQ(void)
  149. {
  150. ppc_md.init_IRQ();
  151. }