|
@@ -87,6 +87,8 @@ static char *rtas_event_type(int type)
|
|
|
return "Resource Deallocation Event";
|
|
|
case RTAS_TYPE_DUMP:
|
|
|
return "Dump Notification Event";
|
|
|
+ case RTAS_TYPE_PRRN:
|
|
|
+ return "Platform Resource Reassignment Event";
|
|
|
}
|
|
|
|
|
|
return rtas_type[0];
|
|
@@ -265,9 +267,49 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
|
|
|
spin_unlock_irqrestore(&rtasd_log_lock, s);
|
|
|
return;
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef CONFIG_PPC_PSERIES
|
|
|
+static s32 prrn_update_scope;
|
|
|
+
|
|
|
+static void prrn_work_fn(struct work_struct *work)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * For PRRN, we must pass the negative of the scope value in
|
|
|
+ * the RTAS event.
|
|
|
+ */
|
|
|
+ pseries_devicetree_update(-prrn_update_scope);
|
|
|
+}
|
|
|
+
|
|
|
+static DECLARE_WORK(prrn_work, prrn_work_fn);
|
|
|
+
|
|
|
+void prrn_schedule_update(u32 scope)
|
|
|
+{
|
|
|
+ flush_work(&prrn_work);
|
|
|
+ prrn_update_scope = scope;
|
|
|
+ schedule_work(&prrn_work);
|
|
|
+}
|
|
|
+
|
|
|
+static void handle_rtas_event(const struct rtas_error_log *log)
|
|
|
+{
|
|
|
+ if (log->type == RTAS_TYPE_PRRN)
|
|
|
+ /* For PRRN Events the extended log length is used to denote
|
|
|
+ * the scope for calling rtas update-nodes.
|
|
|
+ */
|
|
|
+ prrn_schedule_update(log->extended_log_length);
|
|
|
+
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
|
|
|
+static void handle_rtas_event(const struct rtas_error_log *log)
|
|
|
+{
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
+#endif
|
|
|
+
|
|
|
static int rtas_log_open(struct inode * inode, struct file * file)
|
|
|
{
|
|
|
return 0;
|
|
@@ -388,8 +430,10 @@ static void do_event_scan(void)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (error == 0)
|
|
|
+ if (error == 0) {
|
|
|
pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0);
|
|
|
+ handle_rtas_event((struct rtas_error_log *)logdata);
|
|
|
+ }
|
|
|
|
|
|
} while(error == 0);
|
|
|
}
|