diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-09-24 15:30:05 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-10-30 02:20:53 -0400 |
commit | 3d541c4b7f6efd55a98189afd1b2f1c9d048c1b3 (patch) | |
tree | 37ea005412feedefe836afd0752051b0c93f4f71 | |
parent | 188917e183cf9ad0374b571006d0fc6d48a7f447 (diff) |
powerpc/chrp: Use the same RTAS daemon as pSeries
The CHRP code has some fishy timer based code to scan the RTAS event
log, which uses a 1KB stack buffer and doesn't even use the results.
The pSeries code as a nicer daemon that allows userspace to read the
event log and basically uses the same RTAS interface
This patch moves rtasd.c out of platform/pseries and makes it usable
by CHRP, after removing the old crufty event log mechanism in there.
The nvram logging part of the daemon is still only available on 64-bit
since the underlying nvram management routines aren't currently shared.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtasd.c (renamed from arch/powerpc/platforms/pseries/rtasd.c) | 48 | ||||
-rw-r--r-- | arch/powerpc/platforms/Kconfig | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/Kconfig | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/setup.c | 50 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/Makefile | 2 |
7 files changed, 44 insertions, 65 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 3faa39114219..c002b0410219 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -46,6 +46,7 @@ procfs-y := proc_powerpc.o | |||
46 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | 46 | obj-$(CONFIG_PROC_FS) += $(procfs-y) |
47 | rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o | 47 | rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o |
48 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) | 48 | obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) |
49 | obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o | ||
49 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o | 50 | obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o |
50 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o | 51 | obj-$(CONFIG_RTAS_PROC) += rtas-proc.o |
51 | obj-$(CONFIG_LPARCFG) += lparcfg.o | 52 | obj-$(CONFIG_LPARCFG) += lparcfg.o |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/kernel/rtasd.c index b3cbac855924..2e4832ab2108 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c | |||
@@ -39,6 +39,7 @@ static unsigned long rtas_log_start; | |||
39 | static unsigned long rtas_log_size; | 39 | static unsigned long rtas_log_size; |
40 | 40 | ||
41 | static int surveillance_timeout = -1; | 41 | static int surveillance_timeout = -1; |
42 | |||
42 | static unsigned int rtas_error_log_max; | 43 | static unsigned int rtas_error_log_max; |
43 | static unsigned int rtas_error_log_buffer_max; | 44 | static unsigned int rtas_error_log_buffer_max; |
44 | 45 | ||
@@ -213,9 +214,11 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
213 | return; | 214 | return; |
214 | } | 215 | } |
215 | 216 | ||
217 | #ifdef CONFIG_PPC64 | ||
216 | /* Write error to NVRAM */ | 218 | /* Write error to NVRAM */ |
217 | if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) | 219 | if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) |
218 | nvram_write_error_log(buf, len, err_type, error_log_cnt); | 220 | nvram_write_error_log(buf, len, err_type, error_log_cnt); |
221 | #endif /* CONFIG_PPC64 */ | ||
219 | 222 | ||
220 | /* | 223 | /* |
221 | * rtas errors can occur during boot, and we do want to capture | 224 | * rtas errors can occur during boot, and we do want to capture |
@@ -264,7 +267,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
264 | 267 | ||
265 | } | 268 | } |
266 | 269 | ||
267 | |||
268 | static int rtas_log_open(struct inode * inode, struct file * file) | 270 | static int rtas_log_open(struct inode * inode, struct file * file) |
269 | { | 271 | { |
270 | return 0; | 272 | return 0; |
@@ -300,6 +302,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, | |||
300 | return -ENOMEM; | 302 | return -ENOMEM; |
301 | 303 | ||
302 | spin_lock_irqsave(&rtasd_log_lock, s); | 304 | spin_lock_irqsave(&rtasd_log_lock, s); |
305 | |||
303 | /* if it's 0, then we know we got the last one (the one in NVRAM) */ | 306 | /* if it's 0, then we know we got the last one (the one in NVRAM) */ |
304 | while (rtas_log_size == 0) { | 307 | while (rtas_log_size == 0) { |
305 | if (file->f_flags & O_NONBLOCK) { | 308 | if (file->f_flags & O_NONBLOCK) { |
@@ -313,7 +316,9 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, | |||
313 | error = -ENODATA; | 316 | error = -ENODATA; |
314 | goto out; | 317 | goto out; |
315 | } | 318 | } |
319 | #ifdef CONFIG_PPC64 | ||
316 | nvram_clear_error_log(); | 320 | nvram_clear_error_log(); |
321 | #endif /* CONFIG_PPC64 */ | ||
317 | 322 | ||
318 | spin_unlock_irqrestore(&rtasd_log_lock, s); | 323 | spin_unlock_irqrestore(&rtasd_log_lock, s); |
319 | error = wait_event_interruptible(rtas_log_wait, rtas_log_size); | 324 | error = wait_event_interruptible(rtas_log_wait, rtas_log_size); |
@@ -427,14 +432,11 @@ static void rtas_event_scan(struct work_struct *w) | |||
427 | put_online_cpus(); | 432 | put_online_cpus(); |
428 | } | 433 | } |
429 | 434 | ||
430 | static void start_event_scan(void) | 435 | #ifdef CONFIG_PPC64 |
436 | static void retreive_nvram_error_log(void) | ||
431 | { | 437 | { |
432 | unsigned int err_type; | 438 | unsigned int err_type ; |
433 | int rc; | 439 | int rc ; |
434 | |||
435 | printk(KERN_DEBUG "RTAS daemon started\n"); | ||
436 | pr_debug("rtasd: will sleep for %d milliseconds\n", | ||
437 | (30000 / rtas_event_scan_rate)); | ||
438 | 440 | ||
439 | /* See if we have any error stored in NVRAM */ | 441 | /* See if we have any error stored in NVRAM */ |
440 | memset(logdata, 0, rtas_error_log_max); | 442 | memset(logdata, 0, rtas_error_log_max); |
@@ -442,12 +444,26 @@ static void start_event_scan(void) | |||
442 | &err_type, &error_log_cnt); | 444 | &err_type, &error_log_cnt); |
443 | /* We can use rtas_log_buf now */ | 445 | /* We can use rtas_log_buf now */ |
444 | logging_enabled = 1; | 446 | logging_enabled = 1; |
445 | |||
446 | if (!rc) { | 447 | if (!rc) { |
447 | if (err_type != ERR_FLAG_ALREADY_LOGGED) { | 448 | if (err_type != ERR_FLAG_ALREADY_LOGGED) { |
448 | pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); | 449 | pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); |
449 | } | 450 | } |
450 | } | 451 | } |
452 | } | ||
453 | #else /* CONFIG_PPC64 */ | ||
454 | static void retreive_nvram_error_log(void) | ||
455 | { | ||
456 | } | ||
457 | #endif /* CONFIG_PPC64 */ | ||
458 | |||
459 | static void start_event_scan(void) | ||
460 | { | ||
461 | printk(KERN_DEBUG "RTAS daemon started\n"); | ||
462 | pr_debug("rtasd: will sleep for %d milliseconds\n", | ||
463 | (30000 / rtas_event_scan_rate)); | ||
464 | |||
465 | /* Retreive errors from nvram if any */ | ||
466 | retreive_nvram_error_log(); | ||
451 | 467 | ||
452 | schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work, | 468 | schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work, |
453 | event_scan_delay); | 469 | event_scan_delay); |
@@ -457,13 +473,13 @@ static int __init rtas_init(void) | |||
457 | { | 473 | { |
458 | struct proc_dir_entry *entry; | 474 | struct proc_dir_entry *entry; |
459 | 475 | ||
460 | if (!machine_is(pseries)) | 476 | if (!machine_is(pseries) && !machine_is(chrp)) |
461 | return 0; | 477 | return 0; |
462 | 478 | ||
463 | /* No RTAS */ | 479 | /* No RTAS */ |
464 | event_scan = rtas_token("event-scan"); | 480 | event_scan = rtas_token("event-scan"); |
465 | if (event_scan == RTAS_UNKNOWN_SERVICE) { | 481 | if (event_scan == RTAS_UNKNOWN_SERVICE) { |
466 | printk(KERN_DEBUG "rtasd: no event-scan on system\n"); | 482 | printk(KERN_INFO "rtasd: No event-scan on system\n"); |
467 | return -ENODEV; | 483 | return -ENODEV; |
468 | } | 484 | } |
469 | 485 | ||
@@ -483,7 +499,7 @@ static int __init rtas_init(void) | |||
483 | return -ENOMEM; | 499 | return -ENOMEM; |
484 | } | 500 | } |
485 | 501 | ||
486 | entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL, | 502 | entry = proc_create("powerpc/rtas/error_log", S_IRUSR, NULL, |
487 | &proc_rtas_log_operations); | 503 | &proc_rtas_log_operations); |
488 | if (!entry) | 504 | if (!entry) |
489 | printk(KERN_ERR "Failed to create error_log proc entry\n"); | 505 | printk(KERN_ERR "Failed to create error_log proc entry\n"); |
@@ -492,11 +508,16 @@ static int __init rtas_init(void) | |||
492 | 508 | ||
493 | return 0; | 509 | return 0; |
494 | } | 510 | } |
511 | __initcall(rtas_init); | ||
495 | 512 | ||
496 | static int __init surveillance_setup(char *str) | 513 | static int __init surveillance_setup(char *str) |
497 | { | 514 | { |
498 | int i; | 515 | int i; |
499 | 516 | ||
517 | /* We only do surveillance on pseries */ | ||
518 | if (!machine_is(pseries)) | ||
519 | return 0; | ||
520 | |||
500 | if (get_option(&str,&i)) { | 521 | if (get_option(&str,&i)) { |
501 | if (i >= 0 && i <= 255) | 522 | if (i >= 0 && i <= 255) |
502 | surveillance_timeout = i; | 523 | surveillance_timeout = i; |
@@ -504,6 +525,7 @@ static int __init surveillance_setup(char *str) | |||
504 | 525 | ||
505 | return 1; | 526 | return 1; |
506 | } | 527 | } |
528 | __setup("surveillance=", surveillance_setup); | ||
507 | 529 | ||
508 | static int __init rtasmsgs_setup(char *str) | 530 | static int __init rtasmsgs_setup(char *str) |
509 | { | 531 | { |
@@ -514,6 +536,4 @@ static int __init rtasmsgs_setup(char *str) | |||
514 | 536 | ||
515 | return 1; | 537 | return 1; |
516 | } | 538 | } |
517 | __initcall(rtas_init); | ||
518 | __setup("surveillance=", surveillance_setup); | ||
519 | __setup("rtasmsgs=", rtasmsgs_setup); | 539 | __setup("rtasmsgs=", rtasmsgs_setup); |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 04a8061045c4..56bf12692f37 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -86,6 +86,11 @@ config RTAS_ERROR_LOGGING | |||
86 | depends on PPC_RTAS | 86 | depends on PPC_RTAS |
87 | default n | 87 | default n |
88 | 88 | ||
89 | config PPC_RTAS_DAEMON | ||
90 | bool | ||
91 | depends on PPC_RTAS | ||
92 | default n | ||
93 | |||
89 | config RTAS_PROC | 94 | config RTAS_PROC |
90 | bool "Proc interface to RTAS" | 95 | bool "Proc interface to RTAS" |
91 | depends on PPC_RTAS | 96 | depends on PPC_RTAS |
diff --git a/arch/powerpc/platforms/chrp/Kconfig b/arch/powerpc/platforms/chrp/Kconfig index 37d438bd5b7a..bc0b0efdc5fe 100644 --- a/arch/powerpc/platforms/chrp/Kconfig +++ b/arch/powerpc/platforms/chrp/Kconfig | |||
@@ -5,6 +5,8 @@ config PPC_CHRP | |||
5 | select PPC_I8259 | 5 | select PPC_I8259 |
6 | select PPC_INDIRECT_PCI | 6 | select PPC_INDIRECT_PCI |
7 | select PPC_RTAS | 7 | select PPC_RTAS |
8 | select PPC_RTAS_DAEMON | ||
9 | select RTAS_ERROR_LOGGING | ||
8 | select PPC_MPC106 | 10 | select PPC_MPC106 |
9 | select PPC_UDBG_16550 | 11 | select PPC_UDBG_16550 |
10 | select PPC_NATIVE | 12 | select PPC_NATIVE |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index cd4ad9aea760..52f3df3b4ca0 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -364,19 +364,6 @@ void __init chrp_setup_arch(void) | |||
364 | if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); | 364 | if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); |
365 | } | 365 | } |
366 | 366 | ||
367 | void | ||
368 | chrp_event_scan(unsigned long unused) | ||
369 | { | ||
370 | unsigned char log[1024]; | ||
371 | int ret = 0; | ||
372 | |||
373 | /* XXX: we should loop until the hardware says no more error logs -- Cort */ | ||
374 | rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, | ||
375 | __pa(log), 1024); | ||
376 | mod_timer(&__get_cpu_var(heartbeat_timer), | ||
377 | jiffies + event_scan_interval); | ||
378 | } | ||
379 | |||
380 | static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc) | 367 | static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc) |
381 | { | 368 | { |
382 | unsigned int cascade_irq = i8259_irq(); | 369 | unsigned int cascade_irq = i8259_irq(); |
@@ -568,9 +555,6 @@ void __init chrp_init_IRQ(void) | |||
568 | void __init | 555 | void __init |
569 | chrp_init2(void) | 556 | chrp_init2(void) |
570 | { | 557 | { |
571 | struct device_node *device; | ||
572 | const unsigned int *p = NULL; | ||
573 | |||
574 | #ifdef CONFIG_NVRAM | 558 | #ifdef CONFIG_NVRAM |
575 | chrp_nvram_init(); | 559 | chrp_nvram_init(); |
576 | #endif | 560 | #endif |
@@ -582,40 +566,6 @@ chrp_init2(void) | |||
582 | request_region(0x80,0x10,"dma page reg"); | 566 | request_region(0x80,0x10,"dma page reg"); |
583 | request_region(0xc0,0x20,"dma2"); | 567 | request_region(0xc0,0x20,"dma2"); |
584 | 568 | ||
585 | /* Get the event scan rate for the rtas so we know how | ||
586 | * often it expects a heartbeat. -- Cort | ||
587 | */ | ||
588 | device = of_find_node_by_name(NULL, "rtas"); | ||
589 | if (device) | ||
590 | p = of_get_property(device, "rtas-event-scan-rate", NULL); | ||
591 | if (p && *p) { | ||
592 | /* | ||
593 | * Arrange to call chrp_event_scan at least *p times | ||
594 | * per minute. We use 59 rather than 60 here so that | ||
595 | * the rate will be slightly higher than the minimum. | ||
596 | * This all assumes we don't do hotplug CPU on any | ||
597 | * machine that needs the event scans done. | ||
598 | */ | ||
599 | unsigned long interval, offset; | ||
600 | int cpu, ncpus; | ||
601 | struct timer_list *timer; | ||
602 | |||
603 | interval = HZ * 59 / *p; | ||
604 | offset = HZ; | ||
605 | ncpus = num_online_cpus(); | ||
606 | event_scan_interval = ncpus * interval; | ||
607 | for (cpu = 0; cpu < ncpus; ++cpu) { | ||
608 | timer = &per_cpu(heartbeat_timer, cpu); | ||
609 | setup_timer(timer, chrp_event_scan, 0); | ||
610 | timer->expires = jiffies + offset; | ||
611 | add_timer_on(timer, cpu); | ||
612 | offset += interval; | ||
613 | } | ||
614 | printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", | ||
615 | *p, interval); | ||
616 | } | ||
617 | of_node_put(device); | ||
618 | |||
619 | if (ppc_md.progress) | 569 | if (ppc_md.progress) |
620 | ppc_md.progress(" Have fun! ", 0x7777); | 570 | ppc_md.progress(" Have fun! ", 0x7777); |
621 | } | 571 | } |
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index f0e6f28427bd..26a24bd92623 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -4,6 +4,7 @@ config PPC_PSERIES | |||
4 | select MPIC | 4 | select MPIC |
5 | select PPC_I8259 | 5 | select PPC_I8259 |
6 | select PPC_RTAS | 6 | select PPC_RTAS |
7 | select PPC_RTAS_DAEMON | ||
7 | select RTAS_ERROR_LOGGING | 8 | select RTAS_ERROR_LOGGING |
8 | select PPC_UDBG_16550 | 9 | select PPC_UDBG_16550 |
9 | select PPC_NATIVE | 10 | select PPC_NATIVE |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 790c0b872d4f..4b1c422b8145 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -7,7 +7,7 @@ EXTRA_CFLAGS += -DDEBUG | |||
7 | endif | 7 | endif |
8 | 8 | ||
9 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | 9 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ |
10 | setup.o iommu.o ras.o rtasd.o \ | 10 | setup.o iommu.o ras.o \ |
11 | firmware.o power.o | 11 | firmware.o power.o |
12 | obj-$(CONFIG_SMP) += smp.o | 12 | obj-$(CONFIG_SMP) += smp.o |
13 | obj-$(CONFIG_XICS) += xics.o | 13 | obj-$(CONFIG_XICS) += xics.o |