19 #include <linux/sched.h>
24 #include <linux/reboot.h>
26 #include <asm/machdep.h>
32 static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
35 static char global_mce_data_buf[RTAS_ERROR_LOG_MAX];
38 static int ras_check_exception_token;
40 #define EPOW_SENSOR_TOKEN 9
41 #define EPOW_SENSOR_INDEX 0
51 static int __init init_ras_IRQ(
void)
55 ras_check_exception_token =
rtas_token(
"check-exception");
76 #define EPOW_SHUTDOWN_NORMAL 1
77 #define EPOW_SHUTDOWN_ON_UPS 2
78 #define EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS 3
79 #define EPOW_SHUTDOWN_AMBIENT_TEMPERATURE_TOO_HIGH 4
83 switch (event_modifier) {
85 pr_emerg(
"Firmware initiated power off");
90 pr_emerg(
"Loss of power reported by firmware, system is "
91 "running on UPS/battery");
95 pr_emerg(
"Loss of system critical functions reported by "
97 pr_emerg(
"Check RTAS error log for details");
102 pr_emerg(
"Ambient temperature too high reported by firmware");
103 pr_emerg(
"Check RTAS error log for details");
108 pr_err(
"Unknown power/cooling shutdown event (modifier %d)",
122 #define EPOW_WARN_COOLING 1
123 #define EPOW_WARN_POWER 2
124 #define EPOW_SYSTEM_SHUTDOWN 3
125 #define EPOW_SYSTEM_HALT 4
126 #define EPOW_MAIN_ENCLOSURE 5
127 #define EPOW_POWER_OFF 7
131 struct pseries_errorlog *pseries_log;
137 if (pseries_log ==
NULL)
144 switch (action_code) {
146 pr_err(
"Non critical power or cooling issue cleared");
150 pr_err(
"Non critical cooling issue reported by firmware");
151 pr_err(
"Check RTAS error log for details");
155 pr_err(
"Non critical power issue reported by firmware");
156 pr_err(
"Check RTAS error log for details");
164 pr_emerg(
"Firmware initiated power off");
170 pr_emerg(
"Critical power/cooling issue reported by firmware");
171 pr_emerg(
"Check RTAS error log for details");
178 pr_err(
"Unknown power/cooling event (action code %d)",
197 spin_lock(&ras_log_buf_lock);
200 RTAS_VECTOR_EXTERNAL_INTERRUPT,
203 critical,
__pa(&ras_log_buf),
204 rtas_get_error_log_max());
206 log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);
210 spin_unlock(&ras_log_buf_lock);
222 static irqreturn_t ras_error_interrupt(
int irq,
void *dev_id)
224 struct rtas_error_log *rtas_elog;
228 spin_lock(&ras_log_buf_lock);
231 RTAS_VECTOR_EXTERNAL_INTERRUPT,
233 RTAS_INTERNAL_ERROR, 1 ,
235 rtas_get_error_log_max());
237 rtas_elog = (
struct rtas_error_log *)ras_log_buf;
239 if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC))
245 log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);
248 pr_emerg(
"Fatal hardware error reported by firmware");
249 pr_emerg(
"Check RTAS error log for details");
254 pr_err(
"Recoverable hardware error reported by firmware");
257 spin_unlock(&ras_log_buf_lock);
265 #define VALID_FWNMI_BUFFER(A) \
266 ((((A) >= 0x7000) && ((A) < 0x7ff0)) || \
267 (((A) >= rtas.base) && ((A) < (rtas.base + rtas.size - 16))))
285 static struct rtas_error_log *fwnmi_get_errinfo(
struct pt_regs *
regs)
287 unsigned long *savep;
288 struct rtas_error_log *
h, *errhdr =
NULL;
296 regs->
gpr[3] = savep[0];
299 h = (
struct rtas_error_log *)&savep[1];
302 errhdr = (
struct rtas_error_log *)&
__get_cpu_var(mce_data_buf);
306 len =
max_t(
int, 8+h->extended_log_length, RTAS_ERROR_LOG_MAX);
307 memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
308 memcpy(global_mce_data_buf, h, len);
309 errhdr = (
struct rtas_error_log *)global_mce_data_buf;
319 static void fwnmi_release_errinfo(
void)
329 struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
333 fwnmi_release_errinfo();
347 static int recover_mce(
struct pt_regs *
regs,
struct rtas_error_log *
err)
355 }
else if (err->disposition == RTAS_DISP_FULLY_RECOVERED) {
359 }
else if (err->disposition == RTAS_DISP_LIMITED_RECOVERY) {
366 err->severity == RTAS_SEVERITY_ERROR_SYNC) {
381 log_error((
char *)err, ERR_TYPE_RTAS_LOG, 0);
398 struct rtas_error_log *errp;
401 errp = fwnmi_get_errinfo(regs);
402 fwnmi_release_errinfo();
403 if (errp && recover_mce(regs, errp))