1/*
2 *	linux/arch/alpha/kernel/err_marvel.c
3 *
4 *	Copyright (C) 2001 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 */
7
8#include <linux/init.h>
9#include <linux/pci.h>
10#include <linux/sched.h>
11
12#include <asm/io.h>
13#include <asm/console.h>
14#include <asm/core_marvel.h>
15#include <asm/hwrpb.h>
16#include <asm/smp.h>
17#include <asm/err_common.h>
18#include <asm/err_ev7.h>
19
20#include "err_impl.h"
21#include "proto.h"
22
23static void
24marvel_print_680_frame(struct ev7_lf_subpackets *lf_subpackets)
25{
26#ifdef CONFIG_VERBOSE_MCHECK
27	struct ev7_pal_environmental_subpacket *env;
28	struct { int type; char *name; } ev_packets[] = {
29		{ EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE,
30		  "Ambient Temperature" },
31		{ EL_TYPE__PAL__ENV__AIRMOVER_FAN,
32		  "AirMover / Fan" },
33		{ EL_TYPE__PAL__ENV__VOLTAGE,
34		  "Voltage" },
35		{ EL_TYPE__PAL__ENV__INTRUSION,
36		  "Intrusion" },
37		{ EL_TYPE__PAL__ENV__POWER_SUPPLY,
38		  "Power Supply" },
39		{ EL_TYPE__PAL__ENV__LAN,
40		  "LAN" },
41		{ EL_TYPE__PAL__ENV__HOT_PLUG,
42		  "Hot Plug" },
43		{ 0, NULL }
44	};
45	int i;
46
47	for (i = 0; ev_packets[i].type != 0; i++) {
48		env = lf_subpackets->env[ev7_lf_env_index(ev_packets[i].type)];
49		if (!env)
50			continue;
51
52		printk("%s**%s event (cabinet %d, drawer %d)\n",
53		       err_print_prefix,
54		       ev_packets[i].name,
55		       env->cabinet,
56		       env->drawer);
57		printk("%s   Module Type: 0x%x - Unit ID 0x%x - "
58		       "Condition 0x%x\n",
59		       err_print_prefix,
60		       env->module_type,
61		       env->unit_id,
62		       env->condition);
63	}
64#endif /* CONFIG_VERBOSE_MCHECK */
65}
66
67static int
68marvel_process_680_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
69{
70	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
71	int i;
72
73	for (i = ev7_lf_env_index(EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE);
74	     i <= ev7_lf_env_index(EL_TYPE__PAL__ENV__HOT_PLUG);
75	     i++) {
76		if (lf_subpackets->env[i])
77			status = MCHK_DISPOSITION_REPORT;
78	}
79
80	if (print)
81		marvel_print_680_frame(lf_subpackets);
82
83	return status;
84}
85
86#ifdef CONFIG_VERBOSE_MCHECK
87
88static void
89marvel_print_err_cyc(u64 err_cyc)
90{
91	static char *packet_desc[] = {
92		"No Error",
93		"UNKNOWN",
94		"1 cycle (1 or 2 flit packet)",
95		"2 cycles (3 flit packet)",
96		"9 cycles (18 flit packet)",
97		"10 cycles (19 flit packet)",
98		"UNKNOWN",
99		"UNKNOWN",
100		"UNKNOWN"
101	};
102
103#define IO7__ERR_CYC__ODD_FLT	(1UL <<  0)
104#define IO7__ERR_CYC__EVN_FLT	(1UL <<  1)
105#define IO7__ERR_CYC__PACKET__S	(6)
106#define IO7__ERR_CYC__PACKET__M	(0x7)
107#define IO7__ERR_CYC__LOC	(1UL <<  5)
108#define IO7__ERR_CYC__CYCLE__S	(2)
109#define IO7__ERR_CYC__CYCLE__M	(0x7)
110
111	printk("%s        Packet In Error: %s\n"
112	       "%s        Error in %s, cycle %ld%s%s\n",
113	       err_print_prefix,
114	       packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)],
115	       err_print_prefix,
116	       (err_cyc & IO7__ERR_CYC__LOC) ? "DATA" : "HEADER",
117	       EXTRACT(err_cyc, IO7__ERR_CYC__CYCLE),
118	       (err_cyc & IO7__ERR_CYC__ODD_FLT) ? " [ODD Flit]": "",
119	       (err_cyc & IO7__ERR_CYC__EVN_FLT) ? " [Even Flit]": "");
120}
121
122static void
123marvel_print_po7_crrct_sym(u64 crrct_sym)
124{
125#define IO7__PO7_CRRCT_SYM__SYN__S	(0)
126#define IO7__PO7_CRRCT_SYM__SYN__M	(0x7f)
127#define IO7__PO7_CRRCT_SYM__ERR_CYC__S	(7)   /* ERR_CYC + ODD_FLT + EVN_FLT */
128#define IO7__PO7_CRRCT_SYM__ERR_CYC__M	(0x1ff)
129
130
131	printk("%s      Correctable Error Symptoms:\n"
132	       "%s        Syndrome: 0x%lx\n",
133	       err_print_prefix,
134	       err_print_prefix, EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__SYN));
135	marvel_print_err_cyc(EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__ERR_CYC));
136}
137
138static void
139marvel_print_po7_uncrr_sym(u64 uncrr_sym, u64 valid_mask)
140{
141	static char *clk_names[] = { "_h[0]", "_h[1]", "_n[0]", "_n[1]" };
142	static char *clk_decode[] = {
143		"No Error",
144		"One extra rising edge",
145		"Two extra rising edges",
146		"Lost one clock"
147	};
148	static char *port_names[] = { "Port 0", 	"Port 1",
149				      "Port 2", 	"Port 3",
150				      "Unknown Port",	"Unknown Port",
151				      "Unknown Port",	"Port 7" };
152	int scratch, i;
153
154#define IO7__PO7_UNCRR_SYM__SYN__S	    (0)
155#define IO7__PO7_UNCRR_SYM__SYN__M	    (0x7f)
156#define IO7__PO7_UNCRR_SYM__ERR_CYC__S	    (7)      /* ERR_CYC + ODD_FLT... */
157#define IO7__PO7_UNCRR_SYM__ERR_CYC__M	    (0x1ff)  /* ... + EVN_FLT        */
158#define IO7__PO7_UNCRR_SYM__CLK__S	    (16)
159#define IO7__PO7_UNCRR_SYM__CLK__M	    (0xff)
160#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__REQ (1UL << 24)
161#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__RIO (1UL << 25)
162#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__WIO (1UL << 26)
163#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__BLK (1UL << 27)
164#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__NBK (1UL << 28)
165#define IO7__PO7_UNCRR_SYM__OVF__READIO	    (1UL << 29)
166#define IO7__PO7_UNCRR_SYM__OVF__WRITEIO    (1UL << 30)
167#define IO7__PO7_UNCRR_SYM__OVF__FWD        (1UL << 31)
168#define IO7__PO7_UNCRR_SYM__VICTIM_SP__S    (32)
169#define IO7__PO7_UNCRR_SYM__VICTIM_SP__M    (0xff)
170#define IO7__PO7_UNCRR_SYM__DETECT_SP__S    (40)
171#define IO7__PO7_UNCRR_SYM__DETECT_SP__M    (0xff)
172#define IO7__PO7_UNCRR_SYM__STRV_VTR__S     (48)
173#define IO7__PO7_UNCRR_SYM__STRV_VTR__M     (0x3ff)
174
175#define IO7__STRV_VTR__LSI__INTX__S	    (0)
176#define IO7__STRV_VTR__LSI__INTX__M	    (0x3)
177#define IO7__STRV_VTR__LSI__SLOT__S	    (2)
178#define IO7__STRV_VTR__LSI__SLOT__M	    (0x7)
179#define IO7__STRV_VTR__LSI__BUS__S	    (5)
180#define IO7__STRV_VTR__LSI__BUS__M	    (0x3)
181#define IO7__STRV_VTR__MSI__INTNUM__S	    (0)
182#define IO7__STRV_VTR__MSI__INTNUM__M	    (0x1ff)
183#define IO7__STRV_VTR__IS_MSI		    (1UL << 9)
184
185	printk("%s      Uncorrectable Error Symptoms:\n", err_print_prefix);
186	uncrr_sym &= valid_mask;
187
188	if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__SYN))
189		printk("%s        Syndrome: 0x%lx\n",
190		       err_print_prefix,
191		       EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__SYN));
192
193	if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__ERR_CYC))
194		marvel_print_err_cyc(EXTRACT(uncrr_sym,
195					     IO7__PO7_UNCRR_SYM__ERR_CYC));
196
197	scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__CLK);
198	for (i = 0; i < 4; i++, scratch >>= 2) {
199		if (scratch & 0x3)
200			printk("%s        Clock %s: %s\n",
201			       err_print_prefix,
202			       clk_names[i], clk_decode[scratch & 0x3]);
203	}
204
205	if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__REQ)
206		printk("%s       REQ Credit Timeout or Overflow\n",
207		       err_print_prefix);
208	if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__RIO)
209		printk("%s       RIO Credit Timeout or Overflow\n",
210		       err_print_prefix);
211	if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__WIO)
212		printk("%s       WIO Credit Timeout or Overflow\n",
213		       err_print_prefix);
214	if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__BLK)
215		printk("%s       BLK Credit Timeout or Overflow\n",
216		       err_print_prefix);
217	if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__NBK)
218		printk("%s       NBK Credit Timeout or Overflow\n",
219		       err_print_prefix);
220
221	if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__READIO)
222		printk("%s       Read I/O Buffer Overflow\n",
223		       err_print_prefix);
224	if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__WRITEIO)
225		printk("%s       Write I/O Buffer Overflow\n",
226		       err_print_prefix);
227	if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__FWD)
228		printk("%s       FWD Buffer Overflow\n",
229		       err_print_prefix);
230
231	if ((scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__VICTIM_SP))) {
232		int lost = scratch & (1UL << 4);
233		scratch &= ~lost;
234		for (i = 0; i < 8; i++, scratch >>= 1) {
235			if (!(scratch & 1))
236				continue;
237			printk("%s        Error Response sent to %s",
238			       err_print_prefix, port_names[i]);
239		}
240		if (lost)
241			printk("%s        Lost Error sent somewhere else\n",
242			       err_print_prefix);
243	}
244
245	if ((scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__DETECT_SP))) {
246		for (i = 0; i < 8; i++, scratch >>= 1) {
247			if (!(scratch & 1))
248				continue;
249			printk("%s        Error Reported by %s",
250			       err_print_prefix, port_names[i]);
251		}
252	}
253
254	if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__STRV_VTR)) {
255		char starvation_message[80];
256
257		scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__STRV_VTR);
258		if (scratch & IO7__STRV_VTR__IS_MSI)
259			sprintf(starvation_message,
260				"MSI Interrupt 0x%x",
261				EXTRACT(scratch, IO7__STRV_VTR__MSI__INTNUM));
262		else
263			sprintf(starvation_message,
264				"LSI INT%c for Bus:Slot (%d:%d)\n",
265				'A' + EXTRACT(scratch,
266					      IO7__STRV_VTR__LSI__INTX),
267				EXTRACT(scratch, IO7__STRV_VTR__LSI__BUS),
268				EXTRACT(scratch, IO7__STRV_VTR__LSI__SLOT));
269
270		printk("%s        Starvation Int Trigger By: %s\n",
271		       err_print_prefix, starvation_message);
272	}
273}
274
275static void
276marvel_print_po7_ugbge_sym(u64 ugbge_sym)
277{
278	char opcode_str[10];
279
280#define IO7__PO7_UGBGE_SYM__UPH_PKT_OFF__S	(6)
281#define IO7__PO7_UGBGE_SYM__UPH_PKT_OFF__M	(0xfffffffful)
282#define IO7__PO7_UGBGE_SYM__UPH_OPCODE__S	(40)
283#define IO7__PO7_UGBGE_SYM__UPH_OPCODE__M	(0xff)
284#define IO7__PO7_UGBGE_SYM__UPH_SRC_PORT__S	(48)
285#define IO7__PO7_UGBGE_SYM__UPH_SRC_PORT__M	(0xf)
286#define IO7__PO7_UGBGE_SYM__UPH_DEST_PID__S	(52)
287#define IO7__PO7_UGBGE_SYM__UPH_DEST_PID__M	(0x7ff)
288#define IO7__PO7_UGBGE_SYM__VALID		(1UL << 63)
289
290	if (!(ugbge_sym & IO7__PO7_UGBGE_SYM__VALID))
291		return;
292
293	switch(EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE)) {
294	case 0x51:
295		sprintf(opcode_str, "Wr32");
296		break;
297	case 0x50:
298		sprintf(opcode_str, "WrQW");
299		break;
300	case 0x54:
301		sprintf(opcode_str, "WrIPR");
302		break;
303	case 0xD8:
304		sprintf(opcode_str, "Victim");
305		break;
306	case 0xC5:
307		sprintf(opcode_str, "BlkIO");
308		break;
309	default:
310		sprintf(opcode_str, "0x%lx\n",
311			EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE));
312		break;
313	}
314
315	printk("%s      Up Hose Garbage Symptom:\n"
316	       "%s        Source Port: %ld - Dest PID: %ld - OpCode: %s\n",
317	       err_print_prefix,
318	       err_print_prefix,
319	       EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT),
320	       EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_DEST_PID),
321	       opcode_str);
322
323	if (0xC5 != EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE))
324		printk("%s        Packet Offset 0x%08lx\n",
325		       err_print_prefix,
326		       EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_PKT_OFF));
327}
328
329static void
330marvel_print_po7_err_sum(struct ev7_pal_io_subpacket *io)
331{
332	u64	uncrr_sym_valid = 0;
333
334#define IO7__PO7_ERRSUM__CR_SBE		(1UL << 32)
335#define IO7__PO7_ERRSUM__CR_SBE2	(1UL << 33)
336#define IO7__PO7_ERRSUM__CR_PIO_WBYTE	(1UL << 34)
337#define IO7__PO7_ERRSUM__CR_CSR_NXM	(1UL << 35)
338#define IO7__PO7_ERRSUM__CR_RPID_ACV	(1UL << 36)
339#define IO7__PO7_ERRSUM__CR_RSP_NXM	(1UL << 37)
340#define IO7__PO7_ERRSUM__CR_ERR_RESP	(1UL << 38)
341#define IO7__PO7_ERRSUM__CR_CLK_DERR	(1UL << 39)
342#define IO7__PO7_ERRSUM__CR_DAT_DBE	(1UL << 40)
343#define IO7__PO7_ERRSUM__CR_DAT_GRBG	(1UL << 41)
344#define IO7__PO7_ERRSUM__MAF_TO		(1UL << 42)
345#define IO7__PO7_ERRSUM__UGBGE		(1UL << 43)
346#define IO7__PO7_ERRSUM__UN_MAF_LOST	(1UL << 44)
347#define IO7__PO7_ERRSUM__UN_PKT_OVF	(1UL << 45)
348#define IO7__PO7_ERRSUM__UN_CDT_OVF	(1UL << 46)
349#define IO7__PO7_ERRSUM__UN_DEALLOC	(1UL << 47)
350#define IO7__PO7_ERRSUM__BH_CDT_TO	(1UL << 51)
351#define IO7__PO7_ERRSUM__BH_CLK_HDR	(1UL << 52)
352#define IO7__PO7_ERRSUM__BH_DBE_HDR	(1UL << 53)
353#define IO7__PO7_ERRSUM__BH_GBG_HDR	(1UL << 54)
354#define IO7__PO7_ERRSUM__BH_BAD_CMD	(1UL << 55)
355#define IO7__PO7_ERRSUM__HLT_INT	(1UL << 56)
356#define IO7__PO7_ERRSUM__HP_INT		(1UL << 57)
357#define IO7__PO7_ERRSUM__CRD_INT	(1UL << 58)
358#define IO7__PO7_ERRSUM__STV_INT	(1UL << 59)
359#define IO7__PO7_ERRSUM__HRD_INT	(1UL << 60)
360#define IO7__PO7_ERRSUM__BH_SUM		(1UL << 61)
361#define IO7__PO7_ERRSUM__ERR_LST	(1UL << 62)
362#define IO7__PO7_ERRSUM__ERR_VALID	(1UL << 63)
363
364#define IO7__PO7_ERRSUM__ERR_MASK	(IO7__PO7_ERRSUM__ERR_VALID |	\
365					 IO7__PO7_ERRSUM__CR_SBE)
366
367	/*
368	 * Single bit errors aren't covered by ERR_VALID.
369	 */
370	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_SBE) {
371		printk("%s    %sSingle Bit Error(s) detected/corrected\n",
372		       err_print_prefix,
373		       (io->po7_error_sum & IO7__PO7_ERRSUM__CR_SBE2)
374		       ? "Multiple " : "");
375		marvel_print_po7_crrct_sym(io->po7_crrct_sym);
376	}
377
378	/*
379	 * Neither are the interrupt status bits
380	 */
381	if (io->po7_error_sum & IO7__PO7_ERRSUM__HLT_INT)
382		printk("%s    Halt Interrupt posted", err_print_prefix);
383	if (io->po7_error_sum & IO7__PO7_ERRSUM__HP_INT) {
384		printk("%s    Hot Plug Event Interrupt posted",
385		       err_print_prefix);
386		uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__DETECT_SP);
387	}
388	if (io->po7_error_sum & IO7__PO7_ERRSUM__CRD_INT)
389		printk("%s    Correctable Error Interrupt posted",
390		       err_print_prefix);
391	if (io->po7_error_sum & IO7__PO7_ERRSUM__STV_INT) {
392		printk("%s    Starvation Interrupt posted", err_print_prefix);
393		uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__STRV_VTR);
394	}
395	if (io->po7_error_sum & IO7__PO7_ERRSUM__HRD_INT) {
396		printk("%s    Hard Error Interrupt posted", err_print_prefix);
397		uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__DETECT_SP);
398	}
399
400	/*
401	 * Everything else is valid only with ERR_VALID, so skip to the end
402	 * (uncrr_sym check) unless ERR_VALID is set.
403	 */
404	if (!(io->po7_error_sum & IO7__PO7_ERRSUM__ERR_VALID))
405		goto check_uncrr_sym;
406
407	/*
408	 * Since ERR_VALID is set, VICTIM_SP in uncrr_sym is valid.
409	 * For bits [29:0] to also be valid, the following bits must
410	 * not be set:
411	 *	CR_PIO_WBYTE	CR_CSR_NXM	CR_RSP_NXM
412	 *	CR_ERR_RESP	MAF_TO
413	 */
414	uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__VICTIM_SP);
415	if (!(io->po7_error_sum & (IO7__PO7_ERRSUM__CR_PIO_WBYTE |
416				   IO7__PO7_ERRSUM__CR_CSR_NXM |
417				   IO7__PO7_ERRSUM__CR_RSP_NXM |
418				   IO7__PO7_ERRSUM__CR_ERR_RESP |
419				   IO7__PO7_ERRSUM__MAF_TO)))
420		uncrr_sym_valid |= 0x3ffffffful;
421
422	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_PIO_WBYTE)
423		printk("%s    Write byte into IO7 CSR\n", err_print_prefix);
424	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_CSR_NXM)
425		printk("%s    PIO to non-existent CSR\n", err_print_prefix);
426	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_RPID_ACV)
427		printk("%s    Bus Requester PID (Access Violation)\n",
428		       err_print_prefix);
429	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_RSP_NXM)
430		printk("%s    Received NXM response from EV7\n",
431		       err_print_prefix);
432	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_ERR_RESP)
433		printk("%s    Received ERROR RESPONSE\n", err_print_prefix);
434	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_CLK_DERR)
435		printk("%s    Clock error on data flit\n", err_print_prefix);
436	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_DAT_DBE)
437		printk("%s    Double Bit Error Data Error Detected\n",
438		       err_print_prefix);
439	if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_DAT_GRBG)
440		printk("%s    Garbage Encoding Detected on the data\n",
441		       err_print_prefix);
442	if (io->po7_error_sum & IO7__PO7_ERRSUM__UGBGE) {
443		printk("%s    Garbage Encoding sent up hose\n",
444		       err_print_prefix);
445		marvel_print_po7_ugbge_sym(io->po7_ugbge_sym);
446	}
447	if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_MAF_LOST)
448		printk("%s    Orphan response (unexpected response)\n",
449		       err_print_prefix);
450	if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_PKT_OVF)
451		printk("%s    Down hose packet overflow\n", err_print_prefix);
452	if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_CDT_OVF)
453		printk("%s    Down hose credit overflow\n", err_print_prefix);
454	if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_DEALLOC)
455		printk("%s    Unexpected or bad dealloc field\n",
456		       err_print_prefix);
457
458	/*
459	 * The black hole events.
460	 */
461	if (io->po7_error_sum & IO7__PO7_ERRSUM__MAF_TO)
462		printk("%s    BLACK HOLE: Timeout for all responses\n",
463		       err_print_prefix);
464	if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_CDT_TO)
465		printk("%s    BLACK HOLE: Credit Timeout\n", err_print_prefix);
466	if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_CLK_HDR)
467		printk("%s    BLACK HOLE: Clock check on header\n",
468		       err_print_prefix);
469	if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_DBE_HDR)
470		printk("%s    BLACK HOLE: Uncorrectable Error on header\n",
471		       err_print_prefix);
472	if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_GBG_HDR)
473		printk("%s    BLACK HOLE: Garbage on header\n",
474		       err_print_prefix);
475	if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_BAD_CMD)
476		printk("%s    BLACK HOLE: Bad EV7 command\n",
477		       err_print_prefix);
478
479	if (io->po7_error_sum & IO7__PO7_ERRSUM__ERR_LST)
480		printk("%s    Lost Error\n", err_print_prefix);
481
482	printk("%s    Failing Packet:\n"
483	       "%s      Cycle 1: %016lx\n"
484	       "%s      Cycle 2: %016lx\n",
485	       err_print_prefix,
486	       err_print_prefix, io->po7_err_pkt0,
487	       err_print_prefix, io->po7_err_pkt1);
488	/*
489	 * If there are any valid bits in UNCRR sym for this err,
490	 * print UNCRR_SYM as well.
491	 */
492check_uncrr_sym:
493	if (uncrr_sym_valid)
494		marvel_print_po7_uncrr_sym(io->po7_uncrr_sym, uncrr_sym_valid);
495}
496
497static void
498marvel_print_pox_tlb_err(u64 tlb_err)
499{
500	static char *tlb_errors[] = {
501		"No Error",
502		"North Port Signaled Error fetching TLB entry",
503		"PTE invalid or UCC or GBG error on this entry",
504		"Address did not hit any DMA window"
505	};
506
507#define IO7__POX_TLBERR__ERR_VALID		(1UL << 63)
508#define IO7__POX_TLBERR__ERRCODE__S		(0)
509#define IO7__POX_TLBERR__ERRCODE__M		(0x3)
510#define IO7__POX_TLBERR__ERR_TLB_PTR__S		(3)
511#define IO7__POX_TLBERR__ERR_TLB_PTR__M		(0x7)
512#define IO7__POX_TLBERR__FADDR__S		(6)
513#define IO7__POX_TLBERR__FADDR__M		(0x3fffffffffful)
514
515	if (!(tlb_err & IO7__POX_TLBERR__ERR_VALID))
516		return;
517
518	printk("%s      TLB Error on index 0x%lx:\n"
519	       "%s        - %s\n"
520	       "%s        - Addr: 0x%016lx\n",
521	       err_print_prefix,
522	       EXTRACT(tlb_err, IO7__POX_TLBERR__ERR_TLB_PTR),
523	       err_print_prefix,
524	       tlb_errors[EXTRACT(tlb_err, IO7__POX_TLBERR__ERRCODE)],
525	       err_print_prefix,
526	       EXTRACT(tlb_err, IO7__POX_TLBERR__FADDR) << 6);
527}
528
529static  void
530marvel_print_pox_spl_cmplt(u64 spl_cmplt)
531{
532	char message[80];
533
534#define IO7__POX_SPLCMPLT__MESSAGE__S		(0)
535#define IO7__POX_SPLCMPLT__MESSAGE__M		(0x0fffffffful)
536#define IO7__POX_SPLCMPLT__SOURCE_BUS__S	(40)
537#define IO7__POX_SPLCMPLT__SOURCE_BUS__M	(0xfful)
538#define IO7__POX_SPLCMPLT__SOURCE_DEV__S	(35)
539#define IO7__POX_SPLCMPLT__SOURCE_DEV__M	(0x1ful)
540#define IO7__POX_SPLCMPLT__SOURCE_FUNC__S	(32)
541#define IO7__POX_SPLCMPLT__SOURCE_FUNC__M	(0x07ul)
542
543#define IO7__POX_SPLCMPLT__MSG_CLASS__S		(28)
544#define IO7__POX_SPLCMPLT__MSG_CLASS__M		(0xf)
545#define IO7__POX_SPLCMPLT__MSG_INDEX__S		(20)
546#define IO7__POX_SPLCMPLT__MSG_INDEX__M		(0xff)
547#define IO7__POX_SPLCMPLT__MSG_CLASSINDEX__S	(20)
548#define IO7__POX_SPLCMPLT__MSG_CLASSINDEX__M    (0xfff)
549#define IO7__POX_SPLCMPLT__REM_LOWER_ADDR__S	(12)
550#define IO7__POX_SPLCMPLT__REM_LOWER_ADDR__M	(0x7f)
551#define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__S	(0)
552#define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M	(0xfff)
553
554	printk("%s      Split Completion Error:\n"
555	       "%s         Source (Bus:Dev:Func): %ld:%ld:%ld\n",
556	       err_print_prefix,
557	       err_print_prefix,
558	       EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS),
559	       EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_DEV),
560	       EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_FUNC));
561
562	switch(EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MSG_CLASSINDEX)) {
563	case 0x000:
564		sprintf(message, "Normal completion");
565		break;
566	case 0x100:
567		sprintf(message, "Bridge - Master Abort");
568		break;
569	case 0x101:
570		sprintf(message, "Bridge - Target Abort");
571		break;
572	case 0x102:
573		sprintf(message, "Bridge - Uncorrectable Write Data Error");
574		break;
575	case 0x200:
576		sprintf(message, "Byte Count Out of Range");
577		break;
578	case 0x201:
579		sprintf(message, "Uncorrectable Split Write Data Error");
580		break;
581	default:
582		sprintf(message, "%08lx\n",
583			EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MESSAGE));
584		break;
585	}
586	printk("%s	   Message: %s\n", err_print_prefix, message);
587}
588
589static void
590marvel_print_pox_trans_sum(u64 trans_sum)
591{
592	char *pcix_cmd[] = { "Interrupt Acknowledge",
593			     "Special Cycle",
594			     "I/O Read",
595			     "I/O Write",
596			     "Reserved",
597			     "Reserved / Device ID Message",
598			     "Memory Read",
599			     "Memory Write",
600			     "Reserved / Alias to Memory Read Block",
601			     "Reserved / Alias to Memory Write Block",
602			     "Configuration Read",
603			     "Configuration Write",
604			     "Memory Read Multiple / Split Completion",
605			     "Dual Address Cycle",
606			     "Memory Read Line / Memory Read Block",
607			     "Memory Write and Invalidate / Memory Write Block"
608	};
609
610#define IO7__POX_TRANSUM__PCI_ADDR__S		(0)
611#define IO7__POX_TRANSUM__PCI_ADDR__M		(0x3fffffffffffful)
612#define IO7__POX_TRANSUM__DAC			(1UL << 50)
613#define IO7__POX_TRANSUM__PCIX_MASTER_SLOT__S	(52)
614#define IO7__POX_TRANSUM__PCIX_MASTER_SLOT__M	(0xf)
615#define IO7__POX_TRANSUM__PCIX_CMD__S		(56)
616#define IO7__POX_TRANSUM__PCIX_CMD__M		(0xf)
617#define IO7__POX_TRANSUM__ERR_VALID		(1UL << 63)
618
619	if (!(trans_sum & IO7__POX_TRANSUM__ERR_VALID))
620		return;
621
622	printk("%s      Transaction Summary:\n"
623	       "%s        Command: 0x%lx - %s\n"
624	       "%s        Address: 0x%016lx%s\n"
625	       "%s        PCI-X Master Slot: 0x%lx\n",
626	       err_print_prefix,
627	       err_print_prefix,
628	       EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD),
629	       pcix_cmd[EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD)],
630	       err_print_prefix,
631	       EXTRACT(trans_sum, IO7__POX_TRANSUM__PCI_ADDR),
632	       (trans_sum & IO7__POX_TRANSUM__DAC) ? " (DAC)" : "",
633	       err_print_prefix,
634	       EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_MASTER_SLOT));
635}
636
637static void
638marvel_print_pox_err(u64 err_sum, struct ev7_pal_io_one_port *port)
639{
640#define IO7__POX_ERRSUM__AGP_REQQ_OVFL    (1UL <<  4)
641#define IO7__POX_ERRSUM__AGP_SYNC_ERR     (1UL <<  5)
642#define IO7__POX_ERRSUM__MRETRY_TO        (1UL <<  6)
643#define IO7__POX_ERRSUM__PCIX_UX_SPL      (1UL <<  7)
644#define IO7__POX_ERRSUM__PCIX_SPLIT_TO    (1UL <<  8)
645#define IO7__POX_ERRSUM__PCIX_DISCARD_SPL (1UL <<  9)
646#define IO7__POX_ERRSUM__DMA_RD_TO        (1UL << 10)
647#define IO7__POX_ERRSUM__CSR_NXM_RD       (1UL << 11)
648#define IO7__POX_ERRSUM__CSR_NXM_WR       (1UL << 12)
649#define IO7__POX_ERRSUM__DMA_TO           (1UL << 13)
650#define IO7__POX_ERRSUM__ALL_MABORTS      (1UL << 14)
651#define IO7__POX_ERRSUM__MABORT		  (1UL << 15)
652#define IO7__POX_ERRSUM__MABORT_MASK	  (IO7__POX_ERRSUM__ALL_MABORTS|\
653					   IO7__POX_ERRSUM__MABORT)
654#define IO7__POX_ERRSUM__PT_TABORT        (1UL << 16)
655#define IO7__POX_ERRSUM__PM_TABORT        (1UL << 17)
656#define IO7__POX_ERRSUM__TABORT_MASK      (IO7__POX_ERRSUM__PT_TABORT | \
657                                           IO7__POX_ERRSUM__PM_TABORT)
658#define IO7__POX_ERRSUM__SERR             (1UL << 18)
659#define IO7__POX_ERRSUM__ADDRERR_STB      (1UL << 19)
660#define IO7__POX_ERRSUM__DETECTED_SERR    (1UL << 20)
661#define IO7__POX_ERRSUM__PERR             (1UL << 21)
662#define IO7__POX_ERRSUM__DATAERR_STB_NIOW (1UL << 22)
663#define IO7__POX_ERRSUM__DETECTED_PERR    (1UL << 23)
664#define IO7__POX_ERRSUM__PM_PERR          (1UL << 24)
665#define IO7__POX_ERRSUM__PT_SCERROR       (1UL << 26)
666#define IO7__POX_ERRSUM__HUNG_BUS         (1UL << 28)
667#define IO7__POX_ERRSUM__UPE_ERROR__S     (51)
668#define IO7__POX_ERRSUM__UPE_ERROR__M     (0xffUL)
669#define IO7__POX_ERRSUM__UPE_ERROR        GEN_MASK(IO7__POX_ERRSUM__UPE_ERROR)
670#define IO7__POX_ERRSUM__TLB_ERR          (1UL << 59)
671#define IO7__POX_ERRSUM__ERR_VALID        (1UL << 63)
672
673#define IO7__POX_ERRSUM__TRANS_SUM__MASK  (IO7__POX_ERRSUM__MRETRY_TO |       \
674					   IO7__POX_ERRSUM__PCIX_UX_SPL |     \
675					   IO7__POX_ERRSUM__PCIX_SPLIT_TO |   \
676					   IO7__POX_ERRSUM__DMA_TO |          \
677					   IO7__POX_ERRSUM__MABORT_MASK |     \
678					   IO7__POX_ERRSUM__TABORT_MASK |     \
679					   IO7__POX_ERRSUM__SERR |            \
680					   IO7__POX_ERRSUM__ADDRERR_STB |     \
681					   IO7__POX_ERRSUM__PERR |            \
682					   IO7__POX_ERRSUM__DATAERR_STB_NIOW |\
683					   IO7__POX_ERRSUM__DETECTED_PERR |   \
684					   IO7__POX_ERRSUM__PM_PERR |         \
685					   IO7__POX_ERRSUM__PT_SCERROR |      \
686					   IO7__POX_ERRSUM__UPE_ERROR)
687
688	if (!(err_sum & IO7__POX_ERRSUM__ERR_VALID))
689		return;
690
691	/*
692	 * First the transaction summary errors
693	 */
694	if (err_sum & IO7__POX_ERRSUM__MRETRY_TO)
695		printk("%s    IO7 Master Retry Timeout expired\n",
696		       err_print_prefix);
697	if (err_sum & IO7__POX_ERRSUM__PCIX_UX_SPL)
698		printk("%s    Unexpected Split Completion\n",
699		       err_print_prefix);
700	if (err_sum & IO7__POX_ERRSUM__PCIX_SPLIT_TO)
701		printk("%s    IO7 Split Completion Timeout expired\n",
702		       err_print_prefix);
703	if (err_sum & IO7__POX_ERRSUM__DMA_TO)
704		printk("%s    Hung bus during DMA transaction\n",
705		       err_print_prefix);
706	if (err_sum & IO7__POX_ERRSUM__MABORT_MASK)
707		printk("%s    Master Abort\n", err_print_prefix);
708	if (err_sum & IO7__POX_ERRSUM__PT_TABORT)
709		printk("%s    IO7 Asserted Target Abort\n", err_print_prefix);
710	if (err_sum & IO7__POX_ERRSUM__PM_TABORT)
711		printk("%s    IO7 Received Target Abort\n", err_print_prefix);
712	if (err_sum & IO7__POX_ERRSUM__ADDRERR_STB) {
713		printk("%s    Address or PCI-X Attribute Parity Error\n",
714		       err_print_prefix);
715		if (err_sum & IO7__POX_ERRSUM__SERR)
716			printk("%s     IO7 Asserted SERR\n", err_print_prefix);
717	}
718	if (err_sum & IO7__POX_ERRSUM__PERR) {
719		if (err_sum & IO7__POX_ERRSUM__DATAERR_STB_NIOW)
720			printk("%s    IO7 Detected Data Parity Error\n",
721			       err_print_prefix);
722		else
723			printk("%s    Split Completion Response with "
724			       "Parity Error\n", err_print_prefix);
725	}
726	if (err_sum & IO7__POX_ERRSUM__DETECTED_PERR)
727		printk("%s    PERR detected\n", err_print_prefix);
728	if (err_sum & IO7__POX_ERRSUM__PM_PERR)
729		printk("%s    PERR while IO7 is master\n", err_print_prefix);
730	if (err_sum & IO7__POX_ERRSUM__PT_SCERROR) {
731		printk("%s    IO7 Received Split Completion Error message\n",
732		       err_print_prefix);
733		marvel_print_pox_spl_cmplt(port->pox_spl_cmplt);
734	}
735	if (err_sum & IO7__POX_ERRSUM__UPE_ERROR) {
736		unsigned int upe_error = EXTRACT(err_sum,
737						 IO7__POX_ERRSUM__UPE_ERROR);
738		int i;
739		static char *upe_errors[] = {
740			"Parity Error on MSI write data",
741			"MSI read (MSI window is write only",
742			"TLB - Invalid WR transaction",
743			"TLB - Invalid RD transaction",
744			"DMA - WR error (see north port)",
745			"DMA - RD error (see north port)",
746			"PPR - WR error (see north port)",
747			"PPR - RD error (see north port)"
748		};
749
750		printk("%s    UPE Error:\n", err_print_prefix);
751		for (i = 0; i < 8; i++) {
752			if (upe_error & (1 << i))
753				printk("%s      %s\n", err_print_prefix,
754				       upe_errors[i]);
755		}
756	}
757
758	/*
759	 * POx_TRANS_SUM, if appropriate.
760	 */
761	if (err_sum & IO7__POX_ERRSUM__TRANS_SUM__MASK)
762		marvel_print_pox_trans_sum(port->pox_trans_sum);
763
764	/*
765	 * Then TLB_ERR.
766	 */
767	if (err_sum & IO7__POX_ERRSUM__TLB_ERR) {
768		printk("%s    TLB ERROR\n", err_print_prefix);
769		marvel_print_pox_tlb_err(port->pox_tlb_err);
770	}
771
772	/*
773	 * And the single bit status errors.
774	 */
775	if (err_sum & IO7__POX_ERRSUM__AGP_REQQ_OVFL)
776		printk("%s    AGP Request Queue Overflow\n", err_print_prefix);
777	if (err_sum & IO7__POX_ERRSUM__AGP_SYNC_ERR)
778		printk("%s    AGP Sync Error\n", err_print_prefix);
779	if (err_sum & IO7__POX_ERRSUM__PCIX_DISCARD_SPL)
780		printk("%s    Discarded split completion\n", err_print_prefix);
781	if (err_sum & IO7__POX_ERRSUM__DMA_RD_TO)
782		printk("%s    DMA Read Timeout\n", err_print_prefix);
783	if (err_sum & IO7__POX_ERRSUM__CSR_NXM_RD)
784		printk("%s    CSR NXM READ\n", err_print_prefix);
785	if (err_sum & IO7__POX_ERRSUM__CSR_NXM_WR)
786		printk("%s    CSR NXM WRITE\n", err_print_prefix);
787	if (err_sum & IO7__POX_ERRSUM__DETECTED_SERR)
788		printk("%s    SERR detected\n", err_print_prefix);
789	if (err_sum & IO7__POX_ERRSUM__HUNG_BUS)
790		printk("%s    HUNG BUS detected\n", err_print_prefix);
791}
792
793#endif /* CONFIG_VERBOSE_MCHECK */
794
795static struct ev7_pal_io_subpacket *
796marvel_find_io7_with_error(struct ev7_lf_subpackets *lf_subpackets)
797{
798	struct ev7_pal_io_subpacket *io = lf_subpackets->io;
799	struct io7 *io7;
800	int i;
801
802	/*
803	 * Caller must provide the packet to fill
804	 */
805	if (!io)
806		return NULL;
807
808	/*
809	 * Fill the subpacket with the console's standard fill pattern
810	 */
811	memset(io, 0x55, sizeof(*io));
812
813	for (io7 = NULL; NULL != (io7 = marvel_next_io7(io7)); ) {
814		unsigned long err_sum = 0;
815
816		err_sum |= io7->csrs->PO7_ERROR_SUM.csr;
817		for (i = 0; i < IO7_NUM_PORTS; i++) {
818			if (!io7->ports[i].enabled)
819				continue;
820			err_sum |= io7->ports[i].csrs->POx_ERR_SUM.csr;
821		}
822
823		/*
824		 * Is there at least one error?
825		 */
826		if (err_sum & (1UL << 63))
827			break;
828	}
829
830	/*
831	 * Did we find an IO7 with an error?
832	 */
833	if (!io7)
834		return NULL;
835
836	/*
837	 * We have an IO7 with an error.
838	 *
839	 * Fill in the IO subpacket.
840	 */
841	io->io_asic_rev   = io7->csrs->IO_ASIC_REV.csr;
842	io->io_sys_rev    = io7->csrs->IO_SYS_REV.csr;
843	io->io7_uph       = io7->csrs->IO7_UPH.csr;
844	io->hpi_ctl       = io7->csrs->HPI_CTL.csr;
845	io->crd_ctl       = io7->csrs->CRD_CTL.csr;
846	io->hei_ctl       = io7->csrs->HEI_CTL.csr;
847	io->po7_error_sum = io7->csrs->PO7_ERROR_SUM.csr;
848	io->po7_uncrr_sym = io7->csrs->PO7_UNCRR_SYM.csr;
849	io->po7_crrct_sym = io7->csrs->PO7_CRRCT_SYM.csr;
850	io->po7_ugbge_sym = io7->csrs->PO7_UGBGE_SYM.csr;
851	io->po7_err_pkt0  = io7->csrs->PO7_ERR_PKT[0].csr;
852	io->po7_err_pkt1  = io7->csrs->PO7_ERR_PKT[1].csr;
853
854	for (i = 0; i < IO7_NUM_PORTS; i++) {
855		io7_ioport_csrs *csrs = io7->ports[i].csrs;
856
857		if (!io7->ports[i].enabled)
858			continue;
859
860		io->ports[i].pox_err_sum   = csrs->POx_ERR_SUM.csr;
861		io->ports[i].pox_tlb_err   = csrs->POx_TLB_ERR.csr;
862		io->ports[i].pox_spl_cmplt = csrs->POx_SPL_COMPLT.csr;
863		io->ports[i].pox_trans_sum = csrs->POx_TRANS_SUM.csr;
864		io->ports[i].pox_first_err = csrs->POx_FIRST_ERR.csr;
865		io->ports[i].pox_mult_err  = csrs->POx_MULT_ERR.csr;
866		io->ports[i].pox_dm_source = csrs->POx_DM_SOURCE.csr;
867		io->ports[i].pox_dm_dest   = csrs->POx_DM_DEST.csr;
868		io->ports[i].pox_dm_size   = csrs->POx_DM_SIZE.csr;
869		io->ports[i].pox_dm_ctrl   = csrs->POx_DM_CTRL.csr;
870
871		/*
872		 * Ack this port's errors, if any. POx_ERR_SUM must be last.
873		 *
874		 * Most of the error registers get cleared and unlocked when
875		 * the associated bits in POx_ERR_SUM are cleared (by writing
876		 * 1). POx_TLB_ERR is an exception and must be explicitly
877		 * cleared.
878		 */
879		csrs->POx_TLB_ERR.csr = io->ports[i].pox_tlb_err;
880		csrs->POx_ERR_SUM.csr =	io->ports[i].pox_err_sum;
881		mb();
882		csrs->POx_ERR_SUM.csr;
883	}
884
885	/*
886	 * Ack any port 7 error(s).
887	 */
888	io7->csrs->PO7_ERROR_SUM.csr = io->po7_error_sum;
889	mb();
890	io7->csrs->PO7_ERROR_SUM.csr;
891
892	/*
893	 * Correct the io7_pid.
894	 */
895	lf_subpackets->io_pid = io7->pe;
896
897	return io;
898}
899
900static int
901marvel_process_io_error(struct ev7_lf_subpackets *lf_subpackets, int print)
902{
903	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
904
905#ifdef CONFIG_VERBOSE_MCHECK
906	struct ev7_pal_io_subpacket *io = lf_subpackets->io;
907	int i;
908#endif /* CONFIG_VERBOSE_MCHECK */
909
910#define MARVEL_IO_ERR_VALID(x)  ((x) & (1UL << 63))
911
912	if (!lf_subpackets->logout || !lf_subpackets->io)
913		return status;
914
915	/*
916	 * The PALcode only builds an IO subpacket if there is a
917	 * locally connected IO7. In the cases of
918	 *	1) a uniprocessor kernel
919	 *	2) an mp kernel before the local secondary has called in
920	 * error interrupts are all directed to the primary processor.
921	 * In that case, we may not have an IO subpacket at all and, event
922	 * if we do, it may not be the right now.
923	 *
924	 * If the RBOX indicates an I/O error interrupt, make sure we have
925	 * the correct IO7 information. If we don't have an IO subpacket
926	 * or it's the wrong one, try to find the right one.
927	 *
928	 * RBOX I/O error interrupts are indicated by RBOX_INT<29> and
929	 * RBOX_INT<10>.
930	 */
931	if ((lf_subpackets->io->po7_error_sum & (1UL << 32)) ||
932	    ((lf_subpackets->io->po7_error_sum        |
933	      lf_subpackets->io->ports[0].pox_err_sum |
934	      lf_subpackets->io->ports[1].pox_err_sum |
935	      lf_subpackets->io->ports[2].pox_err_sum |
936	      lf_subpackets->io->ports[3].pox_err_sum) & (1UL << 63))) {
937		/*
938		 * Either we have no IO subpacket or no error is
939		 * indicated in the one we do have. Try find the
940		 * one with the error.
941		 */
942		if (!marvel_find_io7_with_error(lf_subpackets))
943			return status;
944	}
945
946	/*
947	 * We have an IO7 indicating an error - we're going to report it
948	 */
949	status = MCHK_DISPOSITION_REPORT;
950
951#ifdef CONFIG_VERBOSE_MCHECK
952
953	if (!print)
954		return status;
955
956	printk("%s*Error occurred on IO7 at PID %u\n",
957	       err_print_prefix, lf_subpackets->io_pid);
958
959	/*
960	 * Check port 7 first
961	 */
962	if (lf_subpackets->io->po7_error_sum & IO7__PO7_ERRSUM__ERR_MASK) {
963		marvel_print_po7_err_sum(io);
964
965	}
966
967	/*
968	 * Then loop through the ports
969	 */
970	for (i = 0; i < IO7_NUM_PORTS; i++) {
971		if (!MARVEL_IO_ERR_VALID(io->ports[i].pox_err_sum))
972			continue;
973
974		printk("%s  PID %u PORT %d POx_ERR_SUM: %016lx\n",
975		       err_print_prefix,
976		       lf_subpackets->io_pid, i, io->ports[i].pox_err_sum);
977		marvel_print_pox_err(io->ports[i].pox_err_sum, &io->ports[i]);
978
979		printk("%s  [ POx_FIRST_ERR: %016lx ]\n",
980		       err_print_prefix, io->ports[i].pox_first_err);
981		marvel_print_pox_err(io->ports[i].pox_first_err,
982				     &io->ports[i]);
983
984	}
985
986
987#endif /* CONFIG_VERBOSE_MCHECK */
988
989	return status;
990}
991
992static int
993marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
994{
995	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
996
997	/*
998	 * I/O error?
999	 */
1000#define EV7__RBOX_INT__IO_ERROR__MASK 0x20000400ul
1001	if (lf_subpackets->logout &&
1002	    (lf_subpackets->logout->rbox_int & 0x20000400ul))
1003		status = marvel_process_io_error(lf_subpackets, print);
1004
1005	/*
1006	 * Probing behind PCI-X bridges can cause machine checks on
1007	 * Marvel when the probe is handled by the bridge as a split
1008	 * completion transaction. The symptom is an ERROR_RESPONSE
1009	 * to a CONFIG address. Since these errors will happen in
1010	 * normal operation, dismiss them.
1011	 *
1012	 * Dismiss if:
1013	 *	C_STAT		= 0x14 		(Error Reponse)
1014	 *	C_STS<3>	= 0    		(C_ADDR valid)
1015	 *	C_ADDR<42>	= 1    		(I/O)
1016	 *	C_ADDR<31:22>	= 111110xxb	(PCI Config space)
1017	 */
1018	if (lf_subpackets->ev7 &&
1019	    (lf_subpackets->ev7->c_stat == 0x14) &&
1020	    !(lf_subpackets->ev7->c_sts & 0x8) &&
1021	    ((lf_subpackets->ev7->c_addr & 0x400ff000000ul)
1022	     == 0x400fe000000ul))
1023		status = MCHK_DISPOSITION_DISMISS;
1024
1025	return status;
1026}
1027
1028void
1029marvel_machine_check(u64 vector, u64 la_ptr)
1030{
1031	struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
1032	int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL;
1033	struct ev7_lf_subpackets subpacket_collection = { NULL, };
1034	struct ev7_pal_io_subpacket scratch_io_packet = { 0, };
1035	struct ev7_lf_subpackets *lf_subpackets = NULL;
1036	int disposition = MCHK_DISPOSITION_UNKNOWN_ERROR;
1037	char *saved_err_prefix = err_print_prefix;
1038	char *error_type = NULL;
1039
1040	/*
1041	 * Sync the processor
1042	 */
1043	mb();
1044	draina();
1045
1046	switch(vector) {
1047	case SCB_Q_SYSEVENT:
1048		process_frame = marvel_process_680_frame;
1049		error_type = "System Event";
1050		break;
1051
1052	case SCB_Q_SYSMCHK:
1053		process_frame = marvel_process_logout_frame;
1054		error_type = "System Uncorrectable Error";
1055		break;
1056
1057	case SCB_Q_SYSERR:
1058		process_frame = marvel_process_logout_frame;
1059		error_type = "System Correctable Error";
1060		break;
1061
1062	default:
1063		/* Don't know it - pass it up.  */
1064		ev7_machine_check(vector, la_ptr);
1065		return;
1066	}
1067
1068	/*
1069	 * A system event or error has occured, handle it here.
1070	 *
1071	 * Any errors in the logout frame have already been cleared by the
1072	 * PALcode, so just parse it.
1073	 */
1074	err_print_prefix = KERN_CRIT;
1075
1076	/*
1077	 * Parse the logout frame without printing first. If the only error(s)
1078	 * found are classified as "dismissable", then just dismiss them and
1079	 * don't print any message
1080	 */
1081	lf_subpackets =
1082		ev7_collect_logout_frame_subpackets(el_ptr,
1083						    &subpacket_collection);
1084	if (process_frame && lf_subpackets && lf_subpackets->logout) {
1085		/*
1086		 * We might not have the correct (or any) I/O subpacket.
1087		 * [ See marvel_process_io_error() for explanation. ]
1088		 * If we don't have one, point the io subpacket in
1089		 * lf_subpackets at scratch_io_packet so that
1090		 * marvel_find_io7_with_error() will have someplace to
1091		 * store the info.
1092		 */
1093		if (!lf_subpackets->io)
1094			lf_subpackets->io = &scratch_io_packet;
1095
1096		/*
1097		 * Default io_pid to the processor reporting the error
1098		 * [this will get changed in marvel_find_io7_with_error()
1099		 * if a different one is needed]
1100		 */
1101		lf_subpackets->io_pid = lf_subpackets->logout->whami;
1102
1103		/*
1104		 * Evaluate the frames.
1105		 */
1106		disposition = process_frame(lf_subpackets, 0);
1107	}
1108	switch(disposition) {
1109	case MCHK_DISPOSITION_DISMISS:
1110		/* Nothing to do. */
1111		break;
1112
1113	case MCHK_DISPOSITION_REPORT:
1114		/* Recognized error, report it. */
1115		printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
1116		       err_print_prefix, error_type,
1117		       (unsigned int)vector, (int)smp_processor_id());
1118		el_print_timestamp(&lf_subpackets->logout->timestamp);
1119		process_frame(lf_subpackets, 1);
1120		break;
1121
1122	default:
1123		/* Unknown - dump the annotated subpackets. */
1124		printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
1125		       err_print_prefix, error_type,
1126		       (unsigned int)vector, (int)smp_processor_id());
1127		el_process_subpacket(el_ptr);
1128		break;
1129
1130	}
1131
1132	err_print_prefix = saved_err_prefix;
1133
1134        /* Release the logout frame.  */
1135	wrmces(0x7);
1136	mb();
1137}
1138
1139void
1140marvel_register_error_handlers(void)
1141{
1142	ev7_register_error_handlers();
1143}
1144