err_common.c 7.9 KB

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