From 3d541c4b7f6efd55a98189afd1b2f1c9d048c1b3 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 24 Sep 2009 19:30:05 +0000 Subject: [PATCH] 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 --- arch/powerpc/kernel/Makefile | 1 + .../{platforms/pseries => kernel}/rtasd.c | 48 ++++++++++++------ arch/powerpc/platforms/Kconfig | 5 ++ arch/powerpc/platforms/chrp/Kconfig | 2 + arch/powerpc/platforms/chrp/setup.c | 50 ------------------- arch/powerpc/platforms/pseries/Kconfig | 1 + arch/powerpc/platforms/pseries/Makefile | 2 +- 7 files changed, 44 insertions(+), 65 deletions(-) rename arch/powerpc/{platforms/pseries => kernel}/rtasd.c (95%) 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 obj-$(CONFIG_PROC_FS) += $(procfs-y) rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) +obj-$(CONFIG_PPC_RTAS_DAEMON) += rtasd.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_LPARCFG) += lparcfg.o diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/kernel/rtasd.c similarity index 95% rename from arch/powerpc/platforms/pseries/rtasd.c rename to 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; static unsigned long rtas_log_size; static int surveillance_timeout = -1; + static unsigned int rtas_error_log_max; static unsigned int rtas_error_log_buffer_max; @@ -213,9 +214,11 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) return; } +#ifdef CONFIG_PPC64 /* Write error to NVRAM */ if (logging_enabled && !(err_type & ERR_FLAG_BOOT)) nvram_write_error_log(buf, len, err_type, error_log_cnt); +#endif /* CONFIG_PPC64 */ /* * 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) } - static int rtas_log_open(struct inode * inode, struct file * file) { return 0; @@ -300,6 +302,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, return -ENOMEM; spin_lock_irqsave(&rtasd_log_lock, s); + /* if it's 0, then we know we got the last one (the one in NVRAM) */ while (rtas_log_size == 0) { if (file->f_flags & O_NONBLOCK) { @@ -313,7 +316,9 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf, error = -ENODATA; goto out; } +#ifdef CONFIG_PPC64 nvram_clear_error_log(); +#endif /* CONFIG_PPC64 */ spin_unlock_irqrestore(&rtasd_log_lock, s); error = wait_event_interruptible(rtas_log_wait, rtas_log_size); @@ -427,14 +432,11 @@ static void rtas_event_scan(struct work_struct *w) put_online_cpus(); } -static void start_event_scan(void) +#ifdef CONFIG_PPC64 +static void retreive_nvram_error_log(void) { - unsigned int err_type; - int rc; - - printk(KERN_DEBUG "RTAS daemon started\n"); - pr_debug("rtasd: will sleep for %d milliseconds\n", - (30000 / rtas_event_scan_rate)); + unsigned int err_type ; + int rc ; /* See if we have any error stored in NVRAM */ memset(logdata, 0, rtas_error_log_max); @@ -442,12 +444,26 @@ static void start_event_scan(void) &err_type, &error_log_cnt); /* We can use rtas_log_buf now */ logging_enabled = 1; - if (!rc) { if (err_type != ERR_FLAG_ALREADY_LOGGED) { pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); } } +} +#else /* CONFIG_PPC64 */ +static void retreive_nvram_error_log(void) +{ +} +#endif /* CONFIG_PPC64 */ + +static void start_event_scan(void) +{ + printk(KERN_DEBUG "RTAS daemon started\n"); + pr_debug("rtasd: will sleep for %d milliseconds\n", + (30000 / rtas_event_scan_rate)); + + /* Retreive errors from nvram if any */ + retreive_nvram_error_log(); schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work, event_scan_delay); @@ -457,13 +473,13 @@ static int __init rtas_init(void) { struct proc_dir_entry *entry; - if (!machine_is(pseries)) + if (!machine_is(pseries) && !machine_is(chrp)) return 0; /* No RTAS */ event_scan = rtas_token("event-scan"); if (event_scan == RTAS_UNKNOWN_SERVICE) { - printk(KERN_DEBUG "rtasd: no event-scan on system\n"); + printk(KERN_INFO "rtasd: No event-scan on system\n"); return -ENODEV; } @@ -483,7 +499,7 @@ static int __init rtas_init(void) return -ENOMEM; } - entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL, + entry = proc_create("powerpc/rtas/error_log", S_IRUSR, NULL, &proc_rtas_log_operations); if (!entry) printk(KERN_ERR "Failed to create error_log proc entry\n"); @@ -492,11 +508,16 @@ static int __init rtas_init(void) return 0; } +__initcall(rtas_init); static int __init surveillance_setup(char *str) { int i; + /* We only do surveillance on pseries */ + if (!machine_is(pseries)) + return 0; + if (get_option(&str,&i)) { if (i >= 0 && i <= 255) surveillance_timeout = i; @@ -504,6 +525,7 @@ static int __init surveillance_setup(char *str) return 1; } +__setup("surveillance=", surveillance_setup); static int __init rtasmsgs_setup(char *str) { @@ -514,6 +536,4 @@ static int __init rtasmsgs_setup(char *str) return 1; } -__initcall(rtas_init); -__setup("surveillance=", surveillance_setup); __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 depends on PPC_RTAS default n +config PPC_RTAS_DAEMON + bool + depends on PPC_RTAS + default n + config RTAS_PROC bool "Proc interface to RTAS" 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 select PPC_I8259 select PPC_INDIRECT_PCI select PPC_RTAS + select PPC_RTAS_DAEMON + select RTAS_ERROR_LOGGING select PPC_MPC106 select PPC_UDBG_16550 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) if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); } -void -chrp_event_scan(unsigned long unused) -{ - unsigned char log[1024]; - int ret = 0; - - /* XXX: we should loop until the hardware says no more error logs -- Cort */ - rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, - __pa(log), 1024); - mod_timer(&__get_cpu_var(heartbeat_timer), - jiffies + event_scan_interval); -} - static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc) { unsigned int cascade_irq = i8259_irq(); @@ -568,9 +555,6 @@ void __init chrp_init_IRQ(void) void __init chrp_init2(void) { - struct device_node *device; - const unsigned int *p = NULL; - #ifdef CONFIG_NVRAM chrp_nvram_init(); #endif @@ -582,40 +566,6 @@ chrp_init2(void) request_region(0x80,0x10,"dma page reg"); request_region(0xc0,0x20,"dma2"); - /* Get the event scan rate for the rtas so we know how - * often it expects a heartbeat. -- Cort - */ - device = of_find_node_by_name(NULL, "rtas"); - if (device) - p = of_get_property(device, "rtas-event-scan-rate", NULL); - if (p && *p) { - /* - * Arrange to call chrp_event_scan at least *p times - * per minute. We use 59 rather than 60 here so that - * the rate will be slightly higher than the minimum. - * This all assumes we don't do hotplug CPU on any - * machine that needs the event scans done. - */ - unsigned long interval, offset; - int cpu, ncpus; - struct timer_list *timer; - - interval = HZ * 59 / *p; - offset = HZ; - ncpus = num_online_cpus(); - event_scan_interval = ncpus * interval; - for (cpu = 0; cpu < ncpus; ++cpu) { - timer = &per_cpu(heartbeat_timer, cpu); - setup_timer(timer, chrp_event_scan, 0); - timer->expires = jiffies + offset; - add_timer_on(timer, cpu); - offset += interval; - } - printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", - *p, interval); - } - of_node_put(device); - if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); } 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 select MPIC select PPC_I8259 select PPC_RTAS + select PPC_RTAS_DAEMON select RTAS_ERROR_LOGGING select PPC_UDBG_16550 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 endif obj-y := lpar.o hvCall.o nvram.o reconfig.o \ - setup.o iommu.o ras.o rtasd.o \ + setup.o iommu.o ras.o \ firmware.o power.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_XICS) += xics.o