Skip to content

Commit 5ee22fa

Browse files
committed
Merge branch 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm
Pull ARM cpufreq updates for 5.17-rc1 from Viresh Kumar: "- Qcom cpufreq driver updates improve irq support (Ard Biesheuvel, Stephen Boyd, and Vladimir Zapolskiy). - Fixes double devm_remap for mediatek driver (Hector Yuan). - Introduces thermal pressure helpers (Lukasz Luba)." * 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: cpufreq: mediatek-hw: Fix double devm_remap in hotplug case cpufreq: qcom-hw: Use optional irq API cpufreq: qcom-hw: Set CPU affinity of dcvsh interrupts cpufreq: qcom-hw: Fix probable nested interrupt handling cpufreq: qcom-cpufreq-hw: Avoid stack buffer for IRQ name arch_topology: Remove unused topology_set_thermal_pressure() and related cpufreq: qcom-cpufreq-hw: Use new thermal pressure update function cpufreq: qcom-cpufreq-hw: Update offline CPUs per-cpu thermal pressure thermal: cpufreq_cooling: Use new thermal pressure update function arch_topology: Introduce thermal pressure update function
2 parents fe262d5 + d776790 commit 5ee22fa

File tree

9 files changed

+96
-40
lines changed

9 files changed

+96
-40
lines changed

arch/arm/include/asm/topology.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/* Replace task scheduler's default thermal pressure API */
2525
#define arch_scale_thermal_pressure topology_get_thermal_pressure
26-
#define arch_set_thermal_pressure topology_set_thermal_pressure
26+
#define arch_update_thermal_pressure topology_update_thermal_pressure
2727

2828
#else
2929

arch/arm64/include/asm/topology.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ void update_freq_counters_refs(void);
3232

3333
/* Replace task scheduler's default thermal pressure API */
3434
#define arch_scale_thermal_pressure topology_get_thermal_pressure
35-
#define arch_set_thermal_pressure topology_set_thermal_pressure
35+
#define arch_update_thermal_pressure topology_update_thermal_pressure
3636

3737
#include <asm-generic/topology.h>
3838

drivers/base/arch_topology.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
static DEFINE_PER_CPU(struct scale_freq_data __rcu *, sft_data);
2323
static struct cpumask scale_freq_counters_mask;
2424
static bool scale_freq_invariant;
25+
static DEFINE_PER_CPU(u32, freq_factor) = 1;
2526

2627
static bool supports_scale_freq_counters(const struct cpumask *cpus)
2728
{
@@ -155,15 +156,49 @@ void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity)
155156

156157
DEFINE_PER_CPU(unsigned long, thermal_pressure);
157158

158-
void topology_set_thermal_pressure(const struct cpumask *cpus,
159-
unsigned long th_pressure)
159+
/**
160+
* topology_update_thermal_pressure() - Update thermal pressure for CPUs
161+
* @cpus : The related CPUs for which capacity has been reduced
162+
* @capped_freq : The maximum allowed frequency that CPUs can run at
163+
*
164+
* Update the value of thermal pressure for all @cpus in the mask. The
165+
* cpumask should include all (online+offline) affected CPUs, to avoid
166+
* operating on stale data when hot-plug is used for some CPUs. The
167+
* @capped_freq reflects the currently allowed max CPUs frequency due to
168+
* thermal capping. It might be also a boost frequency value, which is bigger
169+
* than the internal 'freq_factor' max frequency. In such case the pressure
170+
* value should simply be removed, since this is an indication that there is
171+
* no thermal throttling. The @capped_freq must be provided in kHz.
172+
*/
173+
void topology_update_thermal_pressure(const struct cpumask *cpus,
174+
unsigned long capped_freq)
160175
{
176+
unsigned long max_capacity, capacity, th_pressure;
177+
u32 max_freq;
161178
int cpu;
162179

180+
cpu = cpumask_first(cpus);
181+
max_capacity = arch_scale_cpu_capacity(cpu);
182+
max_freq = per_cpu(freq_factor, cpu);
183+
184+
/* Convert to MHz scale which is used in 'freq_factor' */
185+
capped_freq /= 1000;
186+
187+
/*
188+
* Handle properly the boost frequencies, which should simply clean
189+
* the thermal pressure value.
190+
*/
191+
if (max_freq <= capped_freq)
192+
capacity = max_capacity;
193+
else
194+
capacity = mult_frac(max_capacity, capped_freq, max_freq);
195+
196+
th_pressure = max_capacity - capacity;
197+
163198
for_each_cpu(cpu, cpus)
164199
WRITE_ONCE(per_cpu(thermal_pressure, cpu), th_pressure);
165200
}
166-
EXPORT_SYMBOL_GPL(topology_set_thermal_pressure);
201+
EXPORT_SYMBOL_GPL(topology_update_thermal_pressure);
167202

168203
static ssize_t cpu_capacity_show(struct device *dev,
169204
struct device_attribute *attr,
@@ -217,7 +252,6 @@ static void update_topology_flags_workfn(struct work_struct *work)
217252
update_topology = 0;
218253
}
219254

220-
static DEFINE_PER_CPU(u32, freq_factor) = 1;
221255
static u32 *raw_capacity;
222256

223257
static int free_raw_capacity(void)

drivers/cpufreq/mediatek-cpufreq-hw.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ enum {
3636
struct mtk_cpufreq_data {
3737
struct cpufreq_frequency_table *table;
3838
void __iomem *reg_bases[REG_ARRAY_SIZE];
39+
struct resource *res;
40+
void __iomem *base;
3941
int nr_opp;
4042
};
4143

@@ -156,6 +158,7 @@ static int mtk_cpu_resources_init(struct platform_device *pdev,
156158
{
157159
struct mtk_cpufreq_data *data;
158160
struct device *dev = &pdev->dev;
161+
struct resource *res;
159162
void __iomem *base;
160163
int ret, i;
161164
int index;
@@ -170,9 +173,26 @@ static int mtk_cpu_resources_init(struct platform_device *pdev,
170173
if (index < 0)
171174
return index;
172175

173-
base = devm_platform_ioremap_resource(pdev, index);
174-
if (IS_ERR(base))
175-
return PTR_ERR(base);
176+
res = platform_get_resource(pdev, IORESOURCE_MEM, index);
177+
if (!res) {
178+
dev_err(dev, "failed to get mem resource %d\n", index);
179+
return -ENODEV;
180+
}
181+
182+
if (!request_mem_region(res->start, resource_size(res), res->name)) {
183+
dev_err(dev, "failed to request resource %pR\n", res);
184+
return -EBUSY;
185+
}
186+
187+
base = ioremap(res->start, resource_size(res));
188+
if (!base) {
189+
dev_err(dev, "failed to map resource %pR\n", res);
190+
ret = -ENOMEM;
191+
goto release_region;
192+
}
193+
194+
data->base = base;
195+
data->res = res;
176196

177197
for (i = REG_FREQ_LUT_TABLE; i < REG_ARRAY_SIZE; i++)
178198
data->reg_bases[i] = base + offsets[i];
@@ -187,6 +207,9 @@ static int mtk_cpu_resources_init(struct platform_device *pdev,
187207
policy->driver_data = data;
188208

189209
return 0;
210+
release_region:
211+
release_mem_region(res->start, resource_size(res));
212+
return ret;
190213
}
191214

192215
static int mtk_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
@@ -233,9 +256,13 @@ static int mtk_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
233256
static int mtk_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
234257
{
235258
struct mtk_cpufreq_data *data = policy->driver_data;
259+
struct resource *res = data->res;
260+
void __iomem *base = data->base;
236261

237262
/* HW should be in paused state now */
238263
writel_relaxed(0x0, data->reg_bases[REG_FREQ_ENABLE]);
264+
iounmap(base);
265+
release_mem_region(res->start, resource_size(res));
239266

240267
return 0;
241268
}

drivers/cpufreq/qcom-cpufreq-hw.c

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct qcom_cpufreq_data {
4646
*/
4747
struct mutex throttle_lock;
4848
int throttle_irq;
49+
char irq_name[15];
4950
bool cancel_throttle;
5051
struct delayed_work throttle_work;
5152
struct cpufreq_policy *policy;
@@ -275,10 +276,10 @@ static unsigned int qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
275276

276277
static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
277278
{
278-
unsigned long max_capacity, capacity, freq_hz, throttled_freq;
279279
struct cpufreq_policy *policy = data->policy;
280280
int cpu = cpumask_first(policy->cpus);
281281
struct device *dev = get_cpu_device(cpu);
282+
unsigned long freq_hz, throttled_freq;
282283
struct dev_pm_opp *opp;
283284
unsigned int freq;
284285

@@ -295,16 +296,8 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
295296

296297
throttled_freq = freq_hz / HZ_PER_KHZ;
297298

298-
/* Update thermal pressure */
299-
300-
max_capacity = arch_scale_cpu_capacity(cpu);
301-
capacity = mult_frac(max_capacity, throttled_freq, policy->cpuinfo.max_freq);
302-
303-
/* Don't pass boost capacity to scheduler */
304-
if (capacity > max_capacity)
305-
capacity = max_capacity;
306-
307-
arch_set_thermal_pressure(policy->cpus, max_capacity - capacity);
299+
/* Update thermal pressure (the boost frequencies are accepted) */
300+
arch_update_thermal_pressure(policy->related_cpus, throttled_freq);
308301

309302
/*
310303
* In the unlikely case policy is unregistered do not enable
@@ -342,9 +335,9 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data)
342335

343336
/* Disable interrupt and enable polling */
344337
disable_irq_nosync(c_data->throttle_irq);
345-
qcom_lmh_dcvs_notify(c_data);
338+
schedule_delayed_work(&c_data->throttle_work, 0);
346339

347-
return 0;
340+
return IRQ_HANDLED;
348341
}
349342

350343
static const struct qcom_cpufreq_soc_data qcom_soc_data = {
@@ -375,31 +368,37 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
375368
{
376369
struct qcom_cpufreq_data *data = policy->driver_data;
377370
struct platform_device *pdev = cpufreq_get_driver_data();
378-
char irq_name[15];
379371
int ret;
380372

381373
/*
382374
* Look for LMh interrupt. If no interrupt line is specified /
383375
* if there is an error, allow cpufreq to be enabled as usual.
384376
*/
385-
data->throttle_irq = platform_get_irq(pdev, index);
386-
if (data->throttle_irq <= 0)
387-
return data->throttle_irq == -EPROBE_DEFER ? -EPROBE_DEFER : 0;
377+
data->throttle_irq = platform_get_irq_optional(pdev, index);
378+
if (data->throttle_irq == -ENXIO)
379+
return 0;
380+
if (data->throttle_irq < 0)
381+
return data->throttle_irq;
388382

389383
data->cancel_throttle = false;
390384
data->policy = policy;
391385

392386
mutex_init(&data->throttle_lock);
393387
INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll);
394388

395-
snprintf(irq_name, sizeof(irq_name), "dcvsh-irq-%u", policy->cpu);
389+
snprintf(data->irq_name, sizeof(data->irq_name), "dcvsh-irq-%u", policy->cpu);
396390
ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq,
397-
IRQF_ONESHOT, irq_name, data);
391+
IRQF_ONESHOT, data->irq_name, data);
398392
if (ret) {
399-
dev_err(&pdev->dev, "Error registering %s: %d\n", irq_name, ret);
393+
dev_err(&pdev->dev, "Error registering %s: %d\n", data->irq_name, ret);
400394
return 0;
401395
}
402396

397+
ret = irq_set_affinity_hint(data->throttle_irq, policy->cpus);
398+
if (ret)
399+
dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n",
400+
data->irq_name, data->throttle_irq);
401+
403402
return 0;
404403
}
405404

drivers/thermal/cpufreq_cooling.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
462462
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
463463
struct cpumask *cpus;
464464
unsigned int frequency;
465-
unsigned long max_capacity, capacity;
466465
int ret;
467466

468467
/* Request state should be less than max_level */
@@ -479,10 +478,7 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
479478
if (ret >= 0) {
480479
cpufreq_cdev->cpufreq_state = state;
481480
cpus = cpufreq_cdev->policy->related_cpus;
482-
max_capacity = arch_scale_cpu_capacity(cpumask_first(cpus));
483-
capacity = frequency * max_capacity;
484-
capacity /= cpufreq_cdev->policy->cpuinfo.max_freq;
485-
arch_set_thermal_pressure(cpus, max_capacity - capacity);
481+
arch_update_thermal_pressure(cpus, frequency);
486482
ret = 0;
487483
}
488484

include/linux/arch_topology.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ static inline unsigned long topology_get_thermal_pressure(int cpu)
5656
return per_cpu(thermal_pressure, cpu);
5757
}
5858

59-
void topology_set_thermal_pressure(const struct cpumask *cpus,
60-
unsigned long th_pressure);
59+
void topology_update_thermal_pressure(const struct cpumask *cpus,
60+
unsigned long capped_freq);
6161

6262
struct cpu_topology {
6363
int thread_id;

include/linux/sched/topology.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,10 @@ unsigned long arch_scale_thermal_pressure(int cpu)
266266
}
267267
#endif
268268

269-
#ifndef arch_set_thermal_pressure
269+
#ifndef arch_update_thermal_pressure
270270
static __always_inline
271-
void arch_set_thermal_pressure(const struct cpumask *cpus,
272-
unsigned long th_pressure)
271+
void arch_update_thermal_pressure(const struct cpumask *cpus,
272+
unsigned long capped_frequency)
273273
{ }
274274
#endif
275275

init/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ config SCHED_THERMAL_PRESSURE
550550
i.e. put less load on throttled CPUs than on non/less throttled ones.
551551

552552
This requires the architecture to implement
553-
arch_set_thermal_pressure() and arch_scale_thermal_pressure().
553+
arch_update_thermal_pressure() and arch_scale_thermal_pressure().
554554

555555
config BSD_PROCESS_ACCT
556556
bool "BSD Process Accounting"

0 commit comments

Comments
 (0)