From: Mauro Carvalho Chehab Date: Tue, 26 Feb 2013 21:31:28 +0000 (-0300) Subject: edactool: add its own parser for ras:mc_event X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=8785b61f2ea735ad71e43a5108da10005e09221c;p=users%2Fmchehab%2Fedactool.git edactool: add its own parser for ras:mc_event The ras:mc_event is too complex for the built-in parser. Adds its own parser for it, that will produce an output similar to the in-kernel one. Signed-off-by: Mauro Carvalho Chehab --- diff --git a/edactool.c b/edactool.c index 15da181..48dc0c1 100644 --- a/edactool.c +++ b/edactool.c @@ -39,7 +39,7 @@ * blocks on read(). So, we need to sleep for a while, to avoid spending * too much CPU cycles. A fix for it is expected for 3.10. */ -#define POLLING_TIME 15 +#define POLLING_TIME 3 #define PAGE_SIZE 0x400 /* Test for a little-endian machine */ @@ -95,7 +95,118 @@ static int toggle_ras_mc_event(int enable) /* * Tracing read code */ -static void parse_ras_data(struct pevent *pevent, struct kbuffer *kbuf, void *data, unsigned long long time_stamp) + +/* Should match the code at Kernel's include/linux/edac.c */ +enum hw_event_mc_err_type { + HW_EVENT_ERR_CORRECTED, + HW_EVENT_ERR_UNCORRECTED, + HW_EVENT_ERR_FATAL, + HW_EVENT_ERR_INFO, +}; + +static char *mc_event_error_type(unsigned long long err_type) +{ + switch (err_type) { + case HW_EVENT_ERR_CORRECTED: + return "Corrected"; + case HW_EVENT_ERR_UNCORRECTED: + return "Uncorrected"; + case HW_EVENT_ERR_FATAL: + return "Fatal"; + default: + case HW_EVENT_ERR_INFO: + return "Info"; + } +} + +static int ras_mc_event_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + int len; + unsigned long long cnt, val, top_l, mid_l, low_l; + const char *str; + + if (pevent_get_field_val(s, event, "error_count", record, &cnt, 0) < 0) + return -1; + trace_seq_printf(s, "%lld ", cnt); + + if (pevent_get_field_val(s, event, "error_type", record, &val, 1) < 0) + return -1; + trace_seq_puts(s, mc_event_error_type(val)); + if (cnt > 1) + trace_seq_puts(s, " errors:"); + else + trace_seq_puts(s, " error:"); + str = pevent_get_field_raw(s, event, "msg", record, &len, 1); + if (!str) + return -1; + if (*str) { + trace_seq_puts(s, " "); + trace_seq_puts(s, str); + } + + str = pevent_get_field_raw(s, event, "label", record, &len, 1); + if (!str) + return -1; + if (*str) { + trace_seq_puts(s, " on "); + trace_seq_puts(s, str); + } + + trace_seq_puts(s, "("); + if (pevent_get_field_val(s, event, "mc_index", record, &val, 0) < 0) + return -1; + trace_seq_printf(s, " mc: %lld", val); + + if (pevent_get_field_val(s, event, "top_layer", record, &top_l, 0) < 0) + return -1; + if (pevent_get_field_val(s, event, "middle_layer", record, &mid_l, 0) < 0) + return -1; + if (pevent_get_field_val(s, event, "lower_layer", record, &low_l, 0) < 0) + return -1; + + if (top_l >= 0 || mid_l >= 0 || low_l >= 0) { + if (low_l >= 0) + trace_seq_printf(s, " location: %lld:%lld:%lld", + top_l, mid_l, low_l); + else if (mid_l >= 0) + trace_seq_printf(s, " location: %lld:%lld", + top_l, mid_l); + else + trace_seq_printf(s, " location: %lld", top_l); + } + + if (pevent_get_field_val(s, event, "address", record, &val, 0) < 0) + return -1; + if (val) + trace_seq_printf(s, " address: 0x%08llx", val); + + if (pevent_get_field_val(s, event, "grain", record, &val, 0) < 0) + return -1; + trace_seq_printf(s, " grain: %lld", val); + + + if (pevent_get_field_val(s, event, "syndrome", record, &val, 0) < 0) + return -1; + if (val) + trace_seq_printf(s, " syndrome: 0x%08llx", val); + + str = pevent_get_field_raw(s, event, "driver_detail", record, &len, 1); + if (!str) + return -1; + if (*str) { + trace_seq_puts(s, " "); + trace_seq_puts(s, str); + } + trace_seq_puts(s, ")"); + + return 0; +} + + +static void parse_ras_data(struct pevent *pevent, struct kbuffer *kbuf, + void *data, unsigned long long time_stamp) { struct pevent_record record; struct trace_seq s; @@ -113,7 +224,8 @@ static void parse_ras_data(struct pevent *pevent, struct kbuffer *kbuf, void *da trace_seq_do_printf(&s); } -static int read_ras_event(int fd, struct pevent *pevent, struct kbuffer *kbuf, void *page) +static int read_ras_event(int fd, struct pevent *pevent, struct kbuffer *kbuf, + void *page) { unsigned size; unsigned long long time_stamp; @@ -174,7 +286,7 @@ static int handle_ras_events_cpu(struct pevent *pevent, int cpu) perror("Can't allocate page"); return errno; } - +printf("Endian: %d\n", ENDIAN); kbuf = kbuffer_alloc(KBUFFER_LSIZE_8, ENDIAN); if (!kbuf) { perror("Can't allocate kbuf"); @@ -242,6 +354,9 @@ static int handle_ras_events(void) goto free_pevent; } + pevent_register_event_handler(pevent, -1, "ras", "mc_event", + ras_mc_event_handler, NULL); + rc = pevent_parse_event(pevent, page, size, "ras"); free(page); if (rc)