Skip to content

Commit 1e4f63a

Browse files
committed
cpufreq: Avoid creating excessively large stack frames
In the process of modifying a cpufreq policy, the cpufreq core makes a copy of it including all of the internals which is stored on the CPU stack. Because struct cpufreq_policy is relatively large, this may cause the size of the stack frame to exceed the 2 KB limit and so the GCC complains when -Wframe-larger-than= is used. In fact, it is not necessary to copy the entire policy structure in order to modify it, however. First, because cpufreq_set_policy() obtains the min and max policy limits from frequency QoS now, it is not necessary to pass the limits to it from the callers. The only things that need to be passed to it from there are the new governor pointer or (if there is a built-in governor in the driver) the "policy" value representing the governor choice. They both can be passed as individual arguments, though, so make cpufreq_set_policy() take them this way and rework its callers accordingly. This avoids making copies of cpufreq policies in the callers of cpufreq_set_policy(). Second, cpufreq_set_policy() still needs to pass the new policy data to the ->verify() callback of the cpufreq driver whose task is to sanitize the min and max policy limits. It still does not need to make a full copy of struct cpufreq_policy for this purpose, but it needs to pass a few items from it to the driver in case they are needed (different drivers have different needs in that respect and all of them have to be covered). For this reason, introduce struct cpufreq_policy_data to hold copies of the members of struct cpufreq_policy used by the existing ->verify() driver callbacks and pass a pointer to a temporary structure of that type to ->verify() (instead of passing a pointer to full struct cpufreq_policy to it). While at it, notice that intel_pstate and longrun don't really need to verify the "policy" value in struct cpufreq_policy, so drop those check from them to avoid copying "policy" into struct cpufreq_policy_data (which allows it to be slightly smaller). Also while at it fix up white space in a couple of places and make cpufreq_set_policy() static (as it can be so). Fixes: 3000ce3 ("cpufreq: Use per-policy frequency QoS") Link: https://lore.kernel.org/linux-pm/CAMuHMdX6-jb1W8uC2_237m8ctCpsnGp=JCxqt8pCWVqNXHmkVg@mail.gmail.com Reported-by: kbuild test robot <[email protected]> Reported-by: Geert Uytterhoeven <[email protected]> Cc: 5.4+ <[email protected]> # 5.4+ Signed-off-by: Rafael J. Wysocki <[email protected]> Acked-by: Viresh Kumar <[email protected]>
1 parent 0a9db0a commit 1e4f63a

File tree

11 files changed

+119
-120
lines changed

11 files changed

+119
-120
lines changed

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
221221
return ret;
222222
}
223223

224-
static int cppc_verify_policy(struct cpufreq_policy *policy)
224+
static int cppc_verify_policy(struct cpufreq_policy_data *policy)
225225
{
226226
cpufreq_verify_within_cpu_limits(policy);
227227
return 0;

drivers/cpufreq/cpufreq-nforce2.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
291291
* nforce2_verify - verifies a new CPUFreq policy
292292
* @policy: new policy
293293
*/
294-
static int nforce2_verify(struct cpufreq_policy *policy)
294+
static int nforce2_verify(struct cpufreq_policy_data *policy)
295295
{
296296
unsigned int fsb_pol_max;
297297

drivers/cpufreq/cpufreq.c

Lines changed: 70 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ static void cpufreq_exit_governor(struct cpufreq_policy *policy);
7474
static int cpufreq_start_governor(struct cpufreq_policy *policy);
7575
static void cpufreq_stop_governor(struct cpufreq_policy *policy);
7676
static void cpufreq_governor_limits(struct cpufreq_policy *policy);
77+
static int cpufreq_set_policy(struct cpufreq_policy *policy,
78+
struct cpufreq_governor *new_gov,
79+
unsigned int new_pol);
7780

7881
/**
7982
* Two notifier lists: the "policy" list is involved in the
@@ -616,25 +619,22 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
616619
return NULL;
617620
}
618621

619-
static int cpufreq_parse_policy(char *str_governor,
620-
struct cpufreq_policy *policy)
622+
static unsigned int cpufreq_parse_policy(char *str_governor)
621623
{
622-
if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
623-
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
624-
return 0;
625-
}
626-
if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
627-
policy->policy = CPUFREQ_POLICY_POWERSAVE;
628-
return 0;
629-
}
630-
return -EINVAL;
624+
if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
625+
return CPUFREQ_POLICY_PERFORMANCE;
626+
627+
if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN))
628+
return CPUFREQ_POLICY_POWERSAVE;
629+
630+
return CPUFREQ_POLICY_UNKNOWN;
631631
}
632632

633633
/**
634634
* cpufreq_parse_governor - parse a governor string only for has_target()
635+
* @str_governor: Governor name.
635636
*/
636-
static int cpufreq_parse_governor(char *str_governor,
637-
struct cpufreq_policy *policy)
637+
static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
638638
{
639639
struct cpufreq_governor *t;
640640

@@ -648,7 +648,7 @@ static int cpufreq_parse_governor(char *str_governor,
648648

649649
ret = request_module("cpufreq_%s", str_governor);
650650
if (ret)
651-
return -EINVAL;
651+
return NULL;
652652

653653
mutex_lock(&cpufreq_governor_mutex);
654654

@@ -659,12 +659,7 @@ static int cpufreq_parse_governor(char *str_governor,
659659

660660
mutex_unlock(&cpufreq_governor_mutex);
661661

662-
if (t) {
663-
policy->governor = t;
664-
return 0;
665-
}
666-
667-
return -EINVAL;
662+
return t;
668663
}
669664

670665
/**
@@ -765,28 +760,33 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
765760
static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
766761
const char *buf, size_t count)
767762
{
763+
char str_governor[16];
768764
int ret;
769-
char str_governor[16];
770-
struct cpufreq_policy new_policy;
771-
772-
memcpy(&new_policy, policy, sizeof(*policy));
773765

774766
ret = sscanf(buf, "%15s", str_governor);
775767
if (ret != 1)
776768
return -EINVAL;
777769

778770
if (cpufreq_driver->setpolicy) {
779-
if (cpufreq_parse_policy(str_governor, &new_policy))
771+
unsigned int new_pol;
772+
773+
new_pol = cpufreq_parse_policy(str_governor);
774+
if (!new_pol)
780775
return -EINVAL;
776+
777+
ret = cpufreq_set_policy(policy, NULL, new_pol);
781778
} else {
782-
if (cpufreq_parse_governor(str_governor, &new_policy))
779+
struct cpufreq_governor *new_gov;
780+
781+
new_gov = cpufreq_parse_governor(str_governor);
782+
if (!new_gov)
783783
return -EINVAL;
784-
}
785784

786-
ret = cpufreq_set_policy(policy, &new_policy);
785+
ret = cpufreq_set_policy(policy, new_gov,
786+
CPUFREQ_POLICY_UNKNOWN);
787787

788-
if (new_policy.governor)
789-
module_put(new_policy.governor->owner);
788+
module_put(new_gov->owner);
789+
}
790790

791791
return ret ? ret : count;
792792
}
@@ -1053,40 +1053,33 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void)
10531053

10541054
static int cpufreq_init_policy(struct cpufreq_policy *policy)
10551055
{
1056-
struct cpufreq_governor *gov = NULL, *def_gov = NULL;
1057-
struct cpufreq_policy new_policy;
1058-
1059-
memcpy(&new_policy, policy, sizeof(*policy));
1060-
1061-
def_gov = cpufreq_default_governor();
1056+
struct cpufreq_governor *def_gov = cpufreq_default_governor();
1057+
struct cpufreq_governor *gov = NULL;
1058+
unsigned int pol = CPUFREQ_POLICY_UNKNOWN;
10621059

10631060
if (has_target()) {
1064-
/*
1065-
* Update governor of new_policy to the governor used before
1066-
* hotplug
1067-
*/
1061+
/* Update policy governor to the one used before hotplug. */
10681062
gov = find_governor(policy->last_governor);
10691063
if (gov) {
10701064
pr_debug("Restoring governor %s for cpu %d\n",
1071-
policy->governor->name, policy->cpu);
1072-
} else {
1073-
if (!def_gov)
1074-
return -ENODATA;
1065+
policy->governor->name, policy->cpu);
1066+
} else if (def_gov) {
10751067
gov = def_gov;
1068+
} else {
1069+
return -ENODATA;
10761070
}
1077-
new_policy.governor = gov;
10781071
} else {
10791072
/* Use the default policy if there is no last_policy. */
10801073
if (policy->last_policy) {
1081-
new_policy.policy = policy->last_policy;
1074+
pol = policy->last_policy;
1075+
} else if (def_gov) {
1076+
pol = cpufreq_parse_policy(def_gov->name);
10821077
} else {
1083-
if (!def_gov)
1084-
return -ENODATA;
1085-
cpufreq_parse_policy(def_gov->name, &new_policy);
1078+
return -ENODATA;
10861079
}
10871080
}
10881081

1089-
return cpufreq_set_policy(policy, &new_policy);
1082+
return cpufreq_set_policy(policy, gov, pol);
10901083
}
10911084

10921085
static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
@@ -1114,13 +1107,10 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
11141107

11151108
void refresh_frequency_limits(struct cpufreq_policy *policy)
11161109
{
1117-
struct cpufreq_policy new_policy;
1118-
11191110
if (!policy_is_inactive(policy)) {
1120-
new_policy = *policy;
11211111
pr_debug("updating policy for CPU %u\n", policy->cpu);
11221112

1123-
cpufreq_set_policy(policy, &new_policy);
1113+
cpufreq_set_policy(policy, policy->governor, policy->policy);
11241114
}
11251115
}
11261116
EXPORT_SYMBOL(refresh_frequency_limits);
@@ -2364,46 +2354,49 @@ EXPORT_SYMBOL(cpufreq_get_policy);
23642354
/**
23652355
* cpufreq_set_policy - Modify cpufreq policy parameters.
23662356
* @policy: Policy object to modify.
2367-
* @new_policy: New policy data.
2357+
* @new_gov: Policy governor pointer.
2358+
* @new_pol: Policy value (for drivers with built-in governors).
23682359
*
2369-
* Pass @new_policy to the cpufreq driver's ->verify() callback. Next, copy the
2370-
* min and max parameters of @new_policy to @policy and either invoke the
2371-
* driver's ->setpolicy() callback (if present) or carry out a governor update
2372-
* for @policy. That is, run the current governor's ->limits() callback (if the
2373-
* governor field in @new_policy points to the same object as the one in
2374-
* @policy) or replace the governor for @policy with the new one stored in
2375-
* @new_policy.
2360+
* Invoke the cpufreq driver's ->verify() callback to sanity-check the frequency
2361+
* limits to be set for the policy, update @policy with the verified limits
2362+
* values and either invoke the driver's ->setpolicy() callback (if present) or
2363+
* carry out a governor update for @policy. That is, run the current governor's
2364+
* ->limits() callback (if @new_gov points to the same object as the one in
2365+
* @policy) or replace the governor for @policy with @new_gov.
23762366
*
23772367
* The cpuinfo part of @policy is not updated by this function.
23782368
*/
2379-
int cpufreq_set_policy(struct cpufreq_policy *policy,
2380-
struct cpufreq_policy *new_policy)
2369+
static int cpufreq_set_policy(struct cpufreq_policy *policy,
2370+
struct cpufreq_governor *new_gov,
2371+
unsigned int new_pol)
23812372
{
2373+
struct cpufreq_policy_data new_data;
23822374
struct cpufreq_governor *old_gov;
23832375
int ret;
23842376

2385-
pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
2386-
new_policy->cpu, new_policy->min, new_policy->max);
2387-
2388-
memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
2389-
2377+
memcpy(&new_data.cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
2378+
new_data.freq_table = policy->freq_table;
2379+
new_data.cpu = policy->cpu;
23902380
/*
23912381
* PM QoS framework collects all the requests from users and provide us
23922382
* the final aggregated value here.
23932383
*/
2394-
new_policy->min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
2395-
new_policy->max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
2384+
new_data.min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
2385+
new_data.max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
2386+
2387+
pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
2388+
new_data.cpu, new_data.min, new_data.max);
23962389

23972390
/*
23982391
* Verify that the CPU speed can be set within these limits and make sure
23992392
* that min <= max.
24002393
*/
2401-
ret = cpufreq_driver->verify(new_policy);
2394+
ret = cpufreq_driver->verify(&new_data);
24022395
if (ret)
24032396
return ret;
24042397

2405-
policy->min = new_policy->min;
2406-
policy->max = new_policy->max;
2398+
policy->min = new_data.min;
2399+
policy->max = new_data.max;
24072400
trace_cpu_frequency_limits(policy);
24082401

24092402
policy->cached_target_freq = UINT_MAX;
@@ -2412,12 +2405,12 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
24122405
policy->min, policy->max);
24132406

24142407
if (cpufreq_driver->setpolicy) {
2415-
policy->policy = new_policy->policy;
2408+
policy->policy = new_pol;
24162409
pr_debug("setting range\n");
24172410
return cpufreq_driver->setpolicy(policy);
24182411
}
24192412

2420-
if (new_policy->governor == policy->governor) {
2413+
if (new_gov == policy->governor) {
24212414
pr_debug("governor limits update\n");
24222415
cpufreq_governor_limits(policy);
24232416
return 0;
@@ -2434,7 +2427,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
24342427
}
24352428

24362429
/* start new governor */
2437-
policy->governor = new_policy->governor;
2430+
policy->governor = new_gov;
24382431
ret = cpufreq_init_governor(policy);
24392432
if (!ret) {
24402433
ret = cpufreq_start_governor(policy);

drivers/cpufreq/freq_table.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
6060
return 0;
6161
}
6262

63-
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
63+
int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
6464
struct cpufreq_frequency_table *table)
6565
{
6666
struct cpufreq_frequency_table *pos;
@@ -100,7 +100,7 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
100100
* Generic routine to verify policy & frequency table, requires driver to set
101101
* policy->freq_table prior to it.
102102
*/
103-
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
103+
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy)
104104
{
105105
if (!policy->freq_table)
106106
return -ENODEV;

drivers/cpufreq/gx-suspmod.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ static void gx_set_cpuspeed(struct cpufreq_policy *policy, unsigned int khz)
328328
* for the hardware supported by the driver.
329329
*/
330330

331-
static int cpufreq_gx_verify(struct cpufreq_policy *policy)
331+
static int cpufreq_gx_verify(struct cpufreq_policy_data *policy)
332332
{
333333
unsigned int tmp_freq = 0;
334334
u8 tmp1, tmp2;

0 commit comments

Comments
 (0)