Merge tag 'riscv-for-linus-5.13-mw0' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / thermal / gov_power_allocator.c
index 92acae53df49b67f41d7f73f1c5d5c877c2a9b31..13e375751d22960bac61bb381bbad7bd761f7087 100644 (file)
@@ -301,9 +301,8 @@ power_actor_set_power(struct thermal_cooling_device *cdev,
 
        instance->target = clamp_val(state, instance->lower, instance->upper);
        mutex_lock(&cdev->lock);
-       cdev->updated = false;
+       __thermal_cdev_update(cdev);
        mutex_unlock(&cdev->lock);
-       thermal_cdev_update(cdev);
 
        return 0;
 }
@@ -374,9 +373,11 @@ static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
         */
        extra_power = min(extra_power, capped_extra_power);
        if (capped_extra_power > 0)
-               for (i = 0; i < num_actors; i++)
-                       granted_power[i] += (extra_actor_power[i] *
-                                       extra_power) / capped_extra_power;
+               for (i = 0; i < num_actors; i++) {
+                       u64 extra_range = (u64)extra_actor_power[i] * extra_power;
+                       granted_power[i] += DIV_ROUND_CLOSEST_ULL(extra_range,
+                                                        capped_extra_power);
+               }
 }
 
 static int allocate_power(struct thermal_zone_device *tz,
@@ -569,22 +570,33 @@ static void reset_pid_controller(struct power_allocator_params *params)
        params->prev_err = 0;
 }
 
-static void allow_maximum_power(struct thermal_zone_device *tz)
+static void allow_maximum_power(struct thermal_zone_device *tz, bool update)
 {
        struct thermal_instance *instance;
        struct power_allocator_params *params = tz->governor_data;
+       u32 req_power;
 
        mutex_lock(&tz->lock);
        list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               struct thermal_cooling_device *cdev = instance->cdev;
+
                if ((instance->trip != params->trip_max_desired_temperature) ||
                    (!cdev_is_power_actor(instance->cdev)))
                        continue;
 
                instance->target = 0;
                mutex_lock(&instance->cdev->lock);
-               instance->cdev->updated = false;
+               /*
+                * 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 (update)
+                       __thermal_cdev_update(instance->cdev);
+
                mutex_unlock(&instance->cdev->lock);
-               thermal_cdev_update(instance->cdev);
        }
        mutex_unlock(&tz->lock);
 }
@@ -698,6 +710,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
        int ret;
        int switch_on_temp, control_temp;
        struct power_allocator_params *params = tz->governor_data;
+       bool update;
 
        /*
         * We get called for every trip point but we only need to do
@@ -709,9 +722,10 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
        ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
                                     &switch_on_temp);
        if (!ret && (tz->temperature < switch_on_temp)) {
+               update = (tz->last_temperature >= switch_on_temp);
                tz->passive = 0;
                reset_pid_controller(params);
-               allow_maximum_power(tz);
+               allow_maximum_power(tz, update);
                return 0;
        }