Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
irq_alpha.c
Go to the documentation of this file.
1 /*
2  * Alpha specific irq code.
3  */
4 
5 #include <linux/init.h>
6 #include <linux/sched.h>
7 #include <linux/irq.h>
8 #include <linux/kernel_stat.h>
9 #include <linux/module.h>
10 
11 #include <asm/machvec.h>
12 #include <asm/dma.h>
13 #include <asm/perf_event.h>
14 #include <asm/mce.h>
15 
16 #include "proto.h"
17 #include "irq_impl.h"
18 
19 /* Hack minimum IPL during interrupt processing for broken hardware. */
20 #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
21 int __min_ipl;
22 EXPORT_SYMBOL(__min_ipl);
23 #endif
24 
25 /*
26  * Performance counter hook. A module can override this to
27  * do something useful.
28  */
29 static void
30 dummy_perf(unsigned long vector, struct pt_regs *regs)
31 {
32  irq_err_count++;
33  printk(KERN_CRIT "Performance counter interrupt!\n");
34 }
35 
36 void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
38 
39 /*
40  * The main interrupt entry point.
41  */
42 
43 asmlinkage void
44 do_entInt(unsigned long type, unsigned long vector,
45  unsigned long la_ptr, struct pt_regs *regs)
46 {
47  struct pt_regs *old_regs;
48  switch (type) {
49  case 0:
50 #ifdef CONFIG_SMP
51  handle_ipi(regs);
52  return;
53 #else
54  irq_err_count++;
55  printk(KERN_CRIT "Interprocessor interrupt? "
56  "You must be kidding!\n");
57 #endif
58  break;
59  case 1:
60  old_regs = set_irq_regs(regs);
61 #ifdef CONFIG_SMP
62  {
63  long cpu;
64 
67  cpu = smp_processor_id();
68  if (cpu != boot_cpuid) {
69  kstat_incr_irqs_this_cpu(RTC_IRQ, irq_to_desc(RTC_IRQ));
70  } else {
72  }
73  }
74 #else
76 #endif
77  set_irq_regs(old_regs);
78  return;
79  case 2:
80  old_regs = set_irq_regs(regs);
81  alpha_mv.machine_check(vector, la_ptr);
82  set_irq_regs(old_regs);
83  return;
84  case 3:
85  old_regs = set_irq_regs(regs);
86  alpha_mv.device_interrupt(vector);
87  set_irq_regs(old_regs);
88  return;
89  case 4:
90  perf_irq(la_ptr, regs);
91  return;
92  default:
93  printk(KERN_CRIT "Hardware intr %ld %lx? Huh?\n",
94  type, vector);
95  }
96  printk(KERN_CRIT "PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
97 }
98 
99 void __init
101 {
102  outb(0, DMA1_RESET_REG);
103  outb(0, DMA2_RESET_REG);
106 }
107 
108 void __init
109 init_IRQ(void)
110 {
111  /* Just in case the platform init_irq() causes interrupts/mchecks
112  (as is the case with RAWHIDE, at least). */
113  wrent(entInt, 0);
114 
115  alpha_mv.init_irq();
116 }
117 
118 /*
119  * machine error checks
120  */
121 #define MCHK_K_TPERR 0x0080
122 #define MCHK_K_TCPERR 0x0082
123 #define MCHK_K_HERR 0x0084
124 #define MCHK_K_ECC_C 0x0086
125 #define MCHK_K_ECC_NC 0x0088
126 #define MCHK_K_OS_BUGCHECK 0x008A
127 #define MCHK_K_PAL_BUGCHECK 0x0090
128 
129 #ifndef CONFIG_SMP
131 #endif
132 
133 void
134 process_mcheck_info(unsigned long vector, unsigned long la_ptr,
135  const char *machine, int expected)
136 {
137  struct el_common *mchk_header;
138  const char *reason;
139 
140  /*
141  * See if the machine check is due to a badaddr() and if so,
142  * ignore it.
143  */
144 
145 #ifdef CONFIG_VERBOSE_MCHECK
146  if (alpha_verbose_mcheck > 1) {
147  printk(KERN_CRIT "%s machine check %s\n", machine,
148  expected ? "expected." : "NOT expected!!!");
149  }
150 #endif
151 
152  if (expected) {
153  int cpu = smp_processor_id();
154  mcheck_expected(cpu) = 0;
155  mcheck_taken(cpu) = 1;
156  return;
157  }
158 
159  mchk_header = (struct el_common *)la_ptr;
160 
161  printk(KERN_CRIT "%s machine check: vector=0x%lx pc=0x%lx code=0x%x\n",
162  machine, vector, get_irq_regs()->pc, mchk_header->code);
163 
164  switch (mchk_header->code) {
165  /* Machine check reasons. Defined according to PALcode sources. */
166  case 0x80: reason = "tag parity error"; break;
167  case 0x82: reason = "tag control parity error"; break;
168  case 0x84: reason = "generic hard error"; break;
169  case 0x86: reason = "correctable ECC error"; break;
170  case 0x88: reason = "uncorrectable ECC error"; break;
171  case 0x8A: reason = "OS-specific PAL bugcheck"; break;
172  case 0x90: reason = "callsys in kernel mode"; break;
173  case 0x96: reason = "i-cache read retryable error"; break;
174  case 0x98: reason = "processor detected hard error"; break;
175 
176  /* System specific (these are for Alcor, at least): */
177  case 0x202: reason = "system detected hard error"; break;
178  case 0x203: reason = "system detected uncorrectable ECC error"; break;
179  case 0x204: reason = "SIO SERR occurred on PCI bus"; break;
180  case 0x205: reason = "parity error detected by core logic"; break;
181  case 0x206: reason = "SIO IOCHK occurred on ISA bus"; break;
182  case 0x207: reason = "non-existent memory error"; break;
183  case 0x208: reason = "MCHK_K_DCSR"; break;
184  case 0x209: reason = "PCI SERR detected"; break;
185  case 0x20b: reason = "PCI data parity error detected"; break;
186  case 0x20d: reason = "PCI address parity error detected"; break;
187  case 0x20f: reason = "PCI master abort error"; break;
188  case 0x211: reason = "PCI target abort error"; break;
189  case 0x213: reason = "scatter/gather PTE invalid error"; break;
190  case 0x215: reason = "flash ROM write error"; break;
191  case 0x217: reason = "IOA timeout detected"; break;
192  case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
193  case 0x21b: reason = "EISA fail-safe timer timeout"; break;
194  case 0x21d: reason = "EISA bus time-out"; break;
195  case 0x21f: reason = "EISA software generated NMI"; break;
196  case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
197  default: reason = "unknown"; break;
198  }
199 
200  printk(KERN_CRIT "machine check type: %s%s\n",
201  reason, mchk_header->retry ? " (retryable)" : "");
202 
204 
205 #ifdef CONFIG_VERBOSE_MCHECK
206  if (alpha_verbose_mcheck > 1) {
207  /* Dump the logout area to give all info. */
208  unsigned long *ptr = (unsigned long *)la_ptr;
209  long i;
210  for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
211  printk(KERN_CRIT " +%8lx %016lx %016lx\n",
212  i*sizeof(long), ptr[i], ptr[i+1]);
213  }
214  }
215 #endif /* CONFIG_VERBOSE_MCHECK */
216 }
217 
218 /*
219  * The special RTC interrupt type. The interrupt itself was
220  * processed by PALcode, and comes in via entInt vector 1.
221  */
222 
224  .handler = timer_interrupt,
225  .flags = IRQF_DISABLED,
226  .name = "timer",
227 };
228 
229 void __init
231 {
233  handle_simple_irq, "RTC");
234  setup_irq(RTC_IRQ, &timer_irqaction);
235 }
236 
237 /* Dummy irqactions. */
239  .handler = no_action,
240  .name = "isa-cascade"
241 };
242 
244  .handler = no_action,
245  .name = "timer-cascade"
246 };
247 
249  .handler = no_action,
250  .name = "halt-switch"
251 };