Sophie

Sophie

distrib > Mageia > 2 > i586 > by-pkgid > 4b72850036257b2db627c2b9bbb2d6c0 > files > 2

kernel-vserver-3.4.69-1.mga2.src.rpm

commit 261cba2deb7d3bebd180c35d5dbf8961f6e9afc4
Author: Zhang Rui <rui.zhang@intel.com>
Date:   Tue Nov 27 20:42:11 2012 +0100

    ACPI / thermal: _TMP and _CRT/_HOT/_PSV/_ACx dependency fix
    
    On some platforms, _TMP and _CRT/_HOT/_PSV/_ACx have dependency.
    And there is no way for OS to detect this dependency.
    
    commit 9bcb8118965ab4631a65ee0726e6518f75cda6c5 shows us a problem
    that _TMP must be evaluate after _CRT/_HOT/_PSV/_ACx, or else
    firmware will shutdown the system.
    
    But the machine in https://bugzilla.kernel.org/show_bug.cgi?id=43284
    shows us that _PSV would return valid value only if _TMP has been
    evaluated once.
    
    With this patch, all of the control methods will be evaluated once,
    in the _CRT/_HOT/_PSV/_CRT/_TMP order, before they are actually used.
    
    [rjw: Added a local variable for the handle and modified the loop
     slightly.]
    Signed-off-by: Zhang Rui <rui.zhang@intel.com>
    Tested-by: katabami <katabami@lavabit.com>
    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 804204d..6e8cc16 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -933,6 +933,38 @@ static void acpi_thermal_notify(struct a
 	}
 }
 
+/*
+ * 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;
@@ -941,6 +973,8 @@ static int acpi_thermal_get_info(struct
 	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)