Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / arch / alpha / kernel / err_titan.c
1 /*
2  *      linux/arch/alpha/kernel/err_titan.c
3  *
4  *      Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5  *
6  *      Error handling code supporting TITAN systems
7  */
8
9 #include <linux/init.h>
10 #include <linux/pci.h>
11 #include <linux/sched.h>
12
13 #include <asm/io.h>
14 #include <asm/core_titan.h>
15 #include <asm/hwrpb.h>
16 #include <asm/smp.h>
17 #include <asm/err_common.h>
18 #include <asm/err_ev6.h>
19 #include <asm/irq_regs.h>
20
21 #include "err_impl.h"
22 #include "proto.h"
23
24
25 static int
26 titan_parse_c_misc(u64 c_misc, int print)
27 {
28 #ifdef CONFIG_VERBOSE_MCHECK
29         char *src;
30         int nxs = 0;
31 #endif
32         int status = MCHK_DISPOSITION_REPORT;
33
34 #define TITAN__CCHIP_MISC__NXM          (1UL << 28)
35 #define TITAN__CCHIP_MISC__NXS__S       (29)
36 #define TITAN__CCHIP_MISC__NXS__M       (0x7)
37
38         if (!(c_misc & TITAN__CCHIP_MISC__NXM))
39                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
40
41 #ifdef CONFIG_VERBOSE_MCHECK
42         if (!print)
43                 return status;
44
45         nxs = EXTRACT(c_misc, TITAN__CCHIP_MISC__NXS);
46         switch(nxs) {
47         case 0: /* CPU 0 */
48         case 1: /* CPU 1 */
49         case 2: /* CPU 2 */
50         case 3: /* CPU 3 */
51                 src = "CPU";
52                 /* num is already the CPU number */
53                 break;
54         case 4: /* Pchip 0 */
55         case 5: /* Pchip 1 */
56                 src = "Pchip";
57                 nxs -= 4;
58                 break;
59         default:/* reserved */
60                 src = "Unknown, NXS =";
61                 /* leave num untouched */
62                 break;
63         }
64
65         printk("%s    Non-existent memory access from: %s %d\n", 
66                err_print_prefix, src, nxs);
67 #endif /* CONFIG_VERBOSE_MCHECK */
68
69         return status;
70 }
71
72 static int
73 titan_parse_p_serror(int which, u64 serror, int print)
74 {
75         int status = MCHK_DISPOSITION_REPORT;
76
77 #ifdef CONFIG_VERBOSE_MCHECK
78         char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"};
79         char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"};
80 #endif /* CONFIG_VERBOSE_MCHECK */
81
82 #define TITAN__PCHIP_SERROR__LOST_UECC  (1UL << 0)
83 #define TITAN__PCHIP_SERROR__UECC       (1UL << 1)
84 #define TITAN__PCHIP_SERROR__CRE        (1UL << 2)
85 #define TITAN__PCHIP_SERROR__NXIO       (1UL << 3)
86 #define TITAN__PCHIP_SERROR__LOST_CRE   (1UL << 4)
87 #define TITAN__PCHIP_SERROR__ECCMASK    (TITAN__PCHIP_SERROR__UECC |      \
88                                          TITAN__PCHIP_SERROR__CRE)
89 #define TITAN__PCHIP_SERROR__ERRMASK    (TITAN__PCHIP_SERROR__LOST_UECC | \
90                                          TITAN__PCHIP_SERROR__UECC |      \
91                                          TITAN__PCHIP_SERROR__CRE |       \
92                                          TITAN__PCHIP_SERROR__NXIO |      \
93                                          TITAN__PCHIP_SERROR__LOST_CRE)
94 #define TITAN__PCHIP_SERROR__SRC__S     (52)
95 #define TITAN__PCHIP_SERROR__SRC__M     (0x3)
96 #define TITAN__PCHIP_SERROR__CMD__S     (54)
97 #define TITAN__PCHIP_SERROR__CMD__M     (0x3)
98 #define TITAN__PCHIP_SERROR__SYN__S     (56)
99 #define TITAN__PCHIP_SERROR__SYN__M     (0xff)
100 #define TITAN__PCHIP_SERROR__ADDR__S    (15)
101 #define TITAN__PCHIP_SERROR__ADDR__M    (0xffffffffUL)
102
103         if (!(serror & TITAN__PCHIP_SERROR__ERRMASK))
104                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
105
106 #ifdef CONFIG_VERBOSE_MCHECK
107         if (!print)
108                 return status;
109
110         printk("%s  PChip %d SERROR: %016lx\n", 
111                err_print_prefix, which, serror);
112         if (serror & TITAN__PCHIP_SERROR__ECCMASK) {
113                 printk("%s    %sorrectable ECC Error:\n"
114                        "      Source: %-6s  Command: %-8s  Syndrome: 0x%08x\n"
115                        "      Address: 0x%lx\n", 
116                        err_print_prefix,
117                        (serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C",
118                        serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)],
119                        serror_cmd[EXTRACT(serror, TITAN__PCHIP_SERROR__CMD)],
120                        (unsigned)EXTRACT(serror, TITAN__PCHIP_SERROR__SYN),
121                        EXTRACT(serror, TITAN__PCHIP_SERROR__ADDR));
122         }
123         if (serror & TITAN__PCHIP_SERROR__NXIO)
124                 printk("%s    Non Existent I/O Error\n", err_print_prefix);
125         if (serror & TITAN__PCHIP_SERROR__LOST_UECC)
126                 printk("%s    Lost Uncorrectable ECC Error\n", 
127                        err_print_prefix);
128         if (serror & TITAN__PCHIP_SERROR__LOST_CRE)
129                 printk("%s    Lost Correctable ECC Error\n", err_print_prefix);
130 #endif /* CONFIG_VERBOSE_MCHECK */
131
132         return status;
133 }
134
135 static int 
136 titan_parse_p_perror(int which, int port, u64 perror, int print)
137 {
138         int cmd;
139         unsigned long addr;
140         int status = MCHK_DISPOSITION_REPORT;
141
142 #ifdef CONFIG_VERBOSE_MCHECK
143         char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle",
144                                "I/O Read",              "I/O Write",
145                                "Reserved",              "Reserved",
146                                "Memory Read",           "Memory Write",
147                                "Reserved",              "Reserved",
148                                "Configuration Read",    "Configuration Write",
149                                "Memory Read Multiple",  "Dual Address Cycle",
150                                "Memory Read Line","Memory Write and Invalidate"
151         };
152 #endif /* CONFIG_VERBOSE_MCHECK */
153
154 #define TITAN__PCHIP_PERROR__LOST       (1UL << 0)
155 #define TITAN__PCHIP_PERROR__SERR       (1UL << 1)
156 #define TITAN__PCHIP_PERROR__PERR       (1UL << 2)
157 #define TITAN__PCHIP_PERROR__DCRTO      (1UL << 3)
158 #define TITAN__PCHIP_PERROR__SGE        (1UL << 4)
159 #define TITAN__PCHIP_PERROR__APE        (1UL << 5)
160 #define TITAN__PCHIP_PERROR__TA         (1UL << 6)
161 #define TITAN__PCHIP_PERROR__DPE        (1UL << 7)
162 #define TITAN__PCHIP_PERROR__NDS        (1UL << 8)
163 #define TITAN__PCHIP_PERROR__IPTPR      (1UL << 9)
164 #define TITAN__PCHIP_PERROR__IPTPW      (1UL << 10)
165 #define TITAN__PCHIP_PERROR__ERRMASK    (TITAN__PCHIP_PERROR__LOST |    \
166                                          TITAN__PCHIP_PERROR__SERR |    \
167                                          TITAN__PCHIP_PERROR__PERR |    \
168                                          TITAN__PCHIP_PERROR__DCRTO |   \
169                                          TITAN__PCHIP_PERROR__SGE |     \
170                                          TITAN__PCHIP_PERROR__APE |     \
171                                          TITAN__PCHIP_PERROR__TA |      \
172                                          TITAN__PCHIP_PERROR__DPE |     \
173                                          TITAN__PCHIP_PERROR__NDS |     \
174                                          TITAN__PCHIP_PERROR__IPTPR |   \
175                                          TITAN__PCHIP_PERROR__IPTPW)
176 #define TITAN__PCHIP_PERROR__DAC        (1UL << 47)
177 #define TITAN__PCHIP_PERROR__MWIN       (1UL << 48)
178 #define TITAN__PCHIP_PERROR__CMD__S     (52)
179 #define TITAN__PCHIP_PERROR__CMD__M     (0x0f)
180 #define TITAN__PCHIP_PERROR__ADDR__S    (14)
181 #define TITAN__PCHIP_PERROR__ADDR__M    (0x1fffffffful)
182
183         if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
184                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
185
186         cmd = EXTRACT(perror, TITAN__PCHIP_PERROR__CMD);
187         addr = EXTRACT(perror, TITAN__PCHIP_PERROR__ADDR) << 2;
188
189         /*
190          * Initializing the BIOS on a video card on a bus without
191          * a south bridge (subtractive decode agent) can result in 
192          * master aborts as the BIOS probes the capabilities of the
193          * card. XFree86 does such initialization. If the error
194          * is a master abort (No DevSel as PCI Master) and the command
195          * is an I/O read or write below the address where we start
196          * assigning PCI I/O spaces (SRM uses 0x1000), then mark the
197          * error as dismissable so starting XFree86 doesn't result
198          * in a series of uncorrectable errors being reported. Also
199          * dismiss master aborts to VGA frame buffer space
200          * (0xA0000 - 0xC0000) and legacy BIOS space (0xC0000 - 0x100000)
201          * for the same reason.
202          *
203          * Also mark the error dismissible if it looks like the right
204          * error but only the Lost bit is set. Since the BIOS initialization
205          * can cause multiple master aborts and the error interrupt can
206          * be handled on a different CPU than the BIOS code is run on,
207          * it is possible for a second master abort to occur between the
208          * time the PALcode reads PERROR and the time it writes PERROR
209          * to acknowledge the error. If this timing happens, a second
210          * error will be signalled after the first, and if no additional
211          * errors occur, will look like a Lost error with no additional 
212          * errors on the same transaction as the previous error.
213          */
214         if (((perror & TITAN__PCHIP_PERROR__NDS) || 
215              ((perror & TITAN__PCHIP_PERROR__ERRMASK) == 
216               TITAN__PCHIP_PERROR__LOST)) &&
217             ((((cmd & 0xE) == 2) && (addr < 0x1000)) ||
218              (((cmd & 0xE) == 6) && (addr >= 0xA0000) && (addr < 0x100000)))) {
219                 status = MCHK_DISPOSITION_DISMISS;
220         }
221
222 #ifdef CONFIG_VERBOSE_MCHECK
223         if (!print) 
224                 return status;
225
226         printk("%s  PChip %d %cPERROR: %016lx\n", 
227                err_print_prefix, which, 
228                port ? 'A' : 'G', perror);
229         if (perror & TITAN__PCHIP_PERROR__IPTPW)
230                 printk("%s    Invalid Peer-to-Peer Write\n", err_print_prefix);
231         if (perror & TITAN__PCHIP_PERROR__IPTPR)
232                 printk("%s    Invalid Peer-to-Peer Read\n", err_print_prefix);
233         if (perror & TITAN__PCHIP_PERROR__NDS)
234                 printk("%s    No DEVSEL as PCI Master [Master Abort]\n",
235                        err_print_prefix);
236         if (perror & TITAN__PCHIP_PERROR__DPE)
237                 printk("%s    Data Parity Error\n", err_print_prefix);
238         if (perror & TITAN__PCHIP_PERROR__TA)
239                 printk("%s    Target Abort\n", err_print_prefix);
240         if (perror & TITAN__PCHIP_PERROR__APE)
241                 printk("%s    Address Parity Error\n", err_print_prefix);
242         if (perror & TITAN__PCHIP_PERROR__SGE)
243                 printk("%s    Scatter-Gather Error, Invalid PTE\n", 
244                        err_print_prefix);
245         if (perror & TITAN__PCHIP_PERROR__DCRTO)
246                 printk("%s    Delayed-Completion Retry Timeout\n", 
247                        err_print_prefix);
248         if (perror & TITAN__PCHIP_PERROR__PERR)
249                 printk("%s    PERR Asserted\n", err_print_prefix);
250         if (perror & TITAN__PCHIP_PERROR__SERR)
251                 printk("%s    SERR Asserted\n", err_print_prefix);
252         if (perror & TITAN__PCHIP_PERROR__LOST)
253                 printk("%s    Lost Error\n", err_print_prefix);
254         printk("%s      Command: 0x%x - %s\n"
255                  "      Address: 0x%lx\n",
256                err_print_prefix,
257                cmd, perror_cmd[cmd],
258                addr);
259         if (perror & TITAN__PCHIP_PERROR__DAC)
260                 printk("%s      Dual Address Cycle\n", err_print_prefix);
261         if (perror & TITAN__PCHIP_PERROR__MWIN)
262                 printk("%s      Hit in Monster Window\n", err_print_prefix);
263 #endif /* CONFIG_VERBOSE_MCHECK */
264
265         return status;
266 }
267
268 static int
269 titan_parse_p_agperror(int which, u64 agperror, int print)
270 {
271         int status = MCHK_DISPOSITION_REPORT;
272 #ifdef CONFIG_VERBOSE_MCHECK
273         int cmd, len;
274         unsigned long addr;
275
276         char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)",
277                                  "Write (low-priority)",
278                                  "Write (high-priority)",
279                                  "Reserved",            "Reserved",
280                                  "Flush",               "Fence"
281         };
282 #endif /* CONFIG_VERBOSE_MCHECK */
283
284 #define TITAN__PCHIP_AGPERROR__LOST     (1UL << 0)
285 #define TITAN__PCHIP_AGPERROR__LPQFULL  (1UL << 1)
286 #define TITAN__PCHIP_AGPERROR__HPQFULL  (1UL << 2)
287 #define TITAN__PCHIP_AGPERROR__RESCMD   (1UL << 3)
288 #define TITAN__PCHIP_AGPERROR__IPTE     (1UL << 4)
289 #define TITAN__PCHIP_AGPERROR__PTP      (1UL << 5)
290 #define TITAN__PCHIP_AGPERROR__NOWINDOW (1UL << 6)
291 #define TITAN__PCHIP_AGPERROR__ERRMASK  (TITAN__PCHIP_AGPERROR__LOST |    \
292                                          TITAN__PCHIP_AGPERROR__LPQFULL | \
293                                          TITAN__PCHIP_AGPERROR__HPQFULL | \
294                                          TITAN__PCHIP_AGPERROR__RESCMD |  \
295                                          TITAN__PCHIP_AGPERROR__IPTE |    \
296                                          TITAN__PCHIP_AGPERROR__PTP |     \
297                                          TITAN__PCHIP_AGPERROR__NOWINDOW)
298 #define TITAN__PCHIP_AGPERROR__DAC      (1UL << 48)
299 #define TITAN__PCHIP_AGPERROR__MWIN     (1UL << 49)
300 #define TITAN__PCHIP_AGPERROR__FENCE    (1UL << 59)
301 #define TITAN__PCHIP_AGPERROR__CMD__S   (50)
302 #define TITAN__PCHIP_AGPERROR__CMD__M   (0x07)
303 #define TITAN__PCHIP_AGPERROR__ADDR__S  (15)
304 #define TITAN__PCHIP_AGPERROR__ADDR__M  (0xffffffffUL)
305 #define TITAN__PCHIP_AGPERROR__LEN__S   (53)
306 #define TITAN__PCHIP_AGPERROR__LEN__M   (0x3f)
307
308         if (!(agperror & TITAN__PCHIP_AGPERROR__ERRMASK))
309                 return MCHK_DISPOSITION_UNKNOWN_ERROR;
310
311 #ifdef CONFIG_VERBOSE_MCHECK
312         if (!print)
313                 return status;
314
315         cmd = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__CMD);
316         addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3;
317         len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN);
318
319         printk("%s  PChip %d AGPERROR: %016lx\n", err_print_prefix,
320                which, agperror);
321         if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW)
322                 printk("%s    No Window\n", err_print_prefix);
323         if (agperror & TITAN__PCHIP_AGPERROR__PTP)
324                 printk("%s    Peer-to-Peer set\n", err_print_prefix);
325         if (agperror & TITAN__PCHIP_AGPERROR__IPTE)
326                 printk("%s    Invalid PTE\n", err_print_prefix);
327         if (agperror & TITAN__PCHIP_AGPERROR__RESCMD)
328                 printk("%s    Reserved Command\n", err_print_prefix);
329         if (agperror & TITAN__PCHIP_AGPERROR__HPQFULL)
330                 printk("%s    HP Transaction Received while Queue Full\n", 
331                        err_print_prefix);
332         if (agperror & TITAN__PCHIP_AGPERROR__LPQFULL)
333                 printk("%s    LP Transaction Received while Queue Full\n", 
334                        err_print_prefix);
335         if (agperror & TITAN__PCHIP_AGPERROR__LOST)
336                 printk("%s    Lost Error\n", err_print_prefix);
337         printk("%s      Command: 0x%x - %s, %d Quadwords%s\n"
338                  "      Address: 0x%lx\n",
339                err_print_prefix, cmd, agperror_cmd[cmd], len,
340                (agperror & TITAN__PCHIP_AGPERROR__FENCE) ? ", FENCE" : "",
341                addr);
342         if (agperror & TITAN__PCHIP_AGPERROR__DAC)
343                 printk("%s      Dual Address Cycle\n", err_print_prefix);
344         if (agperror & TITAN__PCHIP_AGPERROR__MWIN)
345                 printk("%s      Hit in Monster Window\n", err_print_prefix);
346 #endif /* CONFIG_VERBOSE_MCHECK */
347
348         return status;
349 }       
350
351 static int
352 titan_parse_p_chip(int which, u64 serror, u64 gperror, 
353                    u64 aperror, u64 agperror, int print)
354 {
355         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
356         status |= titan_parse_p_serror(which, serror, print);
357         status |= titan_parse_p_perror(which, 0, gperror, print);
358         status |= titan_parse_p_perror(which, 1, aperror, print);
359         status |= titan_parse_p_agperror(which, agperror, print);
360         return status;
361 }
362
363 int
364 titan_process_logout_frame(struct el_common *mchk_header, int print)
365 {
366         struct el_TITAN_sysdata_mcheck *tmchk =
367                 (struct el_TITAN_sysdata_mcheck *)
368                 ((unsigned long)mchk_header + mchk_header->sys_offset);
369         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
370
371         status |= titan_parse_c_misc(tmchk->c_misc, print);
372         status |= titan_parse_p_chip(0, tmchk->p0_serror, tmchk->p0_gperror,
373                                      tmchk->p0_aperror, tmchk->p0_agperror, 
374                                      print);
375         status |= titan_parse_p_chip(1, tmchk->p1_serror, tmchk->p1_gperror,
376                                      tmchk->p1_aperror, tmchk->p1_agperror, 
377                                      print);
378
379         return status;
380 }
381
382 void
383 titan_machine_check(u64 vector, u64 la_ptr)
384 {
385         struct el_common *mchk_header = (struct el_common *)la_ptr;
386         struct el_TITAN_sysdata_mcheck *tmchk =
387                 (struct el_TITAN_sysdata_mcheck *)
388                 ((unsigned long)mchk_header + mchk_header->sys_offset);
389         u64 irqmask;
390
391         /*
392          * Mask of Titan interrupt sources which are reported as machine checks
393          *
394          * 63 - CChip Error
395          * 62 - PChip 0 H_Error
396          * 61 - PChip 1 H_Error
397          * 60 - PChip 0 C_Error
398          * 59 - PChip 1 C_Error
399          */
400 #define TITAN_MCHECK_INTERRUPT_MASK     0xF800000000000000UL
401
402         /*
403          * Sync the processor
404          */
405         mb();
406         draina();
407         
408         /*
409          * Only handle system errors here 
410          */
411         if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR)) {
412                 ev6_machine_check(vector, la_ptr);
413                 return;
414         }
415
416         /* 
417          * It's a system error, handle it here
418          *
419          * The PALcode has already cleared the error, so just parse it
420          */
421         
422         /* 
423          * Parse the logout frame without printing first. If the only error(s)
424          * found are classified as "dismissable", then just dismiss them and
425          * don't print any message
426          */
427         if (titan_process_logout_frame(mchk_header, 0) != 
428             MCHK_DISPOSITION_DISMISS) {
429                 char *saved_err_prefix = err_print_prefix;
430                 err_print_prefix = KERN_CRIT;
431
432                 /*
433                  * Either a nondismissable error was detected or no
434                  * recognized error was detected  in the logout frame 
435                  * -- report the error in either case
436                  */
437                 printk("%s"
438                        "*System %s Error (Vector 0x%x) reported on CPU %d:\n", 
439                        err_print_prefix,
440                        (vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
441                        (unsigned int)vector, (int)smp_processor_id());
442                 
443 #ifdef CONFIG_VERBOSE_MCHECK
444                 titan_process_logout_frame(mchk_header, alpha_verbose_mcheck);
445                 if (alpha_verbose_mcheck)
446                         dik_show_regs(get_irq_regs(), NULL);
447 #endif /* CONFIG_VERBOSE_MCHECK */
448
449                 err_print_prefix = saved_err_prefix;
450
451                 /*
452                  * Convert any pending interrupts which report as system
453                  * machine checks to interrupts
454                  */
455                 irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
456                 titan_dispatch_irqs(irqmask);
457         }       
458
459
460         /* 
461          * Release the logout frame 
462          */
463         wrmces(0x7);
464         mb();
465 }
466
467 /*
468  * Subpacket Annotations
469  */
470 static char *el_titan_pchip0_extended_annotation[] = {
471         "Subpacket Header",     "P0_SCTL",      "P0_SERREN",
472         "P0_APCTL",             "P0_APERREN",   "P0_AGPERREN",
473         "P0_ASPRST",            "P0_AWSBA0",    "P0_AWSBA1",
474         "P0_AWSBA2",            "P0_AWSBA3",    "P0_AWSM0",
475         "P0_AWSM1",             "P0_AWSM2",     "P0_AWSM3",
476         "P0_ATBA0",             "P0_ATBA1",     "P0_ATBA2",
477         "P0_ATBA3",             "P0_GPCTL",     "P0_GPERREN",
478         "P0_GSPRST",            "P0_GWSBA0",    "P0_GWSBA1",
479         "P0_GWSBA2",            "P0_GWSBA3",    "P0_GWSM0",
480         "P0_GWSM1",             "P0_GWSM2",     "P0_GWSM3",
481         "P0_GTBA0",             "P0_GTBA1",     "P0_GTBA2",
482         "P0_GTBA3",             NULL 
483 };
484 static char *el_titan_pchip1_extended_annotation[] = {
485         "Subpacket Header",     "P1_SCTL",      "P1_SERREN",
486         "P1_APCTL",             "P1_APERREN",   "P1_AGPERREN",
487         "P1_ASPRST",            "P1_AWSBA0",    "P1_AWSBA1",
488         "P1_AWSBA2",            "P1_AWSBA3",    "P1_AWSM0",
489         "P1_AWSM1",             "P1_AWSM2",     "P1_AWSM3",
490         "P1_ATBA0",             "P1_ATBA1",     "P1_ATBA2",
491         "P1_ATBA3",             "P1_GPCTL",     "P1_GPERREN",
492         "P1_GSPRST",            "P1_GWSBA0",    "P1_GWSBA1",
493         "P1_GWSBA2",            "P1_GWSBA3",    "P1_GWSM0",
494         "P1_GWSM1",             "P1_GWSM2",     "P1_GWSM3",
495         "P1_GTBA0",             "P1_GTBA1",     "P1_GTBA2",
496         "P1_GTBA3",             NULL 
497 };
498 static char *el_titan_memory_extended_annotation[] = {
499         "Subpacket Header",     "AAR0",         "AAR1",
500         "AAR2",                 "AAR3",         "P0_SCTL",
501         "P0_GPCTL",             "P0_APCTL",     "P1_SCTL",
502         "P1_GPCTL",             "P1_SCTL",      NULL 
503 };
504
505 static struct el_subpacket_annotation el_titan_annotations[] = {
506         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
507                              EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
508                              1,
509                              "Titan PChip 0 Extended Frame",
510                              el_titan_pchip0_extended_annotation),
511         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
512                              EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
513                              1,
514                              "Titan PChip 1 Extended Frame",
515                              el_titan_pchip1_extended_annotation),
516         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
517                              EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
518                              1,
519                              "Titan Memory Extended Frame",
520                              el_titan_memory_extended_annotation),
521         SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
522                              EL_TYPE__TERMINATION__TERMINATION,
523                              1,
524                              "Termination Subpacket",
525                              NULL)
526 };
527
528 static struct el_subpacket *
529 el_process_regatta_subpacket(struct el_subpacket *header)
530 {
531         int status;
532
533         if (header->class != EL_CLASS__REGATTA_FAMILY) {
534                 printk("%s  ** Unexpected header CLASS %d TYPE %d, aborting\n",
535                        err_print_prefix,
536                        header->class, header->type);
537                 return NULL;
538         }
539
540         switch(header->type) {
541         case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
542         case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
543         case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
544         case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
545         case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
546                 printk("%s  ** Occurred on CPU %d:\n", 
547                        err_print_prefix,
548                        (int)header->by_type.regatta_frame.cpuid);
549                 status = privateer_process_logout_frame((struct el_common *)
550                         header->by_type.regatta_frame.data_start, 1);
551                 break;
552         default:
553                 printk("%s  ** REGATTA TYPE %d SUBPACKET\n", 
554                        err_print_prefix, header->type);
555                 el_annotate_subpacket(header);
556                 break;
557         }
558
559
560         return (struct el_subpacket *)((unsigned long)header + header->length);
561
562
563 static struct el_subpacket_handler titan_subpacket_handler = 
564         SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY, 
565                                el_process_regatta_subpacket);
566
567 void __init
568 titan_register_error_handlers(void)
569 {
570         size_t i;
571
572         for (i = 0; i < ARRAY_SIZE (el_titan_annotations); i++)
573                 cdl_register_subpacket_annotation(&el_titan_annotations[i]);
574
575         cdl_register_subpacket_handler(&titan_subpacket_handler);
576
577         ev6_register_error_handlers();
578 }
579
580 \f
581 /*
582  * Privateer
583  */
584
585 static int
586 privateer_process_680_frame(struct el_common *mchk_header, int print)
587 {
588         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
589 #ifdef CONFIG_VERBOSE_MCHECK
590         struct el_PRIVATEER_envdata_mcheck *emchk =
591                 (struct el_PRIVATEER_envdata_mcheck *)
592                 ((unsigned long)mchk_header + mchk_header->sys_offset);
593
594         /* TODO - categorize errors, for now, no error */
595
596         if (!print)
597                 return status;
598
599         /* TODO - decode instead of just dumping... */
600         printk("%s  Summary Flags:         %016lx\n"
601                  "  CChip DIRx:            %016lx\n"
602                  "  System Management IR:  %016lx\n"
603                  "  CPU IR:                %016lx\n"
604                  "  Power Supply IR:       %016lx\n"
605                  "  LM78 Fault Status:     %016lx\n"
606                  "  System Doors:          %016lx\n"
607                  "  Temperature Warning:   %016lx\n"
608                  "  Fan Control:           %016lx\n"
609                  "  Fatal Power Down Code: %016lx\n",
610                err_print_prefix,
611                emchk->summary,
612                emchk->c_dirx,
613                emchk->smir,
614                emchk->cpuir,
615                emchk->psir,
616                emchk->fault,
617                emchk->sys_doors,
618                emchk->temp_warn,
619                emchk->fan_ctrl,
620                emchk->code);
621 #endif /* CONFIG_VERBOSE_MCHECK */
622
623         return status;
624 }
625
626 int
627 privateer_process_logout_frame(struct el_common *mchk_header, int print)
628 {
629         struct el_common_EV6_mcheck *ev6mchk = 
630                 (struct el_common_EV6_mcheck *)mchk_header;
631         int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
632
633         /*
634          * Machine check codes
635          */
636 #define PRIVATEER_MCHK__CORR_ECC                0x86    /* 630 */
637 #define PRIVATEER_MCHK__DC_TAG_PERR             0x9E    /* 630 */
638 #define PRIVATEER_MCHK__PAL_BUGCHECK            0x8E    /* 670 */
639 #define PRIVATEER_MCHK__OS_BUGCHECK             0x90    /* 670 */
640 #define PRIVATEER_MCHK__PROC_HRD_ERR            0x98    /* 670 */
641 #define PRIVATEER_MCHK__ISTREAM_CMOV_PRX        0xA0    /* 670 */
642 #define PRIVATEER_MCHK__ISTREAM_CMOV_FLT        0xA2    /* 670 */
643 #define PRIVATEER_MCHK__SYS_HRD_ERR             0x202   /* 660 */
644 #define PRIVATEER_MCHK__SYS_CORR_ERR            0x204   /* 620 */
645 #define PRIVATEER_MCHK__SYS_ENVIRON             0x206   /* 680 */
646
647         switch(ev6mchk->MCHK_Code) {
648         /*
649          * Vector 630 - Processor, Correctable
650          */
651         case PRIVATEER_MCHK__CORR_ECC:
652         case PRIVATEER_MCHK__DC_TAG_PERR:
653                 /*
654                  * Fall through to vector 670 for processing...
655                  */
656         /*
657          * Vector 670 - Processor, Uncorrectable
658          */
659         case PRIVATEER_MCHK__PAL_BUGCHECK:
660         case PRIVATEER_MCHK__OS_BUGCHECK:
661         case PRIVATEER_MCHK__PROC_HRD_ERR:
662         case PRIVATEER_MCHK__ISTREAM_CMOV_PRX:
663         case PRIVATEER_MCHK__ISTREAM_CMOV_FLT:
664                 status |= ev6_process_logout_frame(mchk_header, print);
665                 break;
666
667         /*
668          * Vector 620 - System, Correctable
669          */
670         case PRIVATEER_MCHK__SYS_CORR_ERR:
671                 /*
672                  * Fall through to vector 660 for processing...
673                  */
674         /*
675          * Vector 660 - System, Uncorrectable
676          */
677         case PRIVATEER_MCHK__SYS_HRD_ERR:
678                 status |= titan_process_logout_frame(mchk_header, print);
679                 break;
680
681         /* 
682          * Vector 680 - System, Environmental
683          */
684         case PRIVATEER_MCHK__SYS_ENVIRON:       /* System, Environmental */
685                 status |= privateer_process_680_frame(mchk_header, print);
686                 break;
687
688         /* 
689          * Unknown
690          */
691         default:
692                 status |= MCHK_DISPOSITION_REPORT;
693                 if (print) {
694                         printk("%s** Unknown Error, frame follows\n", 
695                                err_print_prefix);
696                         mchk_dump_logout_frame(mchk_header);
697                 }
698
699         }
700
701         return status;
702 }
703
704 void
705 privateer_machine_check(u64 vector, u64 la_ptr)
706 {
707         struct el_common *mchk_header = (struct el_common *)la_ptr;
708         struct el_TITAN_sysdata_mcheck *tmchk =
709                 (struct el_TITAN_sysdata_mcheck *)
710                 (la_ptr + mchk_header->sys_offset);
711         u64 irqmask;
712         char *saved_err_prefix = err_print_prefix;
713
714 #define PRIVATEER_680_INTERRUPT_MASK            (0xE00UL)
715 #define PRIVATEER_HOTPLUG_INTERRUPT_MASK        (0xE00UL)
716
717         /*
718          * Sync the processor.
719          */
720         mb();
721         draina();
722
723         /* 
724          * Only handle system events here.
725          */
726         if (vector != SCB_Q_SYSEVENT) 
727                 return titan_machine_check(vector, la_ptr);
728
729         /*
730          * Report the event - System Events should be reported even if no
731          * error is indicated since the event could indicate the return
732          * to normal status.
733          */
734         err_print_prefix = KERN_CRIT;
735         printk("%s*System Event (Vector 0x%x) reported on CPU %d:\n", 
736                err_print_prefix,
737                (unsigned int)vector, (int)smp_processor_id());
738         privateer_process_680_frame(mchk_header, 1);
739         err_print_prefix = saved_err_prefix;
740         
741         /* 
742          * Convert any pending interrupts which report as 680 machine
743          * checks to interrupts.
744          */
745         irqmask = tmchk->c_dirx & PRIVATEER_680_INTERRUPT_MASK;
746
747         /*
748          * Dispatch the interrupt(s).
749          */
750         titan_dispatch_irqs(irqmask);
751
752         /* 
753          * Release the logout frame.
754          */
755         wrmces(0x7);
756         mb();
757 }