upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / arch / ppc64 / kernel / rtas.c
index 0eb8956..5575603 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/udbg.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
+#include <asm/systemcfg.h>
 
 struct flash_block_list_header rtas_firmware_flash_list = {0, NULL};
 
@@ -40,7 +41,7 @@ EXPORT_SYMBOL(rtas);
 
 char rtas_err_buf[RTAS_ERROR_LOG_MAX];
 
-spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(rtas_data_buf_lock);
 char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned;
 unsigned long rtas_rmo_buf;
 
@@ -254,29 +255,59 @@ rtas_extended_busy_delay_time(int status)
        return ms; 
 }
 
-int
-rtas_get_power_level(int powerdomain, int *level)
+int rtas_error_rc(int rtas_rc)
+{
+       int rc;
+
+       switch (rtas_rc) {
+               case -1:                /* Hardware Error */
+                       rc = -EIO;
+                       break;
+               case -3:                /* Bad indicator/domain/etc */
+                       rc = -EINVAL;
+                       break;
+               case -9000:             /* Isolation error */
+                       rc = -EFAULT;
+                       break;
+               case -9001:             /* Outstanding TCE/PTE */
+                       rc = -EEXIST;
+                       break;
+               case -9002:             /* No usable slot */
+                       rc = -ENODEV;
+                       break;
+               default:
+                       printk(KERN_ERR "%s: unexpected RTAS error %d\n",
+                                       __FUNCTION__, rtas_rc);
+                       rc = -ERANGE;
+                       break;
+       }
+       return rc;
+}
+
+int rtas_get_power_level(int powerdomain, int *level)
 {
        int token = rtas_token("get-power-level");
        int rc;
 
        if (token == RTAS_UNKNOWN_SERVICE)
-               return RTAS_UNKNOWN_OP;
+               return -ENOENT;
 
        while ((rc = rtas_call(token, 1, 2, level, powerdomain)) == RTAS_BUSY)
                udelay(1);
+
+       if (rc < 0)
+               return rtas_error_rc(rc);
        return rc;
 }
 
-int
-rtas_set_power_level(int powerdomain, int level, int *setlevel)
+int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 {
        int token = rtas_token("set-power-level");
        unsigned int wait_time;
        int rc;
 
        if (token == RTAS_UNKNOWN_SERVICE)
-               return RTAS_UNKNOWN_OP;
+               return -ENOENT;
 
        while (1) {
                rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
@@ -288,18 +319,20 @@ rtas_set_power_level(int powerdomain, int level, int *setlevel)
                } else
                        break;
        }
+
+       if (rc < 0)
+               return rtas_error_rc(rc);
        return rc;
 }
 
-int
-rtas_get_sensor(int sensor, int index, int *state)
+int rtas_get_sensor(int sensor, int index, int *state)
 {
        int token = rtas_token("get-sensor-state");
        unsigned int wait_time;
        int rc;
 
        if (token == RTAS_UNKNOWN_SERVICE)
-               return RTAS_UNKNOWN_OP;
+               return -ENOENT;
 
        while (1) {
                rc = rtas_call(token, 2, 2, state, sensor, index);
@@ -311,18 +344,20 @@ rtas_get_sensor(int sensor, int index, int *state)
                } else
                        break;
        }
+
+       if (rc < 0)
+               return rtas_error_rc(rc);
        return rc;
 }
 
-int
-rtas_set_indicator(int indicator, int index, int new_value)
+int rtas_set_indicator(int indicator, int index, int new_value)
 {
        int token = rtas_token("set-indicator");
        unsigned int wait_time;
        int rc;
 
        if (token == RTAS_UNKNOWN_SERVICE)
-               return RTAS_UNKNOWN_OP;
+               return -ENOENT;
 
        while (1) {
                rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
@@ -336,6 +371,8 @@ rtas_set_indicator(int indicator, int index, int new_value)
                        break;
        }
 
+       if (rc < 0)
+               return rtas_error_rc(rc);
        return rc;
 }