Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
[~shefty/rdma-dev.git] / drivers / acpi / thermal.c
index 1794468223c4c0d52847fbdb917246cb1c5e6f09..506fbd4b5733b5f1751d8c23521aaa398447e33d 100644 (file)
@@ -984,6 +984,38 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
        }
 }
 
+/*
+ * On some platforms, the AML code has dependency about
+ * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
+ * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
+ *    /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
+ * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
+ *    if _TMP has never been evaluated.
+ *
+ * As this dependency is totally transparent to OS, evaluate
+ * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
+ * _TMP, before they are actually used.
+ */
+static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
+{
+       acpi_handle handle = tz->device->handle;
+       unsigned long long value;
+       int i;
+
+       acpi_evaluate_integer(handle, "_CRT", NULL, &value);
+       acpi_evaluate_integer(handle, "_HOT", NULL, &value);
+       acpi_evaluate_integer(handle, "_PSV", NULL, &value);
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
+               acpi_status status;
+
+               status = acpi_evaluate_integer(handle, name, NULL, &value);
+               if (status == AE_NOT_FOUND)
+                       break;
+       }
+       acpi_evaluate_integer(handle, "_TMP", NULL, &value);
+}
+
 static int acpi_thermal_get_info(struct acpi_thermal *tz)
 {
        int result = 0;
@@ -992,6 +1024,8 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
        if (!tz)
                return -EINVAL;
 
+       acpi_thermal_aml_dependency_fix(tz);
+
        /* Get trip points [_CRT, _PSV, etc.] (required) */
        result = acpi_thermal_get_trip_points(tz);
        if (result)