Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[sfrench/cifs-2.6.git] / arch / powerpc / platforms / pseries / rtasd.c
index 9797b10b29351a44ea918aac081fe52fbec33790..7d3e2b0bd4d299d5f467fde2a014dec0fb835fdb 100644 (file)
 #include <asm/atomic.h>
 #include <asm/machdep.h>
 
-#if 0
-#define DEBUG(A...)    printk(KERN_ERR A)
-#else
-#define DEBUG(A...)
-#endif
 
 static DEFINE_SPINLOCK(rtasd_log_lock);
 
@@ -44,15 +39,20 @@ static unsigned long rtas_log_start;
 static unsigned long rtas_log_size;
 
 static int surveillance_timeout = -1;
-static unsigned int rtas_event_scan_rate;
 static unsigned int rtas_error_log_max;
 static unsigned int rtas_error_log_buffer_max;
 
-static int full_rtas_msgs = 0;
+/* RTAS service tokens */
+static unsigned int event_scan;
+static unsigned int rtas_event_scan_rate;
 
-extern int no_logging;
+static int full_rtas_msgs = 0;
 
-volatile int error_log_cnt = 0;
+/* Stop logging to nvram after first fatal error */
+static int logging_enabled; /* Until we initialize everything,
+                             * make sure we don't try logging
+                             * anything */
+static int error_log_cnt;
 
 /*
  * Since we use 32 bit RTAS, the physical address of this must be below
@@ -61,8 +61,6 @@ volatile int error_log_cnt = 0;
  */
 static unsigned char logdata[RTAS_ERROR_LOG_MAX];
 
-static int get_eventscan_parms(void);
-
 static char *rtas_type[] = {
        "Unknown", "Retry", "TCE Error", "Internal Device Failure",
        "Timeout", "Data Parity", "Address Parity", "Cache Parity",
@@ -166,9 +164,9 @@ static int log_rtas_len(char * buf)
                len += err->extended_log_length;
        }
 
-       if (rtas_error_log_max == 0) {
-               get_eventscan_parms();
-       }
+       if (rtas_error_log_max == 0)
+               rtas_error_log_max = rtas_get_error_log_max();
+
        if (len > rtas_error_log_max)
                len = rtas_error_log_max;
 
@@ -195,7 +193,7 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
        unsigned long s;
        int len = 0;
 
-       DEBUG("logging event\n");
+       pr_debug("rtasd: logging event\n");
        if (buf == NULL)
                return;
 
@@ -215,8 +213,8 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
        }
 
        /* Write error to NVRAM */
-       if (!no_logging && !(err_type & ERR_FLAG_BOOT))
-               nvram_write_error_log(buf, len, err_type);
+       if (logging_enabled && !(err_type & ERR_FLAG_BOOT))
+               nvram_write_error_log(buf, len, err_type, error_log_cnt);
 
        /*
         * rtas errors can occur during boot, and we do want to capture
@@ -227,8 +225,8 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
                printk_log_rtas(buf, len);
 
        /* Check to see if we need to or have stopped logging */
-       if (fatal || no_logging) {
-               no_logging = 1;
+       if (fatal || !logging_enabled) {
+               logging_enabled = 0;
                spin_unlock_irqrestore(&rtasd_log_lock, s);
                return;
        }
@@ -300,7 +298,7 @@ static ssize_t rtas_log_read(struct file * file, char __user * buf,
 
        spin_lock_irqsave(&rtasd_log_lock, s);
        /* if it's 0, then we know we got the last one (the one in NVRAM) */
-       if (rtas_log_size == 0 && !no_logging)
+       if (rtas_log_size == 0 && logging_enabled)
                nvram_clear_error_log();
        spin_unlock_irqrestore(&rtasd_log_lock, s);
 
@@ -356,32 +354,7 @@ static int enable_surveillance(int timeout)
        return -1;
 }
 
-static int get_eventscan_parms(void)
-{
-       struct device_node *node;
-       const int *ip;
-
-       node = of_find_node_by_path("/rtas");
-
-       ip = of_get_property(node, "rtas-event-scan-rate", NULL);
-       if (ip == NULL) {
-               printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n");
-               of_node_put(node);
-               return -1;
-       }
-       rtas_event_scan_rate = *ip;
-       DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate);
-
-       /* Make room for the sequence number */
-       rtas_error_log_max = rtas_get_error_log_max();
-       rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
-
-       of_node_put(node);
-
-       return 0;
-}
-
-static void do_event_scan(int event_scan)
+static void do_event_scan(void)
 {
        int error;
        do {
@@ -404,53 +377,42 @@ static void do_event_scan_all_cpus(long delay)
 {
        int cpu;
 
-       lock_cpu_hotplug();
+       get_online_cpus();
        cpu = first_cpu(cpu_online_map);
        for (;;) {
                set_cpus_allowed(current, cpumask_of_cpu(cpu));
-               do_event_scan(rtas_token("event-scan"));
+               do_event_scan();
                set_cpus_allowed(current, CPU_MASK_ALL);
 
                /* Drop hotplug lock, and sleep for the specified delay */
-               unlock_cpu_hotplug();
+               put_online_cpus();
                msleep_interruptible(delay);
-               lock_cpu_hotplug();
+               get_online_cpus();
 
                cpu = next_cpu(cpu, cpu_online_map);
                if (cpu == NR_CPUS)
                        break;
        }
-       unlock_cpu_hotplug();
+       put_online_cpus();
 }
 
 static int rtasd(void *unused)
 {
        unsigned int err_type;
-       int event_scan = rtas_token("event-scan");
        int rc;
 
        daemonize("rtasd");
 
-       if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1)
-               goto error;
-
-       rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER);
-       if (!rtas_log_buf) {
-               printk(KERN_ERR "rtasd: no memory\n");
-               goto error;
-       }
-
        printk(KERN_DEBUG "RTAS daemon started\n");
-
-       DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
+       pr_debug("rtasd: will sleep for %d milliseconds\n",
+                (30000 / rtas_event_scan_rate));
 
        /* See if we have any error stored in NVRAM */
        memset(logdata, 0, rtas_error_log_max);
-
-       rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type);
-
+       rc = nvram_read_error_log(logdata, rtas_error_log_max,
+                                 &err_type, &error_log_cnt);
        /* We can use rtas_log_buf now */
-       no_logging = 0;
+       logging_enabled = 1;
 
        if (!rc) {
                if (err_type != ERR_FLAG_ALREADY_LOGGED) {
@@ -462,9 +424,9 @@ static int rtasd(void *unused)
        do_event_scan_all_cpus(1000);
 
        if (surveillance_timeout != -1) {
-               DEBUG("enabling surveillance\n");
+               pr_debug("rtasd: enabling surveillance\n");
                enable_surveillance(surveillance_timeout);
-               DEBUG("surveillance enabled\n");
+               pr_debug("rtasd: surveillance enabled\n");
        }
 
        /* Delay should be at least one second since some
@@ -473,8 +435,6 @@ static int rtasd(void *unused)
        for (;;)
                do_event_scan_all_cpus(30000/rtas_event_scan_rate);
 
-error:
-       /* Should delete proc entries */
        return -EINVAL;
 }
 
@@ -486,15 +446,31 @@ static int __init rtas_init(void)
                return 0;
 
        /* No RTAS */
-       if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
+       event_scan = rtas_token("event-scan");
+       if (event_scan == RTAS_UNKNOWN_SERVICE) {
                printk(KERN_DEBUG "rtasd: no event-scan on system\n");
                return -ENODEV;
        }
 
-       entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
-       if (entry)
-               entry->proc_fops = &proc_rtas_log_operations;
-       else
+       rtas_event_scan_rate = rtas_token("rtas-event-scan-rate");
+       if (rtas_event_scan_rate == RTAS_UNKNOWN_SERVICE) {
+               printk(KERN_ERR "rtasd: no rtas-event-scan-rate on system\n");
+               return -ENODEV;
+       }
+
+       /* Make room for the sequence number */
+       rtas_error_log_max = rtas_get_error_log_max();
+       rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
+
+       rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER);
+       if (!rtas_log_buf) {
+               printk(KERN_ERR "rtasd: no memory\n");
+               return -ENOMEM;
+       }
+
+       entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL,
+                           &proc_rtas_log_operations);
+       if (!entry)
                printk(KERN_ERR "Failed to create error_log proc entry\n");
 
        if (kernel_thread(rtasd, NULL, CLONE_FS) < 0)