2 * linux/arch/alpha/kernel/err_common.c
4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
6 * Error handling code supporting Alpha systems
9 #include <linux/init.h>
10 #include <linux/sched.h>
13 #include <asm/hwrpb.h>
15 #include <asm/err_common.h>
21 * err_print_prefix -- error handling print routines should prefix
22 * all prints with this
24 char *err_print_prefix
= KERN_NOTICE
;
31 mchk_dump_mem(void *data
, size_t length
, char **annotation
)
33 unsigned long *ldata
= data
;
36 for (i
= 0; (i
* sizeof(*ldata
)) < length
; i
++) {
37 if (annotation
&& !annotation
[i
])
39 printk("%s %08x: %016lx %s\n",
41 (unsigned)(i
* sizeof(*ldata
)), ldata
[i
],
42 annotation
? annotation
[i
] : "");
47 mchk_dump_logout_frame(struct el_common
*mchk_header
)
49 printk("%s -- Frame Header --\n"
50 " Frame Size: %d (0x%x) bytes\n"
54 " Proc Offset: 0x%08x\n"
55 " Sys Offset: 0x%08x\n"
56 " -- Processor Region --\n",
58 mchk_header
->size
, mchk_header
->size
,
59 mchk_header
->retry
? "RETRY " : "",
60 mchk_header
->err2
? "SECOND_ERR " : "",
62 mchk_header
->frame_rev
,
63 mchk_header
->proc_offset
,
64 mchk_header
->sys_offset
);
66 mchk_dump_mem((void *)
67 ((unsigned long)mchk_header
+ mchk_header
->proc_offset
),
68 mchk_header
->sys_offset
- mchk_header
->proc_offset
,
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
,
76 printk("%s -- End of Frame --\n", err_print_prefix
);
84 static struct el_subpacket_handler
*subpacket_handler_list
= NULL
;
85 static struct el_subpacket_annotation
*subpacket_annotation_list
= NULL
;
87 static struct el_subpacket
*
88 el_process_header_subpacket(struct el_subpacket
*header
)
90 union el_timestamp timestamp
;
91 char *name
= "UNKNOWN EVENT";
95 if (header
->class != EL_CLASS__HEADER
) {
96 printk("%s** Unexpected header CLASS %d TYPE %d, aborting\n",
98 header
->class, header
->type
);
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
;
107 header
->by_type
.sys_err
.frame_packet_count
;
108 timestamp
.as_int
= 0;
110 case EL_TYPE__HEADER__SYSTEM_EVENT_FRAME
:
111 name
= "SYSTEM EVENT";
112 length
= header
->by_type
.sys_event
.frame_length
;
114 header
->by_type
.sys_event
.frame_packet_count
;
115 timestamp
= header
->by_type
.sys_event
.timestamp
;
117 case EL_TYPE__HEADER__HALT_FRAME
:
119 length
= header
->by_type
.err_halt
.frame_length
;
121 header
->by_type
.err_halt
.frame_packet_count
;
122 timestamp
= header
->by_type
.err_halt
.timestamp
;
124 case EL_TYPE__HEADER__LOGOUT_FRAME
:
125 name
= "LOGOUT FRAME";
126 length
= header
->by_type
.logout_header
.frame_length
;
128 timestamp
.as_int
= 0;
130 default: /* Unknown */
131 printk("%s** Unknown header - CLASS %d TYPE %d, aborting\n",
133 header
->class, header
->type
);
138 " CLASS %d, TYPE %d\n",
141 header
->class, header
->type
);
142 el_print_timestamp(×tamp
);
145 * Process the subpackets
147 el_process_subpackets(header
, packet_count
);
149 /* return the next header */
150 header
= (struct el_subpacket
*)
151 ((unsigned long)header
+ header
->length
+ length
);
155 static struct el_subpacket
*
156 el_process_subpacket_reg(struct el_subpacket
*header
)
158 struct el_subpacket
*next
= NULL
;
159 struct el_subpacket_handler
*h
= subpacket_handler_list
;
161 for (; h
&& h
->class != header
->class; h
= h
->next
);
162 if (h
) next
= h
->handler(header
);
168 el_print_timestamp(union el_timestamp
*timestamp
)
170 if (timestamp
->as_int
)
171 printk("%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n",
173 timestamp
->b
.month
, timestamp
->b
.day
,
174 timestamp
->b
.year
, timestamp
->b
.hour
,
175 timestamp
->b
.minute
, timestamp
->b
.second
);
179 el_process_subpackets(struct el_subpacket
*header
, int packet_count
)
181 struct el_subpacket
*subpacket
;
184 subpacket
= (struct el_subpacket
*)
185 ((unsigned long)header
+ header
->length
);
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
);
193 struct el_subpacket
*
194 el_process_subpacket(struct el_subpacket
*header
)
196 struct el_subpacket
*next
= NULL
;
198 switch(header
->class) {
199 case EL_CLASS__TERMINATION
:
200 /* Termination packet, there are no more */
202 case EL_CLASS__HEADER
:
203 next
= el_process_header_subpacket(header
);
206 if (NULL
== (next
= el_process_subpacket_reg(header
))) {
207 printk("%s** Unexpected header CLASS %d TYPE %d"
210 header
->class, header
->type
);
219 el_annotate_subpacket(struct el_subpacket
*header
)
221 struct el_subpacket_annotation
*a
;
222 char **annotation
= NULL
;
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
) {
229 * We found the annotation
231 annotation
= a
->annotation
;
232 printk("%s %s\n", err_print_prefix
, a
->description
);
237 mchk_dump_mem(header
, header
->length
, annotation
);
241 cdl_process_console_data_log(int cpu
, struct percpu_struct
*pcpu
)
243 struct el_subpacket
*header
= (struct el_subpacket
*)
244 (IDENT_ADDR
| pcpu
->console_data_log_pa
);
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
);
251 for (err
= 0; header
&& (header
->class != EL_CLASS__TERMINATION
); err
++)
252 header
= el_process_subpacket(header
);
254 /* let the console know it's ok to clear the error(s) at restart */
255 pcpu
->console_data_log_pa
= 0;
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
);
263 cdl_check_console_data_log(void)
265 struct percpu_struct
*pcpu
;
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
);
279 cdl_register_subpacket_annotation(struct el_subpacket_annotation
*new)
281 struct el_subpacket_annotation
*a
= subpacket_annotation_list
;
283 if (a
== NULL
) subpacket_annotation_list
= new;
285 for (; a
->next
!= NULL
; a
= a
->next
) {
286 if ((a
->class == new->class && a
->type
== new->type
) ||
288 printk("Attempted to re-register "
289 "subpacket annotation\n");
301 cdl_register_subpacket_handler(struct el_subpacket_handler
*new)
303 struct el_subpacket_handler
*h
= subpacket_handler_list
;
305 if (h
== NULL
) subpacket_handler_list
= new;
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");