Merge branch 'acpi-thermal'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 25 Aug 2023 18:44:26 +0000 (20:44 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 25 Aug 2023 18:44:26 +0000 (20:44 +0200)
Merge ACPI thermal driver changes for 6.6-rc1:

 - Drop non-functional nocrt parameter from ACPI thermal (Mario
   Limonciello).

 - Clean up the ACPI thermal driver, rework the handling of firmware
   notifications in it and make it provide a table of generic trip point
   structures to the core during initialization (Rafael Wysocki).

* acpi-thermal:
  ACPI: thermal: Eliminate code duplication from acpi_thermal_notify()
  ACPI: thermal: Drop unnecessary thermal zone callbacks
  ACPI: thermal: Rework thermal_get_trend()
  ACPI: thermal: Use trip point table to register thermal zones
  thermal: core: Rework and rename __for_each_thermal_trip()
  ACPI: thermal: Introduce struct acpi_thermal_trip
  ACPI: thermal: Carry out trip point updates under zone lock
  ACPI: thermal: Clean up acpi_thermal_register_thermal_zone()
  thermal: core: Add priv pointer to struct thermal_trip
  thermal: core: Introduce thermal_zone_device_exec()
  thermal: core: Do not handle trip points with invalid temperature
  ACPI: thermal: Drop redundant local variable from acpi_thermal_resume()
  ACPI: thermal: Do not attach private data to ACPI handles
  ACPI: thermal: Drop enabled flag from struct acpi_thermal_active
  ACPI: thermal: Drop nocrt parameter

Documentation/admin-guide/kernel-parameters.txt
drivers/acpi/thermal.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/thermal/thermal_trip.c
include/linux/thermal.h

index 722b6ec..23ebe34 100644 (file)
                        -1: disable all critical trip points in all thermal zones
                        <degrees C>: override all critical trip points
 
-       thermal.nocrt=  [HW,ACPI]
-                       Set to disable actions on ACPI thermal zone
-                       critical and hot trip points.
-
        thermal.off=    [HW,ACPI]
                        1: disable ACPI thermal control
 
index 7d543ed..419590f 100644 (file)
@@ -82,10 +82,6 @@ static int tzp;
 module_param(tzp, int, 0444);
 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
 
-static int nocrt;
-module_param(nocrt, int, 0);
-MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
-
 static int off;
 module_param(off, int, 0);
 MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
@@ -96,35 +92,27 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
 
 static struct workqueue_struct *acpi_thermal_pm_queue;
 
-struct acpi_thermal_critical {
-       unsigned long temperature;
-       bool valid;
-};
-
-struct acpi_thermal_hot {
+struct acpi_thermal_trip {
        unsigned long temperature;
        bool valid;
 };
 
 struct acpi_thermal_passive {
+       struct acpi_thermal_trip trip;
        struct acpi_handle_list devices;
-       unsigned long temperature;
        unsigned long tc1;
        unsigned long tc2;
        unsigned long tsp;
-       bool valid;
 };
 
 struct acpi_thermal_active {
+       struct acpi_thermal_trip trip;
        struct acpi_handle_list devices;
-       unsigned long temperature;
-       bool valid;
-       bool enabled;
 };
 
 struct acpi_thermal_trips {
-       struct acpi_thermal_critical critical;
-       struct acpi_thermal_hot hot;
+       struct acpi_thermal_trip critical;
+       struct acpi_thermal_trip hot;
        struct acpi_thermal_passive passive;
        struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
 };
@@ -137,6 +125,7 @@ struct acpi_thermal {
        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 */
@@ -190,7 +179,16 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
        return 0;
 }
 
-static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
+static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k)
+{
+       if (temp_deci_k == THERMAL_TEMP_INVALID)
+               return THERMAL_TEMP_INVALID;
+
+       return deci_kelvin_to_millicelsius_with_offset(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;
@@ -255,9 +253,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
        }
 
        /* Passive (optional) */
-       if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.valid) ||
+       if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) ||
            flag == ACPI_TRIPS_INIT) {
-               valid = tz->trips.passive.valid;
+               valid = tz->trips.passive.trip.valid;
                if (psv == -1) {
                        status = AE_SUPPORT;
                } else if (psv > 0) {
@@ -269,44 +267,44 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                }
 
                if (ACPI_FAILURE(status)) {
-                       tz->trips.passive.valid = false;
+                       tz->trips.passive.trip.valid = false;
                } else {
-                       tz->trips.passive.temperature = tmp;
-                       tz->trips.passive.valid = true;
+                       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.valid = false;
+                                       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.valid = false;
+                                       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.valid = false;
+                                       tz->trips.passive.trip.valid = false;
                                else
                                        tz->trips.passive.tsp = tmp;
                        }
                }
        }
-       if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.valid) {
+       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.valid = false;
+                       tz->trips.passive.trip.valid = false;
                } else {
-                       tz->trips.passive.valid = true;
+                       tz->trips.passive.trip.valid = true;
                }
 
                if (memcmp(&tz->trips.passive.devices, &devices,
@@ -317,24 +315,24 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                }
        }
        if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
-               if (valid != tz->trips.passive.valid)
+               if (valid != tz->trips.passive.trip.valid)
                        ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
        }
 
        /* Active (optional) */
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
                char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
-               valid = tz->trips.active[i].valid;
+               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].valid)) {
+                   tz->trips.active[i].trip.valid)) {
                        status = acpi_evaluate_integer(tz->device->handle,
                                                       name, NULL, &tmp);
                        if (ACPI_FAILURE(status)) {
-                               tz->trips.active[i].valid = false;
+                               tz->trips.active[i].trip.valid = false;
                                if (i == 0)
                                        break;
 
@@ -342,35 +340,36 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                                        break;
 
                                if (i == 1)
-                                       tz->trips.active[0].temperature = celsius_to_deci_kelvin(act);
+                                       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].temperature =
+                                       tz->trips.active[i-1].trip.temperature =
                                                min_t(unsigned long,
-                                                     tz->trips.active[i-2].temperature,
+                                                     tz->trips.active[i-2].trip.temperature,
                                                      celsius_to_deci_kelvin(act));
 
                                break;
                        } else {
-                               tz->trips.active[i].temperature = tmp;
-                               tz->trips.active[i].valid = true;
+                               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].valid) {
+               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].valid = false;
+                               tz->trips.active[i].trip.valid = false;
                        } else {
-                               tz->trips.active[i].valid = true;
+                               tz->trips.active[i].trip.valid = true;
                        }
 
                        if (memcmp(&tz->trips.active[i].devices, &devices,
@@ -381,10 +380,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        }
                }
                if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
-                       if (valid != tz->trips.active[i].valid)
+                       if (valid != tz->trips.active[i].trip.valid)
                                ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state");
 
-               if (!tz->trips.active[i].valid)
+               if (!tz->trips.active[i].trip.valid)
                        break;
        }
 
@@ -398,24 +397,73 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device");
                }
        }
+}
+
+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;
+
+       if (!acpi_trip)
+               return 0;
+
+       if (acpi_trip->valid)
+               trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature);
+       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))
+               queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
+}
+
+static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event)
+{
+       struct acpi_device *adev = tz->device;
+
+       /*
+        * Use thermal_zone_device_exec() 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);
+       acpi_queue_thermal_check(tz);
+       acpi_bus_generate_netlink_event(adev->pnp.device_class,
+                                       dev_name(&adev->dev), event, 0);
+}
+
 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 {
-       int i, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
        bool valid;
+       int i;
 
-       if (ret)
-               return ret;
+       __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
 
        valid = tz->trips.critical.valid |
                tz->trips.hot.valid |
-               tz->trips.passive.valid;
+               tz->trips.passive.trip.valid;
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
-               valid = valid || tz->trips.active[i].valid;
+               valid = valid || tz->trips.active[i].trip.valid;
 
        if (!valid) {
                pr_warn(FW_BUG "No valid trip found\n");
@@ -443,159 +491,55 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
        return 0;
 }
 
-static int thermal_get_trip_type(struct thermal_zone_device *thermal,
-                                int trip, enum thermal_trip_type *type)
+static int thermal_get_trend(struct thermal_zone_device *thermal,
+                            int trip_index, enum thermal_trend *trend)
 {
        struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
-       int i;
+       struct acpi_thermal_trip *acpi_trip;
+       int t, i;
 
-       if (!tz || trip < 0)
+       if (!tz || trip_index < 0)
                return -EINVAL;
 
-       if (tz->trips.critical.valid) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_CRITICAL;
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.hot.valid) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_HOT;
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.passive.valid) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_PASSIVE;
-                       return 0;
-               }
-               trip--;
-       }
-
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid; i++) {
-               if (!trip) {
-                       *type = THERMAL_TRIP_ACTIVE;
-                       return 0;
-               }
-               trip--;
-       }
-
-       return -EINVAL;
-}
+       if (tz->trips.critical.valid)
+               trip_index--;
 
-static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
-                                int trip, int *temp)
-{
-       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
-       int i;
+       if (tz->trips.hot.valid)
+               trip_index--;
 
-       if (!tz || trip < 0)
+       if (trip_index < 0)
                return -EINVAL;
 
-       if (tz->trips.critical.valid) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.critical.temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.hot.valid) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.hot.temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       if (tz->trips.passive.valid) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.passive.temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
-               tz->trips.active[i].valid; i++) {
-               if (!trip) {
-                       *temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.active[i].temperature,
-                                       tz->kelvin_offset);
-                       return 0;
-               }
-               trip--;
-       }
-
-       return -EINVAL;
-}
-
-static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
-                               int *temperature)
-{
-       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
+       acpi_trip = &tz->trips.passive.trip;
+       if (acpi_trip->valid && !trip_index--) {
+               t = tz->trips.passive.tc1 * (tz->temperature -
+                                               tz->last_temperature) +
+                       tz->trips.passive.tc2 * (tz->temperature -
+                                               acpi_trip->temperature);
+               if (t > 0)
+                       *trend = THERMAL_TREND_RAISING;
+               else if (t < 0)
+                       *trend = THERMAL_TREND_DROPPING;
+               else
+                       *trend = THERMAL_TREND_STABLE;
 
-       if (tz->trips.critical.valid) {
-               *temperature = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->trips.critical.temperature,
-                                       tz->kelvin_offset);
                return 0;
        }
 
-       return -EINVAL;
-}
-
-static int thermal_get_trend(struct thermal_zone_device *thermal,
-                            int trip, enum thermal_trend *trend)
-{
-       struct acpi_thermal *tz = thermal_zone_device_priv(thermal);
-       enum thermal_trip_type type;
-       int i;
+       t = acpi_thermal_temp(tz, tz->temperature);
 
-       if (thermal_get_trip_type(thermal, trip, &type))
-               return -EINVAL;
-
-       if (type == THERMAL_TRIP_ACTIVE) {
-               int trip_temp;
-               int temp = deci_kelvin_to_millicelsius_with_offset(
-                                       tz->temperature, tz->kelvin_offset);
-               if (thermal_get_trip_temp(thermal, trip, &trip_temp))
-                       return -EINVAL;
-
-               if (temp > trip_temp) {
-                       *trend = THERMAL_TREND_RAISING;
-                       return 0;
-               } else {
-                       /* Fall back on default trend */
-                       return -EINVAL;
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               acpi_trip = &tz->trips.active[i].trip;
+               if (acpi_trip->valid && !trip_index--) {
+                       if (t > acpi_thermal_temp(tz, acpi_trip->temperature)) {
+                               *trend = THERMAL_TREND_RAISING;
+                               return 0;
+                       }
+                       break;
                }
        }
 
-       /*
-        * tz->temperature has already been updated by generic thermal layer,
-        * before this callback being invoked
-        */
-       i = tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature) +
-           tz->trips.passive.tc2 * (tz->temperature - tz->trips.passive.temperature);
-
-       if (i > 0)
-               *trend = THERMAL_TREND_RAISING;
-       else if (i < 0)
-               *trend = THERMAL_TREND_DROPPING;
-       else
-               *trend = THERMAL_TREND_STABLE;
-
-       return 0;
+       return -EINVAL;
 }
 
 static void acpi_thermal_zone_device_hot(struct thermal_zone_device *thermal)
@@ -637,7 +581,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
        if (tz->trips.hot.valid)
                trip++;
 
-       if (tz->trips.passive.valid) {
+       if (tz->trips.passive.trip.valid) {
                trip++;
                for (i = 0; i < tz->trips.passive.devices.count; i++) {
                        handle = tz->trips.passive.devices.handles[i];
@@ -662,7 +606,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
        }
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (!tz->trips.active[i].valid)
+               if (!tz->trips.active[i].trip.valid)
                        break;
 
                trip++;
@@ -709,9 +653,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
        .bind = acpi_thermal_bind_cooling_device,
        .unbind = acpi_thermal_unbind_cooling_device,
        .get_temp = thermal_get_temp,
-       .get_trip_type = thermal_get_trip_type,
-       .get_trip_temp = thermal_get_trip_temp,
-       .get_crit_temp = thermal_get_crit_temp,
        .get_trend = thermal_get_trend,
        .hot = acpi_thermal_zone_device_hot,
        .critical = acpi_thermal_zone_device_critical,
@@ -745,63 +686,97 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz)
 
 static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 {
-       int trips = 0;
+       struct acpi_thermal_trip *acpi_trip;
+       struct thermal_trip *trip;
+       int passive_delay = 0;
+       int trip_count = 0;
        int result;
-       acpi_status status;
        int i;
 
        if (tz->trips.critical.valid)
-               trips++;
+               trip_count++;
 
        if (tz->trips.hot.valid)
-               trips++;
+               trip_count++;
 
-       if (tz->trips.passive.valid)
-               trips++;
+       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].valid;
-            i++, trips++);
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++)
+               trip_count++;
 
-       if (tz->trips.passive.valid)
-               tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz,
-                                                               &acpi_thermal_zone_ops, NULL,
-                                                               tz->trips.passive.tsp * 100,
-                                                               tz->polling_frequency * 100);
-       else
-               tz->thermal_zone =
-                       thermal_zone_device_register("acpitz", trips, 0, tz,
-                                                    &acpi_thermal_zone_ops, NULL,
-                                                    0, tz->polling_frequency * 100);
+       trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL);
+       if (!trip)
+               return -ENOMEM;
 
-       if (IS_ERR(tz->thermal_zone))
-               return -ENODEV;
+       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,
+                                                                  trip_count,
+                                                                  0, tz,
+                                                                  &acpi_thermal_zone_ops,
+                                                                  NULL,
+                                                                  passive_delay,
+                                                                  tz->polling_frequency * 100);
+       if (IS_ERR(tz->thermal_zone)) {
+               result = PTR_ERR(tz->thermal_zone);
+               goto free_trip_table;
+       }
 
        result = acpi_thermal_zone_sysfs_add(tz);
        if (result)
                goto unregister_tzd;
 
-       status =  acpi_bus_attach_private_data(tz->device->handle,
-                                              tz->thermal_zone);
-       if (ACPI_FAILURE(status)) {
-               result = -ENODEV;
-               goto remove_links;
-       }
-
        result = thermal_zone_device_enable(tz->thermal_zone);
        if (result)
-               goto acpi_bus_detach;
+               goto remove_links;
 
        dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
                 thermal_zone_device_id(tz->thermal_zone));
 
        return 0;
 
-acpi_bus_detach:
-       acpi_bus_detach_private_data(tz->device->handle);
 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;
 }
@@ -810,8 +785,8 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
 {
        acpi_thermal_zone_sysfs_remove(tz);
        thermal_zone_device_unregister(tz->thermal_zone);
+       kfree(tz->trip_table);
        tz->thermal_zone = NULL;
-       acpi_bus_detach_private_data(tz->device->handle);
 }
 
 
@@ -819,12 +794,6 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
-static void acpi_queue_thermal_check(struct acpi_thermal *tz)
-{
-       if (!work_pending(&tz->thermal_check_work))
-               queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
-}
-
 static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
 {
        struct acpi_device *device = data;
@@ -838,16 +807,8 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
                acpi_queue_thermal_check(tz);
                break;
        case ACPI_THERMAL_NOTIFY_THRESHOLDS:
-               acpi_thermal_trips_update(tz, ACPI_TRIPS_THRESHOLDS);
-               acpi_queue_thermal_check(tz);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                               dev_name(&device->dev), event, 0);
-               break;
        case ACPI_THERMAL_NOTIFY_DEVICES:
-               acpi_thermal_trips_update(tz, ACPI_TRIPS_DEVICES);
-               acpi_queue_thermal_check(tz);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                               dev_name(&device->dev), event, 0);
+               acpi_thermal_trips_update(tz, event);
                break;
        default:
                acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n",
@@ -1044,7 +1005,7 @@ static int acpi_thermal_suspend(struct device *dev)
 static int acpi_thermal_resume(struct device *dev)
 {
        struct acpi_thermal *tz;
-       int i, j, power_state, result;
+       int i, j, power_state;
 
        if (!dev)
                return -EINVAL;
@@ -1054,18 +1015,12 @@ static int acpi_thermal_resume(struct device *dev)
                return -EINVAL;
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (!tz->trips.active[i].valid)
+               if (!tz->trips.active[i].trip.valid)
                        break;
 
-               tz->trips.active[i].enabled = true;
                for (j = 0; j < tz->trips.active[i].devices.count; j++) {
-                       result = acpi_bus_update_power(
-                                       tz->trips.active[i].devices.handles[j],
-                                       &power_state);
-                       if (result || (power_state != ACPI_STATE_D0)) {
-                               tz->trips.active[i].enabled = false;
-                               break;
-                       }
+                       acpi_bus_update_power(tz->trips.active[i].devices.handles[j],
+                                             &power_state);
                }
        }
 
@@ -1107,7 +1062,7 @@ static int thermal_act(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);
-       nocrt = 1;
+       crt = -1;
        return 0;
 }
 static int thermal_tzp(const struct dmi_system_id *d) {
index cc2b5e8..a597005 100644 (file)
@@ -348,7 +348,8 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id)
        struct thermal_trip trip;
 
        /* Ignore disabled trip points */
-       if (test_bit(trip_id, &tz->trips_disabled))
+       if (test_bit(trip_id, &tz->trips_disabled) ||
+           trip.temperature == THERMAL_TEMP_INVALID)
                return;
 
        __thermal_zone_get_trip(tz, trip_id, &trip);
@@ -496,6 +497,25 @@ 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 17c1bbe..04513f9 100644 (file)
@@ -54,10 +54,6 @@ int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *,
 int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *),
                              void *thermal_governor);
 
-int __for_each_thermal_trip(struct thermal_zone_device *,
-                           int (*cb)(struct thermal_trip *, void *),
-                           void *);
-
 struct thermal_zone_device *thermal_zone_get_by_id(int id);
 
 struct thermal_attr {
index 907f3a4..53115cf 100644 (file)
@@ -9,28 +9,26 @@
  */
 #include "thermal_core.h"
 
-int __for_each_thermal_trip(struct thermal_zone_device *tz,
-                           int (*cb)(struct thermal_trip *, void *),
-                           void *data)
+int for_each_thermal_trip(struct thermal_zone_device *tz,
+                         int (*cb)(struct thermal_trip *, void *),
+                         void *data)
 {
        int i, ret;
-       struct thermal_trip trip;
 
        lockdep_assert_held(&tz->lock);
 
-       for (i = 0; i < tz->num_trips; i++) {
-
-               ret = __thermal_zone_get_trip(tz, i, &trip);
-               if (ret)
-                       return ret;
+       if (!tz->trips)
+               return -ENODATA;
 
-               ret = cb(&trip, data);
+       for (i = 0; i < tz->num_trips; i++) {
+               ret = cb(&tz->trips[i], data);
                if (ret)
                        return ret;
        }
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(for_each_thermal_trip);
 
 int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
 {
index dee66ad..b449a46 100644 (file)
@@ -81,11 +81,13 @@ struct thermal_zone_device_ops {
  * @temperature: temperature value in miliCelsius
  * @hysteresis: relative hysteresis in miliCelsius
  * @type: trip point type
+ * @priv: pointer to driver data associated with this trip
  */
 struct thermal_trip {
        int temperature;
        int hysteresis;
        enum thermal_trip_type type;
+       void *priv;
 };
 
 struct thermal_cooling_device_ops {
@@ -287,6 +289,9 @@ int thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id,
 int thermal_zone_set_trip(struct thermal_zone_device *tz, int trip_id,
                          const struct thermal_trip *trip);
 
+int for_each_thermal_trip(struct thermal_zone_device *tz,
+                         int (*cb)(struct thermal_trip *, void *),
+                         void *data);
 int thermal_zone_get_num_trips(struct thermal_zone_device *tz);
 
 int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp);
@@ -323,6 +328,10 @@ 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 *);