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