]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
thermal: core: Move lists of thermal instances to trip descriptors
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 4 Oct 2024 19:39:19 +0000 (21:39 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 22 Oct 2024 10:08:03 +0000 (12:08 +0200)
In almost all places where a thermal zone's list of thermal instances
is walked, there is a check to match a specific trip point and it is
walked in vain whenever there are no cooling devices associated with
the given trip.

To address this, store the lists of thermal instances in trip point
descriptors instead of storing them in thermal zones and adjust all
code using those lists accordingly.

No intentional functional impact.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/5522726.Sb9uPGUboI@rjwysocki.net
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
drivers/thermal/gov_bang_bang.c
drivers/thermal/gov_fair_share.c
drivers/thermal/gov_power_allocator.c
drivers/thermal/gov_step_wise.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/thermal/thermal_helpers.c

index 863e7a4272e66ff5189c16064cb79caf7eadd4cd..b887e48e8c7e676cee10bedf8c8c819ecb9c9468 100644 (file)
@@ -67,6 +67,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);
@@ -75,10 +76,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)
@@ -104,8 +103,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);
                }
        }
index ce0ea571ed67ab569e2350c82d7ef27cca71c93a..d37d57d48c389adcd2f661c6444e09e4b0bab638 100644 (file)
@@ -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
@@ -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;
@@ -116,7 +110,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);
        }
 }
 
index 1b2345a697c5a0338e7f62484356fcb23737ea03..46c81b147662c2387eb3bd20160e65460ec680d5 100644 (file)
@@ -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);
 }
 
 /**
@@ -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;
@@ -400,6 +399,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;
@@ -417,10 +417,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;
@@ -454,10 +454,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,
@@ -538,12 +538,13 @@ 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;
@@ -581,13 +582,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);
@@ -635,14 +634,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)
@@ -652,8 +652,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:
index fd5527188cf91a7e4c99a171dc5b102f9726140b..ea4bf88d37f33791297cf1f0f45148bd5f0a57dd 100644 (file)
@@ -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;
@@ -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);
 
@@ -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 = {
index 13e22fcfad184fba12767e145ce11c932859ca68..363e01e12ec1b2887d0954db0042237f68258566 100644 (file)
@@ -490,7 +490,7 @@ static void thermal_zone_device_check(struct work_struct *work)
 
 static void thermal_zone_device_init(struct thermal_zone_device *tz)
 {
-       struct thermal_instance *pos;
+       struct thermal_trip_desc *td;
 
        INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
 
@@ -498,8 +498,12 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz)
        tz->passive = 0;
        tz->prev_low_trip = -INT_MAX;
        tz->prev_high_trip = INT_MAX;
-       list_for_each_entry(pos, &tz->thermal_instances, tz_node)
-               pos->initialized = false;
+       for_each_trip_desc(tz, td) {
+               struct thermal_instance *instance;
+
+               list_for_each_entry(instance, &td->thermal_instances, trip_node)
+                       instance->initialized = false;
+       }
 }
 
 static void thermal_governor_trip_crossed(struct thermal_governor *governor,
@@ -766,12 +770,12 @@ struct thermal_zone_device *thermal_zone_get_by_id(int id)
  * Return: 0 on success, the proper error value otherwise.
  */
 static int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz,
-                                    const struct thermal_trip *trip,
+                                    struct thermal_trip *trip,
                                     struct thermal_cooling_device *cdev,
                                     struct cooling_spec *cool_spec)
 {
-       struct thermal_instance *dev;
-       struct thermal_instance *pos;
+       struct thermal_trip_desc *td = trip_to_trip_desc(trip);
+       struct thermal_instance *dev, *instance;
        bool upper_no_limit;
        int result;
 
@@ -834,13 +838,13 @@ static int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz,
                goto remove_trip_file;
 
        mutex_lock(&cdev->lock);
-       list_for_each_entry(pos, &tz->thermal_instances, tz_node)
-               if (pos->trip == trip && pos->cdev == cdev) {
+       list_for_each_entry(instance, &td->thermal_instances, trip_node)
+               if (instance->cdev == cdev) {
                        result = -EEXIST;
                        break;
                }
        if (!result) {
-               list_add_tail(&dev->tz_node, &tz->thermal_instances);
+               list_add_tail(&dev->trip_node, &td->thermal_instances);
                list_add_tail(&dev->cdev_node, &cdev->thermal_instances);
 
                thermal_governor_update_tz(tz, THERMAL_TZ_BIND_CDEV);
@@ -873,15 +877,16 @@ free_mem:
  * This function is usually called in the thermal zone device .unbind callback.
  */
 static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
-                                         const struct thermal_trip *trip,
+                                         struct thermal_trip *trip,
                                          struct thermal_cooling_device *cdev)
 {
+       struct thermal_trip_desc *td = trip_to_trip_desc(trip);
        struct thermal_instance *pos, *next;
 
        mutex_lock(&cdev->lock);
-       list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) {
-               if (pos->trip == trip && pos->cdev == cdev) {
-                       list_del(&pos->tz_node);
+       list_for_each_entry_safe(pos, next, &td->thermal_instances, trip_node) {
+               if (pos->cdev == cdev) {
+                       list_del(&pos->trip_node);
                        list_del(&pos->cdev_node);
 
                        thermal_governor_update_tz(tz, THERMAL_TZ_UNBIND_CDEV);
@@ -1462,7 +1467,6 @@ thermal_zone_device_register_with_trips(const char *type,
                }
        }
 
-       INIT_LIST_HEAD(&tz->thermal_instances);
        INIT_LIST_HEAD(&tz->node);
        ida_init(&tz->ida);
        mutex_init(&tz->lock);
@@ -1486,6 +1490,7 @@ thermal_zone_device_register_with_trips(const char *type,
        tz->num_trips = num_trips;
        for_each_trip_desc(tz, td) {
                td->trip = *trip++;
+               INIT_LIST_HEAD(&td->thermal_instances);
                /*
                 * Mark all thresholds as invalid to start with even though
                 * this only matters for the trips that start as invalid and
index a28f7198f91761a13e8f73319e5860033fc05b48..19a698bdbfba8053104ca024c4c172352aa08451 100644 (file)
@@ -31,6 +31,7 @@ struct thermal_trip_desc {
        struct thermal_trip trip;
        struct thermal_trip_attrs trip_attrs;
        struct list_head notify_list_node;
+       struct list_head thermal_instances;
        int notify_temp;
        int threshold;
 };
@@ -100,7 +101,6 @@ struct thermal_governor {
  * @tzp:       thermal zone parameters
  * @governor:  pointer to the governor for this thermal zone
  * @governor_data:     private pointer for governor data
- * @thermal_instances: list of &struct thermal_instance of this thermal zone
  * @ida:       &struct ida to generate unique id for this zone's cooling
  *             devices
  * @lock:      lock to protect thermal_instances list
@@ -133,7 +133,6 @@ struct thermal_zone_device {
        struct thermal_zone_params *tzp;
        struct thermal_governor *governor;
        void *governor_data;
-       struct list_head thermal_instances;
        struct ida ida;
        struct mutex lock;
        struct list_head node;
@@ -231,7 +230,7 @@ struct thermal_instance {
        struct device_attribute attr;
        char weight_attr_name[THERMAL_NAME_LENGTH];
        struct device_attribute weight_attr;
-       struct list_head tz_node; /* node in tz->thermal_instances */
+       struct list_head trip_node; /* node in trip->thermal_instances */
        struct list_head cdev_node; /* node in cdev->thermal_instances */
        unsigned int weight; /* The weight of the cooling device */
        bool upper_no_limit;
index dc374a7a1a659fd8472dce7c40b8e4d061b08873..403d62d3ce77ee8c866b10862ebfdffe3b4ac604 100644 (file)
@@ -43,10 +43,11 @@ static bool thermal_instance_present(struct thermal_zone_device *tz,
                                     struct thermal_cooling_device *cdev,
                                     const struct thermal_trip *trip)
 {
+       const struct thermal_trip_desc *td = trip_to_trip_desc(trip);
        struct thermal_instance *ti;
 
-       list_for_each_entry(ti, &tz->thermal_instances, tz_node) {
-               if (ti->trip == trip && ti->cdev == cdev)
+       list_for_each_entry(ti, &td->thermal_instances, trip_node) {
+               if (ti->cdev == cdev)
                        return true;
        }