diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 118 |
1 files changed, 117 insertions, 1 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index d7efdfe0c12c..08ca8c9f41cd 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -352,6 +352,33 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); | |||
352 | /********************************************************************* | 352 | /********************************************************************* |
353 | * SYSFS INTERFACE * | 353 | * SYSFS INTERFACE * |
354 | *********************************************************************/ | 354 | *********************************************************************/ |
355 | ssize_t show_boost(struct kobject *kobj, | ||
356 | struct attribute *attr, char *buf) | ||
357 | { | ||
358 | return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); | ||
359 | } | ||
360 | |||
361 | static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, | ||
362 | const char *buf, size_t count) | ||
363 | { | ||
364 | int ret, enable; | ||
365 | |||
366 | ret = sscanf(buf, "%d", &enable); | ||
367 | if (ret != 1 || enable < 0 || enable > 1) | ||
368 | return -EINVAL; | ||
369 | |||
370 | if (cpufreq_boost_trigger_state(enable)) { | ||
371 | pr_err("%s: Cannot %s BOOST!\n", __func__, | ||
372 | enable ? "enable" : "disable"); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | |||
376 | pr_debug("%s: cpufreq BOOST %s\n", __func__, | ||
377 | enable ? "enabled" : "disabled"); | ||
378 | |||
379 | return count; | ||
380 | } | ||
381 | define_one_global_rw(boost); | ||
355 | 382 | ||
356 | static struct cpufreq_governor *__find_governor(const char *str_governor) | 383 | static struct cpufreq_governor *__find_governor(const char *str_governor) |
357 | { | 384 | { |
@@ -2184,6 +2211,73 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = { | |||
2184 | }; | 2211 | }; |
2185 | 2212 | ||
2186 | /********************************************************************* | 2213 | /********************************************************************* |
2214 | * BOOST * | ||
2215 | *********************************************************************/ | ||
2216 | static int cpufreq_boost_set_sw(int state) | ||
2217 | { | ||
2218 | struct cpufreq_frequency_table *freq_table; | ||
2219 | struct cpufreq_policy *policy; | ||
2220 | int ret = -EINVAL; | ||
2221 | |||
2222 | list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { | ||
2223 | freq_table = cpufreq_frequency_get_table(policy->cpu); | ||
2224 | if (freq_table) { | ||
2225 | ret = cpufreq_frequency_table_cpuinfo(policy, | ||
2226 | freq_table); | ||
2227 | if (ret) { | ||
2228 | pr_err("%s: Policy frequency update failed\n", | ||
2229 | __func__); | ||
2230 | break; | ||
2231 | } | ||
2232 | policy->user_policy.max = policy->max; | ||
2233 | __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); | ||
2234 | } | ||
2235 | } | ||
2236 | |||
2237 | return ret; | ||
2238 | } | ||
2239 | |||
2240 | int cpufreq_boost_trigger_state(int state) | ||
2241 | { | ||
2242 | unsigned long flags; | ||
2243 | int ret = 0; | ||
2244 | |||
2245 | if (cpufreq_driver->boost_enabled == state) | ||
2246 | return 0; | ||
2247 | |||
2248 | write_lock_irqsave(&cpufreq_driver_lock, flags); | ||
2249 | cpufreq_driver->boost_enabled = state; | ||
2250 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | ||
2251 | |||
2252 | ret = cpufreq_driver->set_boost(state); | ||
2253 | if (ret) { | ||
2254 | write_lock_irqsave(&cpufreq_driver_lock, flags); | ||
2255 | cpufreq_driver->boost_enabled = !state; | ||
2256 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | ||
2257 | |||
2258 | pr_err("%s: Cannot %s BOOST\n", __func__, | ||
2259 | state ? "enable" : "disable"); | ||
2260 | } | ||
2261 | |||
2262 | return ret; | ||
2263 | } | ||
2264 | |||
2265 | int cpufreq_boost_supported(void) | ||
2266 | { | ||
2267 | if (likely(cpufreq_driver)) | ||
2268 | return cpufreq_driver->boost_supported; | ||
2269 | |||
2270 | return 0; | ||
2271 | } | ||
2272 | EXPORT_SYMBOL_GPL(cpufreq_boost_supported); | ||
2273 | |||
2274 | int cpufreq_boost_enabled(void) | ||
2275 | { | ||
2276 | return cpufreq_driver->boost_enabled; | ||
2277 | } | ||
2278 | EXPORT_SYMBOL_GPL(cpufreq_boost_enabled); | ||
2279 | |||
2280 | /********************************************************************* | ||
2187 | * REGISTER / UNREGISTER CPUFREQ DRIVER * | 2281 | * REGISTER / UNREGISTER CPUFREQ DRIVER * |
2188 | *********************************************************************/ | 2282 | *********************************************************************/ |
2189 | 2283 | ||
@@ -2223,9 +2317,25 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
2223 | cpufreq_driver = driver_data; | 2317 | cpufreq_driver = driver_data; |
2224 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 2318 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
2225 | 2319 | ||
2320 | if (cpufreq_boost_supported()) { | ||
2321 | /* | ||
2322 | * Check if driver provides function to enable boost - | ||
2323 | * if not, use cpufreq_boost_set_sw as default | ||
2324 | */ | ||
2325 | if (!cpufreq_driver->set_boost) | ||
2326 | cpufreq_driver->set_boost = cpufreq_boost_set_sw; | ||
2327 | |||
2328 | ret = cpufreq_sysfs_create_file(&boost.attr); | ||
2329 | if (ret) { | ||
2330 | pr_err("%s: cannot register global BOOST sysfs file\n", | ||
2331 | __func__); | ||
2332 | goto err_null_driver; | ||
2333 | } | ||
2334 | } | ||
2335 | |||
2226 | ret = subsys_interface_register(&cpufreq_interface); | 2336 | ret = subsys_interface_register(&cpufreq_interface); |
2227 | if (ret) | 2337 | if (ret) |
2228 | goto err_null_driver; | 2338 | goto err_boost_unreg; |
2229 | 2339 | ||
2230 | if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) { | 2340 | if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) { |
2231 | int i; | 2341 | int i; |
@@ -2252,6 +2362,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
2252 | return 0; | 2362 | return 0; |
2253 | err_if_unreg: | 2363 | err_if_unreg: |
2254 | subsys_interface_unregister(&cpufreq_interface); | 2364 | subsys_interface_unregister(&cpufreq_interface); |
2365 | err_boost_unreg: | ||
2366 | if (cpufreq_boost_supported()) | ||
2367 | cpufreq_sysfs_remove_file(&boost.attr); | ||
2255 | err_null_driver: | 2368 | err_null_driver: |
2256 | write_lock_irqsave(&cpufreq_driver_lock, flags); | 2369 | write_lock_irqsave(&cpufreq_driver_lock, flags); |
2257 | cpufreq_driver = NULL; | 2370 | cpufreq_driver = NULL; |
@@ -2278,6 +2391,9 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) | |||
2278 | pr_debug("unregistering driver %s\n", driver->name); | 2391 | pr_debug("unregistering driver %s\n", driver->name); |
2279 | 2392 | ||
2280 | subsys_interface_unregister(&cpufreq_interface); | 2393 | subsys_interface_unregister(&cpufreq_interface); |
2394 | if (cpufreq_boost_supported()) | ||
2395 | cpufreq_sysfs_remove_file(&boost.attr); | ||
2396 | |||
2281 | unregister_hotcpu_notifier(&cpufreq_cpu_notifier); | 2397 | unregister_hotcpu_notifier(&cpufreq_cpu_notifier); |
2282 | 2398 | ||
2283 | down_write(&cpufreq_rwsem); | 2399 | down_write(&cpufreq_rwsem); |