* 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 */
/*
* 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;
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;
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");
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)