Skip to content

Commit 2dcd851

Browse files
Yadwinder Singh BrarEduardo Valentin
authored andcommitted
thermal: cpu_cooling: Update always cpufreq policy with thermal constraints
Existing code updates cupfreq policy only while executing cpufreq_apply_cooling() function (i.e. when notify_device != NOTIFY_INVALID). It doesn't apply constraints when cpufreq policy update happens from any other place but it should update the cpufreq policy with thermal constraints every time when there is a cpufreq policy update, to keep state of cpufreq_cooling_device and max_feq of cpufreq policy in sync. For instance while resuming cpufreq updates cpufreq_policy and it restores default policy->usr_policy values irrespective of cooling device's cpufreq_state since notification gets missed because (notify_device == NOTIFY_INVALID). Another problem, is that userspace is able to change max_freq irrespective of cooling device's state, as notification gets missed. This patch modifies code to maintain a global cpufreq_dev_list and applies constraints of all matching cooling devices for policy's cpu when there is any policy update(ends up applying the lowest max_freq among the matching cpu cooling devices). This patch also removes redundant check (max_freq > policy->user_policy.max), as cpufreq framework takes care of user_policy constraints already where ever required, otherwise its causing an issue while increasing max_freq in normal scenerio as it restores max_freq with policy->user_policy.max which is old (smaller) value. Signed-off-by: Yadwinder Singh Brar <[email protected]> Signed-off-by: Eduardo Valentin <[email protected]>
1 parent fc14f9c commit 2dcd851

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

drivers/thermal/cpu_cooling.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,14 @@ struct cpufreq_cooling_device {
5050
unsigned int cpufreq_state;
5151
unsigned int cpufreq_val;
5252
struct cpumask allowed_cpus;
53+
struct list_head node;
5354
};
5455
static DEFINE_IDR(cpufreq_idr);
5556
static DEFINE_MUTEX(cooling_cpufreq_lock);
5657

5758
static unsigned int cpufreq_dev_count;
5859

59-
/* notify_table passes value to the CPUFREQ_ADJUST callback function. */
60-
#define NOTIFY_INVALID NULL
61-
static struct cpufreq_cooling_device *notify_device;
60+
static LIST_HEAD(cpufreq_dev_list);
6261

6362
/**
6463
* get_idr - function to get a unique id.
@@ -287,15 +286,12 @@ static int cpufreq_apply_cooling(struct cpufreq_cooling_device *cpufreq_device,
287286

288287
cpufreq_device->cpufreq_state = cooling_state;
289288
cpufreq_device->cpufreq_val = clip_freq;
290-
notify_device = cpufreq_device;
291289

292290
for_each_cpu(cpuid, mask) {
293291
if (is_cpufreq_valid(cpuid))
294292
cpufreq_update_policy(cpuid);
295293
}
296294

297-
notify_device = NOTIFY_INVALID;
298-
299295
return 0;
300296
}
301297

@@ -316,21 +312,28 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
316312
{
317313
struct cpufreq_policy *policy = data;
318314
unsigned long max_freq = 0;
315+
struct cpufreq_cooling_device *cpufreq_dev;
319316

320-
if (event != CPUFREQ_ADJUST || notify_device == NOTIFY_INVALID)
317+
if (event != CPUFREQ_ADJUST)
321318
return 0;
322319

323-
if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
324-
max_freq = notify_device->cpufreq_val;
325-
else
326-
return 0;
320+
mutex_lock(&cooling_cpufreq_lock);
321+
list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
322+
if (!cpumask_test_cpu(policy->cpu,
323+
&cpufreq_dev->allowed_cpus))
324+
continue;
325+
326+
if (!cpufreq_dev->cpufreq_val)
327+
cpufreq_dev->cpufreq_val = get_cpu_frequency(
328+
cpumask_any(&cpufreq_dev->allowed_cpus),
329+
cpufreq_dev->cpufreq_state);
327330

328-
/* Never exceed user_policy.max */
329-
if (max_freq > policy->user_policy.max)
330-
max_freq = policy->user_policy.max;
331+
max_freq = cpufreq_dev->cpufreq_val;
331332

332-
if (policy->max != max_freq)
333-
cpufreq_verify_within_limits(policy, 0, max_freq);
333+
if (policy->max != max_freq)
334+
cpufreq_verify_within_limits(policy, 0, max_freq);
335+
}
336+
mutex_unlock(&cooling_cpufreq_lock);
334337

335338
return 0;
336339
}
@@ -486,6 +489,7 @@ __cpufreq_cooling_register(struct device_node *np,
486489
cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
487490
CPUFREQ_POLICY_NOTIFIER);
488491
cpufreq_dev_count++;
492+
list_add(&cpufreq_dev->node, &cpufreq_dev_list);
489493

490494
mutex_unlock(&cooling_cpufreq_lock);
491495

@@ -549,6 +553,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
549553

550554
cpufreq_dev = cdev->devdata;
551555
mutex_lock(&cooling_cpufreq_lock);
556+
list_del(&cpufreq_dev->node);
552557
cpufreq_dev_count--;
553558

554559
/* Unregister the notifier for the last cpufreq cooling device */

0 commit comments

Comments
 (0)