|
17 | 17 |
|
18 | 18 | static int get_trip_level(struct thermal_zone_device *tz) |
19 | 19 | { |
20 | | - const struct thermal_trip *trip, *level_trip = NULL; |
| 20 | + const struct thermal_trip_desc *level_td = NULL; |
| 21 | + const struct thermal_trip_desc *td; |
21 | 22 | int trip_level = -1; |
22 | 23 |
|
23 | | - for_each_trip(tz, trip) { |
24 | | - if (trip->temperature >= tz->temperature) |
| 24 | + for_each_trip_desc(tz, td) { |
| 25 | + if (td->threshold > tz->temperature) |
25 | 26 | continue; |
26 | 27 |
|
27 | 28 | trip_level++; |
28 | 29 |
|
29 | | - if (!level_trip || trip->temperature > level_trip->temperature) |
30 | | - level_trip = trip; |
| 30 | + if (!level_td || td->threshold > level_td->threshold) |
| 31 | + level_td = td; |
31 | 32 | } |
32 | 33 |
|
33 | 34 | /* Bail out if the temperature is not greater than any trips. */ |
34 | 35 | if (trip_level < 0) |
35 | 36 | return 0; |
36 | 37 |
|
37 | | - trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, level_trip), |
38 | | - level_trip->type); |
| 38 | + trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, &level_td->trip), |
| 39 | + level_td->trip.type); |
39 | 40 |
|
40 | 41 | return trip_level; |
41 | 42 | } |
42 | 43 |
|
43 | | -static long get_target_state(struct thermal_zone_device *tz, |
44 | | - struct thermal_cooling_device *cdev, int percentage, int level) |
45 | | -{ |
46 | | - return (long)(percentage * level * cdev->max_state) / (100 * tz->num_trips); |
47 | | -} |
48 | | - |
49 | 44 | /** |
50 | 45 | * fair_share_throttle - throttles devices associated with the given zone |
51 | 46 | * @tz: thermal_zone_device |
52 | 47 | * @trip: trip point |
| 48 | + * @trip_level: number of trips crossed by the zone temperature |
53 | 49 | * |
54 | 50 | * Throttling Logic: This uses three parameters to calculate the new |
55 | 51 | * throttle state of the cooling devices associated with the given zone. |
56 | 52 | * |
57 | 53 | * Parameters used for Throttling: |
58 | 54 | * P1. max_state: Maximum throttle state exposed by the cooling device. |
59 | | - * P2. percentage[i]/100: |
| 55 | + * P2. weight[i]/total_weight: |
60 | 56 | * How 'effective' the 'i'th device is, in cooling the given zone. |
61 | | - * P3. cur_trip_level/max_no_of_trips: |
| 57 | + * P3. trip_level/max_no_of_trips: |
62 | 58 | * This describes the extent to which the devices should be throttled. |
63 | 59 | * We do not want to throttle too much when we trip a lower temperature, |
64 | 60 | * whereas the throttling is at full swing if we trip critical levels. |
65 | | - * (Heavily assumes the trip points are in ascending order) |
66 | 61 | * new_state of cooling device = P3 * P2 * P1 |
67 | 62 | */ |
68 | | -static int fair_share_throttle(struct thermal_zone_device *tz, |
69 | | - const struct thermal_trip *trip) |
| 63 | +static void fair_share_throttle(struct thermal_zone_device *tz, |
| 64 | + const struct thermal_trip *trip, |
| 65 | + int trip_level) |
70 | 66 | { |
71 | 67 | struct thermal_instance *instance; |
72 | 68 | int total_weight = 0; |
73 | | - int total_instance = 0; |
74 | | - int cur_trip_level = get_trip_level(tz); |
75 | | - |
76 | | - lockdep_assert_held(&tz->lock); |
| 69 | + int nr_instances = 0; |
77 | 70 |
|
78 | 71 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { |
79 | 72 | if (instance->trip != trip) |
80 | 73 | continue; |
81 | 74 |
|
82 | 75 | total_weight += instance->weight; |
83 | | - total_instance++; |
| 76 | + nr_instances++; |
84 | 77 | } |
85 | 78 |
|
86 | 79 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { |
87 | | - int percentage; |
88 | 80 | struct thermal_cooling_device *cdev = instance->cdev; |
| 81 | + u64 dividend; |
| 82 | + u32 divisor; |
89 | 83 |
|
90 | 84 | if (instance->trip != trip) |
91 | 85 | continue; |
92 | 86 |
|
93 | | - if (!total_weight) |
94 | | - percentage = 100 / total_instance; |
95 | | - else |
96 | | - percentage = (instance->weight * 100) / total_weight; |
97 | | - |
98 | | - instance->target = get_target_state(tz, cdev, percentage, |
99 | | - cur_trip_level); |
| 87 | + dividend = trip_level; |
| 88 | + dividend *= cdev->max_state; |
| 89 | + divisor = tz->num_trips; |
| 90 | + if (total_weight) { |
| 91 | + dividend *= instance->weight; |
| 92 | + divisor *= total_weight; |
| 93 | + } else { |
| 94 | + divisor *= nr_instances; |
| 95 | + } |
| 96 | + instance->target = div_u64(dividend, divisor); |
100 | 97 |
|
101 | 98 | mutex_lock(&cdev->lock); |
102 | 99 | __thermal_cdev_update(cdev); |
103 | 100 | mutex_unlock(&cdev->lock); |
104 | 101 | } |
| 102 | +} |
105 | 103 |
|
106 | | - return 0; |
| 104 | +static void fair_share_manage(struct thermal_zone_device *tz) |
| 105 | +{ |
| 106 | + int trip_level = get_trip_level(tz); |
| 107 | + const struct thermal_trip_desc *td; |
| 108 | + |
| 109 | + lockdep_assert_held(&tz->lock); |
| 110 | + |
| 111 | + for_each_trip_desc(tz, td) { |
| 112 | + const struct thermal_trip *trip = &td->trip; |
| 113 | + |
| 114 | + if (trip->temperature == THERMAL_TEMP_INVALID || |
| 115 | + trip->type == THERMAL_TRIP_CRITICAL || |
| 116 | + trip->type == THERMAL_TRIP_HOT) |
| 117 | + continue; |
| 118 | + |
| 119 | + fair_share_throttle(tz, trip, trip_level); |
| 120 | + } |
107 | 121 | } |
108 | 122 |
|
109 | 123 | static struct thermal_governor thermal_gov_fair_share = { |
110 | | - .name = "fair_share", |
111 | | - .throttle = fair_share_throttle, |
| 124 | + .name = "fair_share", |
| 125 | + .manage = fair_share_manage, |
112 | 126 | }; |
113 | 127 | THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share); |
0 commit comments