xref: /linux/arch/alpha/kernel/err_titan.c (revision b24413180f5600bcb3bb70fbed5cf186b60864bd)
1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *	linux/arch/alpha/kernel/err_titan.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *	Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *	Error handling code supporting TITAN systems
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds #include <linux/init.h>
111da177e4SLinus Torvalds #include <linux/pci.h>
121da177e4SLinus Torvalds #include <linux/sched.h>
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include <asm/io.h>
151da177e4SLinus Torvalds #include <asm/core_titan.h>
161da177e4SLinus Torvalds #include <asm/hwrpb.h>
171da177e4SLinus Torvalds #include <asm/smp.h>
181da177e4SLinus Torvalds #include <asm/err_common.h>
191da177e4SLinus Torvalds #include <asm/err_ev6.h>
201b75b05bSIvan Kokshaysky #include <asm/irq_regs.h>
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds #include "err_impl.h"
231da177e4SLinus Torvalds #include "proto.h"
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds static int
271da177e4SLinus Torvalds titan_parse_c_misc(u64 c_misc, int print)
281da177e4SLinus Torvalds {
291da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
301da177e4SLinus Torvalds 	char *src;
311da177e4SLinus Torvalds 	int nxs = 0;
321da177e4SLinus Torvalds #endif
331da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_REPORT;
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds #define TITAN__CCHIP_MISC__NXM		(1UL << 28)
361da177e4SLinus Torvalds #define TITAN__CCHIP_MISC__NXS__S	(29)
371da177e4SLinus Torvalds #define TITAN__CCHIP_MISC__NXS__M	(0x7)
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds 	if (!(c_misc & TITAN__CCHIP_MISC__NXM))
401da177e4SLinus Torvalds 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
431da177e4SLinus Torvalds 	if (!print)
441da177e4SLinus Torvalds 		return status;
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds 	nxs = EXTRACT(c_misc, TITAN__CCHIP_MISC__NXS);
471da177e4SLinus Torvalds 	switch(nxs) {
481da177e4SLinus Torvalds 	case 0:	/* CPU 0 */
491da177e4SLinus Torvalds 	case 1:	/* CPU 1 */
501da177e4SLinus Torvalds 	case 2:	/* CPU 2 */
511da177e4SLinus Torvalds 	case 3:	/* CPU 3 */
521da177e4SLinus Torvalds 		src = "CPU";
531da177e4SLinus Torvalds 		/* num is already the CPU number */
541da177e4SLinus Torvalds 		break;
551da177e4SLinus Torvalds 	case 4:	/* Pchip 0 */
561da177e4SLinus Torvalds 	case 5:	/* Pchip 1 */
571da177e4SLinus Torvalds 		src = "Pchip";
581da177e4SLinus Torvalds 		nxs -= 4;
591da177e4SLinus Torvalds 		break;
601da177e4SLinus Torvalds 	default:/* reserved */
611da177e4SLinus Torvalds 		src = "Unknown, NXS =";
621da177e4SLinus Torvalds 		/* leave num untouched */
631da177e4SLinus Torvalds 		break;
641da177e4SLinus Torvalds 	}
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds 	printk("%s    Non-existent memory access from: %s %d\n",
671da177e4SLinus Torvalds 	       err_print_prefix, src, nxs);
681da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds 	return status;
711da177e4SLinus Torvalds }
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds static int
741da177e4SLinus Torvalds titan_parse_p_serror(int which, u64 serror, int print)
751da177e4SLinus Torvalds {
761da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_REPORT;
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
7931019075SJoe Perches 	static const char * const serror_src[] = {
8031019075SJoe Perches 		"GPCI", "APCI", "AGP HP", "AGP LP"
8131019075SJoe Perches 	};
8231019075SJoe Perches 	static const char * const serror_cmd[] = {
8331019075SJoe Perches 		"DMA Read", "DMA RMW", "SGTE Read", "Reserved"
8431019075SJoe Perches 	};
851da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__LOST_UECC	(1UL << 0)
881da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__UECC	(1UL << 1)
891da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__CRE	(1UL << 2)
901da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__NXIO	(1UL << 3)
911da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__LOST_CRE	(1UL << 4)
921da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__ECCMASK	(TITAN__PCHIP_SERROR__UECC |	  \
931da177e4SLinus Torvalds 					 TITAN__PCHIP_SERROR__CRE)
941da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__ERRMASK	(TITAN__PCHIP_SERROR__LOST_UECC | \
951da177e4SLinus Torvalds 					 TITAN__PCHIP_SERROR__UECC |	  \
961da177e4SLinus Torvalds 					 TITAN__PCHIP_SERROR__CRE |	  \
971da177e4SLinus Torvalds 					 TITAN__PCHIP_SERROR__NXIO |	  \
981da177e4SLinus Torvalds 					 TITAN__PCHIP_SERROR__LOST_CRE)
991da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__SRC__S	(52)
1001da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__SRC__M	(0x3)
1011da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__CMD__S	(54)
1021da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__CMD__M	(0x3)
1031da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__SYN__S	(56)
1041da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__SYN__M	(0xff)
1051da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__ADDR__S	(15)
1061da177e4SLinus Torvalds #define TITAN__PCHIP_SERROR__ADDR__M	(0xffffffffUL)
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds 	if (!(serror & TITAN__PCHIP_SERROR__ERRMASK))
1091da177e4SLinus Torvalds 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
1121da177e4SLinus Torvalds 	if (!print)
1131da177e4SLinus Torvalds 		return status;
1141da177e4SLinus Torvalds 
1155f0e3da6SRandy Dunlap 	printk("%s  PChip %d SERROR: %016llx\n",
1161da177e4SLinus Torvalds 	       err_print_prefix, which, serror);
1171da177e4SLinus Torvalds 	if (serror & TITAN__PCHIP_SERROR__ECCMASK) {
1181da177e4SLinus Torvalds 		printk("%s    %sorrectable ECC Error:\n"
1191da177e4SLinus Torvalds 		       "      Source: %-6s  Command: %-8s  Syndrome: 0x%08x\n"
1205f0e3da6SRandy Dunlap 		       "      Address: 0x%llx\n",
1211da177e4SLinus Torvalds 		       err_print_prefix,
1221da177e4SLinus Torvalds 		       (serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C",
1231da177e4SLinus Torvalds 		       serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)],
1241da177e4SLinus Torvalds 		       serror_cmd[EXTRACT(serror, TITAN__PCHIP_SERROR__CMD)],
1251da177e4SLinus Torvalds 		       (unsigned)EXTRACT(serror, TITAN__PCHIP_SERROR__SYN),
1261da177e4SLinus Torvalds 		       EXTRACT(serror, TITAN__PCHIP_SERROR__ADDR));
1271da177e4SLinus Torvalds 	}
1281da177e4SLinus Torvalds 	if (serror & TITAN__PCHIP_SERROR__NXIO)
1291da177e4SLinus Torvalds 		printk("%s    Non Existent I/O Error\n", err_print_prefix);
1301da177e4SLinus Torvalds 	if (serror & TITAN__PCHIP_SERROR__LOST_UECC)
1311da177e4SLinus Torvalds 		printk("%s    Lost Uncorrectable ECC Error\n",
1321da177e4SLinus Torvalds 		       err_print_prefix);
1331da177e4SLinus Torvalds 	if (serror & TITAN__PCHIP_SERROR__LOST_CRE)
1341da177e4SLinus Torvalds 		printk("%s    Lost Correctable ECC Error\n", err_print_prefix);
1351da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 	return status;
1381da177e4SLinus Torvalds }
1391da177e4SLinus Torvalds 
1401da177e4SLinus Torvalds static int
1411da177e4SLinus Torvalds titan_parse_p_perror(int which, int port, u64 perror, int print)
1421da177e4SLinus Torvalds {
1431da177e4SLinus Torvalds 	int cmd;
1441da177e4SLinus Torvalds 	unsigned long addr;
1451da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_REPORT;
1461da177e4SLinus Torvalds 
1471da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
14831019075SJoe Perches 	static const char * const perror_cmd[] = {
14931019075SJoe Perches 		"Interrupt Acknowledge", "Special Cycle",
1501da177e4SLinus Torvalds 		"I/O Read",		"I/O Write",
1511da177e4SLinus Torvalds 		"Reserved",		"Reserved",
1521da177e4SLinus Torvalds 		"Memory Read",		"Memory Write",
1531da177e4SLinus Torvalds 		"Reserved",		"Reserved",
1541da177e4SLinus Torvalds 		"Configuration Read",	"Configuration Write",
1551da177e4SLinus Torvalds 		"Memory Read Multiple",	"Dual Address Cycle",
1561da177e4SLinus Torvalds 		"Memory Read Line",	"Memory Write and Invalidate"
1571da177e4SLinus Torvalds 	};
1581da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
1591da177e4SLinus Torvalds 
1601da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__LOST	(1UL << 0)
1611da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__SERR	(1UL << 1)
1621da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__PERR	(1UL << 2)
1631da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__DCRTO	(1UL << 3)
1641da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__SGE	(1UL << 4)
1651da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__APE	(1UL << 5)
1661da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__TA		(1UL << 6)
1671da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__DPE	(1UL << 7)
1681da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__NDS	(1UL << 8)
1691da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__IPTPR	(1UL << 9)
1701da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__IPTPW	(1UL << 10)
1711da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__ERRMASK	(TITAN__PCHIP_PERROR__LOST |	\
1721da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__SERR |	\
1731da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__PERR |	\
1741da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__DCRTO |	\
1751da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__SGE |	\
1761da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__APE |	\
1771da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__TA |	\
1781da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__DPE |	\
1791da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__NDS |	\
1801da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__IPTPR |	\
1811da177e4SLinus Torvalds 					 TITAN__PCHIP_PERROR__IPTPW)
1821da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__DAC	(1UL << 47)
1831da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__MWIN	(1UL << 48)
1841da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__CMD__S	(52)
1851da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__CMD__M	(0x0f)
1861da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__ADDR__S	(14)
1871da177e4SLinus Torvalds #define TITAN__PCHIP_PERROR__ADDR__M	(0x1fffffffful)
1881da177e4SLinus Torvalds 
1891da177e4SLinus Torvalds 	if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
1901da177e4SLinus Torvalds 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds 	cmd = EXTRACT(perror, TITAN__PCHIP_PERROR__CMD);
1931da177e4SLinus Torvalds 	addr = EXTRACT(perror, TITAN__PCHIP_PERROR__ADDR) << 2;
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds 	/*
1961da177e4SLinus Torvalds 	 * Initializing the BIOS on a video card on a bus without
1971da177e4SLinus Torvalds 	 * a south bridge (subtractive decode agent) can result in
1981da177e4SLinus Torvalds 	 * master aborts as the BIOS probes the capabilities of the
1991da177e4SLinus Torvalds 	 * card. XFree86 does such initialization. If the error
2001da177e4SLinus Torvalds 	 * is a master abort (No DevSel as PCI Master) and the command
2011da177e4SLinus Torvalds 	 * is an I/O read or write below the address where we start
2021da177e4SLinus Torvalds 	 * assigning PCI I/O spaces (SRM uses 0x1000), then mark the
2031da177e4SLinus Torvalds 	 * error as dismissable so starting XFree86 doesn't result
2041da177e4SLinus Torvalds 	 * in a series of uncorrectable errors being reported. Also
2051da177e4SLinus Torvalds 	 * dismiss master aborts to VGA frame buffer space
2061da177e4SLinus Torvalds 	 * (0xA0000 - 0xC0000) and legacy BIOS space (0xC0000 - 0x100000)
2071da177e4SLinus Torvalds 	 * for the same reason.
2081da177e4SLinus Torvalds 	 *
2091da177e4SLinus Torvalds 	 * Also mark the error dismissible if it looks like the right
2101da177e4SLinus Torvalds 	 * error but only the Lost bit is set. Since the BIOS initialization
2111da177e4SLinus Torvalds 	 * can cause multiple master aborts and the error interrupt can
2121da177e4SLinus Torvalds 	 * be handled on a different CPU than the BIOS code is run on,
2131da177e4SLinus Torvalds 	 * it is possible for a second master abort to occur between the
2141da177e4SLinus Torvalds 	 * time the PALcode reads PERROR and the time it writes PERROR
2151da177e4SLinus Torvalds 	 * to acknowledge the error. If this timing happens, a second
2161da177e4SLinus Torvalds 	 * error will be signalled after the first, and if no additional
2171da177e4SLinus Torvalds 	 * errors occur, will look like a Lost error with no additional
2181da177e4SLinus Torvalds 	 * errors on the same transaction as the previous error.
2191da177e4SLinus Torvalds 	 */
2201da177e4SLinus Torvalds 	if (((perror & TITAN__PCHIP_PERROR__NDS) ||
2211da177e4SLinus Torvalds 	     ((perror & TITAN__PCHIP_PERROR__ERRMASK) ==
2221da177e4SLinus Torvalds 	      TITAN__PCHIP_PERROR__LOST)) &&
2231da177e4SLinus Torvalds 	    ((((cmd & 0xE) == 2) && (addr < 0x1000)) ||
2241da177e4SLinus Torvalds 	     (((cmd & 0xE) == 6) && (addr >= 0xA0000) && (addr < 0x100000)))) {
2251da177e4SLinus Torvalds 		status = MCHK_DISPOSITION_DISMISS;
2261da177e4SLinus Torvalds 	}
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
2291da177e4SLinus Torvalds 	if (!print)
2301da177e4SLinus Torvalds 		return status;
2311da177e4SLinus Torvalds 
2325f0e3da6SRandy Dunlap 	printk("%s  PChip %d %cPERROR: %016llx\n",
2331da177e4SLinus Torvalds 	       err_print_prefix, which,
2341da177e4SLinus Torvalds 	       port ? 'A' : 'G', perror);
2351da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__IPTPW)
2361da177e4SLinus Torvalds 		printk("%s    Invalid Peer-to-Peer Write\n", err_print_prefix);
2371da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__IPTPR)
2381da177e4SLinus Torvalds 		printk("%s    Invalid Peer-to-Peer Read\n", err_print_prefix);
2391da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__NDS)
2401da177e4SLinus Torvalds 		printk("%s    No DEVSEL as PCI Master [Master Abort]\n",
2411da177e4SLinus Torvalds 		       err_print_prefix);
2421da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__DPE)
2431da177e4SLinus Torvalds 		printk("%s    Data Parity Error\n", err_print_prefix);
2441da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__TA)
2451da177e4SLinus Torvalds 		printk("%s    Target Abort\n", err_print_prefix);
2461da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__APE)
2471da177e4SLinus Torvalds 		printk("%s    Address Parity Error\n", err_print_prefix);
2481da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__SGE)
2491da177e4SLinus Torvalds 		printk("%s    Scatter-Gather Error, Invalid PTE\n",
2501da177e4SLinus Torvalds 		       err_print_prefix);
2511da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__DCRTO)
2521da177e4SLinus Torvalds 		printk("%s    Delayed-Completion Retry Timeout\n",
2531da177e4SLinus Torvalds 		       err_print_prefix);
2541da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__PERR)
2551da177e4SLinus Torvalds 		printk("%s    PERR Asserted\n", err_print_prefix);
2561da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__SERR)
2571da177e4SLinus Torvalds 		printk("%s    SERR Asserted\n", err_print_prefix);
2581da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__LOST)
2591da177e4SLinus Torvalds 		printk("%s    Lost Error\n", err_print_prefix);
2601da177e4SLinus Torvalds 	printk("%s      Command: 0x%x - %s\n"
2611da177e4SLinus Torvalds 		 "      Address: 0x%lx\n",
2621da177e4SLinus Torvalds 	       err_print_prefix,
2631da177e4SLinus Torvalds 	       cmd, perror_cmd[cmd],
2641da177e4SLinus Torvalds 	       addr);
2651da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__DAC)
2661da177e4SLinus Torvalds 		printk("%s      Dual Address Cycle\n", err_print_prefix);
2671da177e4SLinus Torvalds 	if (perror & TITAN__PCHIP_PERROR__MWIN)
2681da177e4SLinus Torvalds 		printk("%s      Hit in Monster Window\n", err_print_prefix);
2691da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	return status;
2721da177e4SLinus Torvalds }
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds static int
2751da177e4SLinus Torvalds titan_parse_p_agperror(int which, u64 agperror, int print)
2761da177e4SLinus Torvalds {
2771da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_REPORT;
2781da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
2791da177e4SLinus Torvalds 	int cmd, len;
2801da177e4SLinus Torvalds 	unsigned long addr;
2811da177e4SLinus Torvalds 
28231019075SJoe Perches 	static const char * const agperror_cmd[] = {
28331019075SJoe Perches 		"Read (low-priority)",	"Read (high-priority)",
28431019075SJoe Perches 		"Write (low-priority)",	"Write (high-priority)",
2851da177e4SLinus Torvalds 		"Reserved",		"Reserved",
2861da177e4SLinus Torvalds 		"Flush",		"Fence"
2871da177e4SLinus Torvalds 	};
2881da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
2891da177e4SLinus Torvalds 
2901da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__LOST	(1UL << 0)
2911da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__LPQFULL	(1UL << 1)
2921da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__HPQFULL	(1UL << 2)
2931da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__RESCMD	(1UL << 3)
2941da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__IPTE	(1UL << 4)
2951da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__PTP	(1UL << 5)
2961da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__NOWINDOW	(1UL << 6)
2971da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__ERRMASK	(TITAN__PCHIP_AGPERROR__LOST |    \
2981da177e4SLinus Torvalds 					 TITAN__PCHIP_AGPERROR__LPQFULL | \
2991da177e4SLinus Torvalds 					 TITAN__PCHIP_AGPERROR__HPQFULL | \
3001da177e4SLinus Torvalds 					 TITAN__PCHIP_AGPERROR__RESCMD |  \
3011da177e4SLinus Torvalds 					 TITAN__PCHIP_AGPERROR__IPTE |    \
3021da177e4SLinus Torvalds 					 TITAN__PCHIP_AGPERROR__PTP |     \
3031da177e4SLinus Torvalds 					 TITAN__PCHIP_AGPERROR__NOWINDOW)
3041da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__DAC	(1UL << 48)
3051da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__MWIN	(1UL << 49)
3061da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__FENCE	(1UL << 59)
3071da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__CMD__S	(50)
3081da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__CMD__M	(0x07)
3091da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__ADDR__S	(15)
3101da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__ADDR__M  (0xffffffffUL)
3111da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__LEN__S	(53)
3121da177e4SLinus Torvalds #define TITAN__PCHIP_AGPERROR__LEN__M	(0x3f)
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 	if (!(agperror & TITAN__PCHIP_AGPERROR__ERRMASK))
3151da177e4SLinus Torvalds 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
3181da177e4SLinus Torvalds 	if (!print)
3191da177e4SLinus Torvalds 		return status;
3201da177e4SLinus Torvalds 
3211da177e4SLinus Torvalds 	cmd = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__CMD);
3221da177e4SLinus Torvalds 	addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3;
3231da177e4SLinus Torvalds 	len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN);
3241da177e4SLinus Torvalds 
3255f0e3da6SRandy Dunlap 	printk("%s  PChip %d AGPERROR: %016llx\n", err_print_prefix,
3261da177e4SLinus Torvalds 	       which, agperror);
3271da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW)
3281da177e4SLinus Torvalds 		printk("%s    No Window\n", err_print_prefix);
3291da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__PTP)
3301da177e4SLinus Torvalds 		printk("%s    Peer-to-Peer set\n", err_print_prefix);
3311da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__IPTE)
3321da177e4SLinus Torvalds 		printk("%s    Invalid PTE\n", err_print_prefix);
3331da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__RESCMD)
3341da177e4SLinus Torvalds 		printk("%s    Reserved Command\n", err_print_prefix);
3351da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__HPQFULL)
3361da177e4SLinus Torvalds 		printk("%s    HP Transaction Received while Queue Full\n",
3371da177e4SLinus Torvalds 		       err_print_prefix);
3381da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__LPQFULL)
3391da177e4SLinus Torvalds 		printk("%s    LP Transaction Received while Queue Full\n",
3401da177e4SLinus Torvalds 		       err_print_prefix);
3411da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__LOST)
3421da177e4SLinus Torvalds 		printk("%s    Lost Error\n", err_print_prefix);
3431da177e4SLinus Torvalds 	printk("%s      Command: 0x%x - %s, %d Quadwords%s\n"
3441da177e4SLinus Torvalds 		 "      Address: 0x%lx\n",
3451da177e4SLinus Torvalds 	       err_print_prefix, cmd, agperror_cmd[cmd], len,
3461da177e4SLinus Torvalds 	       (agperror & TITAN__PCHIP_AGPERROR__FENCE) ? ", FENCE" : "",
3471da177e4SLinus Torvalds 	       addr);
3481da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__DAC)
3491da177e4SLinus Torvalds 		printk("%s      Dual Address Cycle\n", err_print_prefix);
3501da177e4SLinus Torvalds 	if (agperror & TITAN__PCHIP_AGPERROR__MWIN)
3511da177e4SLinus Torvalds 		printk("%s      Hit in Monster Window\n", err_print_prefix);
3521da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
3531da177e4SLinus Torvalds 
3541da177e4SLinus Torvalds 	return status;
3551da177e4SLinus Torvalds }
3561da177e4SLinus Torvalds 
3571da177e4SLinus Torvalds static int
3581da177e4SLinus Torvalds titan_parse_p_chip(int which, u64 serror, u64 gperror,
3591da177e4SLinus Torvalds 		   u64 aperror, u64 agperror, int print)
3601da177e4SLinus Torvalds {
3611da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
3621da177e4SLinus Torvalds 	status |= titan_parse_p_serror(which, serror, print);
3631da177e4SLinus Torvalds 	status |= titan_parse_p_perror(which, 0, gperror, print);
3641da177e4SLinus Torvalds 	status |= titan_parse_p_perror(which, 1, aperror, print);
3651da177e4SLinus Torvalds 	status |= titan_parse_p_agperror(which, agperror, print);
3661da177e4SLinus Torvalds 	return status;
3671da177e4SLinus Torvalds }
3681da177e4SLinus Torvalds 
3691da177e4SLinus Torvalds int
3701da177e4SLinus Torvalds titan_process_logout_frame(struct el_common *mchk_header, int print)
3711da177e4SLinus Torvalds {
3721da177e4SLinus Torvalds 	struct el_TITAN_sysdata_mcheck *tmchk =
3731da177e4SLinus Torvalds 		(struct el_TITAN_sysdata_mcheck *)
3741da177e4SLinus Torvalds 		((unsigned long)mchk_header + mchk_header->sys_offset);
3751da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
3761da177e4SLinus Torvalds 
3771da177e4SLinus Torvalds 	status |= titan_parse_c_misc(tmchk->c_misc, print);
3781da177e4SLinus Torvalds 	status |= titan_parse_p_chip(0, tmchk->p0_serror, tmchk->p0_gperror,
3791da177e4SLinus Torvalds 				     tmchk->p0_aperror, tmchk->p0_agperror,
3801da177e4SLinus Torvalds 				     print);
3811da177e4SLinus Torvalds 	status |= titan_parse_p_chip(1, tmchk->p1_serror, tmchk->p1_gperror,
3821da177e4SLinus Torvalds 				     tmchk->p1_aperror, tmchk->p1_agperror,
3831da177e4SLinus Torvalds 				     print);
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds 	return status;
3861da177e4SLinus Torvalds }
3871da177e4SLinus Torvalds 
3881da177e4SLinus Torvalds void
3891ffb1c0cSIvan Kokshaysky titan_machine_check(unsigned long vector, unsigned long la_ptr)
3901da177e4SLinus Torvalds {
3911da177e4SLinus Torvalds 	struct el_common *mchk_header = (struct el_common *)la_ptr;
3921da177e4SLinus Torvalds 	struct el_TITAN_sysdata_mcheck *tmchk =
3931da177e4SLinus Torvalds 		(struct el_TITAN_sysdata_mcheck *)
3941da177e4SLinus Torvalds 		((unsigned long)mchk_header + mchk_header->sys_offset);
3951da177e4SLinus Torvalds 	u64 irqmask;
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 	/*
3981da177e4SLinus Torvalds 	 * Mask of Titan interrupt sources which are reported as machine checks
3991da177e4SLinus Torvalds 	 *
4001da177e4SLinus Torvalds 	 * 63 - CChip Error
4011da177e4SLinus Torvalds 	 * 62 - PChip 0 H_Error
4021da177e4SLinus Torvalds 	 * 61 - PChip 1 H_Error
4031da177e4SLinus Torvalds 	 * 60 - PChip 0 C_Error
4041da177e4SLinus Torvalds 	 * 59 - PChip 1 C_Error
4051da177e4SLinus Torvalds 	 */
4061da177e4SLinus Torvalds #define TITAN_MCHECK_INTERRUPT_MASK	0xF800000000000000UL
4071da177e4SLinus Torvalds 
4081da177e4SLinus Torvalds 	/*
4091da177e4SLinus Torvalds 	 * Sync the processor
4101da177e4SLinus Torvalds 	 */
4111da177e4SLinus Torvalds 	mb();
4121da177e4SLinus Torvalds 	draina();
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds 	/*
4151da177e4SLinus Torvalds 	 * Only handle system errors here
4161da177e4SLinus Torvalds 	 */
4171da177e4SLinus Torvalds 	if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR)) {
4184fa1970aSAl Viro 		ev6_machine_check(vector, la_ptr);
4191da177e4SLinus Torvalds 		return;
4201da177e4SLinus Torvalds 	}
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds 	/*
4231da177e4SLinus Torvalds 	 * It's a system error, handle it here
4241da177e4SLinus Torvalds 	 *
4251da177e4SLinus Torvalds 	 * The PALcode has already cleared the error, so just parse it
4261da177e4SLinus Torvalds 	 */
4271da177e4SLinus Torvalds 
4281da177e4SLinus Torvalds 	/*
4291da177e4SLinus Torvalds 	 * Parse the logout frame without printing first. If the only error(s)
4301da177e4SLinus Torvalds 	 * found are classified as "dismissable", then just dismiss them and
4311da177e4SLinus Torvalds 	 * don't print any message
4321da177e4SLinus Torvalds 	 */
4331da177e4SLinus Torvalds 	if (titan_process_logout_frame(mchk_header, 0) !=
4341da177e4SLinus Torvalds 	    MCHK_DISPOSITION_DISMISS) {
4351da177e4SLinus Torvalds 		char *saved_err_prefix = err_print_prefix;
4361da177e4SLinus Torvalds 		err_print_prefix = KERN_CRIT;
4371da177e4SLinus Torvalds 
4381da177e4SLinus Torvalds 		/*
4391da177e4SLinus Torvalds 		 * Either a nondismissable error was detected or no
4401da177e4SLinus Torvalds 		 * recognized error was detected  in the logout frame
4411da177e4SLinus Torvalds 		 * -- report the error in either case
4421da177e4SLinus Torvalds 		 */
4431da177e4SLinus Torvalds 		printk("%s"
4441da177e4SLinus Torvalds 		       "*System %s Error (Vector 0x%x) reported on CPU %d:\n",
4451da177e4SLinus Torvalds 		       err_print_prefix,
4461da177e4SLinus Torvalds 		       (vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
4471da177e4SLinus Torvalds 		       (unsigned int)vector, (int)smp_processor_id());
4481da177e4SLinus Torvalds 
4491da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
4501da177e4SLinus Torvalds 		titan_process_logout_frame(mchk_header, alpha_verbose_mcheck);
4511da177e4SLinus Torvalds 		if (alpha_verbose_mcheck)
4524fa1970aSAl Viro 			dik_show_regs(get_irq_regs(), NULL);
4531da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
4541da177e4SLinus Torvalds 
4551da177e4SLinus Torvalds 		err_print_prefix = saved_err_prefix;
4561da177e4SLinus Torvalds 
4571da177e4SLinus Torvalds 		/*
4581da177e4SLinus Torvalds 		 * Convert any pending interrupts which report as system
4591da177e4SLinus Torvalds 		 * machine checks to interrupts
4601da177e4SLinus Torvalds 		 */
4611da177e4SLinus Torvalds 		irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
4622f116cbfSAl Viro 		titan_dispatch_irqs(irqmask);
4631da177e4SLinus Torvalds 	}
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds 	/*
4671da177e4SLinus Torvalds 	 * Release the logout frame
4681da177e4SLinus Torvalds 	 */
4691da177e4SLinus Torvalds 	wrmces(0x7);
4701da177e4SLinus Torvalds 	mb();
4711da177e4SLinus Torvalds }
4721da177e4SLinus Torvalds 
4731da177e4SLinus Torvalds /*
4741da177e4SLinus Torvalds  * Subpacket Annotations
4751da177e4SLinus Torvalds  */
4761da177e4SLinus Torvalds static char *el_titan_pchip0_extended_annotation[] = {
4771da177e4SLinus Torvalds 	"Subpacket Header", 	"P0_SCTL",	"P0_SERREN",
4781da177e4SLinus Torvalds 	"P0_APCTL",		"P0_APERREN",	"P0_AGPERREN",
4791da177e4SLinus Torvalds 	"P0_ASPRST",		"P0_AWSBA0",	"P0_AWSBA1",
4801da177e4SLinus Torvalds 	"P0_AWSBA2",		"P0_AWSBA3",	"P0_AWSM0",
4811da177e4SLinus Torvalds 	"P0_AWSM1",		"P0_AWSM2",	"P0_AWSM3",
4821da177e4SLinus Torvalds 	"P0_ATBA0",		"P0_ATBA1",	"P0_ATBA2",
4831da177e4SLinus Torvalds 	"P0_ATBA3",		"P0_GPCTL",	"P0_GPERREN",
4841da177e4SLinus Torvalds 	"P0_GSPRST",		"P0_GWSBA0",	"P0_GWSBA1",
4851da177e4SLinus Torvalds 	"P0_GWSBA2",		"P0_GWSBA3",	"P0_GWSM0",
4861da177e4SLinus Torvalds 	"P0_GWSM1",		"P0_GWSM2",	"P0_GWSM3",
4871da177e4SLinus Torvalds 	"P0_GTBA0",		"P0_GTBA1",	"P0_GTBA2",
4881da177e4SLinus Torvalds 	"P0_GTBA3",		NULL
4891da177e4SLinus Torvalds };
4901da177e4SLinus Torvalds static char *el_titan_pchip1_extended_annotation[] = {
4911da177e4SLinus Torvalds 	"Subpacket Header", 	"P1_SCTL",	"P1_SERREN",
4921da177e4SLinus Torvalds 	"P1_APCTL",		"P1_APERREN",	"P1_AGPERREN",
4931da177e4SLinus Torvalds 	"P1_ASPRST",		"P1_AWSBA0",	"P1_AWSBA1",
4941da177e4SLinus Torvalds 	"P1_AWSBA2",		"P1_AWSBA3",	"P1_AWSM0",
4951da177e4SLinus Torvalds 	"P1_AWSM1",		"P1_AWSM2",	"P1_AWSM3",
4961da177e4SLinus Torvalds 	"P1_ATBA0",		"P1_ATBA1",	"P1_ATBA2",
4971da177e4SLinus Torvalds 	"P1_ATBA3",		"P1_GPCTL",	"P1_GPERREN",
4981da177e4SLinus Torvalds 	"P1_GSPRST",		"P1_GWSBA0",	"P1_GWSBA1",
4991da177e4SLinus Torvalds 	"P1_GWSBA2",		"P1_GWSBA3",	"P1_GWSM0",
5001da177e4SLinus Torvalds 	"P1_GWSM1",		"P1_GWSM2",	"P1_GWSM3",
5011da177e4SLinus Torvalds 	"P1_GTBA0",		"P1_GTBA1",	"P1_GTBA2",
5021da177e4SLinus Torvalds 	"P1_GTBA3",		NULL
5031da177e4SLinus Torvalds };
5041da177e4SLinus Torvalds static char *el_titan_memory_extended_annotation[] = {
5051da177e4SLinus Torvalds 	"Subpacket Header", 	"AAR0",		"AAR1",
5061da177e4SLinus Torvalds 	"AAR2",			"AAR3",		"P0_SCTL",
5071da177e4SLinus Torvalds 	"P0_GPCTL",		"P0_APCTL",	"P1_SCTL",
5081da177e4SLinus Torvalds 	"P1_GPCTL",		"P1_SCTL",	NULL
5091da177e4SLinus Torvalds };
5101da177e4SLinus Torvalds 
5111da177e4SLinus Torvalds static struct el_subpacket_annotation el_titan_annotations[] = {
5121da177e4SLinus Torvalds 	SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
5131da177e4SLinus Torvalds 			     EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
5141da177e4SLinus Torvalds 			     1,
5151da177e4SLinus Torvalds 			     "Titan PChip 0 Extended Frame",
5161da177e4SLinus Torvalds 			     el_titan_pchip0_extended_annotation),
5171da177e4SLinus Torvalds 	SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
5181da177e4SLinus Torvalds 			     EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
5191da177e4SLinus Torvalds 			     1,
5201da177e4SLinus Torvalds 			     "Titan PChip 1 Extended Frame",
5211da177e4SLinus Torvalds 			     el_titan_pchip1_extended_annotation),
5221da177e4SLinus Torvalds 	SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
5231da177e4SLinus Torvalds 			     EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
5241da177e4SLinus Torvalds 			     1,
5251da177e4SLinus Torvalds 			     "Titan Memory Extended Frame",
5261da177e4SLinus Torvalds 			     el_titan_memory_extended_annotation),
5271da177e4SLinus Torvalds 	SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
5281da177e4SLinus Torvalds 			     EL_TYPE__TERMINATION__TERMINATION,
5291da177e4SLinus Torvalds 			     1,
5301da177e4SLinus Torvalds 			     "Termination Subpacket",
5311da177e4SLinus Torvalds 			     NULL)
5321da177e4SLinus Torvalds };
5331da177e4SLinus Torvalds 
5341da177e4SLinus Torvalds static struct el_subpacket *
5351da177e4SLinus Torvalds el_process_regatta_subpacket(struct el_subpacket *header)
5361da177e4SLinus Torvalds {
5371da177e4SLinus Torvalds 	if (header->class != EL_CLASS__REGATTA_FAMILY) {
5381da177e4SLinus Torvalds 		printk("%s  ** Unexpected header CLASS %d TYPE %d, aborting\n",
5391da177e4SLinus Torvalds 		       err_print_prefix,
5401da177e4SLinus Torvalds 		       header->class, header->type);
5411da177e4SLinus Torvalds 		return NULL;
5421da177e4SLinus Torvalds 	}
5431da177e4SLinus Torvalds 
5441da177e4SLinus Torvalds 	switch(header->type) {
5451da177e4SLinus Torvalds 	case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
5461da177e4SLinus Torvalds 	case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
5471da177e4SLinus Torvalds 	case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
5481da177e4SLinus Torvalds 	case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
5491da177e4SLinus Torvalds 	case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
5501da177e4SLinus Torvalds 		printk("%s  ** Occurred on CPU %d:\n",
5511da177e4SLinus Torvalds 		       err_print_prefix,
5521da177e4SLinus Torvalds 		       (int)header->by_type.regatta_frame.cpuid);
553280da4e4SRichard Henderson 		privateer_process_logout_frame((struct el_common *)
5541da177e4SLinus Torvalds 			header->by_type.regatta_frame.data_start, 1);
5551da177e4SLinus Torvalds 		break;
5561da177e4SLinus Torvalds 	default:
5571da177e4SLinus Torvalds 		printk("%s  ** REGATTA TYPE %d SUBPACKET\n",
5581da177e4SLinus Torvalds 		       err_print_prefix, header->type);
5591da177e4SLinus Torvalds 		el_annotate_subpacket(header);
5601da177e4SLinus Torvalds 		break;
5611da177e4SLinus Torvalds 	}
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds 
5641da177e4SLinus Torvalds 	return (struct el_subpacket *)((unsigned long)header + header->length);
5651da177e4SLinus Torvalds }
5661da177e4SLinus Torvalds 
5671da177e4SLinus Torvalds static struct el_subpacket_handler titan_subpacket_handler =
5681da177e4SLinus Torvalds 	SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY,
5691da177e4SLinus Torvalds 			       el_process_regatta_subpacket);
5701da177e4SLinus Torvalds 
5719548b209SIvan Kokshaysky void __init
5721da177e4SLinus Torvalds titan_register_error_handlers(void)
5731da177e4SLinus Torvalds {
5741da177e4SLinus Torvalds 	size_t i;
5751da177e4SLinus Torvalds 
5761da177e4SLinus Torvalds 	for (i = 0; i < ARRAY_SIZE (el_titan_annotations); i++)
5771da177e4SLinus Torvalds 		cdl_register_subpacket_annotation(&el_titan_annotations[i]);
5781da177e4SLinus Torvalds 
5791da177e4SLinus Torvalds 	cdl_register_subpacket_handler(&titan_subpacket_handler);
5801da177e4SLinus Torvalds 
5811da177e4SLinus Torvalds 	ev6_register_error_handlers();
5821da177e4SLinus Torvalds }
5831da177e4SLinus Torvalds 
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds /*
5861da177e4SLinus Torvalds  * Privateer
5871da177e4SLinus Torvalds  */
5881da177e4SLinus Torvalds 
5891da177e4SLinus Torvalds static int
5901da177e4SLinus Torvalds privateer_process_680_frame(struct el_common *mchk_header, int print)
5911da177e4SLinus Torvalds {
5921da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
5931da177e4SLinus Torvalds #ifdef CONFIG_VERBOSE_MCHECK
5941da177e4SLinus Torvalds 	struct el_PRIVATEER_envdata_mcheck *emchk =
5951da177e4SLinus Torvalds 		(struct el_PRIVATEER_envdata_mcheck *)
5961da177e4SLinus Torvalds 		((unsigned long)mchk_header + mchk_header->sys_offset);
5971da177e4SLinus Torvalds 
598c3a2ddeeSSimon Arlott 	/* TODO - categorize errors, for now, no error */
5991da177e4SLinus Torvalds 
6001da177e4SLinus Torvalds 	if (!print)
6011da177e4SLinus Torvalds 		return status;
6021da177e4SLinus Torvalds 
6031da177e4SLinus Torvalds 	/* TODO - decode instead of just dumping... */
6045f0e3da6SRandy Dunlap 	printk("%s  Summary Flags:         %016llx\n"
6055f0e3da6SRandy Dunlap  	         "  CChip DIRx:            %016llx\n"
6065f0e3da6SRandy Dunlap 		 "  System Management IR:  %016llx\n"
6075f0e3da6SRandy Dunlap 		 "  CPU IR:                %016llx\n"
6085f0e3da6SRandy Dunlap 		 "  Power Supply IR:       %016llx\n"
6095f0e3da6SRandy Dunlap 		 "  LM78 Fault Status:     %016llx\n"
6105f0e3da6SRandy Dunlap 		 "  System Doors:          %016llx\n"
6115f0e3da6SRandy Dunlap 		 "  Temperature Warning:   %016llx\n"
6125f0e3da6SRandy Dunlap 		 "  Fan Control:           %016llx\n"
6135f0e3da6SRandy Dunlap 		 "  Fatal Power Down Code: %016llx\n",
6141da177e4SLinus Torvalds 	       err_print_prefix,
6151da177e4SLinus Torvalds 	       emchk->summary,
6161da177e4SLinus Torvalds 	       emchk->c_dirx,
6171da177e4SLinus Torvalds 	       emchk->smir,
6181da177e4SLinus Torvalds 	       emchk->cpuir,
6191da177e4SLinus Torvalds 	       emchk->psir,
6201da177e4SLinus Torvalds 	       emchk->fault,
6211da177e4SLinus Torvalds 	       emchk->sys_doors,
6221da177e4SLinus Torvalds 	       emchk->temp_warn,
6231da177e4SLinus Torvalds 	       emchk->fan_ctrl,
6241da177e4SLinus Torvalds 	       emchk->code);
6251da177e4SLinus Torvalds #endif /* CONFIG_VERBOSE_MCHECK */
6261da177e4SLinus Torvalds 
6271da177e4SLinus Torvalds 	return status;
6281da177e4SLinus Torvalds }
6291da177e4SLinus Torvalds 
6301da177e4SLinus Torvalds int
6311da177e4SLinus Torvalds privateer_process_logout_frame(struct el_common *mchk_header, int print)
6321da177e4SLinus Torvalds {
6331da177e4SLinus Torvalds 	struct el_common_EV6_mcheck *ev6mchk =
6341da177e4SLinus Torvalds 		(struct el_common_EV6_mcheck *)mchk_header;
6351da177e4SLinus Torvalds 	int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds 	/*
6381da177e4SLinus Torvalds 	 * Machine check codes
6391da177e4SLinus Torvalds 	 */
6401da177e4SLinus Torvalds #define PRIVATEER_MCHK__CORR_ECC		0x86	/* 630 */
6411da177e4SLinus Torvalds #define PRIVATEER_MCHK__DC_TAG_PERR		0x9E	/* 630 */
6421da177e4SLinus Torvalds #define PRIVATEER_MCHK__PAL_BUGCHECK		0x8E	/* 670 */
6431da177e4SLinus Torvalds #define PRIVATEER_MCHK__OS_BUGCHECK		0x90	/* 670 */
6441da177e4SLinus Torvalds #define PRIVATEER_MCHK__PROC_HRD_ERR		0x98	/* 670 */
6451da177e4SLinus Torvalds #define PRIVATEER_MCHK__ISTREAM_CMOV_PRX	0xA0	/* 670 */
6461da177e4SLinus Torvalds #define PRIVATEER_MCHK__ISTREAM_CMOV_FLT	0xA2	/* 670 */
6471da177e4SLinus Torvalds #define PRIVATEER_MCHK__SYS_HRD_ERR		0x202	/* 660 */
6481da177e4SLinus Torvalds #define PRIVATEER_MCHK__SYS_CORR_ERR		0x204	/* 620 */
6491da177e4SLinus Torvalds #define PRIVATEER_MCHK__SYS_ENVIRON		0x206	/* 680 */
6501da177e4SLinus Torvalds 
6511da177e4SLinus Torvalds 	switch(ev6mchk->MCHK_Code) {
6521da177e4SLinus Torvalds 	/*
6531da177e4SLinus Torvalds 	 * Vector 630 - Processor, Correctable
6541da177e4SLinus Torvalds 	 */
6551da177e4SLinus Torvalds 	case PRIVATEER_MCHK__CORR_ECC:
6561da177e4SLinus Torvalds 	case PRIVATEER_MCHK__DC_TAG_PERR:
6571da177e4SLinus Torvalds 		/*
6581da177e4SLinus Torvalds 		 * Fall through to vector 670 for processing...
6591da177e4SLinus Torvalds 		 */
6601da177e4SLinus Torvalds 	/*
6611da177e4SLinus Torvalds 	 * Vector 670 - Processor, Uncorrectable
6621da177e4SLinus Torvalds 	 */
6631da177e4SLinus Torvalds 	case PRIVATEER_MCHK__PAL_BUGCHECK:
6641da177e4SLinus Torvalds 	case PRIVATEER_MCHK__OS_BUGCHECK:
6651da177e4SLinus Torvalds 	case PRIVATEER_MCHK__PROC_HRD_ERR:
6661da177e4SLinus Torvalds 	case PRIVATEER_MCHK__ISTREAM_CMOV_PRX:
6671da177e4SLinus Torvalds 	case PRIVATEER_MCHK__ISTREAM_CMOV_FLT:
6681da177e4SLinus Torvalds 		status |= ev6_process_logout_frame(mchk_header, print);
6691da177e4SLinus Torvalds 		break;
6701da177e4SLinus Torvalds 
6711da177e4SLinus Torvalds 	/*
6721da177e4SLinus Torvalds 	 * Vector 620 - System, Correctable
6731da177e4SLinus Torvalds 	 */
6741da177e4SLinus Torvalds 	case PRIVATEER_MCHK__SYS_CORR_ERR:
6751da177e4SLinus Torvalds 		/*
6761da177e4SLinus Torvalds 		 * Fall through to vector 660 for processing...
6771da177e4SLinus Torvalds 		 */
6781da177e4SLinus Torvalds 	/*
6791da177e4SLinus Torvalds 	 * Vector 660 - System, Uncorrectable
6801da177e4SLinus Torvalds 	 */
6811da177e4SLinus Torvalds 	case PRIVATEER_MCHK__SYS_HRD_ERR:
6821da177e4SLinus Torvalds 		status |= titan_process_logout_frame(mchk_header, print);
6831da177e4SLinus Torvalds 		break;
6841da177e4SLinus Torvalds 
6851da177e4SLinus Torvalds 	/*
6861da177e4SLinus Torvalds 	 * Vector 680 - System, Environmental
6871da177e4SLinus Torvalds 	 */
6881da177e4SLinus Torvalds 	case PRIVATEER_MCHK__SYS_ENVIRON:	/* System, Environmental */
6891da177e4SLinus Torvalds 		status |= privateer_process_680_frame(mchk_header, print);
6901da177e4SLinus Torvalds 		break;
6911da177e4SLinus Torvalds 
6921da177e4SLinus Torvalds 	/*
6931da177e4SLinus Torvalds 	 * Unknown
6941da177e4SLinus Torvalds 	 */
6951da177e4SLinus Torvalds 	default:
6961da177e4SLinus Torvalds 		status |= MCHK_DISPOSITION_REPORT;
6971da177e4SLinus Torvalds 		if (print) {
6981da177e4SLinus Torvalds 			printk("%s** Unknown Error, frame follows\n",
6991da177e4SLinus Torvalds 			       err_print_prefix);
7001da177e4SLinus Torvalds 			mchk_dump_logout_frame(mchk_header);
7011da177e4SLinus Torvalds 		}
7021da177e4SLinus Torvalds 
7031da177e4SLinus Torvalds 	}
7041da177e4SLinus Torvalds 
7051da177e4SLinus Torvalds 	return status;
7061da177e4SLinus Torvalds }
7071da177e4SLinus Torvalds 
7081da177e4SLinus Torvalds void
7091ffb1c0cSIvan Kokshaysky privateer_machine_check(unsigned long vector, unsigned long la_ptr)
7101da177e4SLinus Torvalds {
7111da177e4SLinus Torvalds 	struct el_common *mchk_header = (struct el_common *)la_ptr;
7121da177e4SLinus Torvalds 	struct el_TITAN_sysdata_mcheck *tmchk =
7131da177e4SLinus Torvalds 		(struct el_TITAN_sysdata_mcheck *)
7141da177e4SLinus Torvalds 		(la_ptr + mchk_header->sys_offset);
7151da177e4SLinus Torvalds 	u64 irqmask;
7161da177e4SLinus Torvalds 	char *saved_err_prefix = err_print_prefix;
7171da177e4SLinus Torvalds 
7181da177e4SLinus Torvalds #define PRIVATEER_680_INTERRUPT_MASK		(0xE00UL)
7191da177e4SLinus Torvalds #define PRIVATEER_HOTPLUG_INTERRUPT_MASK	(0xE00UL)
7201da177e4SLinus Torvalds 
7211da177e4SLinus Torvalds 	/*
7221da177e4SLinus Torvalds 	 * Sync the processor.
7231da177e4SLinus Torvalds 	 */
7241da177e4SLinus Torvalds 	mb();
7251da177e4SLinus Torvalds 	draina();
7261da177e4SLinus Torvalds 
7271da177e4SLinus Torvalds 	/*
7281da177e4SLinus Torvalds 	 * Only handle system events here.
7291da177e4SLinus Torvalds 	 */
7301da177e4SLinus Torvalds 	if (vector != SCB_Q_SYSEVENT)
7314fa1970aSAl Viro 		return titan_machine_check(vector, la_ptr);
7321da177e4SLinus Torvalds 
7331da177e4SLinus Torvalds 	/*
7341da177e4SLinus Torvalds 	 * Report the event - System Events should be reported even if no
7351da177e4SLinus Torvalds 	 * error is indicated since the event could indicate the return
7361da177e4SLinus Torvalds 	 * to normal status.
7371da177e4SLinus Torvalds 	 */
7381da177e4SLinus Torvalds 	err_print_prefix = KERN_CRIT;
7391da177e4SLinus Torvalds 	printk("%s*System Event (Vector 0x%x) reported on CPU %d:\n",
7401da177e4SLinus Torvalds 	       err_print_prefix,
7411da177e4SLinus Torvalds 	       (unsigned int)vector, (int)smp_processor_id());
7421da177e4SLinus Torvalds 	privateer_process_680_frame(mchk_header, 1);
7431da177e4SLinus Torvalds 	err_print_prefix = saved_err_prefix;
7441da177e4SLinus Torvalds 
7451da177e4SLinus Torvalds 	/*
7461da177e4SLinus Torvalds 	 * Convert any pending interrupts which report as 680 machine
7471da177e4SLinus Torvalds 	 * checks to interrupts.
7481da177e4SLinus Torvalds 	 */
7491da177e4SLinus Torvalds 	irqmask = tmchk->c_dirx & PRIVATEER_680_INTERRUPT_MASK;
7501da177e4SLinus Torvalds 
7511da177e4SLinus Torvalds 	/*
7521da177e4SLinus Torvalds 	 * Dispatch the interrupt(s).
7531da177e4SLinus Torvalds 	 */
7542f116cbfSAl Viro 	titan_dispatch_irqs(irqmask);
7551da177e4SLinus Torvalds 
7561da177e4SLinus Torvalds 	/*
7571da177e4SLinus Torvalds 	 * Release the logout frame.
7581da177e4SLinus Torvalds 	 */
7591da177e4SLinus Torvalds 	wrmces(0x7);
7601da177e4SLinus Torvalds 	mb();
7611da177e4SLinus Torvalds }
762