root/arch/alpha/kernel/err_common.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mchk_dump_mem
  2. mchk_dump_logout_frame
  3. el_process_header_subpacket
  4. el_process_subpacket_reg
  5. el_print_timestamp
  6. el_process_subpackets
  7. el_process_subpacket
  8. el_annotate_subpacket
  9. cdl_process_console_data_log
  10. cdl_check_console_data_log
  11. cdl_register_subpacket_annotation
  12. cdl_register_subpacket_handler

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

/* [<][>][^][v][top][bottom][index][help] */