Merge branch 'acpi-thermal'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 23 Oct 2023 17:51:26 +0000 (19:51 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 23 Oct 2023 17:51:26 +0000 (19:51 +0200)
Merge ACPI thermal driver changes are related thermal core changes for
v6.7-rc1:

 - Untangle the initialization and updates of passive and active trip
   points in the ACPI thermal driver (Rafael Wysocki).

 - Reduce code duplication related to the initialization and updates
   of trip points in the ACPI thermal driver (Rafael Wysocki).

 - Use trip pointers for cooling device binding in the ACPI thermal
   driver (Rafael Wysocki).

 - Simplify critical and hot trips representation in the ACPI thermal
   driver (Rafael Wysocki).

* acpi-thermal: (26 commits)
  thermal: trip: Drop lockdep assertion from thermal_zone_trip_id()
  thermal: trip: Remove lockdep assertion from for_each_thermal_trip()
  thermal: core: Drop thermal_zone_device_exec()
  ACPI: thermal: Use thermal_zone_for_each_trip() for updating trips
  ACPI: thermal: Combine passive and active trip update functions
  ACPI: thermal: Move get_active_temp()
  ACPI: thermal: Fix up function header formatting in two places
  ACPI: thermal: Drop list of device ACPI handles from struct acpi_thermal
  ACPI: thermal: Rename structure fields holding temperature in deci-Kelvin
  ACPI: thermal: Drop critical_valid and hot_valid trip flags
  ACPI: thermal: Do not use trip indices for cooling device binding
  ACPI: thermal: Mark uninitialized active trips as invalid
  ACPI: thermal: Merge trip initialization functions
  ACPI: thermal: Collapse trip devices update function wrappers
  ACPI: thermal: Collapse trip devices update functions
  ACPI: thermal: Add device list to struct acpi_thermal_trip
  ACPI: thermal: Fix a small leak in acpi_thermal_add()
  ACPI: thermal: Drop valid flag from struct acpi_thermal_trip
  ACPI: thermal: Drop redundant trip point flags
  ACPI: thermal: Untangle initialization and updates of active trips
  ...

drivers/acpi/thermal.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_trip.c
include/linux/thermal.h

index 312730f..fb9da37 100644 (file)
 #define ACPI_THERMAL_MAX_ACTIVE                10
 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
 
-#define ACPI_TRIPS_CRITICAL    BIT(0)
-#define ACPI_TRIPS_HOT         BIT(1)
-#define ACPI_TRIPS_PASSIVE     BIT(2)
-#define ACPI_TRIPS_ACTIVE      BIT(3)
-#define ACPI_TRIPS_DEVICES     BIT(4)
-
-#define ACPI_TRIPS_THRESHOLDS  (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
-
-#define ACPI_TRIPS_INIT                (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
-                                ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
-                                ACPI_TRIPS_DEVICES)
+#define ACPI_THERMAL_TRIP_PASSIVE      (-1)
 
 /*
  * This exception is thrown out in two cases:
  * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
  *   We need to re-bind the cooling devices of a thermal zone when this occurs.
  */
-#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \
+#define ACPI_THERMAL_TRIPS_EXCEPTION(tz, str) \
 do { \
-       if (flags != ACPI_TRIPS_INIT) \
-               acpi_handle_info(tz->device->handle, \
-                       "ACPI thermal trip point %s changed\n" \
-                       "Please report to linux-acpi@vger.kernel.org\n", str); \
+       acpi_handle_info(tz->device->handle, \
+                        "ACPI thermal trip point %s changed\n" \
+                        "Please report to linux-acpi@vger.kernel.org\n", str); \
 } while (0)
 
 static int act;
@@ -93,13 +82,12 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
 static struct workqueue_struct *acpi_thermal_pm_queue;
 
 struct acpi_thermal_trip {
-       unsigned long temperature;
-       bool valid;
+       unsigned long temp_dk;
+       struct acpi_handle_list devices;
 };
 
 struct acpi_thermal_passive {
        struct acpi_thermal_trip trip;
-       struct acpi_handle_list devices;
        unsigned long tc1;
        unsigned long tc2;
        unsigned long tsp;
@@ -107,12 +95,9 @@ struct acpi_thermal_passive {
 
 struct acpi_thermal_active {
        struct acpi_thermal_trip trip;
-       struct acpi_handle_list devices;
 };
 
 struct acpi_thermal_trips {
-       struct acpi_thermal_trip critical;
-       struct acpi_thermal_trip hot;
        struct acpi_thermal_passive passive;
        struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
 };
@@ -120,13 +105,12 @@ struct acpi_thermal_trips {
 struct acpi_thermal {
        struct acpi_device *device;
        acpi_bus_id name;
-       unsigned long temperature;
-       unsigned long last_temperature;
+       unsigned long temp_dk;
+       unsigned long last_temp_dk;
        unsigned long polling_frequency;
        volatile u8 zombie;
        struct acpi_thermal_trips trips;
        struct thermal_trip *trip_table;
-       struct acpi_handle_list devices;
        struct thermal_zone_device *thermal_zone;
        int kelvin_offset;      /* in millidegrees */
        struct work_struct thermal_check_work;
@@ -146,16 +130,16 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
        if (!tz)
                return -EINVAL;
 
-       tz->last_temperature = tz->temperature;
+       tz->last_temp_dk = tz->temp_dk;
 
        status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       tz->temperature = tmp;
+       tz->temp_dk = tmp;
 
        acpi_handle_debug(tz->device->handle, "Temperature is %lu dK\n",
-                         tz->temperature);
+                         tz->temp_dk);
 
        return 0;
 }
@@ -188,245 +172,145 @@ 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)
+static bool acpi_thermal_trip_valid(struct acpi_thermal_trip *acpi_trip)
 {
+       return acpi_trip->temp_dk != THERMAL_TEMP_INVALID;
+}
+
+static int active_trip_index(struct acpi_thermal *tz,
+                            struct acpi_thermal_trip *acpi_trip)
+{
+       struct acpi_thermal_active *active;
+
+       active = container_of(acpi_trip, struct acpi_thermal_active, trip);
+       return active - tz->trips.active;
+}
+
+static long get_passive_temp(struct acpi_thermal *tz)
+{
+       unsigned long long tmp;
        acpi_status status;
+
+       status = acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return THERMAL_TEMP_INVALID;
+
+       return tmp;
+}
+
+static long get_active_temp(struct acpi_thermal *tz, int index)
+{
+       char method[] = { '_', 'A', 'C', '0' + index, '\0' };
        unsigned long long tmp;
-       struct acpi_handle_list devices;
-       bool valid = false;
-       int i;
+       acpi_status status;
 
-       /* Critical Shutdown */
-       if (flag & ACPI_TRIPS_CRITICAL) {
-               status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp);
-               tz->trips.critical.temperature = tmp;
-               /*
-                * Treat freezing temperatures as invalid as well; some
-                * BIOSes return really low values and cause reboots at startup.
-                * Below zero (Celsius) values clearly aren't right for sure..
-                * ... so lets discard those as invalid.
-                */
-               if (ACPI_FAILURE(status)) {
-                       tz->trips.critical.valid = false;
-                       acpi_handle_debug(tz->device->handle,
-                                         "No critical threshold\n");
-               } else if (tmp <= 2732) {
-                       pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp);
-                       tz->trips.critical.valid = false;
-               } else {
-                       tz->trips.critical.valid = true;
-                       acpi_handle_debug(tz->device->handle,
-                                         "Found critical threshold [%lu]\n",
-                                         tz->trips.critical.temperature);
-               }
-               if (tz->trips.critical.valid) {
-                       if (crt == -1) {
-                               tz->trips.critical.valid = false;
-                       } else if (crt > 0) {
-                               unsigned long crt_k = celsius_to_deci_kelvin(crt);
-
-                               /*
-                                * Allow override critical threshold
-                                */
-                               if (crt_k > tz->trips.critical.temperature)
-                                       pr_info("Critical threshold %d C\n", crt);
-
-                               tz->trips.critical.temperature = crt_k;
-                       }
-               }
-       }
+       status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return THERMAL_TEMP_INVALID;
 
-       /* Critical Sleep (optional) */
-       if (flag & ACPI_TRIPS_HOT) {
-               status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp);
-               if (ACPI_FAILURE(status)) {
-                       tz->trips.hot.valid = false;
-                       acpi_handle_debug(tz->device->handle,
-                                         "No hot threshold\n");
-               } else {
-                       tz->trips.hot.temperature = tmp;
-                       tz->trips.hot.valid = true;
-                       acpi_handle_debug(tz->device->handle,
-                                         "Found hot threshold [%lu]\n",
-                                         tz->trips.hot.temperature);
-               }
+       /*
+        * 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;
+}
 
-       /* Passive (optional) */
-       if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) ||
-           flag == ACPI_TRIPS_INIT) {
-               valid = tz->trips.passive.trip.valid;
-               if (psv == -1) {
-                       status = AE_SUPPORT;
-               } else if (psv > 0) {
-                       tmp = celsius_to_deci_kelvin(psv);
-                       status = AE_OK;
-               } else {
-                       status = acpi_evaluate_integer(tz->device->handle,
-                                                      "_PSV", NULL, &tmp);
-               }
+static void acpi_thermal_update_trip(struct acpi_thermal *tz,
+                                    const struct thermal_trip *trip)
+{
+       struct acpi_thermal_trip *acpi_trip = trip->priv;
 
-               if (ACPI_FAILURE(status)) {
-                       tz->trips.passive.trip.valid = false;
-               } else {
-                       tz->trips.passive.trip.temperature = tmp;
-                       tz->trips.passive.trip.valid = true;
-                       if (flag == ACPI_TRIPS_INIT) {
-                               status = acpi_evaluate_integer(tz->device->handle,
-                                                              "_TC1", NULL, &tmp);
-                               if (ACPI_FAILURE(status))
-                                       tz->trips.passive.trip.valid = false;
-                               else
-                                       tz->trips.passive.tc1 = tmp;
-
-                               status = acpi_evaluate_integer(tz->device->handle,
-                                                              "_TC2", NULL, &tmp);
-                               if (ACPI_FAILURE(status))
-                                       tz->trips.passive.trip.valid = false;
-                               else
-                                       tz->trips.passive.tc2 = tmp;
-
-                               status = acpi_evaluate_integer(tz->device->handle,
-                                                              "_TSP", NULL, &tmp);
-                               if (ACPI_FAILURE(status))
-                                       tz->trips.passive.trip.valid = false;
-                               else
-                                       tz->trips.passive.tsp = tmp;
-                       }
-               }
+       if (trip->type == THERMAL_TRIP_PASSIVE) {
+               if (psv > 0)
+                       return;
+
+               acpi_trip->temp_dk = get_passive_temp(tz);
+       } else {
+               int index = active_trip_index(tz, acpi_trip);
+
+               acpi_trip->temp_dk = get_active_temp(tz, index);
        }
-       if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.trip.valid) {
-               memset(&devices, 0, sizeof(struct acpi_handle_list));
-               status = acpi_evaluate_reference(tz->device->handle, "_PSL",
-                                                NULL, &devices);
-               if (ACPI_FAILURE(status)) {
-                       acpi_handle_info(tz->device->handle,
-                                        "Invalid passive threshold\n");
-                       tz->trips.passive.trip.valid = false;
-               } else {
-                       tz->trips.passive.trip.valid = true;
-               }
 
-               if (memcmp(&tz->trips.passive.devices, &devices,
-                          sizeof(struct acpi_handle_list))) {
-                       memcpy(&tz->trips.passive.devices, &devices,
-                              sizeof(struct acpi_handle_list));
-                       ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
-               }
+       if (!acpi_thermal_trip_valid(acpi_trip))
+               ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state");
+}
+
+static bool update_trip_devices(struct acpi_thermal *tz,
+                               struct acpi_thermal_trip *acpi_trip,
+                               int index, bool compare)
+{
+       struct acpi_handle_list devices;
+       char method[] = "_PSL";
+       acpi_status status;
+
+       if (index != ACPI_THERMAL_TRIP_PASSIVE) {
+               method[1] = 'A';
+               method[2] = 'L';
+               method[3] = '0' + index;
        }
-       if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
-               if (valid != tz->trips.passive.trip.valid)
-                       ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
+
+       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, "%s evaluation failure\n", method);
+               return false;
        }
 
-       /* 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 (compare && memcmp(&acpi_trip->devices, &devices, sizeof(devices)))
+               ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device");
 
-               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;
-                       }
-               }
+       memcpy(&acpi_trip->devices, &devices, sizeof(devices));
+       return 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");
+static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz,
+                                            const struct thermal_trip *trip)
+{
+       struct acpi_thermal_trip *acpi_trip = trip->priv;
+       int index = trip->type == THERMAL_TRIP_PASSIVE ?
+                       ACPI_THERMAL_TRIP_PASSIVE : active_trip_index(tz, acpi_trip);
 
-               if (!tz->trips.active[i].trip.valid)
-                       break;
-       }
+       if (update_trip_devices(tz, acpi_trip, index, true))
+               return;
 
-       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");
-               }
-       }
+       acpi_trip->temp_dk = THERMAL_TEMP_INVALID;
+       ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state");
 }
 
+struct adjust_trip_data {
+       struct acpi_thermal *tz;
+       u32 event;
+};
+
 static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data)
 {
        struct acpi_thermal_trip *acpi_trip = trip->priv;
-       struct acpi_thermal *tz = data;
+       struct adjust_trip_data *atd = data;
+       struct acpi_thermal *tz = atd->tz;
 
-       if (!acpi_trip)
+       if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip))
                return 0;
 
-       if (acpi_trip->valid)
-               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
+       if (atd->event == ACPI_THERMAL_NOTIFY_THRESHOLDS)
+               acpi_thermal_update_trip(tz, trip);
+       else
+               acpi_thermal_update_trip_devices(tz, trip);
+
+       if (acpi_thermal_trip_valid(acpi_trip))
+               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk);
        else
                trip->temperature = THERMAL_TEMP_INVALID;
 
        return 0;
 }
 
-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 = data == ACPI_THERMAL_NOTIFY_THRESHOLDS ?
-                               ACPI_TRIPS_THRESHOLDS : ACPI_TRIPS_DEVICES;
-
-       __acpi_thermal_trips_update(tz, flag);
-
-       for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz);
-}
-
 static void acpi_queue_thermal_check(struct acpi_thermal *tz)
 {
        if (!work_pending(&tz->thermal_check_work))
@@ -435,41 +319,156 @@ static void acpi_queue_thermal_check(struct acpi_thermal *tz)
 
 static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event)
 {
+       struct adjust_trip_data atd = { .tz = tz, .event = event };
        struct acpi_device *adev = tz->device;
 
        /*
-        * Use thermal_zone_device_exec() to carry out the trip points
+        * Use thermal_zone_for_each_trip() to carry out the trip points
         * update, so as to protect thermal_get_trend() from getting stale
         * trip point temperatures and to prevent thermal_zone_device_update()
         * invoked from acpi_thermal_check_fn() from producing inconsistent
         * results.
         */
-       thermal_zone_device_exec(tz->thermal_zone,
-                                acpi_thermal_adjust_thermal_zone, event);
+       thermal_zone_for_each_trip(tz->thermal_zone,
+                                  acpi_thermal_adjust_trip, &atd);
        acpi_queue_thermal_check(tz);
        acpi_bus_generate_netlink_event(adev->pnp.device_class,
                                        dev_name(&adev->dev), event, 0);
 }
 
+static long acpi_thermal_get_critical_trip(struct acpi_thermal *tz)
+{
+       unsigned long long tmp;
+       acpi_status status;
+
+       if (crt > 0) {
+               tmp = celsius_to_deci_kelvin(crt);
+               goto set;
+       }
+       if (crt == -1) {
+               acpi_handle_debug(tz->device->handle, "Critical threshold disabled\n");
+               return THERMAL_TEMP_INVALID;
+       }
+
+       status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_debug(tz->device->handle, "No critical threshold\n");
+               return THERMAL_TEMP_INVALID;
+       }
+       if (tmp <= 2732) {
+               /*
+                * Below zero (Celsius) values clearly aren't right for sure,
+                * so discard them as invalid.
+                */
+               pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp);
+               return THERMAL_TEMP_INVALID;
+       }
+
+set:
+       acpi_handle_debug(tz->device->handle, "Critical threshold [%llu]\n", tmp);
+       return tmp;
+}
+
+static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz)
+{
+       unsigned long long tmp;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp);
+       if (ACPI_FAILURE(status)) {
+               acpi_handle_debug(tz->device->handle, "No hot threshold\n");
+               return THERMAL_TEMP_INVALID;
+       }
+
+       acpi_handle_debug(tz->device->handle, "Hot threshold [%llu]\n", tmp);
+       return tmp;
+}
+
+static bool passive_trip_params_init(struct acpi_thermal *tz)
+{
+       unsigned long long tmp;
+       acpi_status status;
+
+       status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       tz->trips.passive.tc1 = tmp;
+
+       status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       tz->trips.passive.tc2 = tmp;
+
+       status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp);
+       if (ACPI_FAILURE(status))
+               return false;
+
+       tz->trips.passive.tsp = tmp;
+
+       return true;
+}
+
+static bool acpi_thermal_init_trip(struct acpi_thermal *tz, int index)
+{
+       struct acpi_thermal_trip *acpi_trip;
+       long temp;
+
+       if (index == ACPI_THERMAL_TRIP_PASSIVE) {
+               acpi_trip = &tz->trips.passive.trip;
+
+               if (psv == -1)
+                       goto fail;
+
+               if (!passive_trip_params_init(tz))
+                       goto fail;
+
+               temp = psv > 0 ? celsius_to_deci_kelvin(psv) :
+                                get_passive_temp(tz);
+       } else {
+               acpi_trip = &tz->trips.active[index].trip;
+
+               if (act == -1)
+                       goto fail;
+
+               temp = get_active_temp(tz, index);
+       }
+
+       if (temp == THERMAL_TEMP_INVALID)
+               goto fail;
+
+       if (!update_trip_devices(tz, acpi_trip, index, false))
+               goto fail;
+
+       acpi_trip->temp_dk = temp;
+       return true;
+
+fail:
+       acpi_trip->temp_dk = THERMAL_TEMP_INVALID;
+       return false;
+}
+
 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 {
-       bool valid;
+       unsigned int count = 0;
        int i;
 
-       __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
-
-       valid = tz->trips.critical.valid |
-               tz->trips.hot.valid |
-               tz->trips.passive.trip.valid;
+       if (acpi_thermal_init_trip(tz, ACPI_THERMAL_TRIP_PASSIVE))
+               count++;
 
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
-               valid = valid || tz->trips.active[i].trip.valid;
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               if (acpi_thermal_init_trip(tz, i))
+                       count++;
+               else
+                       break;
 
-       if (!valid) {
-               pr_warn(FW_BUG "No valid trip found\n");
-               return -ENODEV;
        }
-       return 0;
+
+       while (++i < ACPI_THERMAL_MAX_ACTIVE)
+               tz->trips.active[i].trip.temp_dk = THERMAL_TEMP_INVALID;
+
+       return count;
 }
 
 /* sys I/F for generic thermal sysfs support */
@@ -486,7 +485,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
        if (result)
                return result;
 
-       *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature,
+       *temp = deci_kelvin_to_millicelsius_with_offset(tz->temp_dk,
                                                        tz->kelvin_offset);
        return 0;
 }
@@ -503,15 +502,15 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
                return -EINVAL;
 
        acpi_trip = trip->priv;
-       if (!acpi_trip || !acpi_trip->valid)
+       if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip))
                return -EINVAL;
 
        switch (trip->type) {
        case THERMAL_TRIP_PASSIVE:
-               t = tz->trips.passive.tc1 * (tz->temperature -
-                                               tz->last_temperature) +
-                       tz->trips.passive.tc2 * (tz->temperature -
-                                               acpi_trip->temperature);
+               t = tz->trips.passive.tc1 * (tz->temp_dk -
+                                               tz->last_temp_dk) +
+                       tz->trips.passive.tc2 * (tz->temp_dk -
+                                               acpi_trip->temp_dk);
                if (t > 0)
                        *trend = THERMAL_TREND_RAISING;
                else if (t < 0)
@@ -522,7 +521,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
                return 0;
 
        case THERMAL_TRIP_ACTIVE:
-               t = acpi_thermal_temp(tz, tz->temperature);
+               t = acpi_thermal_temp(tz, tz->temp_dk);
                if (t <= trip->temperature)
                        break;
 
@@ -557,91 +556,72 @@ static void acpi_thermal_zone_device_critical(struct thermal_zone_device *therma
        thermal_zone_device_critical(thermal);
 }
 
-static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
-                                         struct thermal_cooling_device *cdev,
-                                         bool bind)
+struct acpi_thermal_bind_data {
+       struct thermal_zone_device *thermal;
+       struct thermal_cooling_device *cdev;
+       bool bind;
+};
+
+static int bind_unbind_cdev_cb(struct thermal_trip *trip, void *arg)
 {
-       struct acpi_device *device = cdev->devdata;
-       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
-       struct acpi_device *dev;
-       acpi_handle handle;
+       struct acpi_thermal_trip *acpi_trip = trip->priv;
+       struct acpi_thermal_bind_data *bd = arg;
+       struct thermal_zone_device *thermal = bd->thermal;
+       struct thermal_cooling_device *cdev = bd->cdev;
+       struct acpi_device *cdev_adev = cdev->devdata;
        int i;
-       int j;
-       int trip = -1;
-       int result = 0;
 
-       if (tz->trips.critical.valid)
-               trip++;
+       /* Skip critical and hot trips. */
+       if (!acpi_trip)
+               return 0;
 
-       if (tz->trips.hot.valid)
-               trip++;
+       for (i = 0; i < acpi_trip->devices.count; i++) {
+               acpi_handle handle = acpi_trip->devices.handles[i];
+               struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
 
-       if (tz->trips.passive.trip.valid) {
-               trip++;
-               for (i = 0; i < tz->trips.passive.devices.count; i++) {
-                       handle = tz->trips.passive.devices.handles[i];
-                       dev = acpi_fetch_acpi_dev(handle);
-                       if (dev != device)
-                               continue;
-
-                       if (bind)
-                               result = thermal_zone_bind_cooling_device(
-                                               thermal, trip, cdev,
-                                               THERMAL_NO_LIMIT,
-                                               THERMAL_NO_LIMIT,
-                                               THERMAL_WEIGHT_DEFAULT);
-                       else
-                               result =
-                                       thermal_zone_unbind_cooling_device(
-                                               thermal, trip, cdev);
-
-                       if (result)
-                               goto failed;
-               }
-       }
+               if (adev != cdev_adev)
+                       continue;
 
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (!tz->trips.active[i].trip.valid)
-                       break;
+               if (bd->bind) {
+                       int ret;
 
-               trip++;
-               for (j = 0; j < tz->trips.active[i].devices.count; j++) {
-                       handle = tz->trips.active[i].devices.handles[j];
-                       dev = acpi_fetch_acpi_dev(handle);
-                       if (dev != device)
-                               continue;
-
-                       if (bind)
-                               result = thermal_zone_bind_cooling_device(
-                                               thermal, trip, cdev,
-                                               THERMAL_NO_LIMIT,
-                                               THERMAL_NO_LIMIT,
-                                               THERMAL_WEIGHT_DEFAULT);
-                       else
-                               result = thermal_zone_unbind_cooling_device(
-                                               thermal, trip, cdev);
-
-                       if (result)
-                               goto failed;
+                       ret = thermal_bind_cdev_to_trip(thermal, trip, cdev,
+                                                       THERMAL_NO_LIMIT,
+                                                       THERMAL_NO_LIMIT,
+                                                       THERMAL_WEIGHT_DEFAULT);
+                       if (ret)
+                               return ret;
+               } else {
+                       thermal_unbind_cdev_from_trip(thermal, trip, cdev);
                }
        }
 
-failed:
-       return result;
+       return 0;
+}
+
+static int acpi_thermal_bind_unbind_cdev(struct thermal_zone_device *thermal,
+                                        struct thermal_cooling_device *cdev,
+                                        bool bind)
+{
+       struct acpi_thermal_bind_data bd = {
+               .thermal = thermal, .cdev = cdev, .bind = bind
+       };
+
+       return for_each_thermal_trip(thermal, bind_unbind_cdev_cb, &bd);
 }
 
 static int
 acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
                                 struct thermal_cooling_device *cdev)
 {
-       return acpi_thermal_cooling_device_cb(thermal, cdev, true);
+       return acpi_thermal_bind_unbind_cdev(thermal, cdev, true);
 }
 
 static int
 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
                                   struct thermal_cooling_device *cdev)
 {
-       return acpi_thermal_cooling_device_cb(thermal, cdev, false);
+       return acpi_thermal_bind_unbind_cdev(thermal, cdev, false);
 }
 
 static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
@@ -679,66 +659,11 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz)
        sysfs_remove_link(&tzdev->kobj, "device");
 }
 
-static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
+static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz,
+                                             unsigned int trip_count,
+                                             int passive_delay)
 {
-       struct acpi_thermal_trip *acpi_trip;
-       struct thermal_trip *trip;
-       int passive_delay = 0;
-       int trip_count = 0;
        int result;
-       int i;
-
-       if (tz->trips.critical.valid)
-               trip_count++;
-
-       if (tz->trips.hot.valid)
-               trip_count++;
-
-       if (tz->trips.passive.trip.valid) {
-               trip_count++;
-               passive_delay = tz->trips.passive.tsp * 100;
-       }
-
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++)
-               trip_count++;
-
-       trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL);
-       if (!trip)
-               return -ENOMEM;
-
-       tz->trip_table = trip;
-
-       if (tz->trips.critical.valid) {
-               trip->type = THERMAL_TRIP_CRITICAL;
-               trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature);
-               trip++;
-       }
-
-       if (tz->trips.hot.valid) {
-               trip->type = THERMAL_TRIP_HOT;
-               trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature);
-               trip++;
-       }
-
-       acpi_trip = &tz->trips.passive.trip;
-       if (acpi_trip->valid) {
-               trip->type = THERMAL_TRIP_PASSIVE;
-               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
-               trip->priv = acpi_trip;
-               trip++;
-       }
-
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               acpi_trip = &tz->trips.active[i].trip;
-
-               if (!acpi_trip->valid)
-                       break;
-
-               trip->type = THERMAL_TRIP_ACTIVE;
-               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
-               trip->priv = acpi_trip;
-               trip++;
-       }
 
        tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz",
                                                                   tz->trip_table,
@@ -748,10 +673,8 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
                                                                   NULL,
                                                                   passive_delay,
                                                                   tz->polling_frequency * 100);
-       if (IS_ERR(tz->thermal_zone)) {
-               result = PTR_ERR(tz->thermal_zone);
-               goto free_trip_table;
-       }
+       if (IS_ERR(tz->thermal_zone))
+               return PTR_ERR(tz->thermal_zone);
 
        result = acpi_thermal_zone_sysfs_add(tz);
        if (result)
@@ -770,8 +693,6 @@ remove_links:
        acpi_thermal_zone_sysfs_remove(tz);
 unregister_tzd:
        thermal_zone_device_unregister(tz->thermal_zone);
-free_trip_table:
-       kfree(tz->trip_table);
 
        return result;
 }
@@ -844,38 +765,6 @@ static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
        acpi_evaluate_integer(handle, "_TMP", NULL, &value);
 }
 
-static int acpi_thermal_get_info(struct acpi_thermal *tz)
-{
-       int result;
-
-       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)
-               return result;
-
-       /* Get temperature [_TMP] (required) */
-       result = acpi_thermal_get_temperature(tz);
-       if (result)
-               return result;
-
-       /* Set the cooling mode [_SCP] to active cooling (default) */
-       acpi_execute_simple_method(tz->device->handle, "_SCP",
-                                  ACPI_THERMAL_MODE_ACTIVE);
-
-       /* Get default polling frequency [_TZP] (optional) */
-       if (tzp)
-               tz->polling_frequency = tzp;
-       else
-               acpi_thermal_get_polling_frequency(tz);
-
-       return 0;
-}
-
 /*
  * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
  * handles temperature values with a single decimal place. As a consequence,
@@ -886,10 +775,9 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
  * The heuristic below should work for all ACPI thermal zones which have a
  * critical trip point with a value being a multiple of 0.5 degree Celsius.
  */
-static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
+static void acpi_thermal_guess_offset(struct acpi_thermal *tz, long crit_temp)
 {
-       if (tz->trips.critical.valid &&
-           (tz->trips.critical.temperature % 5) == 1)
+       if (crit_temp != THERMAL_TEMP_INVALID && crit_temp % 5 == 1)
                tz->kelvin_offset = 273100;
        else
                tz->kelvin_offset = 273200;
@@ -922,8 +810,14 @@ static void acpi_thermal_check_fn(struct work_struct *work)
 
 static int acpi_thermal_add(struct acpi_device *device)
 {
+       struct acpi_thermal_trip *acpi_trip;
+       struct thermal_trip *trip;
        struct acpi_thermal *tz;
+       unsigned int trip_count;
+       int crit_temp, hot_temp;
+       int passive_delay = 0;
        int result;
+       int i;
 
        if (!device)
                return -EINVAL;
@@ -938,22 +832,94 @@ static int acpi_thermal_add(struct acpi_device *device)
        strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
        device->driver_data = tz;
 
-       result = acpi_thermal_get_info(tz);
+       acpi_thermal_aml_dependency_fix(tz);
+
+       /* Get trip points [_CRT, _PSV, etc.] (required). */
+       trip_count = acpi_thermal_get_trip_points(tz);
+
+       crit_temp = acpi_thermal_get_critical_trip(tz);
+       if (crit_temp != THERMAL_TEMP_INVALID)
+               trip_count++;
+
+       hot_temp = acpi_thermal_get_hot_trip(tz);
+       if (hot_temp != THERMAL_TEMP_INVALID)
+               trip_count++;
+
+       if (!trip_count) {
+               pr_warn(FW_BUG "No valid trip points!\n");
+               result = -ENODEV;
+               goto free_memory;
+       }
+
+       /* Get temperature [_TMP] (required). */
+       result = acpi_thermal_get_temperature(tz);
        if (result)
                goto free_memory;
 
-       acpi_thermal_guess_offset(tz);
+       /* Set the cooling mode [_SCP] to active cooling. */
+       acpi_execute_simple_method(tz->device->handle, "_SCP",
+                                  ACPI_THERMAL_MODE_ACTIVE);
 
-       result = acpi_thermal_register_thermal_zone(tz);
-       if (result)
+       /* Determine the default polling frequency [_TZP]. */
+       if (tzp)
+               tz->polling_frequency = tzp;
+       else
+               acpi_thermal_get_polling_frequency(tz);
+
+       acpi_thermal_guess_offset(tz, crit_temp);
+
+       trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL);
+       if (!trip) {
+               result = -ENOMEM;
                goto free_memory;
+       }
+
+       tz->trip_table = trip;
+
+       if (crit_temp != THERMAL_TEMP_INVALID) {
+               trip->type = THERMAL_TRIP_CRITICAL;
+               trip->temperature = acpi_thermal_temp(tz, crit_temp);
+               trip++;
+       }
+
+       if (hot_temp != THERMAL_TEMP_INVALID) {
+               trip->type = THERMAL_TRIP_HOT;
+               trip->temperature = acpi_thermal_temp(tz, hot_temp);
+               trip++;
+       }
+
+       acpi_trip = &tz->trips.passive.trip;
+       if (acpi_thermal_trip_valid(acpi_trip)) {
+               passive_delay = tz->trips.passive.tsp * 100;
+
+               trip->type = THERMAL_TRIP_PASSIVE;
+               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk);
+               trip->priv = acpi_trip;
+               trip++;
+       }
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               acpi_trip =  &tz->trips.active[i].trip;
+
+               if (!acpi_thermal_trip_valid(acpi_trip))
+                       break;
+
+               trip->type = THERMAL_TRIP_ACTIVE;
+               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk);
+               trip->priv = acpi_trip;
+               trip++;
+       }
+
+       result = acpi_thermal_register_thermal_zone(tz, trip_count, passive_delay);
+       if (result)
+               goto free_trips;
 
        refcount_set(&tz->thermal_check_count, 3);
        mutex_init(&tz->thermal_check_lock);
        INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
 
        pr_info("%s [%s] (%ld C)\n", acpi_device_name(device),
-               acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature));
+               acpi_device_bid(device), deci_kelvin_to_celsius(tz->temp_dk));
 
        result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
                                                 acpi_thermal_notify);
@@ -965,6 +931,8 @@ static int acpi_thermal_add(struct acpi_device *device)
 flush_wq:
        flush_workqueue(acpi_thermal_pm_queue);
        acpi_thermal_unregister_thermal_zone(tz);
+free_trips:
+       kfree(tz->trip_table);
 free_memory:
        kfree(tz);
 
@@ -1010,11 +978,13 @@ static int acpi_thermal_resume(struct device *dev)
                return -EINVAL;
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (!tz->trips.active[i].trip.valid)
+               struct acpi_thermal_trip *acpi_trip = &tz->trips.active[i].trip;
+
+               if (!acpi_thermal_trip_valid(acpi_trip))
                        break;
 
-               for (j = 0; j < tz->trips.active[i].devices.count; j++) {
-                       acpi_bus_update_power(tz->trips.active[i].devices.handles[j],
+               for (j = 0; j < acpi_trip->devices.count; j++) {
+                       acpi_bus_update_power(acpi_trip->devices.handles[j],
                                              &power_state);
                }
        }
@@ -1046,7 +1016,8 @@ static struct acpi_driver acpi_thermal_driver = {
        .drv.pm = &acpi_thermal_pm,
 };
 
-static int thermal_act(const struct dmi_system_id *d) {
+static int thermal_act(const struct dmi_system_id *d)
+{
        if (act == 0) {
                pr_notice("%s detected: disabling all active thermal trip points\n",
                          d->ident);
@@ -1054,13 +1025,17 @@ static int thermal_act(const struct dmi_system_id *d) {
        }
        return 0;
 }
-static int thermal_nocrt(const struct dmi_system_id *d) {
+
+static int thermal_nocrt(const struct dmi_system_id *d)
+{
        pr_notice("%s detected: disabling all critical thermal trip point actions.\n",
                  d->ident);
        crt = -1;
        return 0;
 }
-static int thermal_tzp(const struct dmi_system_id *d) {
+
+static int thermal_tzp(const struct dmi_system_id *d)
+{
        if (tzp == 0) {
                pr_notice("%s detected: enabling thermal zone polling\n",
                          d->ident);
@@ -1068,7 +1043,9 @@ static int thermal_tzp(const struct dmi_system_id *d) {
        }
        return 0;
 }
-static int thermal_psv(const struct dmi_system_id *d) {
+
+static int thermal_psv(const struct dmi_system_id *d)
+{
        if (psv == 0) {
                pr_notice("%s detected: disabling all passive thermal trip points\n",
                          d->ident);
index 61f0b5a..2b345f2 100644 (file)
@@ -495,25 +495,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz,
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_update);
 
-/**
- * thermal_zone_device_exec - Run a callback under the zone lock.
- * @tz: Thermal zone.
- * @cb: Callback to run.
- * @data: Data to pass to the callback.
- */
-void thermal_zone_device_exec(struct thermal_zone_device *tz,
-                             void (*cb)(struct thermal_zone_device *,
-                                        unsigned long),
-                             unsigned long data)
-{
-       mutex_lock(&tz->lock);
-
-       cb(tz, data);
-
-       mutex_unlock(&tz->lock);
-}
-EXPORT_SYMBOL_GPL(thermal_zone_device_exec);
-
 static void thermal_zone_device_check(struct work_struct *work)
 {
        struct thermal_zone_device *tz = container_of(work, struct
index 8c649a8..80f3cdb 100644 (file)
@@ -15,8 +15,6 @@ int for_each_thermal_trip(struct thermal_zone_device *tz,
 {
        int i, ret;
 
-       lockdep_assert_held(&tz->lock);
-
        for (i = 0; i < tz->num_trips; i++) {
                ret = cb(&tz->trips[i], data);
                if (ret)
@@ -177,8 +175,6 @@ int thermal_zone_trip_id(struct thermal_zone_device *tz,
 {
        int i;
 
-       lockdep_assert_held(&tz->lock);
-
        for (i = 0; i < tz->num_trips; i++) {
                if (&tz->trips[i] == trip)
                        return i;
index 2bab721..c8600e3 100644 (file)
@@ -339,10 +339,6 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
                                       struct thermal_cooling_device *);
 void thermal_zone_device_update(struct thermal_zone_device *,
                                enum thermal_notify_event);
-void thermal_zone_device_exec(struct thermal_zone_device *tz,
-                             void (*cb)(struct thermal_zone_device *,
-                                        unsigned long),
-                             unsigned long data);
 
 struct thermal_cooling_device *thermal_cooling_device_register(const char *,
                void *, const struct thermal_cooling_device_ops *);