summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/thermal.c197
1 files changed, 100 insertions, 97 deletions
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index bd8d9bfd5df9..a6599b19dba8 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -184,94 +184,6 @@ static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k)
tz->kelvin_offset);
}
-static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
-{
- acpi_status status;
- unsigned long long tmp;
- struct acpi_handle_list devices;
- bool valid = false;
- int i;
-
- /* Active (optional) */
- for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
- valid = tz->trips.active[i].trip.valid;
-
- if (act == -1)
- break; /* disable all active trip points */
-
- if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) &&
- tz->trips.active[i].trip.valid)) {
- status = acpi_evaluate_integer(tz->device->handle,
- name, NULL, &tmp);
- if (ACPI_FAILURE(status)) {
- tz->trips.active[i].trip.valid = false;
- if (i == 0)
- break;
-
- if (act <= 0)
- break;
-
- if (i == 1)
- tz->trips.active[0].trip.temperature =
- celsius_to_deci_kelvin(act);
- else
- /*
- * Don't allow override higher than
- * the next higher trip point
- */
- tz->trips.active[i-1].trip.temperature =
- min_t(unsigned long,
- tz->trips.active[i-2].trip.temperature,
- celsius_to_deci_kelvin(act));
-
- break;
- } else {
- tz->trips.active[i].trip.temperature = tmp;
- tz->trips.active[i].trip.valid = true;
- }
- }
-
- name[2] = 'L';
- if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].trip.valid) {
- memset(&devices, 0, sizeof(struct acpi_handle_list));
- status = acpi_evaluate_reference(tz->device->handle,
- name, NULL, &devices);
- if (ACPI_FAILURE(status)) {
- acpi_handle_info(tz->device->handle,
- "Invalid active%d threshold\n", i);
- tz->trips.active[i].trip.valid = false;
- } else {
- tz->trips.active[i].trip.valid = true;
- }
-
- if (memcmp(&tz->trips.active[i].devices, &devices,
- sizeof(struct acpi_handle_list))) {
- memcpy(&tz->trips.active[i].devices, &devices,
- sizeof(struct acpi_handle_list));
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
- }
- }
- if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
- if (valid != tz->trips.active[i].trip.valid)
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
-
- if (!tz->trips.active[i].trip.valid)
- break;
- }
-
- if (flag & ACPI_TRIPS_DEVICES) {
- memset(&devices, 0, sizeof(devices));
- status = acpi_evaluate_reference(tz->device->handle, "_TZD",
- NULL, &devices);
- if (ACPI_SUCCESS(status) &&
- memcmp(&tz->devices, &devices, sizeof(devices))) {
- tz->devices = devices;
- ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
- }
- }
-}
-
static void update_acpi_thermal_trip_temp(struct acpi_thermal_trip *acpi_trip,
int temp)
{
@@ -338,6 +250,78 @@ static void acpi_thermal_update_passive_devices(struct acpi_thermal *tz)
ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_PASSIVE, tz, "state");
}
+static long get_active_temp(struct acpi_thermal *tz, int index)
+{
+ char method[] = { '_', 'A', 'C', '0' + index, '\0' };
+ unsigned long long tmp;
+ acpi_status status;
+
+ status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp);
+ if (ACPI_FAILURE(status))
+ return THERMAL_TEMP_INVALID;
+
+ /*
+ * If an override has been provided, apply it so there are no active
+ * trips with thresholds greater than the override.
+ */
+ if (act > 0) {
+ unsigned long long override = celsius_to_deci_kelvin(act);
+
+ if (tmp > override)
+ tmp = override;
+ }
+ return tmp;
+}
+
+static void acpi_thermal_update_active_trip(struct acpi_thermal *tz, int index)
+{
+ struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip;
+
+ if (!acpi_trip->valid)
+ return;
+
+ update_acpi_thermal_trip_temp(acpi_trip, get_active_temp(tz, index));
+ if (!acpi_trip->valid)
+ ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "state");
+}
+
+static bool update_active_devices(struct acpi_thermal *tz, int index, bool compare)
+{
+ char method[] = { '_', 'A', 'L', '0' + index, '\0' };
+ struct acpi_handle_list devices;
+ acpi_status status;
+
+ memset(&devices, 0, sizeof(devices));
+
+ status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices);
+ if (ACPI_FAILURE(status)) {
+ acpi_handle_info(tz->device->handle,
+ "Missing device list for active threshold %d\n",
+ index);
+ return false;
+ }
+
+ if (compare && memcmp(&tz->trips.active[index].devices, &devices, sizeof(devices)))
+ ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "device");
+
+ memcpy(&tz->trips.active[index].devices, &devices, sizeof(devices));
+ return true;
+}
+
+static void acpi_thermal_update_active_devices(struct acpi_thermal *tz, int index)
+{
+ struct acpi_thermal_trip *acpi_trip = &tz->trips.active[index].trip;
+
+ if (!acpi_trip->valid)
+ return;
+
+ if (update_active_devices(tz, index, true))
+ return;
+
+ update_acpi_thermal_trip_temp(acpi_trip, THERMAL_TEMP_INVALID);
+ ACPI_THERMAL_TRIPS_EXCEPTION(ACPI_TRIPS_ACTIVE, tz, "state");
+}
+
static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data)
{
struct acpi_thermal_trip *acpi_trip = trip->priv;
@@ -358,18 +342,18 @@ static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal
unsigned long data)
{
struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
- int flag;
+ int i;
if (data == ACPI_THERMAL_NOTIFY_THRESHOLDS) {
acpi_thermal_update_passive_trip(tz);
- flag = ACPI_TRIPS_THRESHOLDS;
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
+ acpi_thermal_update_active_trip(tz, i);
} else {
acpi_thermal_update_passive_devices(tz);
- flag = ACPI_TRIPS_DEVICES;
+ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
+ acpi_thermal_update_active_devices(tz, i);
}
- __acpi_thermal_trips_update(tz, flag);
-
for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz);
}
@@ -498,6 +482,28 @@ fail:
return false;
}
+static bool acpi_thermal_init_active_trip(struct acpi_thermal *tz, int index)
+{
+ long temp;
+
+ if (act == -1)
+ goto fail;
+
+ temp = get_active_temp(tz, index);
+ if (temp == THERMAL_TEMP_INVALID)
+ goto fail;
+
+ if (!update_active_devices(tz, index, false))
+ goto fail;
+
+ update_acpi_thermal_trip_temp(&tz->trips.active[index].trip, temp);
+ return true;
+
+fail:
+ update_acpi_thermal_trip_temp(&tz->trips.active[index].trip, THERMAL_TEMP_INVALID);
+ return false;
+}
+
static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
{
unsigned int count = 0;
@@ -506,11 +512,8 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
if (acpi_thermal_init_passive_trip(tz))
count++;
- /* Active trip points (optional). */
- __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
-
for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
- if (tz->trips.active[i].trip.valid)
+ if (acpi_thermal_init_active_trip(tz, i))
count++;
else
break;