History

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).

Rafael J. Wysocki committed 6 years ago

Commit 1e4f63a1 parent 0a9db0a11 files · +119 −120Browse files

Showing the changes to include/linux (1 of 11 files). Show all

Unified · Split

include/linux/cpufreq.h+23−9
@@ -148,6 +148,20 @@ struct cpufreq_policy { · 147 unmodified lines
148148 struct notifier_block nb_max;
149149 };
150150
151+/*
152+ * Used for passing new cpufreq policy data to the cpufreq driver's ->verify()
153+ * callback for sanitization. That callback is only expected to modify the min
154+ * and max values, if necessary, and specifically it must not update the
155+ * frequency table.
156+ */
157+struct cpufreq_policy_data {
158+ struct cpufreq_cpuinfo cpuinfo;
159+ struct cpufreq_frequency_table *freq_table;
160+ unsigned int cpu;
161+ unsigned int min; /* in kHz */
162+ unsigned int max; /* in kHz */
163+};
164+
151165 struct cpufreq_freqs {
152166 struct cpufreq_policy *policy;
153167 unsigned int old;
@@ -201,8 +215,6 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); · 47 unmodified lines
201215 struct cpufreq_policy *cpufreq_cpu_acquire(unsigned int cpu);
202216 void cpufreq_cpu_release(struct cpufreq_policy *policy);
203217 int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
204−int cpufreq_set_policy(struct cpufreq_policy *policy,
205− struct cpufreq_policy *new_policy);
206218 void refresh_frequency_limits(struct cpufreq_policy *policy);
207219 void cpufreq_update_policy(unsigned int cpu);
208220 void cpufreq_update_limits(unsigned int cpu);
@@ -284,7 +296,7 @@ struct cpufreq_driver { · 75 unmodified lines
284296
285297 /* needed by all drivers */
286298 int (*init)(struct cpufreq_policy *policy);
287− int (*verify)(struct cpufreq_policy *policy);
299+ int (*verify)(struct cpufreq_policy_data *policy);
288300
289301 /* define one out of two */
290302 int (*setpolicy)(struct cpufreq_policy *policy);
@@ -415,8 +427,9 @@ static inline int cpufreq_thermal_control_enabled(struct cpufreq_driver *drv) · 124 unmodified lines
415427 (drv->flags & CPUFREQ_IS_COOLING_DEV);
416428 }
417429
418−static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
419− unsigned int min, unsigned int max)
430+static inline void cpufreq_verify_within_limits(struct cpufreq_policy_data *policy,
431+ unsigned int min,
432+ unsigned int max)
420433 {
421434 if (policy->min < min)
422435 policy->min = min;
@@ -432,10 +445,10 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, · 9 unmodified lines
432445 }
433446
434447 static inline void
435−cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
448+cpufreq_verify_within_cpu_limits(struct cpufreq_policy_data *policy)
436449 {
437450 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
438− policy->cpuinfo.max_freq);
451+ policy->cpuinfo.max_freq);
439452 }
440453
441454 #ifdef CONFIG_CPU_FREQ
@@ -513,6 +526,7 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, · 71 unmodified lines
513526 * CPUFREQ GOVERNORS *
514527 *********************************************************************/
515528
529+#define CPUFREQ_POLICY_UNKNOWN (0)
516530 /*
517531 * If (cpufreq_driver->target) exists, the ->governor decides what frequency
518532 * within the limits is used. If (cpufreq_driver->setpolicy> exists, these
@@ -684,9 +698,9 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev, · 165 unmodified lines
684698 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
685699 struct cpufreq_frequency_table *table);
686700
687−int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
701+int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
688702 struct cpufreq_frequency_table *table);
689−int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
703+int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy);
690704
691705 int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
692706 unsigned int target_freq,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t