1 // SPDX-License-Identifier: GPL-2.0
3 * linux/arch/alpha/kernel/err_common.c
5 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
7 * Error handling code supporting Alpha systems
10 #include <linux/init.h>
11 #include <linux/sched.h>
14 #include <asm/hwrpb.h>
16 #include <asm/err_common.h>
22 * err_print_prefix -- error handling print routines should prefix
23 * all prints with this
25 char *err_print_prefix
= KERN_NOTICE
;
32 mchk_dump_mem(void *data
, size_t length
, char **annotation
)
34 unsigned long *ldata
= data
;
37 for (i
= 0; (i
* sizeof(*ldata
)) < length
; i
++) {
38 if (annotation
&& !annotation
[i
])
40 printk("%s %08x: %016lx %s\n",
42 (unsigned)(i
* sizeof(*ldata
)), ldata
[i
],
43 annotation
? annotation
[i
] : "");
48 mchk_dump_logout_frame(struct el_common
*mchk_header
)
50 printk("%s -- Frame Header --\n"
51 " Frame Size: %d (0x%x) bytes\n"
55 " Proc Offset: 0x%08x\n"
56 " Sys Offset: 0x%08x\n"
57 " -- Processor Region --\n",
59 mchk_header
->size
, mchk_header
->size
,
60 mchk_header
->retry
? "RETRY " : "",
61 mchk_header
->err2
? "SECOND_ERR " : "",
63 mchk_header
->frame_rev
,
64 mchk_header
->proc_offset
,
65 mchk_header
->sys_offset
);
67 mchk_dump_mem((void *)
68 ((unsigned long)mchk_header
+ mchk_header
->proc_offset
),
69 mchk_header
->sys_offset
- mchk_header
->proc_offset
,
72 printk("%s -- System Region --\n", err_print_prefix
);
73 mchk_dump_mem((void *)
74 ((unsigned long)mchk_header
+ mchk_header
->sys_offset
),
75 mchk_header
->size
- mchk_header
->sys_offset
,
77 printk("%s -- End of Frame --\n", err_print_prefix
);
85 static struct el_subpacket_handler
*subpacket_handler_list
= NULL
;
86 static struct el_subpacket_annotation
*subpacket_annotation_list
= NULL
;
88 static struct el_subpacket
*
89 el_process_header_subpacket(struct el_subpacket
*header
)
91 union el_timestamp timestamp
;
92 char *name
= "UNKNOWN EVENT";
96 if (header
->class != EL_CLASS__HEADER
) {
97 printk("%s** Unexpected header CLASS %d TYPE %d, aborting\n",
99 header
->class, header
->type
);
103 switch(header
->type
) {
104 case EL_TYPE__HEADER__SYSTEM_ERROR_FRAME
:
105 name
= "SYSTEM ERROR";
106 length
= header
->by_type
.sys_err
.frame_length
;
108 header
->by_type
.sys_err
.frame_packet_count
;
109 timestamp
.as_int
= 0;
111 case EL_TYPE__HEADER__SYSTEM_EVENT_FRAME
:
112 name
= "SYSTEM EVENT";
113 length
= header
->by_type
.sys_event
.frame_length
;
115 header
->by_type
.sys_event
.frame_packet_count
;
116 timestamp
= header
->by_type
.sys_event
.timestamp
;
118 case EL_TYPE__HEADER__HALT_FRAME
:
120 length
= header
->by_type
.err_halt
.frame_length
;
122 header
->by_type
.err_halt
.frame_packet_count
;
123 timestamp
= header
->by_type
.err_halt
.timestamp
;
125 case EL_TYPE__HEADER__LOGOUT_FRAME
:
126 name
= "LOGOUT FRAME";
127 length
= header
->by_type
.logout_header
.frame_length
;
129 timestamp
.as_int
= 0;
131 default: /* Unknown */
132 printk("%s** Unknown header - CLASS %d TYPE %d, aborting\n",
134 header
->class, header
->type
);
139 " CLASS %d, TYPE %d\n",
142 header
->class, header
->type
);
143 el_print_timestamp(×tamp
);
146 * Process the subpackets
148 el_process_subpackets(header
, packet_count
);
150 /* return the next header */
151 header
= (struct el_subpacket
*)
152 ((unsigned long)header
+ header
->length
+ length
);
156 static struct el_subpacket
*
157 el_process_subpacket_reg(struct el_subpacket
*header
)
159 struct el_subpacket
*next
= NULL
;
160 struct el_subpacket_handler
*h
= subpacket_handler_list
;
162 for (; h
&& h
->class != header
->class; h
= h
->next
);
163 if (h
) next
= h
->handler(header
);
169 el_print_timestamp(union el_timestamp
*timestamp
)
171 if (timestamp
->as_int
)
172 printk("%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n",
174 timestamp
->b
.month
, timestamp
->b
.day
,
175 timestamp
->b
.year
, timestamp
->b
.hour
,
176 timestamp
->b
.minute
, timestamp
->b
.second
);
180 el_process_subpackets(struct el_subpacket
*header
, int packet_count
)
182 struct el_subpacket
*subpacket
;
185 subpacket
= (struct el_subpacket
*)
186 ((unsigned long)header
+ header
->length
);
188 for (i
= 0; subpacket
&& i
< packet_count
; i
++) {
189 printk("%sPROCESSING SUBPACKET %d\n", err_print_prefix
, i
);
190 subpacket
= el_process_subpacket(subpacket
);
194 struct el_subpacket
*
195 el_process_subpacket(struct el_subpacket
*header
)
197 struct el_subpacket
*next
= NULL
;
199 switch(header
->class) {
200 case EL_CLASS__TERMINATION
:
201 /* Termination packet, there are no more */
203 case EL_CLASS__HEADER
:
204 next
= el_process_header_subpacket(header
);
207 if (NULL
== (next
= el_process_subpacket_reg(header
))) {
208 printk("%s** Unexpected header CLASS %d TYPE %d"
211 header
->class, header
->type
);
220 el_annotate_subpacket(struct el_subpacket
*header
)
222 struct el_subpacket_annotation
*a
;
223 char **annotation
= NULL
;
225 for (a
= subpacket_annotation_list
; a
; a
= a
->next
) {
226 if (a
->class == header
->class &&
227 a
->type
== header
->type
&&
228 a
->revision
== header
->revision
) {
230 * We found the annotation
232 annotation
= a
->annotation
;
233 printk("%s %s\n", err_print_prefix
, a
->description
);
238 mchk_dump_mem(header
, header
->length
, annotation
);
242 cdl_process_console_data_log(int cpu
, struct percpu_struct
*pcpu
)
244 struct el_subpacket
*header
= (struct el_subpacket
*)
245 (IDENT_ADDR
| pcpu
->console_data_log_pa
);
248 printk("%s******* CONSOLE DATA LOG FOR CPU %d. *******\n"
249 "*** Error(s) were logged on a previous boot\n",
250 err_print_prefix
, cpu
);
252 for (err
= 0; header
&& (header
->class != EL_CLASS__TERMINATION
); err
++)
253 header
= el_process_subpacket(header
);
255 /* let the console know it's ok to clear the error(s) at restart */
256 pcpu
->console_data_log_pa
= 0;
258 printk("%s*** %d total error(s) logged\n"
259 "**** END OF CONSOLE DATA LOG FOR CPU %d ****\n",
260 err_print_prefix
, err
, cpu
);
264 cdl_check_console_data_log(void)
266 struct percpu_struct
*pcpu
;
269 for (cpu
= 0; cpu
< hwrpb
->nr_processors
; cpu
++) {
270 pcpu
= (struct percpu_struct
*)
271 ((unsigned long)hwrpb
+ hwrpb
->processor_offset
272 + cpu
* hwrpb
->processor_size
);
273 if (pcpu
->console_data_log_pa
)
274 cdl_process_console_data_log(cpu
, pcpu
);
280 cdl_register_subpacket_annotation(struct el_subpacket_annotation
*new)
282 struct el_subpacket_annotation
*a
= subpacket_annotation_list
;
284 if (a
== NULL
) subpacket_annotation_list
= new;
286 for (; a
->next
!= NULL
; a
= a
->next
) {
287 if ((a
->class == new->class && a
->type
== new->type
) ||
289 printk("Attempted to re-register "
290 "subpacket annotation\n");
302 cdl_register_subpacket_handler(struct el_subpacket_handler
*new)
304 struct el_subpacket_handler
*h
= subpacket_handler_list
;
306 if (h
== NULL
) subpacket_handler_list
= new;
308 for (; h
->next
!= NULL
; h
= h
->next
) {
309 if (h
->class == new->class || h
== new) {
310 printk("Attempted to re-register "
311 "subpacket handler\n");