11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	linux/arch/alpha/kernel/err_common.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Error handling code supporting Alpha systems
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hwrpb.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/smp.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/err_common.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "err_impl.h"
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "proto.h"
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * err_print_prefix -- error handling print routines should prefix
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all prints with this
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *err_print_prefix = KERN_NOTICE;
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Generic
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmchk_dump_mem(void *data, size_t length, char **annotation)
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long *ldata = data;
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size_t i;
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; (i * sizeof(*ldata)) < length; i++) {
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (annotation && !annotation[i])
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			annotation = NULL;
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s    %08x: %016lx    %s\n",
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       err_print_prefix,
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       (unsigned)(i * sizeof(*ldata)), ldata[i],
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       annotation ? annotation[i] : "");
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmchk_dump_logout_frame(struct el_common *mchk_header)
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s  -- Frame Header --\n"
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "    Frame Size:   %d (0x%x) bytes\n"
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "    Flags:        %s%s\n"
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "    MCHK Code:    0x%x\n"
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "    Frame Rev:    %d\n"
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "    Proc Offset:  0x%08x\n"
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "    Sys Offset:   0x%08x\n"
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  	         "  -- Processor Region --\n",
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       err_print_prefix,
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       mchk_header->size, mchk_header->size,
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       mchk_header->retry ? "RETRY " : "",
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  	         mchk_header->err2 ? "SECOND_ERR " : "",
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       mchk_header->code,
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       mchk_header->frame_rev,
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       mchk_header->proc_offset,
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       mchk_header->sys_offset);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchk_dump_mem((void *)
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      ((unsigned long)mchk_header + mchk_header->proc_offset),
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      mchk_header->sys_offset - mchk_header->proc_offset,
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      NULL);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s  -- System Region --\n", err_print_prefix);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchk_dump_mem((void *)
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      ((unsigned long)mchk_header + mchk_header->sys_offset),
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      mchk_header->size - mchk_header->sys_offset,
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      NULL);
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s  -- End of Frame --\n", err_print_prefix);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Console Data Log
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Data */
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct el_subpacket_handler *subpacket_handler_list = NULL;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct el_subpacket_annotation *subpacket_annotation_list = NULL;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct el_subpacket *
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsel_process_header_subpacket(struct el_subpacket *header)
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	union el_timestamp timestamp;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *name = "UNKNOWN EVENT";
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int packet_count = 0;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int length = 0;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (header->class != EL_CLASS__HEADER) {
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s** Unexpected header CLASS %d TYPE %d, aborting\n",
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       err_print_prefix,
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       header->class, header->type);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(header->type) {
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EL_TYPE__HEADER__SYSTEM_ERROR_FRAME:
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		name = "SYSTEM ERROR";
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = header->by_type.sys_err.frame_length;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		packet_count =
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			header->by_type.sys_err.frame_packet_count;
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		timestamp.as_int = 0;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EL_TYPE__HEADER__SYSTEM_EVENT_FRAME:
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		name = "SYSTEM EVENT";
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = header->by_type.sys_event.frame_length;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		packet_count =
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			header->by_type.sys_event.frame_packet_count;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		timestamp = header->by_type.sys_event.timestamp;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EL_TYPE__HEADER__HALT_FRAME:
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		name = "ERROR HALT";
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = header->by_type.err_halt.frame_length;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		packet_count =
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			header->by_type.err_halt.frame_packet_count;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		timestamp = header->by_type.err_halt.timestamp;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EL_TYPE__HEADER__LOGOUT_FRAME:
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		name = "LOGOUT FRAME";
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = header->by_type.logout_header.frame_length;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		packet_count = 1;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		timestamp.as_int = 0;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default: /* Unknown */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s** Unknown header - CLASS %d TYPE %d, aborting\n",
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       err_print_prefix,
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       header->class, header->type);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s*** %s:\n"
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "  CLASS %d, TYPE %d\n",
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       err_print_prefix,
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       name,
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       header->class, header->type);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	el_print_timestamp(&timestamp);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Process the subpackets
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	el_process_subpackets(header, packet_count);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* return the next header */
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	header = (struct el_subpacket *)
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		((unsigned long)header + header->length + length);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return header;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct el_subpacket *
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsel_process_subpacket_reg(struct el_subpacket *header)
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket *next = NULL;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket_handler *h = subpacket_handler_list;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (; h && h->class != header->class; h = h->next);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (h) next = h->handler(header);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return next;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsel_print_timestamp(union el_timestamp *timestamp)
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (timestamp->as_int)
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s  TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n",
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       err_print_prefix,
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       timestamp->b.month, timestamp->b.day,
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       timestamp->b.year, timestamp->b.hour,
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       timestamp->b.minute, timestamp->b.second);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsel_process_subpackets(struct el_subpacket *header, int packet_count)
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket *subpacket;
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	subpacket = (struct el_subpacket *)
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		((unsigned long)header + header->length);
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; subpacket && i < packet_count; i++) {
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%sPROCESSING SUBPACKET %d\n", err_print_prefix, i);
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		subpacket = el_process_subpacket(subpacket);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct el_subpacket *
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsel_process_subpacket(struct el_subpacket *header)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket *next = NULL;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(header->class) {
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EL_CLASS__TERMINATION:
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Termination packet, there are no more */
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case EL_CLASS__HEADER:
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		next = el_process_header_subpacket(header);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (NULL == (next = el_process_subpacket_reg(header))) {
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("%s** Unexpected header CLASS %d TYPE %d"
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       " -- aborting.\n",
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       err_print_prefix,
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       header->class, header->type);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return next;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsel_annotate_subpacket(struct el_subpacket *header)
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket_annotation *a;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char **annotation = NULL;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (a = subpacket_annotation_list; a; a = a->next) {
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (a->class == header->class &&
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    a->type == header->type &&
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    a->revision == header->revision) {
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * We found the annotation
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			annotation = a->annotation;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("%s  %s\n", err_print_prefix, a->description);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mchk_dump_mem(header, header->length, annotation);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscdl_process_console_data_log(int cpu, struct percpu_struct *pcpu)
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket *header = (struct el_subpacket *)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(IDENT_ADDR | pcpu->console_data_log_pa);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s******* CONSOLE DATA LOG FOR CPU %d. *******\n"
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "*** Error(s) were logged on a previous boot\n",
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       err_print_prefix, cpu);
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (err = 0; header && (header->class != EL_CLASS__TERMINATION); err++)
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		header = el_process_subpacket(header);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* let the console know it's ok to clear the error(s) at restart */
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pcpu->console_data_log_pa = 0;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s*** %d total error(s) logged\n"
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	         "**** END OF CONSOLE DATA LOG FOR CPU %d ****\n",
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       err_print_prefix, err, cpu);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscdl_check_console_data_log(void)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct percpu_struct *pcpu;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long cpu;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (cpu = 0; cpu < hwrpb->nr_processors; cpu++) {
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pcpu = (struct percpu_struct *)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			((unsigned long)hwrpb + hwrpb->processor_offset
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 + cpu * hwrpb->processor_size);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (pcpu->console_data_log_pa)
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cdl_process_console_data_log(cpu, pcpu);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscdl_register_subpacket_annotation(struct el_subpacket_annotation *new)
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket_annotation *a = subpacket_annotation_list;
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (a == NULL) subpacket_annotation_list = new;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (; a->next != NULL; a = a->next) {
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((a->class == new->class && a->type == new->type) ||
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    a == new) {
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("Attempted to re-register "
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       "subpacket annotation\n");
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EINVAL;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		a->next = new;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new->next = NULL;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscdl_register_subpacket_handler(struct el_subpacket_handler *new)
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct el_subpacket_handler *h = subpacket_handler_list;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (h == NULL) subpacket_handler_list = new;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (; h->next != NULL; h = h->next) {
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (h->class == new->class || h == new) {
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("Attempted to re-register "
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       "subpacket handler\n");
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EINVAL;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		h->next = new;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new->next = NULL;
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
321