vserver 1.9.3
[linux-2.6.git] / arch / ppc64 / kernel / rtasd.c
index 7538cea..c6370a8 100644 (file)
@@ -46,6 +46,8 @@ 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;
+
 extern volatile int no_more_logging;
 
 volatile int error_log_cnt = 0;
@@ -57,6 +59,37 @@ 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",
+       "Address Invalid", "ECC Uncorrected", "ECC Corrupted",
+};
+
+static char *rtas_event_type(int type)
+{
+       if ((type > 0) && (type < 11))
+               return rtas_type[type];
+
+       switch (type) {
+               case RTAS_TYPE_EPOW:
+                       return "EPOW";
+               case RTAS_TYPE_PLATFORM:
+                       return "Platform Error";
+               case RTAS_TYPE_IO:
+                       return "I/O Event";
+               case RTAS_TYPE_INFO:
+                       return "Platform Information Event";
+               case RTAS_TYPE_DEALLOC:
+                       return "Resource Deallocation Event";
+               case RTAS_TYPE_DUMP:
+                       return "Dump Notification Event";
+       }
+
+       return rtas_type[0];
+}
+
 /* To see this info, grep RTAS /var/log/messages and each entry
  * will be collected together with obvious begin/end.
  * There will be a unique identifier on the begin and end lines.
@@ -73,38 +106,48 @@ static unsigned char logdata[RTAS_ERROR_LOG_MAX];
 static void printk_log_rtas(char *buf, int len)
 {
 
-       int i,j,n;
+       int i,j,n = 0;
        int perline = 16;
        char buffer[64];
        char * str = "RTAS event";
 
-       printk(RTAS_DEBUG "%d -------- %s begin --------\n", error_log_cnt, str);
-
-       /*
-        * Print perline bytes on each line, each line will start
-        * with RTAS and a changing number, so syslogd will
-        * print lines that are otherwise the same.  Separate every
-        * 4 bytes with a space.
-        */
-       for (i=0; i < len; i++) {
-               j = i % perline;
-               if (j == 0) {
-                       memset(buffer, 0, sizeof(buffer));
-                       n = sprintf(buffer, "RTAS %d:", i/perline);
+       if (full_rtas_msgs) {
+               printk(RTAS_DEBUG "%d -------- %s begin --------\n",
+                      error_log_cnt, str);
+
+               /*
+                * Print perline bytes on each line, each line will start
+                * with RTAS and a changing number, so syslogd will
+                * print lines that are otherwise the same.  Separate every
+                * 4 bytes with a space.
+                */
+               for (i = 0; i < len; i++) {
+                       j = i % perline;
+                       if (j == 0) {
+                               memset(buffer, 0, sizeof(buffer));
+                               n = sprintf(buffer, "RTAS %d:", i/perline);
+                       }
+
+                       if ((i % 4) == 0)
+                               n += sprintf(buffer+n, " ");
+
+                       n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
+
+                       if (j == (perline-1))
+                               printk(KERN_DEBUG "%s\n", buffer);
                }
+               if ((i % perline) != 0)
+                       printk(KERN_DEBUG "%s\n", buffer);
 
-               if ((i % 4) == 0)
-                       n += sprintf(buffer+n, " ");
-
-               n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
+               printk(RTAS_DEBUG "%d -------- %s end ----------\n",
+                      error_log_cnt, str);
+       } else {
+               struct rtas_error_log *errlog = (struct rtas_error_log *)buf;
 
-               if (j == (perline-1))
-                       printk(KERN_DEBUG "%s\n", buffer);
+               printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n",
+                      error_log_cnt, rtas_event_type(errlog->type),
+                      errlog->severity);
        }
-       if ((i % perline) != 0)
-               printk(KERN_DEBUG "%s\n", buffer);
-
-       printk(RTAS_DEBUG "%d -------- %s end ----------\n", error_log_cnt, str);
 }
 
 static int log_rtas_len(char * buf)
@@ -121,6 +164,9 @@ static int log_rtas_len(char * buf)
                len += err->extended_log_length;
        }
 
+       if (rtas_error_log_max == 0) {
+               get_eventscan_parms();
+       }
        if (len > rtas_error_log_max)
                len = rtas_error_log_max;
 
@@ -148,7 +194,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
        int len = 0;
 
        DEBUG("logging event\n");
-
        if (buf == NULL)
                return;
 
@@ -171,6 +216,14 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
        if (!no_more_logging && !(err_type & ERR_FLAG_BOOT))
                nvram_write_error_log(buf, len, err_type);
 
+       /*
+        * rtas errors can occur during boot, and we do want to capture
+        * those somewhere, even if nvram isn't ready (why not?), and even
+        * if rtasd isn't ready. Put them into the boot log, at least.
+        */
+       if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG)
+               printk_log_rtas(buf, len);
+
        /* Check to see if we need to or have stopped logging */
        if (fatal || no_more_logging) {
                no_more_logging = 1;
@@ -181,9 +234,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
        /* call type specific method for error */
        switch (err_type & ERR_TYPE_MASK) {
        case ERR_TYPE_RTAS_LOG:
-               /* put into syslog and error_log file */
-               printk_log_rtas(buf, len);
-
                offset = rtas_error_log_buffer_max *
                        ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK);
 
@@ -291,15 +341,18 @@ static int enable_surveillance(int timeout)
 {
        int error;
 
-       error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
-                         SURVEILLANCE_TOKEN, 0, timeout);
+       error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout);
 
-       if (error) {
-               printk(KERN_ERR "rtasd: could not enable surveillance\n");
-               return -1;
+       if (error == 0)
+               return 0;
+
+       if (error == RTAS_NO_SUCH_INDICATOR) {
+               printk(KERN_INFO "rtasd: surveillance not supported\n");
+               return 0;
        }
 
-       return 0;
+       printk(KERN_ERR "rtasd: could not update surveillance\n");
+       return -1;
 }
 
 static int get_eventscan_parms(void)
@@ -318,21 +371,8 @@ static int get_eventscan_parms(void)
        rtas_event_scan_rate = *ip;
        DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate);
 
-       ip = (int *)get_property(node, "rtas-error-log-max", NULL);
-       if (ip == NULL) {
-               printk(KERN_ERR "rtasd: no rtas-error-log-max\n");
-               of_node_put(node);
-               return -1;
-       }
-       rtas_error_log_max = *ip;
-       DEBUG("rtas-error-log-max %d\n", rtas_error_log_max);
-
-       if (rtas_error_log_max > RTAS_ERROR_LOG_MAX) {
-               printk(KERN_ERR "rtasd: truncated error log from %d to %d bytes\n", rtas_error_log_max, RTAS_ERROR_LOG_MAX);
-               rtas_error_log_max = RTAS_ERROR_LOG_MAX;
-       }
-
        /* 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);
@@ -473,5 +513,15 @@ static int __init surveillance_setup(char *str)
        return 1;
 }
 
+static int __init rtasmsgs_setup(char *str)
+{
+       if (strcmp(str, "on") == 0)
+               full_rtas_msgs = 1;
+       else if (strcmp(str, "off") == 0)
+               full_rtas_msgs = 0;
+
+       return 1;
+}
 __initcall(rtas_init);
 __setup("surveillance=", surveillance_setup);
+__setup("rtasmsgs=", rtasmsgs_setup);