drivers: thermal: Add a snapshot of thermal framework
This is a snapshot of the thermal framework from msm-4.19 to msm-5.4 as of 'commit <14237cefb3f65441677efd9163852ee148017d0c> (thermal: Fix deadlock in thermal thermal_zone_device_check)'. Change-Id: I5702ad4f314f2dddfc04244d21605444bd7760a3 Signed-off-by: Ram Chandrasekar <rkumbako@codeaurora.org>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 Intel Corp
|
||||
* Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
@@ -41,6 +42,12 @@ static unsigned long get_target_state(struct thermal_instance *instance,
|
||||
unsigned long cur_state;
|
||||
unsigned long next_target;
|
||||
|
||||
/*
|
||||
* If the throttle condition is not reached and there is no
|
||||
* previous mitigaiton request, then there is nothing to compute.
|
||||
*/
|
||||
if (!throttle && instance->target == THERMAL_NO_TARGET)
|
||||
return THERMAL_NO_TARGET;
|
||||
/*
|
||||
* We keep this instance the way it is by default.
|
||||
* Otherwise, we use the current state of the
|
||||
@@ -77,7 +84,9 @@ static unsigned long get_target_state(struct thermal_instance *instance,
|
||||
next_target = instance->upper;
|
||||
break;
|
||||
case THERMAL_TREND_DROPPING:
|
||||
if (cur_state <= instance->lower) {
|
||||
case THERMAL_TREND_STABLE:
|
||||
if (cur_state <= instance->lower ||
|
||||
instance->target <= instance->lower) {
|
||||
if (!throttle)
|
||||
next_target = THERMAL_NO_TARGET;
|
||||
} else {
|
||||
@@ -115,7 +124,7 @@ static void update_passive_instance(struct thermal_zone_device *tz,
|
||||
|
||||
static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
|
||||
{
|
||||
int trip_temp;
|
||||
int trip_temp, hyst_temp;
|
||||
enum thermal_trip_type trip_type;
|
||||
enum thermal_trend trend;
|
||||
struct thermal_instance *instance;
|
||||
@@ -123,20 +132,21 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
|
||||
int old_target;
|
||||
|
||||
if (trip == THERMAL_TRIPS_NONE) {
|
||||
trip_temp = tz->forced_passive;
|
||||
hyst_temp = trip_temp = tz->forced_passive;
|
||||
trip_type = THERMAL_TRIPS_NONE;
|
||||
} else {
|
||||
tz->ops->get_trip_temp(tz, trip, &trip_temp);
|
||||
if (tz->ops->get_trip_hyst) {
|
||||
tz->ops->get_trip_hyst(tz, trip, &hyst_temp);
|
||||
hyst_temp = trip_temp - hyst_temp;
|
||||
} else {
|
||||
hyst_temp = 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);
|
||||
|
||||
@@ -147,6 +157,20 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
|
||||
continue;
|
||||
|
||||
old_target = instance->target;
|
||||
/*
|
||||
* Step wise has to lower the mitigation only if the
|
||||
* temperature goes below the hysteresis temperature.
|
||||
* Atleast, it has to hold on to mitigation device lower
|
||||
* limit if the temperature is above the hysteresis
|
||||
* temperature.
|
||||
*/
|
||||
if (tz->temperature >= trip_temp ||
|
||||
(tz->temperature > hyst_temp &&
|
||||
old_target != THERMAL_NO_TARGET))
|
||||
throttle = true;
|
||||
else
|
||||
throttle = false;
|
||||
|
||||
instance->target = get_target_state(instance, trend, throttle);
|
||||
dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
|
||||
old_target, (int)instance->target);
|
||||
@@ -154,14 +178,27 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
|
||||
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);
|
||||
if (!instance->initialized) {
|
||||
if (instance->target != THERMAL_NO_TARGET) {
|
||||
trace_thermal_zone_trip(tz, trip, trip_type,
|
||||
true);
|
||||
update_passive_instance(tz, trip_type, 1);
|
||||
}
|
||||
} else {
|
||||
/* Activate a passive thermal instance */
|
||||
if (old_target == THERMAL_NO_TARGET &&
|
||||
instance->target != THERMAL_NO_TARGET) {
|
||||
trace_thermal_zone_trip(tz, trip, trip_type,
|
||||
true);
|
||||
update_passive_instance(tz, trip_type, 1);
|
||||
/* Deactivate a passive thermal instance */
|
||||
} else if (old_target != THERMAL_NO_TARGET &&
|
||||
instance->target == THERMAL_NO_TARGET) {
|
||||
trace_thermal_zone_trip(tz, trip, trip_type,
|
||||
false);
|
||||
update_passive_instance(tz, trip_type, -1);
|
||||
}
|
||||
}
|
||||
|
||||
instance->initialized = true;
|
||||
mutex_lock(&instance->cdev->lock);
|
||||
|
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2008 Intel Corp
|
||||
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
|
||||
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
@@ -33,6 +34,8 @@ MODULE_AUTHOR("Zhang Rui");
|
||||
MODULE_DESCRIPTION("Generic thermal management sysfs support");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
#define THERMAL_MAX_ACTIVE 16
|
||||
|
||||
static DEFINE_IDA(thermal_tz_ida);
|
||||
static DEFINE_IDA(thermal_cdev_ida);
|
||||
|
||||
@@ -49,6 +52,8 @@ static bool power_off_triggered;
|
||||
|
||||
static struct thermal_governor *def_governor;
|
||||
|
||||
static struct workqueue_struct *thermal_passive_wq;
|
||||
|
||||
/*
|
||||
* Governor section: set of functions to handle thermal governors
|
||||
*
|
||||
@@ -292,19 +297,18 @@ static int __init thermal_register_governors(void)
|
||||
* - Hot trips will produce a notification to userspace;
|
||||
* - Critical trip point will cause a system shutdown.
|
||||
*/
|
||||
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
|
||||
static void thermal_zone_device_set_polling(struct workqueue_struct *queue,
|
||||
struct thermal_zone_device *tz,
|
||||
int delay)
|
||||
{
|
||||
if (delay > 1000)
|
||||
mod_delayed_work(system_freezable_power_efficient_wq,
|
||||
&tz->poll_queue,
|
||||
mod_delayed_work(queue, &tz->poll_queue,
|
||||
round_jiffies(msecs_to_jiffies(delay)));
|
||||
else if (delay)
|
||||
mod_delayed_work(system_freezable_power_efficient_wq,
|
||||
&tz->poll_queue,
|
||||
mod_delayed_work(queue, &tz->poll_queue,
|
||||
msecs_to_jiffies(delay));
|
||||
else
|
||||
cancel_delayed_work_sync(&tz->poll_queue);
|
||||
cancel_delayed_work(&tz->poll_queue);
|
||||
}
|
||||
|
||||
static void monitor_thermal_zone(struct thermal_zone_device *tz)
|
||||
@@ -312,11 +316,14 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
|
||||
mutex_lock(&tz->lock);
|
||||
|
||||
if (tz->passive)
|
||||
thermal_zone_device_set_polling(tz, tz->passive_delay);
|
||||
thermal_zone_device_set_polling(thermal_passive_wq,
|
||||
tz, tz->passive_delay);
|
||||
else if (tz->polling_delay)
|
||||
thermal_zone_device_set_polling(tz, tz->polling_delay);
|
||||
thermal_zone_device_set_polling(
|
||||
system_freezable_power_efficient_wq,
|
||||
tz, tz->polling_delay);
|
||||
else
|
||||
thermal_zone_device_set_polling(tz, 0);
|
||||
thermal_zone_device_set_polling(NULL, tz, 0);
|
||||
|
||||
mutex_unlock(&tz->lock);
|
||||
}
|
||||
@@ -386,7 +393,7 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
|
||||
if (trip_temp <= 0 || tz->temperature < trip_temp)
|
||||
return;
|
||||
|
||||
trace_thermal_zone_trip(tz, trip, trip_type);
|
||||
trace_thermal_zone_trip(tz, trip, trip_type, true);
|
||||
|
||||
if (tz->ops->notify)
|
||||
tz->ops->notify(tz, trip, trip_type);
|
||||
@@ -428,6 +435,23 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
|
||||
* So, start monitoring again.
|
||||
*/
|
||||
monitor_thermal_zone(tz);
|
||||
trace_thermal_handle_trip(tz, trip);
|
||||
}
|
||||
|
||||
static void store_temperature(struct thermal_zone_device *tz, int temp)
|
||||
{
|
||||
mutex_lock(&tz->lock);
|
||||
tz->last_temperature = tz->temperature;
|
||||
tz->temperature = temp;
|
||||
mutex_unlock(&tz->lock);
|
||||
|
||||
trace_thermal_temperature(tz);
|
||||
if (tz->last_temperature == THERMAL_TEMP_INVALID)
|
||||
dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n",
|
||||
tz->temperature);
|
||||
else
|
||||
dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
|
||||
tz->last_temperature, tz->temperature);
|
||||
}
|
||||
|
||||
static void update_temperature(struct thermal_zone_device *tz)
|
||||
@@ -442,19 +466,7 @@ static void update_temperature(struct thermal_zone_device *tz)
|
||||
ret);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&tz->lock);
|
||||
tz->last_temperature = tz->temperature;
|
||||
tz->temperature = temp;
|
||||
mutex_unlock(&tz->lock);
|
||||
|
||||
trace_thermal_temperature(tz);
|
||||
if (tz->last_temperature == THERMAL_TEMP_INVALID)
|
||||
dev_dbg(&tz->device, "last_temperature N/A, current_temperature=%d\n",
|
||||
tz->temperature);
|
||||
else
|
||||
dev_dbg(&tz->device, "last_temperature=%d, current_temperature=%d\n",
|
||||
tz->last_temperature, tz->temperature);
|
||||
store_temperature(tz, temp);
|
||||
}
|
||||
|
||||
static void thermal_zone_device_init(struct thermal_zone_device *tz)
|
||||
@@ -471,17 +483,36 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz)
|
||||
thermal_zone_device_init(tz);
|
||||
}
|
||||
|
||||
void thermal_zone_device_update_temp(struct thermal_zone_device *tz,
|
||||
enum thermal_notify_event event, int temp)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (atomic_read(&in_suspend) && tz->polling_delay)
|
||||
return;
|
||||
trace_thermal_device_update(tz, event);
|
||||
store_temperature(tz, temp);
|
||||
|
||||
thermal_zone_set_trips(tz);
|
||||
|
||||
tz->notify_event = event;
|
||||
|
||||
for (count = 0; count < tz->trips; count++)
|
||||
handle_thermal_trip(tz, count);
|
||||
}
|
||||
EXPORT_SYMBOL(thermal_zone_device_update_temp);
|
||||
|
||||
void thermal_zone_device_update(struct thermal_zone_device *tz,
|
||||
enum thermal_notify_event event)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (atomic_read(&in_suspend))
|
||||
if (atomic_read(&in_suspend) && tz->polling_delay)
|
||||
return;
|
||||
|
||||
if (!tz->ops->get_temp)
|
||||
return;
|
||||
|
||||
trace_thermal_device_update(tz, event);
|
||||
update_temperature(tz);
|
||||
|
||||
thermal_zone_set_trips(tz);
|
||||
@@ -710,9 +741,26 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* lower default 0, upper default max_state */
|
||||
lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
|
||||
upper = upper == THERMAL_NO_LIMIT ? max_state : upper;
|
||||
/*
|
||||
* If upper or lower has a MACRO to define the mitigation state,
|
||||
* based on the MACRO determine the default state to use or the
|
||||
* offset from the max_state.
|
||||
*/
|
||||
if (upper >= (THERMAL_MAX_LIMIT - max_state)) {
|
||||
/* upper default max_state */
|
||||
if (upper == THERMAL_NO_LIMIT)
|
||||
upper = max_state;
|
||||
else
|
||||
upper = max_state - (THERMAL_MAX_LIMIT - upper);
|
||||
}
|
||||
|
||||
if (lower >= (THERMAL_MAX_LIMIT - max_state)) {
|
||||
/* lower default 0 */
|
||||
if (lower == THERMAL_NO_LIMIT)
|
||||
lower = 0;
|
||||
else
|
||||
lower = max_state - (THERMAL_MAX_LIMIT - lower);
|
||||
}
|
||||
|
||||
if (lower > upper || upper > max_state)
|
||||
return -EINVAL;
|
||||
@@ -839,6 +887,7 @@ static void thermal_release(struct device *dev)
|
||||
{
|
||||
struct thermal_zone_device *tz;
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct thermal_instance *instance;
|
||||
|
||||
if (!strncmp(dev_name(dev), "thermal_zone",
|
||||
sizeof("thermal_zone") - 1)) {
|
||||
@@ -848,6 +897,12 @@ static void thermal_release(struct device *dev)
|
||||
} else if (!strncmp(dev_name(dev), "cooling_device",
|
||||
sizeof("cooling_device") - 1)) {
|
||||
cdev = to_cooling_device(dev);
|
||||
if (list_is_singular(&cdev->thermal_instances)) {
|
||||
instance = list_first_entry(&cdev->thermal_instances,
|
||||
typeof(*instance), cdev_node);
|
||||
list_del(&instance->cdev_node);
|
||||
kfree(instance);
|
||||
}
|
||||
kfree(cdev);
|
||||
}
|
||||
}
|
||||
@@ -953,6 +1008,7 @@ __thermal_cooling_device_register(struct device_node *np,
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct thermal_zone_device *pos = NULL;
|
||||
int result;
|
||||
struct thermal_instance *instance;
|
||||
|
||||
if (type && strlen(type) >= THERMAL_NAME_LENGTH)
|
||||
return ERR_PTR(-EINVAL);
|
||||
@@ -965,9 +1021,16 @@ __thermal_cooling_device_register(struct device_node *np,
|
||||
if (!cdev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
instance = kzalloc(sizeof(*instance), GFP_KERNEL);
|
||||
if (!instance) {
|
||||
kfree(cdev);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
result = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL);
|
||||
if (result < 0) {
|
||||
kfree(cdev);
|
||||
kfree(instance);
|
||||
return ERR_PTR(result);
|
||||
}
|
||||
|
||||
@@ -975,6 +1038,8 @@ __thermal_cooling_device_register(struct device_node *np,
|
||||
strlcpy(cdev->type, type ? : "", sizeof(cdev->type));
|
||||
mutex_init(&cdev->lock);
|
||||
INIT_LIST_HEAD(&cdev->thermal_instances);
|
||||
instance->target = THERMAL_NO_TARGET;
|
||||
list_add_tail(&instance->cdev_node, &cdev->thermal_instances);
|
||||
cdev->np = np;
|
||||
cdev->ops = ops;
|
||||
cdev->updated = false;
|
||||
@@ -1345,7 +1410,7 @@ thermal_zone_device_register(const char *type, int trips, int mask,
|
||||
/* Bind cooling devices for this zone */
|
||||
bind_tz(tz);
|
||||
|
||||
INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
|
||||
INIT_DEFERRABLE_WORK(&(tz->poll_queue), thermal_zone_device_check);
|
||||
|
||||
thermal_zone_device_reset(tz);
|
||||
/* Update the new thermal zone and mark it as already updated. */
|
||||
@@ -1414,7 +1479,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
|
||||
|
||||
mutex_unlock(&thermal_list_lock);
|
||||
|
||||
thermal_zone_device_set_polling(tz, 0);
|
||||
cancel_delayed_work_sync(&tz->poll_queue);
|
||||
|
||||
thermal_set_governor(tz, NULL);
|
||||
|
||||
@@ -1576,7 +1641,8 @@ static int thermal_pm_notify(struct notifier_block *nb,
|
||||
if (tz->ops->get_mode)
|
||||
tz->ops->get_mode(tz, &tz_mode);
|
||||
|
||||
if (tz_mode == THERMAL_DEVICE_DISABLED)
|
||||
if (tz_mode == THERMAL_DEVICE_DISABLED ||
|
||||
tz->polling_delay == 0)
|
||||
continue;
|
||||
|
||||
thermal_zone_device_init(tz);
|
||||
@@ -1599,21 +1665,26 @@ static int __init thermal_init(void)
|
||||
int result;
|
||||
|
||||
mutex_init(&poweroff_lock);
|
||||
thermal_passive_wq = alloc_workqueue("thermal_passive_wq",
|
||||
WQ_HIGHPRI | WQ_UNBOUND
|
||||
| WQ_FREEZABLE,
|
||||
THERMAL_MAX_ACTIVE);
|
||||
if (!thermal_passive_wq) {
|
||||
result = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = thermal_register_governors();
|
||||
if (result)
|
||||
goto error;
|
||||
goto destroy_wq;
|
||||
|
||||
result = class_register(&thermal_class);
|
||||
if (result)
|
||||
goto unregister_governors;
|
||||
|
||||
result = genetlink_init();
|
||||
if (result)
|
||||
goto unregister_class;
|
||||
|
||||
result = of_parse_thermal_zones();
|
||||
if (result)
|
||||
goto exit_netlink;
|
||||
goto unregister_class;
|
||||
|
||||
result = register_pm_notifier(&thermal_pm_nb);
|
||||
if (result)
|
||||
@@ -1622,12 +1693,12 @@ static int __init thermal_init(void)
|
||||
|
||||
return 0;
|
||||
|
||||
exit_netlink:
|
||||
genetlink_exit();
|
||||
unregister_class:
|
||||
class_unregister(&thermal_class);
|
||||
unregister_governors:
|
||||
thermal_unregister_governors();
|
||||
destroy_wq:
|
||||
destroy_workqueue(thermal_passive_wq);
|
||||
error:
|
||||
ida_destroy(&thermal_tz_ida);
|
||||
ida_destroy(&thermal_cdev_ida);
|
||||
@@ -1636,4 +1707,33 @@ error:
|
||||
mutex_destroy(&poweroff_lock);
|
||||
return result;
|
||||
}
|
||||
fs_initcall(thermal_init);
|
||||
|
||||
static void thermal_exit(void)
|
||||
{
|
||||
unregister_pm_notifier(&thermal_pm_nb);
|
||||
of_thermal_destroy_zones();
|
||||
destroy_workqueue(thermal_passive_wq);
|
||||
genetlink_exit();
|
||||
class_unregister(&thermal_class);
|
||||
thermal_unregister_governors();
|
||||
ida_destroy(&thermal_tz_ida);
|
||||
ida_destroy(&thermal_cdev_ida);
|
||||
mutex_destroy(&thermal_list_lock);
|
||||
mutex_destroy(&thermal_governor_lock);
|
||||
}
|
||||
|
||||
static int __init thermal_netlink_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = genetlink_init();
|
||||
if (!ret)
|
||||
goto exit_netlink;
|
||||
|
||||
thermal_exit();
|
||||
exit_netlink:
|
||||
return ret;
|
||||
}
|
||||
|
||||
subsys_initcall(thermal_init);
|
||||
fs_initcall(thermal_netlink_init);
|
||||
|
@@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2012 Intel Corp
|
||||
* Author: Durgadoss R <durgadoss.r@intel.com>
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __THERMAL_CORE_H__
|
||||
@@ -97,6 +98,12 @@ int of_thermal_get_ntrips(struct thermal_zone_device *);
|
||||
bool of_thermal_is_trip_valid(struct thermal_zone_device *, int);
|
||||
const struct thermal_trip *
|
||||
of_thermal_get_trip_points(struct thermal_zone_device *);
|
||||
int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
|
||||
enum thermal_trip_type type,
|
||||
int *low, int *high);
|
||||
void of_thermal_handle_trip(struct thermal_zone_device *tz);
|
||||
void of_thermal_handle_trip_temp(struct thermal_zone_device *tz,
|
||||
int trip_temp);
|
||||
#else
|
||||
static inline int of_parse_thermal_zones(void) { return 0; }
|
||||
static inline void of_thermal_destroy_zones(void) { }
|
||||
@@ -114,6 +121,19 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline int of_thermal_aggregate_trip(struct thermal_zone_device *tz,
|
||||
enum thermal_trip_type type,
|
||||
int *low, int *high)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline
|
||||
void of_thermal_handle_trip(struct thermal_zone_device *tz)
|
||||
{ }
|
||||
static inline
|
||||
void of_thermal_handle_trip_temp(struct thermal_zone_device *tz,
|
||||
int trip_temp)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
#endif /* __THERMAL_CORE_H__ */
|
||||
|
@@ -8,6 +8,7 @@
|
||||
* Copyright (C) 2008 Intel Corp
|
||||
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
|
||||
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
@@ -106,7 +107,7 @@ int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp)
|
||||
if (!ret && *temp < crit_temp)
|
||||
*temp = tz->emul_temperature;
|
||||
}
|
||||
|
||||
trace_thermal_query_temp(tz, *temp);
|
||||
mutex_unlock(&tz->lock);
|
||||
exit:
|
||||
return ret;
|
||||
@@ -140,10 +141,6 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
|
||||
high = trip_temp;
|
||||
}
|
||||
|
||||
/* No need to change trip points */
|
||||
if (tz->prev_low_trip == low && tz->prev_high_trip == high)
|
||||
goto exit;
|
||||
|
||||
tz->prev_low_trip = low;
|
||||
tz->prev_high_trip = high;
|
||||
|
||||
@@ -157,6 +154,7 @@ void thermal_zone_set_trips(struct thermal_zone_device *tz)
|
||||
ret = tz->ops->set_trips(tz, low, high);
|
||||
if (ret)
|
||||
dev_err(&tz->device, "Failed to set trips: %d\n", ret);
|
||||
trace_thermal_set_trip(tz);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&tz->lock);
|
||||
@@ -177,8 +175,13 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
|
||||
|
||||
/* Make sure cdev enters the deepest cooling state */
|
||||
list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
|
||||
dev_dbg(&cdev->device, "zone%d->target=%lu\n",
|
||||
instance->tz->id, instance->target);
|
||||
if (list_is_first(&instance->cdev_node,
|
||||
&cdev->thermal_instances))
|
||||
dev_dbg(&cdev->device, "userspace->target=%lu\n",
|
||||
instance->target);
|
||||
else
|
||||
dev_dbg(&cdev->device, "zone%d->target=%lu\n",
|
||||
instance->tz->id, instance->target);
|
||||
if (instance->target == THERMAL_NO_TARGET)
|
||||
continue;
|
||||
if (instance->target > target)
|
||||
|
@@ -8,6 +8,7 @@
|
||||
* Copyright (C) 2008 Intel Corp
|
||||
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
|
||||
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
@@ -63,6 +64,28 @@ mode_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
: "disabled");
|
||||
}
|
||||
|
||||
static int thermal_zone_device_clear(struct thermal_zone_device *tz)
|
||||
{
|
||||
struct thermal_instance *pos;
|
||||
int ret = 0;
|
||||
|
||||
ret = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
|
||||
mutex_lock(&tz->lock);
|
||||
tz->temperature = THERMAL_TEMP_INVALID;
|
||||
tz->passive = 0;
|
||||
list_for_each_entry(pos, &tz->thermal_instances, tz_node) {
|
||||
pos->initialized = false;
|
||||
pos->target = THERMAL_NO_TARGET;
|
||||
mutex_lock(&pos->cdev->lock);
|
||||
pos->cdev->updated = false; /* cdev needs update */
|
||||
mutex_unlock(&pos->cdev->lock);
|
||||
thermal_cdev_update(pos->cdev);
|
||||
}
|
||||
mutex_unlock(&tz->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
mode_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
@@ -76,7 +99,7 @@ mode_store(struct device *dev, struct device_attribute *attr,
|
||||
if (!strncmp(buf, "enabled", sizeof("enabled") - 1))
|
||||
result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED);
|
||||
else if (!strncmp(buf, "disabled", sizeof("disabled") - 1))
|
||||
result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED);
|
||||
result = thermal_zone_device_clear(tz);
|
||||
else
|
||||
result = -EINVAL;
|
||||
|
||||
@@ -348,6 +371,24 @@ sustainable_power_store(struct device *dev, struct device_attribute *devattr,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
polling_delay_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct thermal_zone_device *tz = to_thermal_zone(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", tz->polling_delay);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
passive_delay_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct thermal_zone_device *tz = to_thermal_zone(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", tz->passive_delay);
|
||||
}
|
||||
|
||||
#define create_s32_tzp_attr(name) \
|
||||
static ssize_t \
|
||||
name##_show(struct device *dev, struct device_attribute *devattr, \
|
||||
@@ -399,6 +440,8 @@ static DEVICE_ATTR_RO(temp);
|
||||
static DEVICE_ATTR_RW(policy);
|
||||
static DEVICE_ATTR_RO(available_policies);
|
||||
static DEVICE_ATTR_RW(sustainable_power);
|
||||
static DEVICE_ATTR_RO(passive_delay);
|
||||
static DEVICE_ATTR_RO(polling_delay);
|
||||
|
||||
/* These thermal zone device attributes are created based on conditions */
|
||||
static DEVICE_ATTR_RW(mode);
|
||||
@@ -414,6 +457,8 @@ static struct attribute *thermal_zone_dev_attrs[] = {
|
||||
&dev_attr_policy.attr,
|
||||
&dev_attr_available_policies.attr,
|
||||
&dev_attr_sustainable_power.attr,
|
||||
&dev_attr_passive_delay.attr,
|
||||
&dev_attr_polling_delay.attr,
|
||||
&dev_attr_k_po.attr,
|
||||
&dev_attr_k_pu.attr,
|
||||
&dev_attr_k_i.attr,
|
||||
@@ -704,7 +749,7 @@ cur_state_store(struct device *dev, struct device_attribute *attr,
|
||||
{
|
||||
struct thermal_cooling_device *cdev = to_cooling_device(dev);
|
||||
unsigned long state;
|
||||
int result;
|
||||
struct thermal_instance *instance = NULL;
|
||||
|
||||
if (sscanf(buf, "%ld\n", &state) != 1)
|
||||
return -EINVAL;
|
||||
@@ -713,13 +758,15 @@ cur_state_store(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&cdev->lock);
|
||||
instance = list_first_entry(&cdev->thermal_instances,
|
||||
typeof(*instance), cdev_node);
|
||||
instance->target = state;
|
||||
|
||||
result = cdev->ops->set_cur_state(cdev, state);
|
||||
if (!result)
|
||||
thermal_cooling_device_stats_update(cdev, state);
|
||||
|
||||
cdev->updated = false;
|
||||
mutex_unlock(&cdev->lock);
|
||||
return result ? result : count;
|
||||
thermal_cdev_update(cdev);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute
|
||||
@@ -770,6 +817,9 @@ void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
|
||||
{
|
||||
struct cooling_dev_stats *stats = cdev->stats;
|
||||
|
||||
if (!stats)
|
||||
return;
|
||||
|
||||
spin_lock(&stats->lock);
|
||||
|
||||
if (stats->state == new_state)
|
||||
@@ -791,6 +841,9 @@ static ssize_t total_trans_show(struct device *dev,
|
||||
struct cooling_dev_stats *stats = cdev->stats;
|
||||
int ret;
|
||||
|
||||
if (!stats)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock(&stats->lock);
|
||||
ret = sprintf(buf, "%u\n", stats->total_trans);
|
||||
spin_unlock(&stats->lock);
|
||||
@@ -807,6 +860,9 @@ time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
|
||||
ssize_t len = 0;
|
||||
int i;
|
||||
|
||||
if (!stats)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock(&stats->lock);
|
||||
update_time_in_state(stats);
|
||||
|
||||
@@ -825,8 +881,12 @@ reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
|
||||
{
|
||||
struct thermal_cooling_device *cdev = to_cooling_device(dev);
|
||||
struct cooling_dev_stats *stats = cdev->stats;
|
||||
int i, states = stats->max_states;
|
||||
int i, states;
|
||||
|
||||
if (!stats)
|
||||
return -ENODEV;
|
||||
|
||||
states = stats->max_states;
|
||||
spin_lock(&stats->lock);
|
||||
|
||||
stats->total_trans = 0;
|
||||
@@ -850,6 +910,9 @@ static ssize_t trans_table_show(struct device *dev,
|
||||
ssize_t len = 0;
|
||||
int i, j;
|
||||
|
||||
if (!stats)
|
||||
return -ENODEV;
|
||||
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, " : ");
|
||||
for (i = 0; i < stats->max_states; i++) {
|
||||
|
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2008 Intel Corp
|
||||
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
|
||||
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com>
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __THERMAL_H__
|
||||
@@ -26,6 +27,9 @@
|
||||
/* No upper/lower limit requirement */
|
||||
#define THERMAL_NO_LIMIT ((u32)~0)
|
||||
|
||||
/* upper limit requirement */
|
||||
#define THERMAL_MAX_LIMIT (THERMAL_NO_LIMIT - 1)
|
||||
|
||||
/* Default weight of a bound cooling device */
|
||||
#define THERMAL_WEIGHT_DEFAULT 0
|
||||
|
||||
@@ -440,6 +444,8 @@ 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_update_temp(struct thermal_zone_device *tz,
|
||||
enum thermal_notify_event event, int temp);
|
||||
void thermal_zone_set_trips(struct thermal_zone_device *);
|
||||
|
||||
struct thermal_cooling_device *thermal_cooling_device_register(const char *,
|
||||
@@ -498,6 +504,10 @@ static inline int thermal_zone_unbind_cooling_device(
|
||||
static inline void thermal_zone_device_update(struct thermal_zone_device *tz,
|
||||
enum thermal_notify_event event)
|
||||
{ }
|
||||
static inline void thermal_zone_device_update_temp(
|
||||
struct thermal_zone_device *tz, enum thermal_notify_event event,
|
||||
int temp)
|
||||
{ }
|
||||
static inline void thermal_zone_set_trips(struct thermal_zone_device *tz)
|
||||
{ }
|
||||
static inline struct thermal_cooling_device *
|
||||
|
@@ -21,6 +21,29 @@ TRACE_DEFINE_ENUM(THERMAL_TRIP_ACTIVE);
|
||||
{ THERMAL_TRIP_PASSIVE, "PASSIVE"}, \
|
||||
{ THERMAL_TRIP_ACTIVE, "ACTIVE"})
|
||||
|
||||
TRACE_EVENT(thermal_query_temp,
|
||||
|
||||
TP_PROTO(struct thermal_zone_device *tz, int temp),
|
||||
|
||||
TP_ARGS(tz, temp),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(thermal_zone, tz->type)
|
||||
__field(int, id)
|
||||
__field(int, temp)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(thermal_zone, tz->type);
|
||||
__entry->id = tz->id;
|
||||
__entry->temp = temp;
|
||||
),
|
||||
|
||||
TP_printk("thermal_zone=%s id=%d temp=%d",
|
||||
__get_str(thermal_zone), __entry->id,
|
||||
__entry->temp)
|
||||
);
|
||||
|
||||
TRACE_EVENT(thermal_temperature,
|
||||
|
||||
TP_PROTO(struct thermal_zone_device *tz),
|
||||
@@ -68,15 +91,16 @@ TRACE_EVENT(cdev_update,
|
||||
TRACE_EVENT(thermal_zone_trip,
|
||||
|
||||
TP_PROTO(struct thermal_zone_device *tz, int trip,
|
||||
enum thermal_trip_type trip_type),
|
||||
enum thermal_trip_type trip_type, bool is_trip),
|
||||
|
||||
TP_ARGS(tz, trip, trip_type),
|
||||
TP_ARGS(tz, trip, trip_type, is_trip),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(thermal_zone, tz->type)
|
||||
__field(int, id)
|
||||
__field(int, trip)
|
||||
__field(enum thermal_trip_type, trip_type)
|
||||
__field(bool, is_trip)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
@@ -84,13 +108,85 @@ TRACE_EVENT(thermal_zone_trip,
|
||||
__entry->id = tz->id;
|
||||
__entry->trip = trip;
|
||||
__entry->trip_type = trip_type;
|
||||
__entry->is_trip = is_trip;
|
||||
),
|
||||
|
||||
TP_printk("thermal_zone=%s id=%d trip=%d trip_type=%s",
|
||||
__get_str(thermal_zone), __entry->id, __entry->trip,
|
||||
TP_printk("thermal_zone=%s id=%d %s=%d trip_type=%s",
|
||||
__get_str(thermal_zone), __entry->id,
|
||||
(__entry->is_trip) ? "trip" : "hyst",
|
||||
__entry->trip,
|
||||
show_tzt_type(__entry->trip_type))
|
||||
);
|
||||
|
||||
TRACE_EVENT(thermal_handle_trip,
|
||||
|
||||
TP_PROTO(struct thermal_zone_device *tz, int trip),
|
||||
|
||||
TP_ARGS(tz, trip),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(thermal_zone, tz->type)
|
||||
__field(int, id)
|
||||
__field(int, trip)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(thermal_zone, tz->type);
|
||||
__entry->id = tz->id;
|
||||
__entry->trip = trip;
|
||||
),
|
||||
|
||||
TP_printk("thermal_zone=%s id=%d handle trip=%d",
|
||||
__get_str(thermal_zone), __entry->id, __entry->trip)
|
||||
);
|
||||
|
||||
TRACE_EVENT(thermal_device_update,
|
||||
|
||||
TP_PROTO(struct thermal_zone_device *tz, int event),
|
||||
|
||||
TP_ARGS(tz, event),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(thermal_zone, tz->type)
|
||||
__field(int, id)
|
||||
__field(int, event)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(thermal_zone, tz->type);
|
||||
__entry->id = tz->id;
|
||||
__entry->event = event;
|
||||
),
|
||||
|
||||
TP_printk("thermal_zone=%s id=%d received event:%d",
|
||||
__get_str(thermal_zone), __entry->id, __entry->event)
|
||||
);
|
||||
|
||||
TRACE_EVENT(thermal_set_trip,
|
||||
|
||||
TP_PROTO(struct thermal_zone_device *tz),
|
||||
|
||||
TP_ARGS(tz),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(thermal_zone, tz->type)
|
||||
__field(int, id)
|
||||
__field(int, low)
|
||||
__field(int, high)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(thermal_zone, tz->type);
|
||||
__entry->id = tz->id;
|
||||
__entry->low = tz->prev_low_trip;
|
||||
__entry->high = tz->prev_high_trip;
|
||||
),
|
||||
|
||||
TP_printk("thermal_zone=%s id=%d low trip=%d high trip=%d",
|
||||
__get_str(thermal_zone), __entry->id, __entry->low,
|
||||
__entry->high)
|
||||
);
|
||||
|
||||
#ifdef CONFIG_CPU_THERMAL
|
||||
TRACE_EVENT(thermal_power_cpu_get_power,
|
||||
TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load,
|
||||
|
Reference in New Issue
Block a user