Skip to content

Commit

Permalink
Merge tag 'thermal-6.13-rc1' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
 "These are thermal core changes, including the addition of support for
  temperature thresholds that can be set from user space, fixes related
  to thermal zone initialization, suspend/resume and exit, locking
  rework and rearrangement of the code handling thermal zone temperature
  updates.

  Specifics:

   - Add support for thermal thresholds that can be added and removed
     from user space via netlink along with a related library update
     (Daniel Lezcano)

   - Fix thermal zone initialization, suspend/resume and exit
     synchronization issues (Rafael Wysocki)

   - Rearrange locking in the thermal core to use guards (Rafael
     Wysocki)

   - Make the code handling thermal zone temperature updates use sorted
     lists of trip points to reduce the number of trip points table
     walks in the thermal core (Rafael Wysocki)

   - Fix and clean up the thermal testing facility code (Rafael Wysocki)

   - Fix a Power Allocator thermal governor issue (ZhengShaobo)"

* tag 'thermal-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (45 commits)
  thermal: testing: Initialize some variables annoteded with _free()
  thermal: testing: Use DEFINE_FREE() and __free() to simplify code
  thermal: testing: Simplify tt_get_tt_zone()
  thermal: gov_power_allocator: Granted power set to max when nobody request power
  thermal: core: Relocate thermal zone initialization routine
  thermal: core: Use trip lists for trip crossing detection
  thermal: core: Eliminate thermal_zone_trip_down()
  thermal: core: Relocate functions that update trip points
  thermal: core: Move some trip processing to thermal_trip_crossed()
  thermal: core: Pass trip descriptor to thermal_trip_crossed()
  thermal: core: Rearrange __thermal_zone_device_update()
  thermal: core: Prepare for moving trips between sorted lists
  thermal: core: Rename trip list node in struct thermal_trip_desc
  thermal: core: Build sorted lists instead of sorting them later
  thermal/lib: Fix memory leak on error in thermal_genl_auto()
  thermal: thresholds: Fix thermal lock annotation issue
  tools/thermal/thermal-engine: Take into account the thresholds API
  tools/lib/thermal: Add the threshold netlink ABI
  tools/lib/thermal: Make more generic the command encoding function
  thermal: netlink: Add the commands and the events for the thresholds
  ...
  • Loading branch information
Linus Torvalds committed Nov 19, 2024
2 parents ad52c55 + 0104dcd commit cd7fa3e
Show file tree
Hide file tree
Showing 26 changed files with 1,650 additions and 733 deletions.
1 change: 1 addition & 0 deletions drivers/thermal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ CFLAGS_thermal_core.o := -I$(src)
obj-$(CONFIG_THERMAL) += thermal_sys.o
thermal_sys-y += thermal_core.o thermal_sysfs.o
thermal_sys-y += thermal_trip.o thermal_helpers.o
thermal_sys-y += thermal_thresholds.o

# netlink interface to manage the thermal framework
thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o
Expand Down
15 changes: 6 additions & 9 deletions drivers/thermal/gov_bang_bang.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ static void bang_bang_set_instance_target(struct thermal_instance *instance,

dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);

mutex_lock(&instance->cdev->lock);
__thermal_cdev_update(instance->cdev);
mutex_unlock(&instance->cdev->lock);
thermal_cdev_update_nocheck(instance->cdev);
}

/**
Expand Down Expand Up @@ -67,6 +65,7 @@ static void bang_bang_control(struct thermal_zone_device *tz,
const struct thermal_trip *trip,
bool crossed_up)
{
const struct thermal_trip_desc *td = trip_to_trip_desc(trip);
struct thermal_instance *instance;

lockdep_assert_held(&tz->lock);
Expand All @@ -75,10 +74,8 @@ static void bang_bang_control(struct thermal_zone_device *tz,
thermal_zone_trip_id(tz, trip), trip->temperature,
tz->temperature, trip->hysteresis);

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (instance->trip == trip)
bang_bang_set_instance_target(instance, crossed_up);
}
list_for_each_entry(instance, &td->thermal_instances, trip_node)
bang_bang_set_instance_target(instance, crossed_up);
}

static void bang_bang_manage(struct thermal_zone_device *tz)
Expand All @@ -104,8 +101,8 @@ static void bang_bang_manage(struct thermal_zone_device *tz)
* to the thermal zone temperature and the trip point threshold.
*/
turn_on = tz->temperature >= td->threshold;
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (!instance->initialized && instance->trip == trip)
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
if (!instance->initialized)
bang_bang_set_instance_target(instance, turn_on);
}
}
Expand Down
20 changes: 6 additions & 14 deletions drivers/thermal/gov_fair_share.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ static int get_trip_level(struct thermal_zone_device *tz)
/**
* fair_share_throttle - throttles devices associated with the given zone
* @tz: thermal_zone_device
* @trip: trip point
* @td: trip point descriptor
* @trip_level: number of trips crossed by the zone temperature
*
* Throttling Logic: This uses three parameters to calculate the new
Expand All @@ -61,29 +61,23 @@ static int get_trip_level(struct thermal_zone_device *tz)
* new_state of cooling device = P3 * P2 * P1
*/
static void fair_share_throttle(struct thermal_zone_device *tz,
const struct thermal_trip *trip,
const struct thermal_trip_desc *td,
int trip_level)
{
struct thermal_instance *instance;
int total_weight = 0;
int nr_instances = 0;

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (instance->trip != trip)
continue;

list_for_each_entry(instance, &td->thermal_instances, trip_node) {
total_weight += instance->weight;
nr_instances++;
}

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
struct thermal_cooling_device *cdev = instance->cdev;
u64 dividend;
u32 divisor;

if (instance->trip != trip)
continue;

dividend = trip_level;
dividend *= cdev->max_state;
divisor = tz->num_trips;
Expand All @@ -95,9 +89,7 @@ static void fair_share_throttle(struct thermal_zone_device *tz,
}
instance->target = div_u64(dividend, divisor);

mutex_lock(&cdev->lock);
__thermal_cdev_update(cdev);
mutex_unlock(&cdev->lock);
thermal_cdev_update_nocheck(cdev);
}
}

Expand All @@ -116,7 +108,7 @@ static void fair_share_manage(struct thermal_zone_device *tz)
trip->type == THERMAL_TRIP_HOT)
continue;

fair_share_throttle(tz, trip, trip_level);
fair_share_throttle(tz, td, trip_level);
}
}

Expand Down
86 changes: 46 additions & 40 deletions drivers/thermal/gov_power_allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,9 @@ struct power_allocator_params {
struct power_actor *power;
};

static bool power_actor_is_valid(struct power_allocator_params *params,
struct thermal_instance *instance)
static bool power_actor_is_valid(struct thermal_instance *instance)
{
return (instance->trip == params->trip_max &&
cdev_is_power_actor(instance->cdev));
return cdev_is_power_actor(instance->cdev);
}

/**
Expand All @@ -118,13 +116,14 @@ static bool power_actor_is_valid(struct power_allocator_params *params,
static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
{
struct power_allocator_params *params = tz->governor_data;
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
struct thermal_cooling_device *cdev;
struct thermal_instance *instance;
u32 sustainable_power = 0;
u32 min_power;

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (!power_actor_is_valid(params, instance))
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
if (!power_actor_is_valid(instance))
continue;

cdev = instance->cdev;
Expand Down Expand Up @@ -323,9 +322,8 @@ power_actor_set_power(struct thermal_cooling_device *cdev,
return ret;

instance->target = clamp_val(state, instance->lower, instance->upper);
mutex_lock(&cdev->lock);
__thermal_cdev_update(cdev);
mutex_unlock(&cdev->lock);

thermal_cdev_update_nocheck(cdev);

return 0;
}
Expand Down Expand Up @@ -356,11 +354,19 @@ static void divvy_up_power(struct power_actor *power, int num_actors,
u32 extra_power = 0;
int i;

/*
* Prevent division by 0 if none of the actors request power.
*/
if (!total_req_power)
total_req_power = 1;
if (!total_req_power) {
/*
* Nobody requested anything, just give everybody
* the maximum power
*/
for (i = 0; i < num_actors; i++) {
struct power_actor *pa = &power[i];

pa->granted_power = pa->max_power;
}

return;
}

for (i = 0; i < num_actors; i++) {
struct power_actor *pa = &power[i];
Expand Down Expand Up @@ -400,6 +406,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors,
static void allocate_power(struct thermal_zone_device *tz, int control_temp)
{
struct power_allocator_params *params = tz->governor_data;
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
unsigned int num_actors = params->num_actors;
struct power_actor *power = params->power;
struct thermal_cooling_device *cdev;
Expand All @@ -417,10 +424,10 @@ static void allocate_power(struct thermal_zone_device *tz, int control_temp)
/* Clean all buffers for new power estimations */
memset(power, 0, params->buffer_size);

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
struct power_actor *pa = &power[i];

if (!power_actor_is_valid(params, instance))
if (!power_actor_is_valid(instance))
continue;

cdev = instance->cdev;
Expand Down Expand Up @@ -454,10 +461,10 @@ static void allocate_power(struct thermal_zone_device *tz, int control_temp)
power_range);

i = 0;
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
struct power_actor *pa = &power[i];

if (!power_actor_is_valid(params, instance))
if (!power_actor_is_valid(instance))
continue;

power_actor_set_power(instance->cdev, instance,
Expand Down Expand Up @@ -538,29 +545,29 @@ static void reset_pid_controller(struct power_allocator_params *params)
static void allow_maximum_power(struct thermal_zone_device *tz)
{
struct power_allocator_params *params = tz->governor_data;
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
struct thermal_cooling_device *cdev;
struct thermal_instance *instance;
u32 req_power;

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (!power_actor_is_valid(params, instance))
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
if (!power_actor_is_valid(instance))
continue;

cdev = instance->cdev;

instance->target = 0;
mutex_lock(&cdev->lock);
/*
* Call for updating the cooling devices local stats and avoid
* periods of dozen of seconds when those have not been
* maintained.
*/
cdev->ops->get_requested_power(cdev, &req_power);

if (params->update_cdevs)
__thermal_cdev_update(cdev);

mutex_unlock(&cdev->lock);
scoped_guard(cooling_dev, cdev) {
/*
* Call for updating the cooling devices local stats and
* avoid periods of dozen of seconds when those have not
* been maintained.
*/
cdev->ops->get_requested_power(cdev, &req_power);

if (params->update_cdevs)
__thermal_cdev_update(cdev);
}
}
}

Expand All @@ -581,13 +588,11 @@ static void allow_maximum_power(struct thermal_zone_device *tz)
static int check_power_actors(struct thermal_zone_device *tz,
struct power_allocator_params *params)
{
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
struct thermal_instance *instance;
int ret = 0;

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (instance->trip != params->trip_max)
continue;

list_for_each_entry(instance, &td->thermal_instances, trip_node) {
if (!cdev_is_power_actor(instance->cdev)) {
dev_warn(&tz->device, "power_allocator: %s is not a power actor\n",
instance->cdev->type);
Expand Down Expand Up @@ -635,14 +640,15 @@ static void power_allocator_update_tz(struct thermal_zone_device *tz,
enum thermal_notify_event reason)
{
struct power_allocator_params *params = tz->governor_data;
const struct thermal_trip_desc *td = trip_to_trip_desc(params->trip_max);
struct thermal_instance *instance;
int num_actors = 0;

switch (reason) {
case THERMAL_TZ_BIND_CDEV:
case THERMAL_TZ_UNBIND_CDEV:
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
if (power_actor_is_valid(params, instance))
list_for_each_entry(instance, &td->thermal_instances, trip_node)
if (power_actor_is_valid(instance))
num_actors++;

if (num_actors == params->num_actors)
Expand All @@ -652,8 +658,8 @@ static void power_allocator_update_tz(struct thermal_zone_device *tz,
break;
case THERMAL_INSTANCE_WEIGHT_CHANGED:
params->total_weight = 0;
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
if (power_actor_is_valid(params, instance))
list_for_each_entry(instance, &td->thermal_instances, trip_node)
if (power_actor_is_valid(instance))
params->total_weight += instance->weight;
break;
default:
Expand Down
22 changes: 11 additions & 11 deletions drivers/thermal/gov_step_wise.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ static unsigned long get_target_state(struct thermal_instance *instance,
}

static void thermal_zone_trip_update(struct thermal_zone_device *tz,
const struct thermal_trip *trip,
const struct thermal_trip_desc *td,
int trip_threshold)
{
const struct thermal_trip *trip = &td->trip;
enum thermal_trend trend = get_tz_trend(tz, trip);
int trip_id = thermal_zone_trip_id(tz, trip);
struct thermal_instance *instance;
Expand All @@ -82,12 +83,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
trip_id, trip->type, trip_threshold, trend, throttle);

list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
list_for_each_entry(instance, &td->thermal_instances, trip_node) {
int old_target;

if (instance->trip != trip)
continue;

old_target = instance->target;
instance->target = get_target_state(instance, trend, throttle);

Expand All @@ -99,9 +97,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,

instance->initialized = true;

mutex_lock(&instance->cdev->lock);
instance->cdev->updated = false; /* cdev needs update */
mutex_unlock(&instance->cdev->lock);
scoped_guard(cooling_dev, instance->cdev) {
instance->cdev->updated = false; /* cdev needs update */
}
}
}

Expand All @@ -127,11 +125,13 @@ static void step_wise_manage(struct thermal_zone_device *tz)
trip->type == THERMAL_TRIP_HOT)
continue;

thermal_zone_trip_update(tz, trip, td->threshold);
thermal_zone_trip_update(tz, td, td->threshold);
}

list_for_each_entry(instance, &tz->thermal_instances, tz_node)
thermal_cdev_update(instance->cdev);
for_each_trip_desc(tz, td) {
list_for_each_entry(instance, &td->thermal_instances, trip_node)
thermal_cdev_update(instance->cdev);
}
}

static struct thermal_governor thermal_gov_step_wise = {
Expand Down
Loading

0 comments on commit cd7fa3e

Please sign in to comment.