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