aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-07-29 06:53:09 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-08-06 21:25:23 -0400
commit44139ed4943ee8ec186eea3e9072ca16d2b48133 (patch)
tree97b8a6f9415cd70669f7643b94768011dcb546f4
parent79eea44a5d7b9170d12d75c701d8c0e2d8d83c06 (diff)
cpufreq: Allow drivers to enable boost support after registering driver
In some cases it wouldn't be known at time of driver registration, if the driver needs to support boost frequencies. For example, while getting boost information from DT with opp-v2 bindings, we need to parse the bindings for all the CPUs to know if turbo/boost OPPs are supported or not. One way out to do that efficiently is to delay supporting boost mode (i.e. creating /sys/devices/system/cpu/cpufreq/boost file), until the time OPP bindings are parsed. At that point, the driver can enable boost support. This can be done at ->init(), where the frequency table is created. To do that, the driver requires few APIs from cpufreq core that let him do this. This patch provides these APIs. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/cpufreq.c68
-rw-r--r--drivers/cpufreq/freq_table.c15
-rw-r--r--include/linux/cpufreq.h12
3 files changed, 75 insertions, 20 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 76a26609d96b..e48242119d77 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2437,6 +2437,49 @@ int cpufreq_boost_supported(void)
2437} 2437}
2438EXPORT_SYMBOL_GPL(cpufreq_boost_supported); 2438EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
2439 2439
2440static int create_boost_sysfs_file(void)
2441{
2442 int ret;
2443
2444 if (!cpufreq_boost_supported())
2445 return 0;
2446
2447 /*
2448 * Check if driver provides function to enable boost -
2449 * if not, use cpufreq_boost_set_sw as default
2450 */
2451 if (!cpufreq_driver->set_boost)
2452 cpufreq_driver->set_boost = cpufreq_boost_set_sw;
2453
2454 ret = cpufreq_sysfs_create_file(&boost.attr);
2455 if (ret)
2456 pr_err("%s: cannot register global BOOST sysfs file\n",
2457 __func__);
2458
2459 return ret;
2460}
2461
2462static void remove_boost_sysfs_file(void)
2463{
2464 if (cpufreq_boost_supported())
2465 cpufreq_sysfs_remove_file(&boost.attr);
2466}
2467
2468int cpufreq_enable_boost_support(void)
2469{
2470 if (!cpufreq_driver)
2471 return -EINVAL;
2472
2473 if (cpufreq_boost_supported())
2474 return 0;
2475
2476 cpufreq_driver->boost_supported = true;
2477
2478 /* This will get removed on driver unregister */
2479 return create_boost_sysfs_file();
2480}
2481EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support);
2482
2440int cpufreq_boost_enabled(void) 2483int cpufreq_boost_enabled(void)
2441{ 2484{
2442 return cpufreq_driver->boost_enabled; 2485 return cpufreq_driver->boost_enabled;
@@ -2490,21 +2533,9 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
2490 if (driver_data->setpolicy) 2533 if (driver_data->setpolicy)
2491 driver_data->flags |= CPUFREQ_CONST_LOOPS; 2534 driver_data->flags |= CPUFREQ_CONST_LOOPS;
2492 2535
2493 if (cpufreq_boost_supported()) { 2536 ret = create_boost_sysfs_file();
2494 /* 2537 if (ret)
2495 * Check if driver provides function to enable boost - 2538 goto err_null_driver;
2496 * if not, use cpufreq_boost_set_sw as default
2497 */
2498 if (!cpufreq_driver->set_boost)
2499 cpufreq_driver->set_boost = cpufreq_boost_set_sw;
2500
2501 ret = cpufreq_sysfs_create_file(&boost.attr);
2502 if (ret) {
2503 pr_err("%s: cannot register global BOOST sysfs file\n",
2504 __func__);
2505 goto err_null_driver;
2506 }
2507 }
2508 2539
2509 ret = subsys_interface_register(&cpufreq_interface); 2540 ret = subsys_interface_register(&cpufreq_interface);
2510 if (ret) 2541 if (ret)
@@ -2528,8 +2559,7 @@ out:
2528err_if_unreg: 2559err_if_unreg:
2529 subsys_interface_unregister(&cpufreq_interface); 2560 subsys_interface_unregister(&cpufreq_interface);
2530err_boost_unreg: 2561err_boost_unreg:
2531 if (cpufreq_boost_supported()) 2562 remove_boost_sysfs_file();
2532 cpufreq_sysfs_remove_file(&boost.attr);
2533err_null_driver: 2563err_null_driver:
2534 write_lock_irqsave(&cpufreq_driver_lock, flags); 2564 write_lock_irqsave(&cpufreq_driver_lock, flags);
2535 cpufreq_driver = NULL; 2565 cpufreq_driver = NULL;
@@ -2558,9 +2588,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
2558 /* Protect against concurrent cpu hotplug */ 2588 /* Protect against concurrent cpu hotplug */
2559 get_online_cpus(); 2589 get_online_cpus();
2560 subsys_interface_unregister(&cpufreq_interface); 2590 subsys_interface_unregister(&cpufreq_interface);
2561 if (cpufreq_boost_supported()) 2591 remove_boost_sysfs_file();
2562 cpufreq_sysfs_remove_file(&boost.attr);
2563
2564 unregister_hotcpu_notifier(&cpufreq_cpu_notifier); 2592 unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
2565 2593
2566 write_lock_irqsave(&cpufreq_driver_lock, flags); 2594 write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index dfbbf981ed56..a8f1daffc9bc 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -18,6 +18,21 @@
18 * FREQUENCY TABLE HELPERS * 18 * FREQUENCY TABLE HELPERS *
19 *********************************************************************/ 19 *********************************************************************/
20 20
21bool policy_has_boost_freq(struct cpufreq_policy *policy)
22{
23 struct cpufreq_frequency_table *pos, *table = policy->freq_table;
24
25 if (!table)
26 return false;
27
28 cpufreq_for_each_valid_entry(pos, table)
29 if (pos->flags & CPUFREQ_BOOST_FREQ)
30 return true;
31
32 return false;
33}
34EXPORT_SYMBOL_GPL(policy_has_boost_freq);
35
21int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 36int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
22 struct cpufreq_frequency_table *table) 37 struct cpufreq_frequency_table *table)
23{ 38{
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index bde1e567b3a9..95f018649abf 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -578,6 +578,8 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
578int cpufreq_boost_trigger_state(int state); 578int cpufreq_boost_trigger_state(int state);
579int cpufreq_boost_supported(void); 579int cpufreq_boost_supported(void);
580int cpufreq_boost_enabled(void); 580int cpufreq_boost_enabled(void);
581int cpufreq_enable_boost_support(void);
582bool policy_has_boost_freq(struct cpufreq_policy *policy);
581#else 583#else
582static inline int cpufreq_boost_trigger_state(int state) 584static inline int cpufreq_boost_trigger_state(int state)
583{ 585{
@@ -591,6 +593,16 @@ static inline int cpufreq_boost_enabled(void)
591{ 593{
592 return 0; 594 return 0;
593} 595}
596
597static inline int cpufreq_enable_boost_support(void)
598{
599 return -EINVAL;
600}
601
602static inline bool policy_has_boost_freq(struct cpufreq_policy *policy)
603{
604 return false;
605}
594#endif 606#endif
595/* the following funtion is for cpufreq core use only */ 607/* the following funtion is for cpufreq core use only */
596struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu); 608struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);