1 /* 2 * linux/arch/alpha/kernel/err_common.c 3 * 4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation) 5 * 6 * Error handling code supporting Alpha systems 7 */ 8 9 #include <linux/init.h> 10 #include <linux/sched.h> 11 12 #include <asm/io.h> 13 #include <asm/hwrpb.h> 14 #include <asm/smp.h> 15 #include <asm/err_common.h> 16 17 #include "err_impl.h" 18 #include "proto.h" 19 20 /* 21 * err_print_prefix -- error handling print routines should prefix 22 * all prints with this 23 */ 24 char *err_print_prefix = KERN_NOTICE; 25 26 27 /* 28 * Generic 29 */ 30 void 31 mchk_dump_mem(void *data, size_t length, char **annotation) 32 { 33 unsigned long *ldata = data; 34 size_t i; 35 36 for (i = 0; (i * sizeof(*ldata)) < length; i++) { 37 if (annotation && !annotation[i]) 38 annotation = NULL; 39 printk("%s %08x: %016lx %s\n", 40 err_print_prefix, 41 (unsigned)(i * sizeof(*ldata)), ldata[i], 42 annotation ? annotation[i] : ""); 43 } 44 } 45 46 void 47 mchk_dump_logout_frame(struct el_common *mchk_header) 48 { 49 printk("%s -- Frame Header --\n" 50 " Frame Size: %d (0x%x) bytes\n" 51 " Flags: %s%s\n" 52 " MCHK Code: 0x%x\n" 53 " Frame Rev: %d\n" 54 " Proc Offset: 0x%08x\n" 55 " Sys Offset: 0x%08x\n" 56 " -- Processor Region --\n", 57 err_print_prefix, 58 mchk_header->size, mchk_header->size, 59 mchk_header->retry ? "RETRY " : "", 60 mchk_header->err2 ? "SECOND_ERR " : "", 61 mchk_header->code, 62 mchk_header->frame_rev, 63 mchk_header->proc_offset, 64 mchk_header->sys_offset); 65 66 mchk_dump_mem((void *) 67 ((unsigned long)mchk_header + mchk_header->proc_offset), 68 mchk_header->sys_offset - mchk_header->proc_offset, 69 NULL); 70 71 printk("%s -- System Region --\n", err_print_prefix); 72 mchk_dump_mem((void *) 73 ((unsigned long)mchk_header + mchk_header->sys_offset), 74 mchk_header->size - mchk_header->sys_offset, 75 NULL); 76 printk("%s -- End of Frame --\n", err_print_prefix); 77 } 78 79 80 /* 81 * Console Data Log 82 */ 83 /* Data */ 84 static struct el_subpacket_handler *subpacket_handler_list = NULL; 85 static struct el_subpacket_annotation *subpacket_annotation_list = NULL; 86 87 static struct el_subpacket * 88 el_process_header_subpacket(struct el_subpacket *header) 89 { 90 union el_timestamp timestamp; 91 char *name = "UNKNOWN EVENT"; 92 int packet_count = 0; 93 int length = 0; 94 95 if (header->class != EL_CLASS__HEADER) { 96 printk("%s** Unexpected header CLASS %d TYPE %d, aborting\n", 97 err_print_prefix, 98 header->class, header->type); 99 return NULL; 100 } 101 102 switch(header->type) { 103 case EL_TYPE__HEADER__SYSTEM_ERROR_FRAME: 104 name = "SYSTEM ERROR"; 105 length = header->by_type.sys_err.frame_length; 106 packet_count = 107 header->by_type.sys_err.frame_packet_count; 108 timestamp.as_int = 0; 109 break; 110 case EL_TYPE__HEADER__SYSTEM_EVENT_FRAME: 111 name = "SYSTEM EVENT"; 112 length = header->by_type.sys_event.frame_length; 113 packet_count = 114 header->by_type.sys_event.frame_packet_count; 115 timestamp = header->by_type.sys_event.timestamp; 116 break; 117 case EL_TYPE__HEADER__HALT_FRAME: 118 name = "ERROR HALT"; 119 length = header->by_type.err_halt.frame_length; 120 packet_count = 121 header->by_type.err_halt.frame_packet_count; 122 timestamp = header->by_type.err_halt.timestamp; 123 break; 124 case EL_TYPE__HEADER__LOGOUT_FRAME: 125 name = "LOGOUT FRAME"; 126 length = header->by_type.logout_header.frame_length; 127 packet_count = 1; 128 timestamp.as_int = 0; 129 break; 130 default: /* Unknown */ 131 printk("%s** Unknown header - CLASS %d TYPE %d, aborting\n", 132 err_print_prefix, 133 header->class, header->type); 134 return NULL; 135 } 136 137 printk("%s*** %s:\n" 138 " CLASS %d, TYPE %d\n", 139 err_print_prefix, 140 name, 141 header->class, header->type); 142 el_print_timestamp(×tamp); 143 144 /* 145 * Process the subpackets 146 */ 147 el_process_subpackets(header, packet_count); 148 149 /* return the next header */ 150 header = (struct el_subpacket *) 151 ((unsigned long)header + header->length + length); 152 return header; 153 } 154 155 static struct el_subpacket * 156 el_process_subpacket_reg(struct el_subpacket *header) 157 { 158 struct el_subpacket *next = NULL; 159 struct el_subpacket_handler *h = subpacket_handler_list; 160 161 for (; h && h->class != header->class; h = h->next); 162 if (h) next = h->handler(header); 163 164 return next; 165 } 166 167 void 168 el_print_timestamp(union el_timestamp *timestamp) 169 { 170 if (timestamp->as_int) 171 printk("%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n", 172 err_print_prefix, 173 timestamp->b.month, timestamp->b.day, 174 timestamp->b.year, timestamp->b.hour, 175 timestamp->b.minute, timestamp->b.second); 176 } 177 178 void 179 el_process_subpackets(struct el_subpacket *header, int packet_count) 180 { 181 struct el_subpacket *subpacket; 182 int i; 183 184 subpacket = (struct el_subpacket *) 185 ((unsigned long)header + header->length); 186 187 for (i = 0; subpacket && i < packet_count; i++) { 188 printk("%sPROCESSING SUBPACKET %d\n", err_print_prefix, i); 189 subpacket = el_process_subpacket(subpacket); 190 } 191 } 192 193 struct el_subpacket * 194 el_process_subpacket(struct el_subpacket *header) 195 { 196 struct el_subpacket *next = NULL; 197 198 switch(header->class) { 199 case EL_CLASS__TERMINATION: 200 /* Termination packet, there are no more */ 201 break; 202 case EL_CLASS__HEADER: 203 next = el_process_header_subpacket(header); 204 break; 205 default: 206 if (NULL == (next = el_process_subpacket_reg(header))) { 207 printk("%s** Unexpected header CLASS %d TYPE %d" 208 " -- aborting.\n", 209 err_print_prefix, 210 header->class, header->type); 211 } 212 break; 213 } 214 215 return next; 216 } 217 218 void 219 el_annotate_subpacket(struct el_subpacket *header) 220 { 221 struct el_subpacket_annotation *a; 222 char **annotation = NULL; 223 224 for (a = subpacket_annotation_list; a; a = a->next) { 225 if (a->class == header->class && 226 a->type == header->type && 227 a->revision == header->revision) { 228 /* 229 * We found the annotation 230 */ 231 annotation = a->annotation; 232 printk("%s %s\n", err_print_prefix, a->description); 233 break; 234 } 235 } 236 237 mchk_dump_mem(header, header->length, annotation); 238 } 239 240 static void __init 241 cdl_process_console_data_log(int cpu, struct percpu_struct *pcpu) 242 { 243 struct el_subpacket *header = (struct el_subpacket *) 244 (IDENT_ADDR | pcpu->console_data_log_pa); 245 int err; 246 247 printk("%s******* CONSOLE DATA LOG FOR CPU %d. *******\n" 248 "*** Error(s) were logged on a previous boot\n", 249 err_print_prefix, cpu); 250 251 for (err = 0; header && (header->class != EL_CLASS__TERMINATION); err++) 252 header = el_process_subpacket(header); 253 254 /* let the console know it's ok to clear the error(s) at restart */ 255 pcpu->console_data_log_pa = 0; 256 257 printk("%s*** %d total error(s) logged\n" 258 "**** END OF CONSOLE DATA LOG FOR CPU %d ****\n", 259 err_print_prefix, err, cpu); 260 } 261 262 void __init 263 cdl_check_console_data_log(void) 264 { 265 struct percpu_struct *pcpu; 266 unsigned long cpu; 267 268 for (cpu = 0; cpu < hwrpb->nr_processors; cpu++) { 269 pcpu = (struct percpu_struct *) 270 ((unsigned long)hwrpb + hwrpb->processor_offset 271 + cpu * hwrpb->processor_size); 272 if (pcpu->console_data_log_pa) 273 cdl_process_console_data_log(cpu, pcpu); 274 } 275 276 } 277 278 int __init 279 cdl_register_subpacket_annotation(struct el_subpacket_annotation *new) 280 { 281 struct el_subpacket_annotation *a = subpacket_annotation_list; 282 283 if (a == NULL) subpacket_annotation_list = new; 284 else { 285 for (; a->next != NULL; a = a->next) { 286 if ((a->class == new->class && a->type == new->type) || 287 a == new) { 288 printk("Attempted to re-register " 289 "subpacket annotation\n"); 290 return -EINVAL; 291 } 292 } 293 a->next = new; 294 } 295 new->next = NULL; 296 297 return 0; 298 } 299 300 int __init 301 cdl_register_subpacket_handler(struct el_subpacket_handler *new) 302 { 303 struct el_subpacket_handler *h = subpacket_handler_list; 304 305 if (h == NULL) subpacket_handler_list = new; 306 else { 307 for (; h->next != NULL; h = h->next) { 308 if (h->class == new->class || h == new) { 309 printk("Attempted to re-register " 310 "subpacket handler\n"); 311 return -EINVAL; 312 } 313 } 314 h->next = new; 315 } 316 new->next = NULL; 317 318 return 0; 319 } 320 321