]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/acpi/processor_thermal.c
ACPI EC: remove potential deadlock from EC
[linux-2.6-omap-h63xx.git] / drivers / acpi / processor_thermal.c
index 37528c3b64b02baeb0aafbae96f2775495177453..06e6f3fb88254d61dda243f390a7eabc509696aa 100644 (file)
@@ -41,9 +41,8 @@
 
 #define ACPI_PROCESSOR_COMPONENT        0x01000000
 #define ACPI_PROCESSOR_CLASS            "processor"
-#define ACPI_PROCESSOR_DRIVER_NAME      "ACPI Processor Driver"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
-ACPI_MODULE_NAME("acpi_processor")
+ACPI_MODULE_NAME("processor_thermal");
 
 /* --------------------------------------------------------------------------
                                  Limit Interface
@@ -54,13 +53,12 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
        u16 px = 0;
        u16 tx = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_processor_apply_limit");
 
        if (!pr)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        if (!pr->flags.limit)
-               return_VALUE(-ENODEV);
+               return -ENODEV;
 
        if (pr->flags.throttling) {
                if (pr->limit.user.tx > tx)
@@ -82,9 +80,9 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
 
       end:
        if (result)
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to set limit\n"));
+               printk(KERN_ERR PREFIX "Unable to set limit\n");
 
-       return_VALUE(result);
+       return result;
 }
 
 #ifdef CONFIG_CPU_FREQ
@@ -101,11 +99,9 @@ static unsigned int acpi_thermal_cpufreq_is_init = 0;
 static int cpu_has_cpufreq(unsigned int cpu)
 {
        struct cpufreq_policy policy;
-       if (!acpi_thermal_cpufreq_is_init)
-               return -ENODEV;
-       if (!cpufreq_get_policy(&policy, cpu))
-               return -ENODEV;
-       return 0;
+       if (!acpi_thermal_cpufreq_is_init || cpufreq_get_policy(&policy, cpu))
+               return 0;
+       return 1;
 }
 
 static int acpi_thermal_cpufreq_increase(unsigned int cpu)
@@ -127,13 +123,13 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
        if (!cpu_has_cpufreq(cpu))
                return -ENODEV;
 
-       if (cpufreq_thermal_reduction_pctg[cpu] >= 20) {
+       if (cpufreq_thermal_reduction_pctg[cpu] > 20)
                cpufreq_thermal_reduction_pctg[cpu] -= 20;
-               cpufreq_update_policy(cpu);
-               return 0;
-       }
-
-       return -ERANGE;
+       else
+               cpufreq_thermal_reduction_pctg[cpu] = 0;
+       cpufreq_update_policy(cpu);
+       /* We reached max freq again and can leave passive mode */
+       return !cpufreq_thermal_reduction_pctg[cpu];
 }
 
 static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
@@ -200,21 +196,20 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
        int result = 0;
        struct acpi_processor *pr = NULL;
        struct acpi_device *device = NULL;
-       int tx = 0;
+       int tx = 0, max_tx_px = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit");
 
        if ((type < ACPI_PROCESSOR_LIMIT_NONE)
            || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        result = acpi_bus_get_device(handle, &device);
        if (result)
-               return_VALUE(result);
+               return result;
 
-       pr = (struct acpi_processor *)acpi_driver_data(device);
+       pr = acpi_driver_data(device);
        if (!pr)
-               return_VALUE(-ENODEV);
+               return -ENODEV;
 
        /* Thermal limits are always relative to the current Px/Tx state. */
        if (pr->flags.throttling)
@@ -259,19 +254,27 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
                /* if going down: T-states first, P-states later */
 
                if (pr->flags.throttling) {
-                       if (tx == 0)
+                       if (tx == 0) {
+                               max_tx_px = 1;
                                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                                  "At minimum throttling state\n"));
-                       else {
+                       else {
                                tx--;
                                goto end;
                        }
                }
 
                result = acpi_thermal_cpufreq_decrease(pr->id);
-               if (result == -ERANGE)
+               if (result) {
+                       /*
+                        * We only could get -ERANGE, 1 or 0.
+                        * In the first two cases we reached max freq again.
+                        */
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                          "At minimum performance state\n"));
+                       max_tx_px = 1;
+               } else
+                       max_tx_px = 0;
 
                break;
        }
@@ -283,28 +286,28 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
 
                result = acpi_processor_apply_limit(pr);
                if (result)
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "Unable to set thermal limit\n"));
+                       printk(KERN_ERR PREFIX "Unable to set thermal limit\n");
 
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
                                  pr->limit.thermal.px, pr->limit.thermal.tx));
        } else
                result = 0;
-
-       return_VALUE(result);
+       if (max_tx_px)
+               return 1;
+       else
+               return result;
 }
 
 int acpi_processor_get_limit_info(struct acpi_processor *pr)
 {
-       ACPI_FUNCTION_TRACE("acpi_processor_get_limit_info");
 
        if (!pr)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        if (pr->flags.throttling)
                pr->flags.limit = 1;
 
-       return_VALUE(0);
+       return 0;
 }
 
 /* /proc interface */
@@ -313,7 +316,6 @@ static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
 {
        struct acpi_processor *pr = (struct acpi_processor *)seq->private;
 
-       ACPI_FUNCTION_TRACE("acpi_processor_limit_seq_show");
 
        if (!pr)
                goto end;
@@ -331,7 +333,7 @@ static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
                   pr->limit.thermal.px, pr->limit.thermal.tx);
 
       end:
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
@@ -340,52 +342,50 @@ static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
                           PDE(inode)->data);
 }
 
-ssize_t acpi_processor_write_limit(struct file * file,
-                                  const char __user * buffer,
-                                  size_t count, loff_t * data)
+static ssize_t acpi_processor_write_limit(struct file * file,
+                                         const char __user * buffer,
+                                         size_t count, loff_t * data)
 {
        int result = 0;
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_processor *pr = (struct acpi_processor *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_processor *pr = m->private;
        char limit_string[25] = { '\0' };
        int px = 0;
        int tx = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_processor_write_limit");
 
        if (!pr || (count > sizeof(limit_string) - 1)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
-               return_VALUE(-EINVAL);
+               return -EINVAL;
        }
 
        if (copy_from_user(limit_string, buffer, count)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
-               return_VALUE(-EFAULT);
+               return -EFAULT;
        }
 
        limit_string[count] = '\0';
 
        if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
-               return_VALUE(-EINVAL);
+               printk(KERN_ERR PREFIX "Invalid data format\n");
+               return -EINVAL;
        }
 
        if (pr->flags.throttling) {
                if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid tx\n"));
-                       return_VALUE(-EINVAL);
+                       printk(KERN_ERR PREFIX "Invalid tx\n");
+                       return -EINVAL;
                }
                pr->limit.user.tx = tx;
        }
 
        result = acpi_processor_apply_limit(pr);
 
-       return_VALUE(count);
+       return count;
 }
 
 struct file_operations acpi_processor_limit_fops = {
        .open = acpi_processor_limit_open_fs,
        .read = seq_read,
+       .write = acpi_processor_write_limit,
        .llseek = seq_lseek,
        .release = single_release,
 };