thermal/governors: Prefix all source files with gov_
authorAmit Kucheria <amit.kucheria@linaro.org>
Mon, 11 May 2020 12:25:01 +0000 (17:55 +0530)
committerDaniel Lezcano <daniel.lezcano@linaro.org>
Fri, 22 May 2020 16:48:54 +0000 (18:48 +0200)
Bang-bang governor source file is prefixed with gov_. Do the same for
other governors for consistency so they're easy to find in the sources.

Signed-off-by: Amit Kucheria <amit.kucheria@linaro.org>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/b9a85d3204712f14e320504948c12712dc0b291b.1589199124.git.amit.kucheria@linaro.org
drivers/thermal/Makefile
drivers/thermal/fair_share.c [deleted file]
drivers/thermal/gov_fair_share.c [new file with mode: 0644]
drivers/thermal/gov_power_allocator.c [new file with mode: 0644]
drivers/thermal/gov_step_wise.c [new file with mode: 0644]
drivers/thermal/gov_user_space.c [new file with mode: 0644]
drivers/thermal/power_allocator.c [deleted file]
drivers/thermal/step_wise.c [deleted file]
drivers/thermal/user_space.c [deleted file]

index 86c5064..757c40a 100644 (file)
@@ -12,11 +12,11 @@ thermal_sys-$(CONFIG_THERMAL_HWMON)         += thermal_hwmon.o
 thermal_sys-$(CONFIG_THERMAL_OF)               += of-thermal.o
 
 # governors
-thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += fair_share.o
+thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE)   += gov_fair_share.o
 thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG)    += gov_bang_bang.o
-thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE)    += step_wise.o
-thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE)   += user_space.o
-thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR)      += power_allocator.o
+thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE)    += gov_step_wise.o
+thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE)   += gov_user_space.o
+thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR)      += gov_power_allocator.o
 
 # cpufreq cooling
 thermal_sys-$(CONFIG_CPU_FREQ_THERMAL) += cpufreq_cooling.o
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
deleted file mode 100644 (file)
index aaa0718..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- *  fair_share.c - A simple weight based Thermal governor
- *
- *  Copyright (C) 2012 Intel Corp
- *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
- *
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <linux/thermal.h>
-#include <trace/events/thermal.h>
-
-#include "thermal_core.h"
-
-/**
- * get_trip_level: - obtains the current trip level for a zone
- * @tz:                thermal zone device
- */
-static int get_trip_level(struct thermal_zone_device *tz)
-{
-       int count = 0;
-       int trip_temp;
-       enum thermal_trip_type trip_type;
-
-       if (tz->trips == 0 || !tz->ops->get_trip_temp)
-               return 0;
-
-       for (count = 0; count < tz->trips; count++) {
-               tz->ops->get_trip_temp(tz, count, &trip_temp);
-               if (tz->temperature < trip_temp)
-                       break;
-       }
-
-       /*
-        * count > 0 only if temperature is greater than first trip
-        * point, in which case, trip_point = count - 1
-        */
-       if (count > 0) {
-               tz->ops->get_trip_type(tz, count - 1, &trip_type);
-               trace_thermal_zone_trip(tz, count - 1, trip_type);
-       }
-
-       return count;
-}
-
-static long get_target_state(struct thermal_zone_device *tz,
-               struct thermal_cooling_device *cdev, int percentage, int level)
-{
-       unsigned long max_state;
-
-       cdev->ops->get_max_state(cdev, &max_state);
-
-       return (long)(percentage * level * max_state) / (100 * tz->trips);
-}
-
-/**
- * fair_share_throttle - throttles devices associated with the given zone
- * @tz: thermal_zone_device
- * @trip: trip point index
- *
- * Throttling Logic: This uses three parameters to calculate the new
- * throttle state of the cooling devices associated with the given zone.
- *
- * Parameters used for Throttling:
- * P1. max_state: Maximum throttle state exposed by the cooling device.
- * P2. percentage[i]/100:
- *     How 'effective' the 'i'th device is, in cooling the given zone.
- * P3. cur_trip_level/max_no_of_trips:
- *     This describes the extent to which the devices should be throttled.
- *     We do not want to throttle too much when we trip a lower temperature,
- *     whereas the throttling is at full swing if we trip critical levels.
- *     (Heavily assumes the trip points are in ascending order)
- * new_state of cooling device = P3 * P2 * P1
- */
-static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
-{
-       struct thermal_instance *instance;
-       int total_weight = 0;
-       int total_instance = 0;
-       int cur_trip_level = get_trip_level(tz);
-
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               if (instance->trip != trip)
-                       continue;
-
-               total_weight += instance->weight;
-               total_instance++;
-       }
-
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               int percentage;
-               struct thermal_cooling_device *cdev = instance->cdev;
-
-               if (instance->trip != trip)
-                       continue;
-
-               if (!total_weight)
-                       percentage = 100 / total_instance;
-               else
-                       percentage = (instance->weight * 100) / total_weight;
-
-               instance->target = get_target_state(tz, cdev, percentage,
-                                                   cur_trip_level);
-
-               mutex_lock(&instance->cdev->lock);
-               instance->cdev->updated = false;
-               mutex_unlock(&instance->cdev->lock);
-               thermal_cdev_update(cdev);
-       }
-       return 0;
-}
-
-static struct thermal_governor thermal_gov_fair_share = {
-       .name           = "fair_share",
-       .throttle       = fair_share_throttle,
-};
-THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share);
diff --git a/drivers/thermal/gov_fair_share.c b/drivers/thermal/gov_fair_share.c
new file mode 100644 (file)
index 0000000..aaa0718
--- /dev/null
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  fair_share.c - A simple weight based Thermal governor
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/thermal.h>
+#include <trace/events/thermal.h>
+
+#include "thermal_core.h"
+
+/**
+ * get_trip_level: - obtains the current trip level for a zone
+ * @tz:                thermal zone device
+ */
+static int get_trip_level(struct thermal_zone_device *tz)
+{
+       int count = 0;
+       int trip_temp;
+       enum thermal_trip_type trip_type;
+
+       if (tz->trips == 0 || !tz->ops->get_trip_temp)
+               return 0;
+
+       for (count = 0; count < tz->trips; count++) {
+               tz->ops->get_trip_temp(tz, count, &trip_temp);
+               if (tz->temperature < trip_temp)
+                       break;
+       }
+
+       /*
+        * count > 0 only if temperature is greater than first trip
+        * point, in which case, trip_point = count - 1
+        */
+       if (count > 0) {
+               tz->ops->get_trip_type(tz, count - 1, &trip_type);
+               trace_thermal_zone_trip(tz, count - 1, trip_type);
+       }
+
+       return count;
+}
+
+static long get_target_state(struct thermal_zone_device *tz,
+               struct thermal_cooling_device *cdev, int percentage, int level)
+{
+       unsigned long max_state;
+
+       cdev->ops->get_max_state(cdev, &max_state);
+
+       return (long)(percentage * level * max_state) / (100 * tz->trips);
+}
+
+/**
+ * fair_share_throttle - throttles devices associated with the given zone
+ * @tz: thermal_zone_device
+ * @trip: trip point index
+ *
+ * Throttling Logic: This uses three parameters to calculate the new
+ * throttle state of the cooling devices associated with the given zone.
+ *
+ * Parameters used for Throttling:
+ * P1. max_state: Maximum throttle state exposed by the cooling device.
+ * P2. percentage[i]/100:
+ *     How 'effective' the 'i'th device is, in cooling the given zone.
+ * P3. cur_trip_level/max_no_of_trips:
+ *     This describes the extent to which the devices should be throttled.
+ *     We do not want to throttle too much when we trip a lower temperature,
+ *     whereas the throttling is at full swing if we trip critical levels.
+ *     (Heavily assumes the trip points are in ascending order)
+ * new_state of cooling device = P3 * P2 * P1
+ */
+static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
+{
+       struct thermal_instance *instance;
+       int total_weight = 0;
+       int total_instance = 0;
+       int cur_trip_level = get_trip_level(tz);
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if (instance->trip != trip)
+                       continue;
+
+               total_weight += instance->weight;
+               total_instance++;
+       }
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               int percentage;
+               struct thermal_cooling_device *cdev = instance->cdev;
+
+               if (instance->trip != trip)
+                       continue;
+
+               if (!total_weight)
+                       percentage = 100 / total_instance;
+               else
+                       percentage = (instance->weight * 100) / total_weight;
+
+               instance->target = get_target_state(tz, cdev, percentage,
+                                                   cur_trip_level);
+
+               mutex_lock(&instance->cdev->lock);
+               instance->cdev->updated = false;
+               mutex_unlock(&instance->cdev->lock);
+               thermal_cdev_update(cdev);
+       }
+       return 0;
+}
+
+static struct thermal_governor thermal_gov_fair_share = {
+       .name           = "fair_share",
+       .throttle       = fair_share_throttle,
+};
+THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share);
diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c
new file mode 100644 (file)
index 0000000..4463647
--- /dev/null
@@ -0,0 +1,654 @@
+/*
+ * A power allocator to manage temperature
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "Power allocator: " fmt
+
+#include <linux/rculist.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/thermal_power_allocator.h>
+
+#include "thermal_core.h"
+
+#define INVALID_TRIP -1
+
+#define FRAC_BITS 10
+#define int_to_frac(x) ((x) << FRAC_BITS)
+#define frac_to_int(x) ((x) >> FRAC_BITS)
+
+/**
+ * mul_frac() - multiply two fixed-point numbers
+ * @x: first multiplicand
+ * @y: second multiplicand
+ *
+ * Return: the result of multiplying two fixed-point numbers.  The
+ * result is also a fixed-point number.
+ */
+static inline s64 mul_frac(s64 x, s64 y)
+{
+       return (x * y) >> FRAC_BITS;
+}
+
+/**
+ * div_frac() - divide two fixed-point numbers
+ * @x: the dividend
+ * @y: the divisor
+ *
+ * Return: the result of dividing two fixed-point numbers.  The
+ * result is also a fixed-point number.
+ */
+static inline s64 div_frac(s64 x, s64 y)
+{
+       return div_s64(x << FRAC_BITS, y);
+}
+
+/**
+ * struct power_allocator_params - parameters for the power allocator governor
+ * @allocated_tzp:     whether we have allocated tzp for this thermal zone and
+ *                     it needs to be freed on unbind
+ * @err_integral:      accumulated error in the PID controller.
+ * @prev_err:  error in the previous iteration of the PID controller.
+ *             Used to calculate the derivative term.
+ * @trip_switch_on:    first passive trip point of the thermal zone.  The
+ *                     governor switches on when this trip point is crossed.
+ *                     If the thermal zone only has one passive trip point,
+ *                     @trip_switch_on should be INVALID_TRIP.
+ * @trip_max_desired_temperature:      last passive trip point of the thermal
+ *                                     zone.  The temperature we are
+ *                                     controlling for.
+ */
+struct power_allocator_params {
+       bool allocated_tzp;
+       s64 err_integral;
+       s32 prev_err;
+       int trip_switch_on;
+       int trip_max_desired_temperature;
+};
+
+/**
+ * estimate_sustainable_power() - Estimate the sustainable power of a thermal zone
+ * @tz: thermal zone we are operating in
+ *
+ * For thermal zones that don't provide a sustainable_power in their
+ * thermal_zone_params, estimate one.  Calculate it using the minimum
+ * power of all the cooling devices as that gives a valid value that
+ * can give some degree of functionality.  For optimal performance of
+ * this governor, provide a sustainable_power in the thermal zone's
+ * thermal_zone_params.
+ */
+static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
+{
+       u32 sustainable_power = 0;
+       struct thermal_instance *instance;
+       struct power_allocator_params *params = tz->governor_data;
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               struct thermal_cooling_device *cdev = instance->cdev;
+               u32 min_power;
+
+               if (instance->trip != params->trip_max_desired_temperature)
+                       continue;
+
+               if (power_actor_get_min_power(cdev, tz, &min_power))
+                       continue;
+
+               sustainable_power += min_power;
+       }
+
+       return sustainable_power;
+}
+
+/**
+ * estimate_pid_constants() - Estimate the constants for the PID controller
+ * @tz:                thermal zone for which to estimate the constants
+ * @sustainable_power: sustainable power for the thermal zone
+ * @trip_switch_on:    trip point number for the switch on temperature
+ * @control_temp:      target temperature for the power allocator governor
+ * @force:     whether to force the update of the constants
+ *
+ * This function is used to update the estimation of the PID
+ * controller constants in struct thermal_zone_parameters.
+ * Sustainable power is provided in case it was estimated.  The
+ * estimated sustainable_power should not be stored in the
+ * thermal_zone_parameters so it has to be passed explicitly to this
+ * function.
+ *
+ * If @force is not set, the values in the thermal zone's parameters
+ * are preserved if they are not zero.  If @force is set, the values
+ * in thermal zone's parameters are overwritten.
+ */
+static void estimate_pid_constants(struct thermal_zone_device *tz,
+                                  u32 sustainable_power, int trip_switch_on,
+                                  int control_temp, bool force)
+{
+       int ret;
+       int switch_on_temp;
+       u32 temperature_threshold;
+
+       ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp);
+       if (ret)
+               switch_on_temp = 0;
+
+       temperature_threshold = control_temp - switch_on_temp;
+       /*
+        * estimate_pid_constants() tries to find appropriate default
+        * values for thermal zones that don't provide them. If a
+        * system integrator has configured a thermal zone with two
+        * passive trip points at the same temperature, that person
+        * hasn't put any effort to set up the thermal zone properly
+        * so just give up.
+        */
+       if (!temperature_threshold)
+               return;
+
+       if (!tz->tzp->k_po || force)
+               tz->tzp->k_po = int_to_frac(sustainable_power) /
+                       temperature_threshold;
+
+       if (!tz->tzp->k_pu || force)
+               tz->tzp->k_pu = int_to_frac(2 * sustainable_power) /
+                       temperature_threshold;
+
+       if (!tz->tzp->k_i || force)
+               tz->tzp->k_i = int_to_frac(10) / 1000;
+       /*
+        * The default for k_d and integral_cutoff is 0, so we can
+        * leave them as they are.
+        */
+}
+
+/**
+ * pid_controller() - PID controller
+ * @tz:        thermal zone we are operating in
+ * @control_temp:      the target temperature in millicelsius
+ * @max_allocatable_power:     maximum allocatable power for this thermal zone
+ *
+ * This PID controller increases the available power budget so that the
+ * temperature of the thermal zone gets as close as possible to
+ * @control_temp and limits the power if it exceeds it.  k_po is the
+ * proportional term when we are overshooting, k_pu is the
+ * proportional term when we are undershooting.  integral_cutoff is a
+ * threshold below which we stop accumulating the error.  The
+ * accumulated error is only valid if the requested power will make
+ * the system warmer.  If the system is mostly idle, there's no point
+ * in accumulating positive error.
+ *
+ * Return: The power budget for the next period.
+ */
+static u32 pid_controller(struct thermal_zone_device *tz,
+                         int control_temp,
+                         u32 max_allocatable_power)
+{
+       s64 p, i, d, power_range;
+       s32 err, max_power_frac;
+       u32 sustainable_power;
+       struct power_allocator_params *params = tz->governor_data;
+
+       max_power_frac = int_to_frac(max_allocatable_power);
+
+       if (tz->tzp->sustainable_power) {
+               sustainable_power = tz->tzp->sustainable_power;
+       } else {
+               sustainable_power = estimate_sustainable_power(tz);
+               estimate_pid_constants(tz, sustainable_power,
+                                      params->trip_switch_on, control_temp,
+                                      true);
+       }
+
+       err = control_temp - tz->temperature;
+       err = int_to_frac(err);
+
+       /* Calculate the proportional term */
+       p = mul_frac(err < 0 ? tz->tzp->k_po : tz->tzp->k_pu, err);
+
+       /*
+        * Calculate the integral term
+        *
+        * if the error is less than cut off allow integration (but
+        * the integral is limited to max power)
+        */
+       i = mul_frac(tz->tzp->k_i, params->err_integral);
+
+       if (err < int_to_frac(tz->tzp->integral_cutoff)) {
+               s64 i_next = i + mul_frac(tz->tzp->k_i, err);
+
+               if (abs(i_next) < max_power_frac) {
+                       i = i_next;
+                       params->err_integral += err;
+               }
+       }
+
+       /*
+        * Calculate the derivative term
+        *
+        * We do err - prev_err, so with a positive k_d, a decreasing
+        * error (i.e. driving closer to the line) results in less
+        * power being applied, slowing down the controller)
+        */
+       d = mul_frac(tz->tzp->k_d, err - params->prev_err);
+       d = div_frac(d, tz->passive_delay);
+       params->prev_err = err;
+
+       power_range = p + i + d;
+
+       /* feed-forward the known sustainable dissipatable power */
+       power_range = sustainable_power + frac_to_int(power_range);
+
+       power_range = clamp(power_range, (s64)0, (s64)max_allocatable_power);
+
+       trace_thermal_power_allocator_pid(tz, frac_to_int(err),
+                                         frac_to_int(params->err_integral),
+                                         frac_to_int(p), frac_to_int(i),
+                                         frac_to_int(d), power_range);
+
+       return power_range;
+}
+
+/**
+ * divvy_up_power() - divvy the allocated power between the actors
+ * @req_power: each actor's requested power
+ * @max_power: each actor's maximum available power
+ * @num_actors:        size of the @req_power, @max_power and @granted_power's array
+ * @total_req_power: sum of @req_power
+ * @power_range:       total allocated power
+ * @granted_power:     output array: each actor's granted power
+ * @extra_actor_power: an appropriately sized array to be used in the
+ *                     function as temporary storage of the extra power given
+ *                     to the actors
+ *
+ * This function divides the total allocated power (@power_range)
+ * fairly between the actors.  It first tries to give each actor a
+ * share of the @power_range according to how much power it requested
+ * compared to the rest of the actors.  For example, if only one actor
+ * requests power, then it receives all the @power_range.  If
+ * three actors each requests 1mW, each receives a third of the
+ * @power_range.
+ *
+ * If any actor received more than their maximum power, then that
+ * surplus is re-divvied among the actors based on how far they are
+ * from their respective maximums.
+ *
+ * Granted power for each actor is written to @granted_power, which
+ * should've been allocated by the calling function.
+ */
+static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
+                          u32 total_req_power, u32 power_range,
+                          u32 *granted_power, u32 *extra_actor_power)
+{
+       u32 extra_power, capped_extra_power;
+       int i;
+
+       /*
+        * Prevent division by 0 if none of the actors request power.
+        */
+       if (!total_req_power)
+               total_req_power = 1;
+
+       capped_extra_power = 0;
+       extra_power = 0;
+       for (i = 0; i < num_actors; i++) {
+               u64 req_range = (u64)req_power[i] * power_range;
+
+               granted_power[i] = DIV_ROUND_CLOSEST_ULL(req_range,
+                                                        total_req_power);
+
+               if (granted_power[i] > max_power[i]) {
+                       extra_power += granted_power[i] - max_power[i];
+                       granted_power[i] = max_power[i];
+               }
+
+               extra_actor_power[i] = max_power[i] - granted_power[i];
+               capped_extra_power += extra_actor_power[i];
+       }
+
+       if (!extra_power)
+               return;
+
+       /*
+        * Re-divvy the reclaimed extra among actors based on
+        * how far they are from the max
+        */
+       extra_power = min(extra_power, capped_extra_power);
+       if (capped_extra_power > 0)
+               for (i = 0; i < num_actors; i++)
+                       granted_power[i] += (extra_actor_power[i] *
+                                       extra_power) / capped_extra_power;
+}
+
+static int allocate_power(struct thermal_zone_device *tz,
+                         int control_temp)
+{
+       struct thermal_instance *instance;
+       struct power_allocator_params *params = tz->governor_data;
+       u32 *req_power, *max_power, *granted_power, *extra_actor_power;
+       u32 *weighted_req_power;
+       u32 total_req_power, max_allocatable_power, total_weighted_req_power;
+       u32 total_granted_power, power_range;
+       int i, num_actors, total_weight, ret = 0;
+       int trip_max_desired_temperature = params->trip_max_desired_temperature;
+
+       mutex_lock(&tz->lock);
+
+       num_actors = 0;
+       total_weight = 0;
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if ((instance->trip == trip_max_desired_temperature) &&
+                   cdev_is_power_actor(instance->cdev)) {
+                       num_actors++;
+                       total_weight += instance->weight;
+               }
+       }
+
+       if (!num_actors) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+
+       /*
+        * We need to allocate five arrays of the same size:
+        * req_power, max_power, granted_power, extra_actor_power and
+        * weighted_req_power.  They are going to be needed until this
+        * function returns.  Allocate them all in one go to simplify
+        * the allocation and deallocation logic.
+        */
+       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power));
+       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power));
+       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power));
+       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power));
+       req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL);
+       if (!req_power) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       max_power = &req_power[num_actors];
+       granted_power = &req_power[2 * num_actors];
+       extra_actor_power = &req_power[3 * num_actors];
+       weighted_req_power = &req_power[4 * num_actors];
+
+       i = 0;
+       total_weighted_req_power = 0;
+       total_req_power = 0;
+       max_allocatable_power = 0;
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               int weight;
+               struct thermal_cooling_device *cdev = instance->cdev;
+
+               if (instance->trip != trip_max_desired_temperature)
+                       continue;
+
+               if (!cdev_is_power_actor(cdev))
+                       continue;
+
+               if (cdev->ops->get_requested_power(cdev, tz, &req_power[i]))
+                       continue;
+
+               if (!total_weight)
+                       weight = 1 << FRAC_BITS;
+               else
+                       weight = instance->weight;
+
+               weighted_req_power[i] = frac_to_int(weight * req_power[i]);
+
+               if (power_actor_get_max_power(cdev, tz, &max_power[i]))
+                       continue;
+
+               total_req_power += req_power[i];
+               max_allocatable_power += max_power[i];
+               total_weighted_req_power += weighted_req_power[i];
+
+               i++;
+       }
+
+       power_range = pid_controller(tz, control_temp, max_allocatable_power);
+
+       divvy_up_power(weighted_req_power, max_power, num_actors,
+                      total_weighted_req_power, power_range, granted_power,
+                      extra_actor_power);
+
+       total_granted_power = 0;
+       i = 0;
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if (instance->trip != trip_max_desired_temperature)
+                       continue;
+
+               if (!cdev_is_power_actor(instance->cdev))
+                       continue;
+
+               power_actor_set_power(instance->cdev, instance,
+                                     granted_power[i]);
+               total_granted_power += granted_power[i];
+
+               i++;
+       }
+
+       trace_thermal_power_allocator(tz, req_power, total_req_power,
+                                     granted_power, total_granted_power,
+                                     num_actors, power_range,
+                                     max_allocatable_power, tz->temperature,
+                                     control_temp - tz->temperature);
+
+       kfree(req_power);
+unlock:
+       mutex_unlock(&tz->lock);
+
+       return ret;
+}
+
+/**
+ * get_governor_trips() - get the number of the two trip points that are key for this governor
+ * @tz:        thermal zone to operate on
+ * @params:    pointer to private data for this governor
+ *
+ * The power allocator governor works optimally with two trips points:
+ * a "switch on" trip point and a "maximum desired temperature".  These
+ * are defined as the first and last passive trip points.
+ *
+ * If there is only one trip point, then that's considered to be the
+ * "maximum desired temperature" trip point and the governor is always
+ * on.  If there are no passive or active trip points, then the
+ * governor won't do anything.  In fact, its throttle function
+ * won't be called at all.
+ */
+static void get_governor_trips(struct thermal_zone_device *tz,
+                              struct power_allocator_params *params)
+{
+       int i, last_active, last_passive;
+       bool found_first_passive;
+
+       found_first_passive = false;
+       last_active = INVALID_TRIP;
+       last_passive = INVALID_TRIP;
+
+       for (i = 0; i < tz->trips; i++) {
+               enum thermal_trip_type type;
+               int ret;
+
+               ret = tz->ops->get_trip_type(tz, i, &type);
+               if (ret) {
+                       dev_warn(&tz->device,
+                                "Failed to get trip point %d type: %d\n", i,
+                                ret);
+                       continue;
+               }
+
+               if (type == THERMAL_TRIP_PASSIVE) {
+                       if (!found_first_passive) {
+                               params->trip_switch_on = i;
+                               found_first_passive = true;
+                       } else  {
+                               last_passive = i;
+                       }
+               } else if (type == THERMAL_TRIP_ACTIVE) {
+                       last_active = i;
+               } else {
+                       break;
+               }
+       }
+
+       if (last_passive != INVALID_TRIP) {
+               params->trip_max_desired_temperature = last_passive;
+       } else if (found_first_passive) {
+               params->trip_max_desired_temperature = params->trip_switch_on;
+               params->trip_switch_on = INVALID_TRIP;
+       } else {
+               params->trip_switch_on = INVALID_TRIP;
+               params->trip_max_desired_temperature = last_active;
+       }
+}
+
+static void reset_pid_controller(struct power_allocator_params *params)
+{
+       params->err_integral = 0;
+       params->prev_err = 0;
+}
+
+static void allow_maximum_power(struct thermal_zone_device *tz)
+{
+       struct thermal_instance *instance;
+       struct power_allocator_params *params = tz->governor_data;
+
+       mutex_lock(&tz->lock);
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if ((instance->trip != params->trip_max_desired_temperature) ||
+                   (!cdev_is_power_actor(instance->cdev)))
+                       continue;
+
+               instance->target = 0;
+               mutex_lock(&instance->cdev->lock);
+               instance->cdev->updated = false;
+               mutex_unlock(&instance->cdev->lock);
+               thermal_cdev_update(instance->cdev);
+       }
+       mutex_unlock(&tz->lock);
+}
+
+/**
+ * power_allocator_bind() - bind the power_allocator governor to a thermal zone
+ * @tz:        thermal zone to bind it to
+ *
+ * Initialize the PID controller parameters and bind it to the thermal
+ * zone.
+ *
+ * Return: 0 on success, or -ENOMEM if we ran out of memory.
+ */
+static int power_allocator_bind(struct thermal_zone_device *tz)
+{
+       int ret;
+       struct power_allocator_params *params;
+       int control_temp;
+
+       params = kzalloc(sizeof(*params), GFP_KERNEL);
+       if (!params)
+               return -ENOMEM;
+
+       if (!tz->tzp) {
+               tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL);
+               if (!tz->tzp) {
+                       ret = -ENOMEM;
+                       goto free_params;
+               }
+
+               params->allocated_tzp = true;
+       }
+
+       if (!tz->tzp->sustainable_power)
+               dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
+
+       get_governor_trips(tz, params);
+
+       if (tz->trips > 0) {
+               ret = tz->ops->get_trip_temp(tz,
+                                       params->trip_max_desired_temperature,
+                                       &control_temp);
+               if (!ret)
+                       estimate_pid_constants(tz, tz->tzp->sustainable_power,
+                                              params->trip_switch_on,
+                                              control_temp, false);
+       }
+
+       reset_pid_controller(params);
+
+       tz->governor_data = params;
+
+       return 0;
+
+free_params:
+       kfree(params);
+
+       return ret;
+}
+
+static void power_allocator_unbind(struct thermal_zone_device *tz)
+{
+       struct power_allocator_params *params = tz->governor_data;
+
+       dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
+
+       if (params->allocated_tzp) {
+               kfree(tz->tzp);
+               tz->tzp = NULL;
+       }
+
+       kfree(tz->governor_data);
+       tz->governor_data = NULL;
+}
+
+static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
+{
+       int ret;
+       int switch_on_temp, control_temp;
+       struct power_allocator_params *params = tz->governor_data;
+
+       /*
+        * We get called for every trip point but we only need to do
+        * our calculations once
+        */
+       if (trip != params->trip_max_desired_temperature)
+               return 0;
+
+       ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
+                                    &switch_on_temp);
+       if (!ret && (tz->temperature < switch_on_temp)) {
+               tz->passive = 0;
+               reset_pid_controller(params);
+               allow_maximum_power(tz);
+               return 0;
+       }
+
+       tz->passive = 1;
+
+       ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature,
+                               &control_temp);
+       if (ret) {
+               dev_warn(&tz->device,
+                        "Failed to get the maximum desired temperature: %d\n",
+                        ret);
+               return ret;
+       }
+
+       return allocate_power(tz, control_temp);
+}
+
+static struct thermal_governor thermal_gov_power_allocator = {
+       .name           = "power_allocator",
+       .bind_to_tz     = power_allocator_bind,
+       .unbind_from_tz = power_allocator_unbind,
+       .throttle       = power_allocator_throttle,
+};
+THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator);
diff --git a/drivers/thermal/gov_step_wise.c b/drivers/thermal/gov_step_wise.c
new file mode 100644 (file)
index 0000000..2ae7198
--- /dev/null
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  step_wise.c - A step-by-step Thermal throttling governor
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/thermal.h>
+#include <trace/events/thermal.h>
+
+#include "thermal_core.h"
+
+/*
+ * If the temperature is higher than a trip point,
+ *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
+ *       state for this trip point
+ *    b. if the trend is THERMAL_TREND_DROPPING, do nothing
+ *    c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit
+ *       for this trip point
+ *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit
+ *       for this trip point
+ * If the temperature is lower than a trip point,
+ *    a. if the trend is THERMAL_TREND_RAISING, do nothing
+ *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
+ *       state for this trip point, if the cooling state already
+ *       equals lower limit, deactivate the thermal instance
+ *    c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing
+ *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit,
+ *       if the cooling state already equals lower limit,
+ *       deactivate the thermal instance
+ */
+static unsigned long get_target_state(struct thermal_instance *instance,
+                               enum thermal_trend trend, bool throttle)
+{
+       struct thermal_cooling_device *cdev = instance->cdev;
+       unsigned long cur_state;
+       unsigned long next_target;
+
+       /*
+        * We keep this instance the way it is by default.
+        * Otherwise, we use the current state of the
+        * cdev in use to determine the next_target.
+        */
+       cdev->ops->get_cur_state(cdev, &cur_state);
+       next_target = instance->target;
+       dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
+
+       if (!instance->initialized) {
+               if (throttle) {
+                       next_target = (cur_state + 1) >= instance->upper ?
+                                       instance->upper :
+                                       ((cur_state + 1) < instance->lower ?
+                                       instance->lower : (cur_state + 1));
+               } else {
+                       next_target = THERMAL_NO_TARGET;
+               }
+
+               return next_target;
+       }
+
+       switch (trend) {
+       case THERMAL_TREND_RAISING:
+               if (throttle) {
+                       next_target = cur_state < instance->upper ?
+                                   (cur_state + 1) : instance->upper;
+                       if (next_target < instance->lower)
+                               next_target = instance->lower;
+               }
+               break;
+       case THERMAL_TREND_RAISE_FULL:
+               if (throttle)
+                       next_target = instance->upper;
+               break;
+       case THERMAL_TREND_DROPPING:
+               if (cur_state <= instance->lower) {
+                       if (!throttle)
+                               next_target = THERMAL_NO_TARGET;
+               } else {
+                       if (!throttle) {
+                               next_target = cur_state - 1;
+                               if (next_target > instance->upper)
+                                       next_target = instance->upper;
+                       }
+               }
+               break;
+       case THERMAL_TREND_DROP_FULL:
+               if (cur_state == instance->lower) {
+                       if (!throttle)
+                               next_target = THERMAL_NO_TARGET;
+               } else
+                       next_target = instance->lower;
+               break;
+       default:
+               break;
+       }
+
+       return next_target;
+}
+
+static void update_passive_instance(struct thermal_zone_device *tz,
+                               enum thermal_trip_type type, int value)
+{
+       /*
+        * If value is +1, activate a passive instance.
+        * If value is -1, deactivate a passive instance.
+        */
+       if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
+               tz->passive += value;
+}
+
+static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
+{
+       int trip_temp;
+       enum thermal_trip_type trip_type;
+       enum thermal_trend trend;
+       struct thermal_instance *instance;
+       bool throttle = false;
+       int old_target;
+
+       if (trip == THERMAL_TRIPS_NONE) {
+               trip_temp = tz->forced_passive;
+               trip_type = THERMAL_TRIPS_NONE;
+       } else {
+               tz->ops->get_trip_temp(tz, trip, &trip_temp);
+               tz->ops->get_trip_type(tz, trip, &trip_type);
+       }
+
+       trend = get_tz_trend(tz, trip);
+
+       if (tz->temperature >= trip_temp) {
+               throttle = true;
+               trace_thermal_zone_trip(tz, trip, trip_type);
+       }
+
+       dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
+                               trip, trip_type, trip_temp, trend, throttle);
+
+       mutex_lock(&tz->lock);
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               if (instance->trip != trip)
+                       continue;
+
+               old_target = instance->target;
+               instance->target = get_target_state(instance, trend, throttle);
+               dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
+                                       old_target, (int)instance->target);
+
+               if (instance->initialized && old_target == instance->target)
+                       continue;
+
+               /* Activate a passive thermal instance */
+               if (old_target == THERMAL_NO_TARGET &&
+                       instance->target != THERMAL_NO_TARGET)
+                       update_passive_instance(tz, trip_type, 1);
+               /* Deactivate a passive thermal instance */
+               else if (old_target != THERMAL_NO_TARGET &&
+                       instance->target == THERMAL_NO_TARGET)
+                       update_passive_instance(tz, trip_type, -1);
+
+               instance->initialized = true;
+               mutex_lock(&instance->cdev->lock);
+               instance->cdev->updated = false; /* cdev needs update */
+               mutex_unlock(&instance->cdev->lock);
+       }
+
+       mutex_unlock(&tz->lock);
+}
+
+/**
+ * step_wise_throttle - throttles devices associated with the given zone
+ * @tz: thermal_zone_device
+ * @trip: trip point index
+ *
+ * Throttling Logic: This uses the trend of the thermal zone to throttle.
+ * If the thermal zone is 'heating up' this throttles all the cooling
+ * devices associated with the zone and its particular trip point, by one
+ * step. If the zone is 'cooling down' it brings back the performance of
+ * the devices by one step.
+ */
+static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
+{
+       struct thermal_instance *instance;
+
+       thermal_zone_trip_update(tz, trip);
+
+       if (tz->forced_passive)
+               thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
+
+       mutex_lock(&tz->lock);
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node)
+               thermal_cdev_update(instance->cdev);
+
+       mutex_unlock(&tz->lock);
+
+       return 0;
+}
+
+static struct thermal_governor thermal_gov_step_wise = {
+       .name           = "step_wise",
+       .throttle       = step_wise_throttle,
+};
+THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);
diff --git a/drivers/thermal/gov_user_space.c b/drivers/thermal/gov_user_space.c
new file mode 100644 (file)
index 0000000..82a7198
--- /dev/null
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  user_space.c - A simple user space Thermal events notifier
+ *
+ *  Copyright (C) 2012 Intel Corp
+ *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/slab.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+/**
+ * notify_user_space - Notifies user space about thermal events
+ * @tz: thermal_zone_device
+ * @trip: trip point index
+ *
+ * This function notifies the user space through UEvents.
+ */
+static int notify_user_space(struct thermal_zone_device *tz, int trip)
+{
+       char *thermal_prop[5];
+       int i;
+
+       mutex_lock(&tz->lock);
+       thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", tz->type);
+       thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", tz->temperature);
+       thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=%d", trip);
+       thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", tz->notify_event);
+       thermal_prop[4] = NULL;
+       kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, thermal_prop);
+       for (i = 0; i < 4; ++i)
+               kfree(thermal_prop[i]);
+       mutex_unlock(&tz->lock);
+       return 0;
+}
+
+static struct thermal_governor thermal_gov_user_space = {
+       .name           = "user_space",
+       .throttle       = notify_user_space,
+};
+THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space);
diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c
deleted file mode 100644 (file)
index 4463647..0000000
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
- * A power allocator to manage temperature
- *
- * Copyright (C) 2014 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt) "Power allocator: " fmt
-
-#include <linux/rculist.h>
-#include <linux/slab.h>
-#include <linux/thermal.h>
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/thermal_power_allocator.h>
-
-#include "thermal_core.h"
-
-#define INVALID_TRIP -1
-
-#define FRAC_BITS 10
-#define int_to_frac(x) ((x) << FRAC_BITS)
-#define frac_to_int(x) ((x) >> FRAC_BITS)
-
-/**
- * mul_frac() - multiply two fixed-point numbers
- * @x: first multiplicand
- * @y: second multiplicand
- *
- * Return: the result of multiplying two fixed-point numbers.  The
- * result is also a fixed-point number.
- */
-static inline s64 mul_frac(s64 x, s64 y)
-{
-       return (x * y) >> FRAC_BITS;
-}
-
-/**
- * div_frac() - divide two fixed-point numbers
- * @x: the dividend
- * @y: the divisor
- *
- * Return: the result of dividing two fixed-point numbers.  The
- * result is also a fixed-point number.
- */
-static inline s64 div_frac(s64 x, s64 y)
-{
-       return div_s64(x << FRAC_BITS, y);
-}
-
-/**
- * struct power_allocator_params - parameters for the power allocator governor
- * @allocated_tzp:     whether we have allocated tzp for this thermal zone and
- *                     it needs to be freed on unbind
- * @err_integral:      accumulated error in the PID controller.
- * @prev_err:  error in the previous iteration of the PID controller.
- *             Used to calculate the derivative term.
- * @trip_switch_on:    first passive trip point of the thermal zone.  The
- *                     governor switches on when this trip point is crossed.
- *                     If the thermal zone only has one passive trip point,
- *                     @trip_switch_on should be INVALID_TRIP.
- * @trip_max_desired_temperature:      last passive trip point of the thermal
- *                                     zone.  The temperature we are
- *                                     controlling for.
- */
-struct power_allocator_params {
-       bool allocated_tzp;
-       s64 err_integral;
-       s32 prev_err;
-       int trip_switch_on;
-       int trip_max_desired_temperature;
-};
-
-/**
- * estimate_sustainable_power() - Estimate the sustainable power of a thermal zone
- * @tz: thermal zone we are operating in
- *
- * For thermal zones that don't provide a sustainable_power in their
- * thermal_zone_params, estimate one.  Calculate it using the minimum
- * power of all the cooling devices as that gives a valid value that
- * can give some degree of functionality.  For optimal performance of
- * this governor, provide a sustainable_power in the thermal zone's
- * thermal_zone_params.
- */
-static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
-{
-       u32 sustainable_power = 0;
-       struct thermal_instance *instance;
-       struct power_allocator_params *params = tz->governor_data;
-
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               struct thermal_cooling_device *cdev = instance->cdev;
-               u32 min_power;
-
-               if (instance->trip != params->trip_max_desired_temperature)
-                       continue;
-
-               if (power_actor_get_min_power(cdev, tz, &min_power))
-                       continue;
-
-               sustainable_power += min_power;
-       }
-
-       return sustainable_power;
-}
-
-/**
- * estimate_pid_constants() - Estimate the constants for the PID controller
- * @tz:                thermal zone for which to estimate the constants
- * @sustainable_power: sustainable power for the thermal zone
- * @trip_switch_on:    trip point number for the switch on temperature
- * @control_temp:      target temperature for the power allocator governor
- * @force:     whether to force the update of the constants
- *
- * This function is used to update the estimation of the PID
- * controller constants in struct thermal_zone_parameters.
- * Sustainable power is provided in case it was estimated.  The
- * estimated sustainable_power should not be stored in the
- * thermal_zone_parameters so it has to be passed explicitly to this
- * function.
- *
- * If @force is not set, the values in the thermal zone's parameters
- * are preserved if they are not zero.  If @force is set, the values
- * in thermal zone's parameters are overwritten.
- */
-static void estimate_pid_constants(struct thermal_zone_device *tz,
-                                  u32 sustainable_power, int trip_switch_on,
-                                  int control_temp, bool force)
-{
-       int ret;
-       int switch_on_temp;
-       u32 temperature_threshold;
-
-       ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp);
-       if (ret)
-               switch_on_temp = 0;
-
-       temperature_threshold = control_temp - switch_on_temp;
-       /*
-        * estimate_pid_constants() tries to find appropriate default
-        * values for thermal zones that don't provide them. If a
-        * system integrator has configured a thermal zone with two
-        * passive trip points at the same temperature, that person
-        * hasn't put any effort to set up the thermal zone properly
-        * so just give up.
-        */
-       if (!temperature_threshold)
-               return;
-
-       if (!tz->tzp->k_po || force)
-               tz->tzp->k_po = int_to_frac(sustainable_power) /
-                       temperature_threshold;
-
-       if (!tz->tzp->k_pu || force)
-               tz->tzp->k_pu = int_to_frac(2 * sustainable_power) /
-                       temperature_threshold;
-
-       if (!tz->tzp->k_i || force)
-               tz->tzp->k_i = int_to_frac(10) / 1000;
-       /*
-        * The default for k_d and integral_cutoff is 0, so we can
-        * leave them as they are.
-        */
-}
-
-/**
- * pid_controller() - PID controller
- * @tz:        thermal zone we are operating in
- * @control_temp:      the target temperature in millicelsius
- * @max_allocatable_power:     maximum allocatable power for this thermal zone
- *
- * This PID controller increases the available power budget so that the
- * temperature of the thermal zone gets as close as possible to
- * @control_temp and limits the power if it exceeds it.  k_po is the
- * proportional term when we are overshooting, k_pu is the
- * proportional term when we are undershooting.  integral_cutoff is a
- * threshold below which we stop accumulating the error.  The
- * accumulated error is only valid if the requested power will make
- * the system warmer.  If the system is mostly idle, there's no point
- * in accumulating positive error.
- *
- * Return: The power budget for the next period.
- */
-static u32 pid_controller(struct thermal_zone_device *tz,
-                         int control_temp,
-                         u32 max_allocatable_power)
-{
-       s64 p, i, d, power_range;
-       s32 err, max_power_frac;
-       u32 sustainable_power;
-       struct power_allocator_params *params = tz->governor_data;
-
-       max_power_frac = int_to_frac(max_allocatable_power);
-
-       if (tz->tzp->sustainable_power) {
-               sustainable_power = tz->tzp->sustainable_power;
-       } else {
-               sustainable_power = estimate_sustainable_power(tz);
-               estimate_pid_constants(tz, sustainable_power,
-                                      params->trip_switch_on, control_temp,
-                                      true);
-       }
-
-       err = control_temp - tz->temperature;
-       err = int_to_frac(err);
-
-       /* Calculate the proportional term */
-       p = mul_frac(err < 0 ? tz->tzp->k_po : tz->tzp->k_pu, err);
-
-       /*
-        * Calculate the integral term
-        *
-        * if the error is less than cut off allow integration (but
-        * the integral is limited to max power)
-        */
-       i = mul_frac(tz->tzp->k_i, params->err_integral);
-
-       if (err < int_to_frac(tz->tzp->integral_cutoff)) {
-               s64 i_next = i + mul_frac(tz->tzp->k_i, err);
-
-               if (abs(i_next) < max_power_frac) {
-                       i = i_next;
-                       params->err_integral += err;
-               }
-       }
-
-       /*
-        * Calculate the derivative term
-        *
-        * We do err - prev_err, so with a positive k_d, a decreasing
-        * error (i.e. driving closer to the line) results in less
-        * power being applied, slowing down the controller)
-        */
-       d = mul_frac(tz->tzp->k_d, err - params->prev_err);
-       d = div_frac(d, tz->passive_delay);
-       params->prev_err = err;
-
-       power_range = p + i + d;
-
-       /* feed-forward the known sustainable dissipatable power */
-       power_range = sustainable_power + frac_to_int(power_range);
-
-       power_range = clamp(power_range, (s64)0, (s64)max_allocatable_power);
-
-       trace_thermal_power_allocator_pid(tz, frac_to_int(err),
-                                         frac_to_int(params->err_integral),
-                                         frac_to_int(p), frac_to_int(i),
-                                         frac_to_int(d), power_range);
-
-       return power_range;
-}
-
-/**
- * divvy_up_power() - divvy the allocated power between the actors
- * @req_power: each actor's requested power
- * @max_power: each actor's maximum available power
- * @num_actors:        size of the @req_power, @max_power and @granted_power's array
- * @total_req_power: sum of @req_power
- * @power_range:       total allocated power
- * @granted_power:     output array: each actor's granted power
- * @extra_actor_power: an appropriately sized array to be used in the
- *                     function as temporary storage of the extra power given
- *                     to the actors
- *
- * This function divides the total allocated power (@power_range)
- * fairly between the actors.  It first tries to give each actor a
- * share of the @power_range according to how much power it requested
- * compared to the rest of the actors.  For example, if only one actor
- * requests power, then it receives all the @power_range.  If
- * three actors each requests 1mW, each receives a third of the
- * @power_range.
- *
- * If any actor received more than their maximum power, then that
- * surplus is re-divvied among the actors based on how far they are
- * from their respective maximums.
- *
- * Granted power for each actor is written to @granted_power, which
- * should've been allocated by the calling function.
- */
-static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
-                          u32 total_req_power, u32 power_range,
-                          u32 *granted_power, u32 *extra_actor_power)
-{
-       u32 extra_power, capped_extra_power;
-       int i;
-
-       /*
-        * Prevent division by 0 if none of the actors request power.
-        */
-       if (!total_req_power)
-               total_req_power = 1;
-
-       capped_extra_power = 0;
-       extra_power = 0;
-       for (i = 0; i < num_actors; i++) {
-               u64 req_range = (u64)req_power[i] * power_range;
-
-               granted_power[i] = DIV_ROUND_CLOSEST_ULL(req_range,
-                                                        total_req_power);
-
-               if (granted_power[i] > max_power[i]) {
-                       extra_power += granted_power[i] - max_power[i];
-                       granted_power[i] = max_power[i];
-               }
-
-               extra_actor_power[i] = max_power[i] - granted_power[i];
-               capped_extra_power += extra_actor_power[i];
-       }
-
-       if (!extra_power)
-               return;
-
-       /*
-        * Re-divvy the reclaimed extra among actors based on
-        * how far they are from the max
-        */
-       extra_power = min(extra_power, capped_extra_power);
-       if (capped_extra_power > 0)
-               for (i = 0; i < num_actors; i++)
-                       granted_power[i] += (extra_actor_power[i] *
-                                       extra_power) / capped_extra_power;
-}
-
-static int allocate_power(struct thermal_zone_device *tz,
-                         int control_temp)
-{
-       struct thermal_instance *instance;
-       struct power_allocator_params *params = tz->governor_data;
-       u32 *req_power, *max_power, *granted_power, *extra_actor_power;
-       u32 *weighted_req_power;
-       u32 total_req_power, max_allocatable_power, total_weighted_req_power;
-       u32 total_granted_power, power_range;
-       int i, num_actors, total_weight, ret = 0;
-       int trip_max_desired_temperature = params->trip_max_desired_temperature;
-
-       mutex_lock(&tz->lock);
-
-       num_actors = 0;
-       total_weight = 0;
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               if ((instance->trip == trip_max_desired_temperature) &&
-                   cdev_is_power_actor(instance->cdev)) {
-                       num_actors++;
-                       total_weight += instance->weight;
-               }
-       }
-
-       if (!num_actors) {
-               ret = -ENODEV;
-               goto unlock;
-       }
-
-       /*
-        * We need to allocate five arrays of the same size:
-        * req_power, max_power, granted_power, extra_actor_power and
-        * weighted_req_power.  They are going to be needed until this
-        * function returns.  Allocate them all in one go to simplify
-        * the allocation and deallocation logic.
-        */
-       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power));
-       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power));
-       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power));
-       BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power));
-       req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL);
-       if (!req_power) {
-               ret = -ENOMEM;
-               goto unlock;
-       }
-
-       max_power = &req_power[num_actors];
-       granted_power = &req_power[2 * num_actors];
-       extra_actor_power = &req_power[3 * num_actors];
-       weighted_req_power = &req_power[4 * num_actors];
-
-       i = 0;
-       total_weighted_req_power = 0;
-       total_req_power = 0;
-       max_allocatable_power = 0;
-
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               int weight;
-               struct thermal_cooling_device *cdev = instance->cdev;
-
-               if (instance->trip != trip_max_desired_temperature)
-                       continue;
-
-               if (!cdev_is_power_actor(cdev))
-                       continue;
-
-               if (cdev->ops->get_requested_power(cdev, tz, &req_power[i]))
-                       continue;
-
-               if (!total_weight)
-                       weight = 1 << FRAC_BITS;
-               else
-                       weight = instance->weight;
-
-               weighted_req_power[i] = frac_to_int(weight * req_power[i]);
-
-               if (power_actor_get_max_power(cdev, tz, &max_power[i]))
-                       continue;
-
-               total_req_power += req_power[i];
-               max_allocatable_power += max_power[i];
-               total_weighted_req_power += weighted_req_power[i];
-
-               i++;
-       }
-
-       power_range = pid_controller(tz, control_temp, max_allocatable_power);
-
-       divvy_up_power(weighted_req_power, max_power, num_actors,
-                      total_weighted_req_power, power_range, granted_power,
-                      extra_actor_power);
-
-       total_granted_power = 0;
-       i = 0;
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               if (instance->trip != trip_max_desired_temperature)
-                       continue;
-
-               if (!cdev_is_power_actor(instance->cdev))
-                       continue;
-
-               power_actor_set_power(instance->cdev, instance,
-                                     granted_power[i]);
-               total_granted_power += granted_power[i];
-
-               i++;
-       }
-
-       trace_thermal_power_allocator(tz, req_power, total_req_power,
-                                     granted_power, total_granted_power,
-                                     num_actors, power_range,
-                                     max_allocatable_power, tz->temperature,
-                                     control_temp - tz->temperature);
-
-       kfree(req_power);
-unlock:
-       mutex_unlock(&tz->lock);
-
-       return ret;
-}
-
-/**
- * get_governor_trips() - get the number of the two trip points that are key for this governor
- * @tz:        thermal zone to operate on
- * @params:    pointer to private data for this governor
- *
- * The power allocator governor works optimally with two trips points:
- * a "switch on" trip point and a "maximum desired temperature".  These
- * are defined as the first and last passive trip points.
- *
- * If there is only one trip point, then that's considered to be the
- * "maximum desired temperature" trip point and the governor is always
- * on.  If there are no passive or active trip points, then the
- * governor won't do anything.  In fact, its throttle function
- * won't be called at all.
- */
-static void get_governor_trips(struct thermal_zone_device *tz,
-                              struct power_allocator_params *params)
-{
-       int i, last_active, last_passive;
-       bool found_first_passive;
-
-       found_first_passive = false;
-       last_active = INVALID_TRIP;
-       last_passive = INVALID_TRIP;
-
-       for (i = 0; i < tz->trips; i++) {
-               enum thermal_trip_type type;
-               int ret;
-
-               ret = tz->ops->get_trip_type(tz, i, &type);
-               if (ret) {
-                       dev_warn(&tz->device,
-                                "Failed to get trip point %d type: %d\n", i,
-                                ret);
-                       continue;
-               }
-
-               if (type == THERMAL_TRIP_PASSIVE) {
-                       if (!found_first_passive) {
-                               params->trip_switch_on = i;
-                               found_first_passive = true;
-                       } else  {
-                               last_passive = i;
-                       }
-               } else if (type == THERMAL_TRIP_ACTIVE) {
-                       last_active = i;
-               } else {
-                       break;
-               }
-       }
-
-       if (last_passive != INVALID_TRIP) {
-               params->trip_max_desired_temperature = last_passive;
-       } else if (found_first_passive) {
-               params->trip_max_desired_temperature = params->trip_switch_on;
-               params->trip_switch_on = INVALID_TRIP;
-       } else {
-               params->trip_switch_on = INVALID_TRIP;
-               params->trip_max_desired_temperature = last_active;
-       }
-}
-
-static void reset_pid_controller(struct power_allocator_params *params)
-{
-       params->err_integral = 0;
-       params->prev_err = 0;
-}
-
-static void allow_maximum_power(struct thermal_zone_device *tz)
-{
-       struct thermal_instance *instance;
-       struct power_allocator_params *params = tz->governor_data;
-
-       mutex_lock(&tz->lock);
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               if ((instance->trip != params->trip_max_desired_temperature) ||
-                   (!cdev_is_power_actor(instance->cdev)))
-                       continue;
-
-               instance->target = 0;
-               mutex_lock(&instance->cdev->lock);
-               instance->cdev->updated = false;
-               mutex_unlock(&instance->cdev->lock);
-               thermal_cdev_update(instance->cdev);
-       }
-       mutex_unlock(&tz->lock);
-}
-
-/**
- * power_allocator_bind() - bind the power_allocator governor to a thermal zone
- * @tz:        thermal zone to bind it to
- *
- * Initialize the PID controller parameters and bind it to the thermal
- * zone.
- *
- * Return: 0 on success, or -ENOMEM if we ran out of memory.
- */
-static int power_allocator_bind(struct thermal_zone_device *tz)
-{
-       int ret;
-       struct power_allocator_params *params;
-       int control_temp;
-
-       params = kzalloc(sizeof(*params), GFP_KERNEL);
-       if (!params)
-               return -ENOMEM;
-
-       if (!tz->tzp) {
-               tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL);
-               if (!tz->tzp) {
-                       ret = -ENOMEM;
-                       goto free_params;
-               }
-
-               params->allocated_tzp = true;
-       }
-
-       if (!tz->tzp->sustainable_power)
-               dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
-
-       get_governor_trips(tz, params);
-
-       if (tz->trips > 0) {
-               ret = tz->ops->get_trip_temp(tz,
-                                       params->trip_max_desired_temperature,
-                                       &control_temp);
-               if (!ret)
-                       estimate_pid_constants(tz, tz->tzp->sustainable_power,
-                                              params->trip_switch_on,
-                                              control_temp, false);
-       }
-
-       reset_pid_controller(params);
-
-       tz->governor_data = params;
-
-       return 0;
-
-free_params:
-       kfree(params);
-
-       return ret;
-}
-
-static void power_allocator_unbind(struct thermal_zone_device *tz)
-{
-       struct power_allocator_params *params = tz->governor_data;
-
-       dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
-
-       if (params->allocated_tzp) {
-               kfree(tz->tzp);
-               tz->tzp = NULL;
-       }
-
-       kfree(tz->governor_data);
-       tz->governor_data = NULL;
-}
-
-static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
-{
-       int ret;
-       int switch_on_temp, control_temp;
-       struct power_allocator_params *params = tz->governor_data;
-
-       /*
-        * We get called for every trip point but we only need to do
-        * our calculations once
-        */
-       if (trip != params->trip_max_desired_temperature)
-               return 0;
-
-       ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
-                                    &switch_on_temp);
-       if (!ret && (tz->temperature < switch_on_temp)) {
-               tz->passive = 0;
-               reset_pid_controller(params);
-               allow_maximum_power(tz);
-               return 0;
-       }
-
-       tz->passive = 1;
-
-       ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature,
-                               &control_temp);
-       if (ret) {
-               dev_warn(&tz->device,
-                        "Failed to get the maximum desired temperature: %d\n",
-                        ret);
-               return ret;
-       }
-
-       return allocate_power(tz, control_temp);
-}
-
-static struct thermal_governor thermal_gov_power_allocator = {
-       .name           = "power_allocator",
-       .bind_to_tz     = power_allocator_bind,
-       .unbind_from_tz = power_allocator_unbind,
-       .throttle       = power_allocator_throttle,
-};
-THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator);
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
deleted file mode 100644 (file)
index 2ae7198..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- *  step_wise.c - A step-by-step Thermal throttling governor
- *
- *  Copyright (C) 2012 Intel Corp
- *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
- *
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <linux/thermal.h>
-#include <trace/events/thermal.h>
-
-#include "thermal_core.h"
-
-/*
- * If the temperature is higher than a trip point,
- *    a. if the trend is THERMAL_TREND_RAISING, use higher cooling
- *       state for this trip point
- *    b. if the trend is THERMAL_TREND_DROPPING, do nothing
- *    c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit
- *       for this trip point
- *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit
- *       for this trip point
- * If the temperature is lower than a trip point,
- *    a. if the trend is THERMAL_TREND_RAISING, do nothing
- *    b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
- *       state for this trip point, if the cooling state already
- *       equals lower limit, deactivate the thermal instance
- *    c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing
- *    d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit,
- *       if the cooling state already equals lower limit,
- *       deactivate the thermal instance
- */
-static unsigned long get_target_state(struct thermal_instance *instance,
-                               enum thermal_trend trend, bool throttle)
-{
-       struct thermal_cooling_device *cdev = instance->cdev;
-       unsigned long cur_state;
-       unsigned long next_target;
-
-       /*
-        * We keep this instance the way it is by default.
-        * Otherwise, we use the current state of the
-        * cdev in use to determine the next_target.
-        */
-       cdev->ops->get_cur_state(cdev, &cur_state);
-       next_target = instance->target;
-       dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
-
-       if (!instance->initialized) {
-               if (throttle) {
-                       next_target = (cur_state + 1) >= instance->upper ?
-                                       instance->upper :
-                                       ((cur_state + 1) < instance->lower ?
-                                       instance->lower : (cur_state + 1));
-               } else {
-                       next_target = THERMAL_NO_TARGET;
-               }
-
-               return next_target;
-       }
-
-       switch (trend) {
-       case THERMAL_TREND_RAISING:
-               if (throttle) {
-                       next_target = cur_state < instance->upper ?
-                                   (cur_state + 1) : instance->upper;
-                       if (next_target < instance->lower)
-                               next_target = instance->lower;
-               }
-               break;
-       case THERMAL_TREND_RAISE_FULL:
-               if (throttle)
-                       next_target = instance->upper;
-               break;
-       case THERMAL_TREND_DROPPING:
-               if (cur_state <= instance->lower) {
-                       if (!throttle)
-                               next_target = THERMAL_NO_TARGET;
-               } else {
-                       if (!throttle) {
-                               next_target = cur_state - 1;
-                               if (next_target > instance->upper)
-                                       next_target = instance->upper;
-                       }
-               }
-               break;
-       case THERMAL_TREND_DROP_FULL:
-               if (cur_state == instance->lower) {
-                       if (!throttle)
-                               next_target = THERMAL_NO_TARGET;
-               } else
-                       next_target = instance->lower;
-               break;
-       default:
-               break;
-       }
-
-       return next_target;
-}
-
-static void update_passive_instance(struct thermal_zone_device *tz,
-                               enum thermal_trip_type type, int value)
-{
-       /*
-        * If value is +1, activate a passive instance.
-        * If value is -1, deactivate a passive instance.
-        */
-       if (type == THERMAL_TRIP_PASSIVE || type == THERMAL_TRIPS_NONE)
-               tz->passive += value;
-}
-
-static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
-{
-       int trip_temp;
-       enum thermal_trip_type trip_type;
-       enum thermal_trend trend;
-       struct thermal_instance *instance;
-       bool throttle = false;
-       int old_target;
-
-       if (trip == THERMAL_TRIPS_NONE) {
-               trip_temp = tz->forced_passive;
-               trip_type = THERMAL_TRIPS_NONE;
-       } else {
-               tz->ops->get_trip_temp(tz, trip, &trip_temp);
-               tz->ops->get_trip_type(tz, trip, &trip_type);
-       }
-
-       trend = get_tz_trend(tz, trip);
-
-       if (tz->temperature >= trip_temp) {
-               throttle = true;
-               trace_thermal_zone_trip(tz, trip, trip_type);
-       }
-
-       dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
-                               trip, trip_type, trip_temp, trend, throttle);
-
-       mutex_lock(&tz->lock);
-
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
-               if (instance->trip != trip)
-                       continue;
-
-               old_target = instance->target;
-               instance->target = get_target_state(instance, trend, throttle);
-               dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
-                                       old_target, (int)instance->target);
-
-               if (instance->initialized && old_target == instance->target)
-                       continue;
-
-               /* Activate a passive thermal instance */
-               if (old_target == THERMAL_NO_TARGET &&
-                       instance->target != THERMAL_NO_TARGET)
-                       update_passive_instance(tz, trip_type, 1);
-               /* Deactivate a passive thermal instance */
-               else if (old_target != THERMAL_NO_TARGET &&
-                       instance->target == THERMAL_NO_TARGET)
-                       update_passive_instance(tz, trip_type, -1);
-
-               instance->initialized = true;
-               mutex_lock(&instance->cdev->lock);
-               instance->cdev->updated = false; /* cdev needs update */
-               mutex_unlock(&instance->cdev->lock);
-       }
-
-       mutex_unlock(&tz->lock);
-}
-
-/**
- * step_wise_throttle - throttles devices associated with the given zone
- * @tz: thermal_zone_device
- * @trip: trip point index
- *
- * Throttling Logic: This uses the trend of the thermal zone to throttle.
- * If the thermal zone is 'heating up' this throttles all the cooling
- * devices associated with the zone and its particular trip point, by one
- * step. If the zone is 'cooling down' it brings back the performance of
- * the devices by one step.
- */
-static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
-{
-       struct thermal_instance *instance;
-
-       thermal_zone_trip_update(tz, trip);
-
-       if (tz->forced_passive)
-               thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE);
-
-       mutex_lock(&tz->lock);
-
-       list_for_each_entry(instance, &tz->thermal_instances, tz_node)
-               thermal_cdev_update(instance->cdev);
-
-       mutex_unlock(&tz->lock);
-
-       return 0;
-}
-
-static struct thermal_governor thermal_gov_step_wise = {
-       .name           = "step_wise",
-       .throttle       = step_wise_throttle,
-};
-THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);
diff --git a/drivers/thermal/user_space.c b/drivers/thermal/user_space.c
deleted file mode 100644 (file)
index 82a7198..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- *  user_space.c - A simple user space Thermal events notifier
- *
- *  Copyright (C) 2012 Intel Corp
- *  Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
- *
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <linux/slab.h>
-#include <linux/thermal.h>
-
-#include "thermal_core.h"
-
-/**
- * notify_user_space - Notifies user space about thermal events
- * @tz: thermal_zone_device
- * @trip: trip point index
- *
- * This function notifies the user space through UEvents.
- */
-static int notify_user_space(struct thermal_zone_device *tz, int trip)
-{
-       char *thermal_prop[5];
-       int i;
-
-       mutex_lock(&tz->lock);
-       thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", tz->type);
-       thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", tz->temperature);
-       thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=%d", trip);
-       thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", tz->notify_event);
-       thermal_prop[4] = NULL;
-       kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, thermal_prop);
-       for (i = 0; i < 4; ++i)
-               kfree(thermal_prop[i]);
-       mutex_unlock(&tz->lock);
-       return 0;
-}
-
-static struct thermal_governor thermal_gov_user_space = {
-       .name           = "user_space",
-       .throttle       = notify_user_space,
-};
-THERMAL_GOVERNOR_DECLARE(thermal_gov_user_space);