diff options
-rw-r--r-- | Documentation/cpu-freq/cpu-drivers.txt | 29 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 67 | ||||
-rw-r--r-- | include/linux/cpufreq.h | 25 |
3 files changed, 112 insertions, 9 deletions
diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index b045fe54986a..14f4e6336d88 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt | |||
@@ -26,6 +26,7 @@ Contents: | |||
26 | 1.4 target/target_index or setpolicy? | 26 | 1.4 target/target_index or setpolicy? |
27 | 1.5 target/target_index | 27 | 1.5 target/target_index |
28 | 1.6 setpolicy | 28 | 1.6 setpolicy |
29 | 1.7 get_intermediate and target_intermediate | ||
29 | 2. Frequency Table Helpers | 30 | 2. Frequency Table Helpers |
30 | 31 | ||
31 | 32 | ||
@@ -79,6 +80,10 @@ cpufreq_driver.attr - A pointer to a NULL-terminated list of | |||
79 | "struct freq_attr" which allow to | 80 | "struct freq_attr" which allow to |
80 | export values to sysfs. | 81 | export values to sysfs. |
81 | 82 | ||
83 | cpufreq_driver.get_intermediate | ||
84 | and target_intermediate Used to switch to stable frequency while | ||
85 | changing CPU frequency. | ||
86 | |||
82 | 87 | ||
83 | 1.2 Per-CPU Initialization | 88 | 1.2 Per-CPU Initialization |
84 | -------------------------- | 89 | -------------------------- |
@@ -151,7 +156,7 @@ Some cpufreq-capable processors switch the frequency between certain | |||
151 | limits on their own. These shall use the ->setpolicy call | 156 | limits on their own. These shall use the ->setpolicy call |
152 | 157 | ||
153 | 158 | ||
154 | 1.4. target/target_index | 159 | 1.5. target/target_index |
155 | ------------- | 160 | ------------- |
156 | 161 | ||
157 | The target_index call has two arguments: struct cpufreq_policy *policy, | 162 | The target_index call has two arguments: struct cpufreq_policy *policy, |
@@ -160,6 +165,9 @@ and unsigned int index (into the exposed frequency table). | |||
160 | The CPUfreq driver must set the new frequency when called here. The | 165 | The CPUfreq driver must set the new frequency when called here. The |
161 | actual frequency must be determined by freq_table[index].frequency. | 166 | actual frequency must be determined by freq_table[index].frequency. |
162 | 167 | ||
168 | It should always restore to earlier frequency (i.e. policy->restore_freq) in | ||
169 | case of errors, even if we switched to intermediate frequency earlier. | ||
170 | |||
163 | Deprecated: | 171 | Deprecated: |
164 | ---------- | 172 | ---------- |
165 | The target call has three arguments: struct cpufreq_policy *policy, | 173 | The target call has three arguments: struct cpufreq_policy *policy, |
@@ -179,7 +187,7 @@ Here again the frequency table helper might assist you - see section 2 | |||
179 | for details. | 187 | for details. |
180 | 188 | ||
181 | 189 | ||
182 | 1.5 setpolicy | 190 | 1.6 setpolicy |
183 | --------------- | 191 | --------------- |
184 | 192 | ||
185 | The setpolicy call only takes a struct cpufreq_policy *policy as | 193 | The setpolicy call only takes a struct cpufreq_policy *policy as |
@@ -190,6 +198,23 @@ setting when policy->policy is CPUFREQ_POLICY_PERFORMANCE, and a | |||
190 | powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check | 198 | powersaving-oriented setting when CPUFREQ_POLICY_POWERSAVE. Also check |
191 | the reference implementation in drivers/cpufreq/longrun.c | 199 | the reference implementation in drivers/cpufreq/longrun.c |
192 | 200 | ||
201 | 1.7 get_intermediate and target_intermediate | ||
202 | -------------------------------------------- | ||
203 | |||
204 | Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION unset. | ||
205 | |||
206 | get_intermediate should return a stable intermediate frequency platform wants to | ||
207 | switch to, and target_intermediate() should set CPU to to that frequency, before | ||
208 | jumping to the frequency corresponding to 'index'. Core will take care of | ||
209 | sending notifications and driver doesn't have to handle them in | ||
210 | target_intermediate() or target_index(). | ||
211 | |||
212 | Drivers can return '0' from get_intermediate() in case they don't wish to switch | ||
213 | to intermediate frequency for some target frequency. In that case core will | ||
214 | directly call ->target_index(). | ||
215 | |||
216 | NOTE: ->target_index() should restore to policy->restore_freq in case of | ||
217 | failures as core would send notifications for that. | ||
193 | 218 | ||
194 | 219 | ||
195 | 2. Frequency Table Helpers | 220 | 2. Frequency Table Helpers |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index ae11dd51f81d..aed2b0cb83dc 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -1816,20 +1816,55 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier); | |||
1816 | * GOVERNORS * | 1816 | * GOVERNORS * |
1817 | *********************************************************************/ | 1817 | *********************************************************************/ |
1818 | 1818 | ||
1819 | /* Must set freqs->new to intermediate frequency */ | ||
1820 | static int __target_intermediate(struct cpufreq_policy *policy, | ||
1821 | struct cpufreq_freqs *freqs, int index) | ||
1822 | { | ||
1823 | int ret; | ||
1824 | |||
1825 | freqs->new = cpufreq_driver->get_intermediate(policy, index); | ||
1826 | |||
1827 | /* We don't need to switch to intermediate freq */ | ||
1828 | if (!freqs->new) | ||
1829 | return 0; | ||
1830 | |||
1831 | pr_debug("%s: cpu: %d, switching to intermediate freq: oldfreq: %u, intermediate freq: %u\n", | ||
1832 | __func__, policy->cpu, freqs->old, freqs->new); | ||
1833 | |||
1834 | cpufreq_freq_transition_begin(policy, freqs); | ||
1835 | ret = cpufreq_driver->target_intermediate(policy, index); | ||
1836 | cpufreq_freq_transition_end(policy, freqs, ret); | ||
1837 | |||
1838 | if (ret) | ||
1839 | pr_err("%s: Failed to change to intermediate frequency: %d\n", | ||
1840 | __func__, ret); | ||
1841 | |||
1842 | return ret; | ||
1843 | } | ||
1844 | |||
1819 | static int __target_index(struct cpufreq_policy *policy, | 1845 | static int __target_index(struct cpufreq_policy *policy, |
1820 | struct cpufreq_frequency_table *freq_table, int index) | 1846 | struct cpufreq_frequency_table *freq_table, int index) |
1821 | { | 1847 | { |
1822 | struct cpufreq_freqs freqs; | 1848 | struct cpufreq_freqs freqs = {.old = policy->cur, .flags = 0}; |
1849 | unsigned int intermediate_freq = 0; | ||
1823 | int retval = -EINVAL; | 1850 | int retval = -EINVAL; |
1824 | bool notify; | 1851 | bool notify; |
1825 | 1852 | ||
1826 | notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION); | 1853 | notify = !(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION); |
1827 | |||
1828 | if (notify) { | 1854 | if (notify) { |
1829 | freqs.old = policy->cur; | 1855 | /* Handle switching to intermediate frequency */ |
1830 | freqs.new = freq_table[index].frequency; | 1856 | if (cpufreq_driver->get_intermediate) { |
1831 | freqs.flags = 0; | 1857 | retval = __target_intermediate(policy, &freqs, index); |
1858 | if (retval) | ||
1859 | return retval; | ||
1860 | |||
1861 | intermediate_freq = freqs.new; | ||
1862 | /* Set old freq to intermediate */ | ||
1863 | if (intermediate_freq) | ||
1864 | freqs.old = freqs.new; | ||
1865 | } | ||
1832 | 1866 | ||
1867 | freqs.new = freq_table[index].frequency; | ||
1833 | pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", | 1868 | pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n", |
1834 | __func__, policy->cpu, freqs.old, freqs.new); | 1869 | __func__, policy->cpu, freqs.old, freqs.new); |
1835 | 1870 | ||
@@ -1841,9 +1876,23 @@ static int __target_index(struct cpufreq_policy *policy, | |||
1841 | pr_err("%s: Failed to change cpu frequency: %d\n", __func__, | 1876 | pr_err("%s: Failed to change cpu frequency: %d\n", __func__, |
1842 | retval); | 1877 | retval); |
1843 | 1878 | ||
1844 | if (notify) | 1879 | if (notify) { |
1845 | cpufreq_freq_transition_end(policy, &freqs, retval); | 1880 | cpufreq_freq_transition_end(policy, &freqs, retval); |
1846 | 1881 | ||
1882 | /* | ||
1883 | * Failed after setting to intermediate freq? Driver should have | ||
1884 | * reverted back to initial frequency and so should we. Check | ||
1885 | * here for intermediate_freq instead of get_intermediate, in | ||
1886 | * case we have't switched to intermediate freq at all. | ||
1887 | */ | ||
1888 | if (unlikely(retval && intermediate_freq)) { | ||
1889 | freqs.old = intermediate_freq; | ||
1890 | freqs.new = policy->restore_freq; | ||
1891 | cpufreq_freq_transition_begin(policy, &freqs); | ||
1892 | cpufreq_freq_transition_end(policy, &freqs, 0); | ||
1893 | } | ||
1894 | } | ||
1895 | |||
1847 | return retval; | 1896 | return retval; |
1848 | } | 1897 | } |
1849 | 1898 | ||
@@ -1875,6 +1924,9 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, | |||
1875 | if (target_freq == policy->cur) | 1924 | if (target_freq == policy->cur) |
1876 | return 0; | 1925 | return 0; |
1877 | 1926 | ||
1927 | /* Save last value to restore later on errors */ | ||
1928 | policy->restore_freq = policy->cur; | ||
1929 | |||
1878 | if (cpufreq_driver->target) | 1930 | if (cpufreq_driver->target) |
1879 | retval = cpufreq_driver->target(policy, target_freq, relation); | 1931 | retval = cpufreq_driver->target(policy, target_freq, relation); |
1880 | else if (cpufreq_driver->target_index) { | 1932 | else if (cpufreq_driver->target_index) { |
@@ -2361,7 +2413,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
2361 | !(driver_data->setpolicy || driver_data->target_index || | 2413 | !(driver_data->setpolicy || driver_data->target_index || |
2362 | driver_data->target) || | 2414 | driver_data->target) || |
2363 | (driver_data->setpolicy && (driver_data->target_index || | 2415 | (driver_data->setpolicy && (driver_data->target_index || |
2364 | driver_data->target))) | 2416 | driver_data->target)) || |
2417 | (!!driver_data->get_intermediate != !!driver_data->target_intermediate)) | ||
2365 | return -EINVAL; | 2418 | return -EINVAL; |
2366 | 2419 | ||
2367 | pr_debug("trying to register driver %s\n", driver_data->name); | 2420 | pr_debug("trying to register driver %s\n", driver_data->name); |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 3f458896d45c..ec4112d257bc 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -75,6 +75,7 @@ struct cpufreq_policy { | |||
75 | unsigned int max; /* in kHz */ | 75 | unsigned int max; /* in kHz */ |
76 | unsigned int cur; /* in kHz, only needed if cpufreq | 76 | unsigned int cur; /* in kHz, only needed if cpufreq |
77 | * governors are used */ | 77 | * governors are used */ |
78 | unsigned int restore_freq; /* = policy->cur before transition */ | ||
78 | unsigned int suspend_freq; /* freq to set during suspend */ | 79 | unsigned int suspend_freq; /* freq to set during suspend */ |
79 | 80 | ||
80 | unsigned int policy; /* see above */ | 81 | unsigned int policy; /* see above */ |
@@ -221,11 +222,35 @@ struct cpufreq_driver { | |||
221 | 222 | ||
222 | /* define one out of two */ | 223 | /* define one out of two */ |
223 | int (*setpolicy) (struct cpufreq_policy *policy); | 224 | int (*setpolicy) (struct cpufreq_policy *policy); |
225 | |||
226 | /* | ||
227 | * On failure, should always restore frequency to policy->restore_freq | ||
228 | * (i.e. old freq). | ||
229 | */ | ||
224 | int (*target) (struct cpufreq_policy *policy, /* Deprecated */ | 230 | int (*target) (struct cpufreq_policy *policy, /* Deprecated */ |
225 | unsigned int target_freq, | 231 | unsigned int target_freq, |
226 | unsigned int relation); | 232 | unsigned int relation); |
227 | int (*target_index) (struct cpufreq_policy *policy, | 233 | int (*target_index) (struct cpufreq_policy *policy, |
228 | unsigned int index); | 234 | unsigned int index); |
235 | /* | ||
236 | * Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION | ||
237 | * unset. | ||
238 | * | ||
239 | * get_intermediate should return a stable intermediate frequency | ||
240 | * platform wants to switch to and target_intermediate() should set CPU | ||
241 | * to to that frequency, before jumping to the frequency corresponding | ||
242 | * to 'index'. Core will take care of sending notifications and driver | ||
243 | * doesn't have to handle them in target_intermediate() or | ||
244 | * target_index(). | ||
245 | * | ||
246 | * Drivers can return '0' from get_intermediate() in case they don't | ||
247 | * wish to switch to intermediate frequency for some target frequency. | ||
248 | * In that case core will directly call ->target_index(). | ||
249 | */ | ||
250 | unsigned int (*get_intermediate)(struct cpufreq_policy *policy, | ||
251 | unsigned int index); | ||
252 | int (*target_intermediate)(struct cpufreq_policy *policy, | ||
253 | unsigned int index); | ||
229 | 254 | ||
230 | /* should be defined, if possible */ | 255 | /* should be defined, if possible */ |
231 | unsigned int (*get) (unsigned int cpu); | 256 | unsigned int (*get) (unsigned int cpu); |