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:
Ram Chandrasekar
2019-10-21 17:15:50 -06:00
parent 915d2b2efe
commit 50dc9bdad7
7 changed files with 404 additions and 75 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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__ */

View File

@@ -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)

View File

@@ -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++) {

View File

@@ -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 *

View File

@@ -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,