|
4 | 4 | * Copyright (C) 2013 Mauro Carvalho Chehab <[email protected]> |
5 | 5 | */ |
6 | 6 |
|
| 7 | +#define _GNU_SOURCE |
7 | 8 | #include <pci/pci.h> |
8 | 9 | #include <stdio.h> |
9 | 10 | #include <stdlib.h> |
| 11 | +#include <stdio.h> |
10 | 12 | #include <string.h> |
11 | 13 | #include <traceevent/kbuffer.h> |
12 | 14 | #include <unistd.h> |
|
16 | 18 | #include "ras-logger.h" |
17 | 19 | #include "ras-report.h" |
18 | 20 | #include "unified-sel.h" |
| 21 | +#include "trigger.h" |
19 | 22 | #include "types.h" |
20 | 23 |
|
21 | 24 | /* bit field meaning for correctable error */ |
@@ -53,7 +56,46 @@ static const char *aer_uncor_errors[32] = { |
53 | 56 | [26] = "Poisoned TLP Egrees Blocked", |
54 | 57 | }; |
55 | 58 |
|
56 | | -static bool use_ipmitool = false; |
| 59 | +#define MAX_ENV 30 |
| 60 | +static const char *aer_ce_trigger = NULL; |
| 61 | +static const char *aer_ue_trigger = NULL; |
| 62 | + |
| 63 | +void aer_event_trigger_setup(void) |
| 64 | +{ |
| 65 | + const char *trigger; |
| 66 | + |
| 67 | + trigger = getenv("AER_CE_TRIGGER"); |
| 68 | + if (trigger && strcmp(trigger, "")) { |
| 69 | + aer_ce_trigger = trigger_check(trigger); |
| 70 | + |
| 71 | + if (!aer_ce_trigger) { |
| 72 | + log(ALL, LOG_ERR, |
| 73 | + "Cannot access aer_event ce trigger `%s`\n", |
| 74 | + trigger); |
| 75 | + } else { |
| 76 | + log(ALL, LOG_INFO, |
| 77 | + "Setup aer_event ce trigger `%s`\n", |
| 78 | + trigger); |
| 79 | + } |
| 80 | + } else { |
| 81 | + log(TERM, LOG_ERR, "\t no AER_CE_TRIGGER (%p)\n", trigger); |
| 82 | + } |
| 83 | + |
| 84 | + trigger = getenv("AER_UE_TRIGGER"); |
| 85 | + if (trigger && strcmp(trigger, "")) { |
| 86 | + aer_ue_trigger = trigger_check(trigger); |
| 87 | + |
| 88 | + if (!aer_ue_trigger) { |
| 89 | + log(ALL, LOG_ERR, |
| 90 | + "Cannot access aer_event ue trigger `%s`\n", |
| 91 | + trigger); |
| 92 | + } else { |
| 93 | + log(ALL, LOG_INFO, |
| 94 | + "Setup aer_event ue trigger `%s`\n", |
| 95 | + trigger); |
| 96 | + } |
| 97 | + } |
| 98 | +} |
57 | 99 |
|
58 | 100 | void ras_aer_handler_init(int enable_ipmitool) |
59 | 101 | { |
@@ -103,6 +145,32 @@ static void get_pci_dev_name(char *bdf, char *pci_name, ssize_t len, u16 *vendor |
103 | 145 | pci_cleanup(pacc); |
104 | 146 | } |
105 | 147 |
|
| 148 | +static void run_aer_trigger(struct ras_aer_event *ev, const char *aer_trigger) |
| 149 | +{ |
| 150 | + char *env[MAX_ENV]; |
| 151 | + int ei = 0; |
| 152 | + int i; |
| 153 | + |
| 154 | + if (asprintf(&env[ei++], "PATH=%s", getenv("PATH") ?: "/sbin:/usr/sbin:/bin:/usr/bin") < 0) |
| 155 | + goto free; |
| 156 | + if (asprintf(&env[ei++], "TIMESTAMP=%s", ev->timestamp) < 0) |
| 157 | + goto free; |
| 158 | + if (asprintf(&env[ei++], "TYPE=%s", ev->error_type) < 0) |
| 159 | + goto free; |
| 160 | + if (asprintf(&env[ei++], "MESSAGE=%s", ev->msg) < 0) |
| 161 | + goto free; |
| 162 | + if (asprintf(&env[ei++], "NAME=%s", ev->dev_name) < 0) |
| 163 | + goto free; |
| 164 | + env[ei] = NULL; |
| 165 | + assert(ei < MAX_ENV); |
| 166 | + |
| 167 | + run_trigger(aer_trigger, NULL, env, "aer_event"); |
| 168 | + |
| 169 | +free: |
| 170 | + for (i = 0; i < ei; i++) |
| 171 | + free(env[i]); |
| 172 | +} |
| 173 | + |
106 | 174 | int ras_aer_event_handler(struct trace_seq *s, |
107 | 175 | struct tep_record *record, |
108 | 176 | struct tep_event *event, void *context) |
@@ -270,5 +338,11 @@ int ras_aer_event_handler(struct trace_seq *s, |
270 | 338 | return -1; |
271 | 339 | #endif |
272 | 340 |
|
| 341 | + if (aer_ce_trigger && !strcmp(ev.error_type, "Corrected")) |
| 342 | + run_aer_trigger(&ev, aer_ce_trigger); |
| 343 | + |
| 344 | + if (aer_ue_trigger && !strncmp(ev.error_type, "Uncorrected", 11)) |
| 345 | + run_aer_trigger(&ev, aer_ue_trigger); |
| 346 | + |
273 | 347 | return 0; |
274 | 348 | } |
0 commit comments