Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Viresh Kumar and committed by
Rafael J. Wysocki
44139ed4 79eea44a

+75 -20
+48 -20
drivers/cpufreq/cpufreq.c
··· 2437 2437 } 2438 2438 EXPORT_SYMBOL_GPL(cpufreq_boost_supported); 2439 2439 2440 + static 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 + 2462 + static void remove_boost_sysfs_file(void) 2463 + { 2464 + if (cpufreq_boost_supported()) 2465 + cpufreq_sysfs_remove_file(&boost.attr); 2466 + } 2467 + 2468 + int 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 + } 2481 + EXPORT_SYMBOL_GPL(cpufreq_enable_boost_support); 2482 + 2440 2483 int cpufreq_boost_enabled(void) 2441 2484 { 2442 2485 return cpufreq_driver->boost_enabled; ··· 2533 2490 if (driver_data->setpolicy) 2534 2491 driver_data->flags |= CPUFREQ_CONST_LOOPS; 2535 2492 2536 - if (cpufreq_boost_supported()) { 2537 - /* 2538 - * Check if driver provides function to enable boost - 2539 - * if not, use cpufreq_boost_set_sw as default 2540 - */ 2541 - if (!cpufreq_driver->set_boost) 2542 - cpufreq_driver->set_boost = cpufreq_boost_set_sw; 2543 - 2544 - ret = cpufreq_sysfs_create_file(&boost.attr); 2545 - if (ret) { 2546 - pr_err("%s: cannot register global BOOST sysfs file\n", 2547 - __func__); 2548 - goto err_null_driver; 2549 - } 2550 - } 2493 + ret = create_boost_sysfs_file(); 2494 + if (ret) 2495 + goto err_null_driver; 2551 2496 2552 2497 ret = subsys_interface_register(&cpufreq_interface); 2553 2498 if (ret) ··· 2559 2528 err_if_unreg: 2560 2529 subsys_interface_unregister(&cpufreq_interface); 2561 2530 err_boost_unreg: 2562 - if (cpufreq_boost_supported()) 2563 - cpufreq_sysfs_remove_file(&boost.attr); 2531 + remove_boost_sysfs_file(); 2564 2532 err_null_driver: 2565 2533 write_lock_irqsave(&cpufreq_driver_lock, flags); 2566 2534 cpufreq_driver = NULL; ··· 2588 2558 /* Protect against concurrent cpu hotplug */ 2589 2559 get_online_cpus(); 2590 2560 subsys_interface_unregister(&cpufreq_interface); 2591 - if (cpufreq_boost_supported()) 2592 - cpufreq_sysfs_remove_file(&boost.attr); 2593 - 2561 + remove_boost_sysfs_file(); 2594 2562 unregister_hotcpu_notifier(&cpufreq_cpu_notifier); 2595 2563 2596 2564 write_lock_irqsave(&cpufreq_driver_lock, flags);
+15
drivers/cpufreq/freq_table.c
··· 18 18 * FREQUENCY TABLE HELPERS * 19 19 *********************************************************************/ 20 20 21 + bool 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 + } 34 + EXPORT_SYMBOL_GPL(policy_has_boost_freq); 35 + 21 36 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 22 37 struct cpufreq_frequency_table *table) 23 38 {
+12
include/linux/cpufreq.h
··· 578 578 int cpufreq_boost_trigger_state(int state); 579 579 int cpufreq_boost_supported(void); 580 580 int cpufreq_boost_enabled(void); 581 + int cpufreq_enable_boost_support(void); 582 + bool policy_has_boost_freq(struct cpufreq_policy *policy); 581 583 #else 582 584 static inline int cpufreq_boost_trigger_state(int state) 583 585 { ··· 592 590 static inline int cpufreq_boost_enabled(void) 593 591 { 594 592 return 0; 593 + } 594 + 595 + static inline int cpufreq_enable_boost_support(void) 596 + { 597 + return -EINVAL; 598 + } 599 + 600 + static inline bool policy_has_boost_freq(struct cpufreq_policy *policy) 601 + { 602 + return false; 595 603 } 596 604 #endif 597 605 /* the following funtion is for cpufreq core use only */