diff options
Diffstat (limited to 'arch/powerpc/kernel/rtasd.c')
-rw-r--r-- | arch/powerpc/kernel/rtasd.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 1045ff49cc6d..1130c53ad652 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/nvram.h> | 29 | #include <asm/nvram.h> |
30 | #include <linux/atomic.h> | 30 | #include <linux/atomic.h> |
31 | #include <asm/machdep.h> | 31 | #include <asm/machdep.h> |
32 | #include <asm/topology.h> | ||
32 | 33 | ||
33 | 34 | ||
34 | static DEFINE_SPINLOCK(rtasd_log_lock); | 35 | static DEFINE_SPINLOCK(rtasd_log_lock); |
@@ -87,6 +88,8 @@ static char *rtas_event_type(int type) | |||
87 | return "Resource Deallocation Event"; | 88 | return "Resource Deallocation Event"; |
88 | case RTAS_TYPE_DUMP: | 89 | case RTAS_TYPE_DUMP: |
89 | return "Dump Notification Event"; | 90 | return "Dump Notification Event"; |
91 | case RTAS_TYPE_PRRN: | ||
92 | return "Platform Resource Reassignment Event"; | ||
90 | } | 93 | } |
91 | 94 | ||
92 | return rtas_type[0]; | 95 | return rtas_type[0]; |
@@ -265,9 +268,51 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
265 | spin_unlock_irqrestore(&rtasd_log_lock, s); | 268 | spin_unlock_irqrestore(&rtasd_log_lock, s); |
266 | return; | 269 | return; |
267 | } | 270 | } |
271 | } | ||
272 | |||
273 | #ifdef CONFIG_PPC_PSERIES | ||
274 | static s32 prrn_update_scope; | ||
268 | 275 | ||
276 | static void prrn_work_fn(struct work_struct *work) | ||
277 | { | ||
278 | /* | ||
279 | * For PRRN, we must pass the negative of the scope value in | ||
280 | * the RTAS event. | ||
281 | */ | ||
282 | pseries_devicetree_update(-prrn_update_scope); | ||
269 | } | 283 | } |
270 | 284 | ||
285 | static DECLARE_WORK(prrn_work, prrn_work_fn); | ||
286 | |||
287 | void prrn_schedule_update(u32 scope) | ||
288 | { | ||
289 | flush_work(&prrn_work); | ||
290 | prrn_update_scope = scope; | ||
291 | schedule_work(&prrn_work); | ||
292 | } | ||
293 | |||
294 | static void handle_rtas_event(const struct rtas_error_log *log) | ||
295 | { | ||
296 | if (log->type == RTAS_TYPE_PRRN) { | ||
297 | /* For PRRN Events the extended log length is used to denote | ||
298 | * the scope for calling rtas update-nodes. | ||
299 | */ | ||
300 | if (prrn_is_enabled()) | ||
301 | prrn_schedule_update(log->extended_log_length); | ||
302 | } | ||
303 | |||
304 | return; | ||
305 | } | ||
306 | |||
307 | #else | ||
308 | |||
309 | static void handle_rtas_event(const struct rtas_error_log *log) | ||
310 | { | ||
311 | return; | ||
312 | } | ||
313 | |||
314 | #endif | ||
315 | |||
271 | static int rtas_log_open(struct inode * inode, struct file * file) | 316 | static int rtas_log_open(struct inode * inode, struct file * file) |
272 | { | 317 | { |
273 | return 0; | 318 | return 0; |
@@ -388,8 +433,10 @@ static void do_event_scan(void) | |||
388 | break; | 433 | break; |
389 | } | 434 | } |
390 | 435 | ||
391 | if (error == 0) | 436 | if (error == 0) { |
392 | pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); | 437 | pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); |
438 | handle_rtas_event((struct rtas_error_log *)logdata); | ||
439 | } | ||
393 | 440 | ||
394 | } while(error == 0); | 441 | } while(error == 0); |
395 | } | 442 | } |