diff mbox series

cpufreq: Fix per-policy boost behavior after CPU hotplug

Message ID 20240611115920.28665-1-poshao.chen@mediatek.com (mailing list archive)
State Superseded, archived
Headers show
Series cpufreq: Fix per-policy boost behavior after CPU hotplug | expand

Commit Message

PoShao Chen June 11, 2024, 11:59 a.m. UTC
This patch fixes the behavior of the cpufreq boost when the
global boost flag is toggled during CPU hotplug offline. This action
previously led to incorrect scaling_max_freq values when the CPU was
brought back online. The issue also manifested as incorrect
scaling_cur_freq under the performance governor.

For example, after the following operations, even if the global boost
is disabled, the resulting scaling_max_freq and scaling_cur_freq
will still reflect the settings of an enabled boost.

$ echo performance > /sys/devices/system/cpu/cpufreq/policy7/scaling_governor
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq
3200000
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_max_freq
3200000

$ echo 1 > /sys/devices/system/cpu/cpufreq/boost
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq
3250000
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_max_freq
3250000

$ echo 0 > /sys/devices/system/cpu/cpu7/online
$ echo 0 > /sys/devices/system/cpu/cpufreq/boost
$ echo 1 > /sys/devices/system/cpu/cpu7/online
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_cur_freq
3250000
$ cat /sys/devices/system/cpu/cpufreq/policy7/scaling_max_freq
3250000

Signed-off-by: PoShao Chen <poshao.chen@mediatek.com>
---
 drivers/cpufreq/cpufreq.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Comments

kernel test robot June 11, 2024, 9:50 p.m. UTC | #1
Hi PoShao,

kernel test robot noticed the following build errors:

[auto build test ERROR on rafael-pm/linux-next]
[also build test ERROR on rafael-pm/bleeding-edge linus/master v6.10-rc3 next-20240611]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/PoShao-Chen/cpufreq-Fix-per-policy-boost-behavior-after-CPU-hotplug/20240611-200804
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link:    https://lore.kernel.org/r/20240611115920.28665-1-poshao.chen%40mediatek.com
patch subject: [PATCH] cpufreq: Fix per-policy boost behavior after CPU hotplug
config: sh-defconfig (https://download.01.org/0day-ci/archive/20240612/202406120519.mhrkBEkJ-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240612/202406120519.mhrkBEkJ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202406120519.mhrkBEkJ-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   drivers/cpufreq/cpufreq.c: In function 'cpufreq_online':
   drivers/cpufreq/cpufreq.c:1515:41: warning: missing terminating " character
    1515 |                                 pr_info("%s: per-policy boost flag mirror the cpufreq_driver
         |                                         ^
   drivers/cpufreq/cpufreq.c:1516:48: warning: missing terminating " character
    1516 |                                         boost\n", __func__);
         |                                                ^
   drivers/cpufreq/cpufreq.c:1522:48: warning: missing terminating " character
    1522 |                                         pr_err("%s: per-policy boost flag mirror the cpufreq_driver
         |                                                ^
   drivers/cpufreq/cpufreq.c:1523:63: warning: missing terminating " character
    1523 |                                                 boost failed\n", __func__);
         |                                                               ^
>> drivers/cpufreq/cpufreq.c:3092:34: error: unterminated argument list invoking macro "pr_info"
    3092 | core_initcall(cpufreq_core_init);
         |                                  ^
>> drivers/cpufreq/cpufreq.c:1515:33: error: 'pr_info' undeclared (first use in this function); did you mean 'qc_info'?
    1515 |                                 pr_info("%s: per-policy boost flag mirror the cpufreq_driver
         |                                 ^~~~~~~
         |                                 qc_info
   drivers/cpufreq/cpufreq.c:1515:33: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/cpufreq/cpufreq.c:1515:40: error: expected ';' at end of input
    1515 |                                 pr_info("%s: per-policy boost flag mirror the cpufreq_driver
         |                                        ^
         |                                        ;
   ......
>> drivers/cpufreq/cpufreq.c:1515:33: error: expected declaration or statement at end of input
    1515 |                                 pr_info("%s: per-policy boost flag mirror the cpufreq_driver
         |                                 ^~~~~~~
>> drivers/cpufreq/cpufreq.c:1515:33: error: expected declaration or statement at end of input
>> drivers/cpufreq/cpufreq.c:1515:33: error: expected declaration or statement at end of input
>> drivers/cpufreq/cpufreq.c:1515:33: error: expected declaration or statement at end of input
>> drivers/cpufreq/cpufreq.c:1493:25: error: label 'out_destroy_policy' used but not defined
    1493 |                         goto out_destroy_policy;
         |                         ^~~~
>> drivers/cpufreq/cpufreq.c:1443:25: error: label 'out_offline_policy' used but not defined
    1443 |                         goto out_offline_policy;
         |                         ^~~~
>> drivers/cpufreq/cpufreq.c:1430:25: error: label 'out_free_policy' used but not defined
    1430 |                         goto out_free_policy;
         |                         ^~~~
>> drivers/cpufreq/cpufreq.c:1417:25: error: label 'out_exit_policy' used but not defined
    1417 |                         goto out_exit_policy;
         |                         ^~~~
>> drivers/cpufreq/cpufreq.c:1383:23: warning: unused variable 'flags' [-Wunused-variable]
    1383 |         unsigned long flags;
         |                       ^~~~~
   drivers/cpufreq/cpufreq.c: At top level:
>> drivers/cpufreq/cpufreq.c:82:21: warning: '__cpufreq_get' used but never defined
      82 | static unsigned int __cpufreq_get(struct cpufreq_policy *policy);
         |                     ^~~~~~~~~~~~~
>> drivers/cpufreq/cpufreq.c:83:12: warning: 'cpufreq_init_governor' declared 'static' but never defined [-Wunused-function]
      83 | static int cpufreq_init_governor(struct cpufreq_policy *policy);
         |            ^~~~~~~~~~~~~~~~~~~~~
>> drivers/cpufreq/cpufreq.c:84:13: warning: 'cpufreq_exit_governor' declared 'static' but never defined [-Wunused-function]
      84 | static void cpufreq_exit_governor(struct cpufreq_policy *policy);
         |             ^~~~~~~~~~~~~~~~~~~~~
>> drivers/cpufreq/cpufreq.c:85:13: warning: 'cpufreq_governor_limits' declared 'static' but never defined [-Wunused-function]
      85 | static void cpufreq_governor_limits(struct cpufreq_policy *policy);
         |             ^~~~~~~~~~~~~~~~~~~~~~~
>> drivers/cpufreq/cpufreq.c:86:12: warning: 'cpufreq_set_policy' used but never defined
      86 | static int cpufreq_set_policy(struct cpufreq_policy *policy,
         |            ^~~~~~~~~~~~~~~~~~
>> drivers/cpufreq/cpufreq.c:89:13: warning: 'cpufreq_boost_supported' used but never defined
      89 | static bool cpufreq_boost_supported(void);
         |             ^~~~~~~~~~~~~~~~~~~~~~~
>> drivers/cpufreq/cpufreq.c:1379:12: warning: 'cpufreq_online' defined but not used [-Wunused-function]
    1379 | static int cpufreq_online(unsigned int cpu)
         |            ^~~~~~~~~~~~~~
>> drivers/cpufreq/cpufreq.c:1330:13: warning: 'cpufreq_policy_free' defined but not used [-Wunused-function]
    1330 | static void cpufreq_policy_free(struct cpufreq_policy *policy)
         |             ^~~~~~~~~~~~~~~~~~~
   drivers/cpufreq/cpufreq.c:1115:12: warning: 'cpufreq_init_policy' defined but not used [-Wunused-function]
    1115 | static int cpufreq_init_policy(struct cpufreq_policy *policy)
         |            ^~~~~~~~~~~~~~~~~~~
   drivers/cpufreq/cpufreq.c:1077:12: warning: 'cpufreq_add_dev_interface' defined but not used [-Wunused-function]
    1077 | static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
         |            ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/cpufreq/cpufreq.c:1069:13: warning: 'remove_cpu_dev_symlink' defined but not used [-Wunused-function]
    1069 | static void remove_cpu_dev_symlink(struct cpufreq_policy *policy, int cpu,
         |             ^~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/cpufreq/cpufreq.c:18:
   drivers/cpufreq/cpufreq.c:634:22: warning: 'boost' defined but not used [-Wunused-variable]
     634 | define_one_global_rw(boost);
         |                      ^~~~~
   include/linux/cpufreq.h:332:30: note: in definition of macro 'define_one_global_rw'
     332 | static struct kobj_attribute _name =            \
         |                              ^~~~~
   drivers/cpufreq/cpufreq.c:69:13: warning: 'cpufreq_suspended' defined but not used [-Wunused-variable]
      69 | static bool cpufreq_suspended;
         |             ^~~~~~~~~~~~~~~~~


vim +/pr_info +3092 drivers/cpufreq/cpufreq.c

5a01f2e8f3ac13 Venkatesh Pallipadi   2007-02-05  3069  
5a01f2e8f3ac13 Venkatesh Pallipadi   2007-02-05  3070  static int __init cpufreq_core_init(void)
5a01f2e8f3ac13 Venkatesh Pallipadi   2007-02-05  3071  {
8412b4563e5910 Quentin Perret        2020-06-29  3072  	struct cpufreq_governor *gov = cpufreq_default_governor();
2744a63c1aec32 Greg Kroah-Hartman    2023-03-13  3073  	struct device *dev_root;
8412b4563e5910 Quentin Perret        2020-06-29  3074  
a7b422cda5084d Konrad Rzeszutek Wilk 2012-03-13  3075  	if (cpufreq_disabled())
a7b422cda5084d Konrad Rzeszutek Wilk 2012-03-13  3076  		return -ENODEV;
a7b422cda5084d Konrad Rzeszutek Wilk 2012-03-13  3077  
2744a63c1aec32 Greg Kroah-Hartman    2023-03-13  3078  	dev_root = bus_get_dev_root(&cpu_subsys);
2744a63c1aec32 Greg Kroah-Hartman    2023-03-13  3079  	if (dev_root) {
2744a63c1aec32 Greg Kroah-Hartman    2023-03-13  3080  		cpufreq_global_kobject = kobject_create_and_add("cpufreq", &dev_root->kobj);
2744a63c1aec32 Greg Kroah-Hartman    2023-03-13  3081  		put_device(dev_root);
2744a63c1aec32 Greg Kroah-Hartman    2023-03-13  3082  	}
8aa84ad8d6c740 Thomas Renninger      2009-07-24  3083  	BUG_ON(!cpufreq_global_kobject);
8aa84ad8d6c740 Thomas Renninger      2009-07-24  3084  
8412b4563e5910 Quentin Perret        2020-06-29  3085  	if (!strlen(default_governor))
0faf84caee63a5 Justin Stitt          2023-09-13  3086  		strscpy(default_governor, gov->name, CPUFREQ_NAME_LEN);
8412b4563e5910 Quentin Perret        2020-06-29  3087  
5a01f2e8f3ac13 Venkatesh Pallipadi   2007-02-05  3088  	return 0;
5a01f2e8f3ac13 Venkatesh Pallipadi   2007-02-05  3089  }
d82f26925599ca Len Brown             2017-02-28  3090  module_param(off, int, 0444);
8412b4563e5910 Quentin Perret        2020-06-29  3091  module_param_string(default_governor, default_governor, CPUFREQ_NAME_LEN, 0444);
5a01f2e8f3ac13 Venkatesh Pallipadi   2007-02-05 @3092  core_initcall(cpufreq_core_init);
kernel test robot June 11, 2024, 10:22 p.m. UTC | #2
Hi PoShao,

kernel test robot noticed the following build errors:

[auto build test ERROR on rafael-pm/linux-next]
[also build test ERROR on rafael-pm/bleeding-edge linus/master v6.10-rc3 next-20240611]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/PoShao-Chen/cpufreq-Fix-per-policy-boost-behavior-after-CPU-hotplug/20240611-200804
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link:    https://lore.kernel.org/r/20240611115920.28665-1-poshao.chen%40mediatek.com
patch subject: [PATCH] cpufreq: Fix per-policy boost behavior after CPU hotplug
config: riscv-defconfig (https://download.01.org/0day-ci/archive/20240612/202406120637.OfjjCrcJ-lkp@intel.com/config)
compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project 4403cdbaf01379de96f8d0d6ea4f51a085e37766)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240612/202406120637.OfjjCrcJ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202406120637.OfjjCrcJ-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

   In file included from drivers/cpufreq/cpufreq.c:23:
   In file included from include/linux/kernel_stat.h:9:
   In file included from include/linux/interrupt.h:21:
   In file included from arch/riscv/include/asm/sections.h:9:
   In file included from include/linux/mm.h:2253:
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
>> drivers/cpufreq/cpufreq.c:1515:13: warning: missing terminating '"' character [-Winvalid-pp-token]
    1515 |                                 pr_info("%s: per-policy boost flag mirror the cpufreq_driver
         |                                         ^
   drivers/cpufreq/cpufreq.c:1516:13: warning: missing terminating '"' character [-Winvalid-pp-token]
    1516 |                                         boost\n", __func__);
         |                                                ^
   drivers/cpufreq/cpufreq.c:1522:13: warning: missing terminating '"' character [-Winvalid-pp-token]
    1522 |                                         pr_err("%s: per-policy boost flag mirror the cpufreq_driver
         |                                                ^
   drivers/cpufreq/cpufreq.c:1523:21: warning: missing terminating '"' character [-Winvalid-pp-token]
    1523 |                                                 boost failed\n", __func__);
         |                                                               ^
>> drivers/cpufreq/cpufreq.c:1515:5: error: unterminated function-like macro invocation
    1515 |                                 pr_info("%s: per-policy boost flag mirror the cpufreq_driver
         |                                 ^
   include/linux/printk.h:536:9: note: macro 'pr_info' defined here
     536 | #define pr_info(fmt, ...) \
         |         ^
>> drivers/cpufreq/cpufreq.c:3092:34: error: expected '}'
    3092 | core_initcall(cpufreq_core_init);
         |                                  ^
   drivers/cpufreq/cpufreq.c:1514:65: note: to match this '{'
    1514 |                         if (policy->boost_enabled && !cpufreq_driver->boost_enabled) {
         |                                                                                      ^
>> drivers/cpufreq/cpufreq.c:3092:34: error: expected '}'
    3092 | core_initcall(cpufreq_core_init);
         |                                  ^
   drivers/cpufreq/cpufreq.c:1509:10: note: to match this '{'
    1509 |                 } else {
         |                        ^
>> drivers/cpufreq/cpufreq.c:3092:34: error: expected '}'
    3092 | core_initcall(cpufreq_core_init);
         |                                  ^
   drivers/cpufreq/cpufreq.c:1498:9: note: to match this '{'
    1498 |         } else {
         |                ^
>> drivers/cpufreq/cpufreq.c:3092:34: error: expected '}'
    3092 | core_initcall(cpufreq_core_init);
         |                                  ^
   drivers/cpufreq/cpufreq.c:1380:1: note: to match this '{'
    1380 | {
         | ^
>> drivers/cpufreq/cpufreq.c:1417:9: error: use of undeclared label 'out_exit_policy'
    1417 |                         goto out_exit_policy;
         |                              ^
>> drivers/cpufreq/cpufreq.c:1430:9: error: use of undeclared label 'out_free_policy'
    1430 |                         goto out_free_policy;
         |                              ^
>> drivers/cpufreq/cpufreq.c:1443:9: error: use of undeclared label 'out_offline_policy'
    1443 |                         goto out_offline_policy;
         |                              ^
>> drivers/cpufreq/cpufreq.c:1465:9: error: use of undeclared label 'out_destroy_policy'
    1465 |                         goto out_destroy_policy;
         |                              ^
   5 warnings and 9 errors generated.


vim +1515 drivers/cpufreq/cpufreq.c

  1378	
  1379	static int cpufreq_online(unsigned int cpu)
  1380	{
  1381		struct cpufreq_policy *policy;
  1382		bool new_policy;
  1383		unsigned long flags;
  1384		unsigned int j;
  1385		int ret;
  1386	
  1387		pr_debug("%s: bringing CPU%u online\n", __func__, cpu);
  1388	
  1389		/* Check if this CPU already has a policy to manage it */
  1390		policy = per_cpu(cpufreq_cpu_data, cpu);
  1391		if (policy) {
  1392			WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus));
  1393			if (!policy_is_inactive(policy))
  1394				return cpufreq_add_policy_cpu(policy, cpu);
  1395	
  1396			/* This is the only online CPU for the policy.  Start over. */
  1397			new_policy = false;
  1398			down_write(&policy->rwsem);
  1399			policy->cpu = cpu;
  1400			policy->governor = NULL;
  1401		} else {
  1402			new_policy = true;
  1403			policy = cpufreq_policy_alloc(cpu);
  1404			if (!policy)
  1405				return -ENOMEM;
  1406			down_write(&policy->rwsem);
  1407		}
  1408	
  1409		if (!new_policy && cpufreq_driver->online) {
  1410			/* Recover policy->cpus using related_cpus */
  1411			cpumask_copy(policy->cpus, policy->related_cpus);
  1412	
  1413			ret = cpufreq_driver->online(policy);
  1414			if (ret) {
  1415				pr_debug("%s: %d: initialization failed\n", __func__,
  1416					 __LINE__);
> 1417				goto out_exit_policy;
  1418			}
  1419		} else {
  1420			cpumask_copy(policy->cpus, cpumask_of(cpu));
  1421	
  1422			/*
  1423			 * Call driver. From then on the cpufreq must be able
  1424			 * to accept all calls to ->verify and ->setpolicy for this CPU.
  1425			 */
  1426			ret = cpufreq_driver->init(policy);
  1427			if (ret) {
  1428				pr_debug("%s: %d: initialization failed\n", __func__,
  1429					 __LINE__);
> 1430				goto out_free_policy;
  1431			}
  1432	
  1433			/* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
  1434			policy->boost_enabled = cpufreq_boost_enabled() && policy_has_boost_freq(policy);
  1435	
  1436			/*
  1437			 * The initialization has succeeded and the policy is online.
  1438			 * If there is a problem with its frequency table, take it
  1439			 * offline and drop it.
  1440			 */
  1441			ret = cpufreq_table_validate_and_sort(policy);
  1442			if (ret)
> 1443				goto out_offline_policy;
  1444	
  1445			/* related_cpus should at least include policy->cpus. */
  1446			cpumask_copy(policy->related_cpus, policy->cpus);
  1447		}
  1448	
  1449		/*
  1450		 * affected cpus must always be the one, which are online. We aren't
  1451		 * managing offline cpus here.
  1452		 */
  1453		cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
  1454	
  1455		if (new_policy) {
  1456			for_each_cpu(j, policy->related_cpus) {
  1457				per_cpu(cpufreq_cpu_data, j) = policy;
  1458				add_cpu_dev_symlink(policy, j, get_cpu_device(j));
  1459			}
  1460	
  1461			policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req),
  1462						       GFP_KERNEL);
  1463			if (!policy->min_freq_req) {
  1464				ret = -ENOMEM;
> 1465				goto out_destroy_policy;
  1466			}
  1467	
  1468			ret = freq_qos_add_request(&policy->constraints,
  1469						   policy->min_freq_req, FREQ_QOS_MIN,
  1470						   FREQ_QOS_MIN_DEFAULT_VALUE);
  1471			if (ret < 0) {
  1472				/*
  1473				 * So we don't call freq_qos_remove_request() for an
  1474				 * uninitialized request.
  1475				 */
  1476				kfree(policy->min_freq_req);
  1477				policy->min_freq_req = NULL;
  1478				goto out_destroy_policy;
  1479			}
  1480	
  1481			/*
  1482			 * This must be initialized right here to avoid calling
  1483			 * freq_qos_remove_request() on uninitialized request in case
  1484			 * of errors.
  1485			 */
  1486			policy->max_freq_req = policy->min_freq_req + 1;
  1487	
  1488			ret = freq_qos_add_request(&policy->constraints,
  1489						   policy->max_freq_req, FREQ_QOS_MAX,
  1490						   FREQ_QOS_MAX_DEFAULT_VALUE);
  1491			if (ret < 0) {
  1492				policy->max_freq_req = NULL;
  1493				goto out_destroy_policy;
  1494			}
  1495	
  1496			blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
  1497					CPUFREQ_CREATE_POLICY, policy);
  1498		} else {
  1499			/*
  1500			 * Call freq_qos_update_request() for the per-policy boost flag mirror
  1501			 * the cpufreq_driver boost during hotplug online.
  1502			 * Register an online callback if the default mirroring of the global
  1503			 * boost setting is not intended.
  1504			 */
  1505			if (!cpufreq_driver->online) {
  1506				ret = freq_qos_update_request(policy->max_freq_req, policy->max);
  1507				if (ret)
  1508					pr_err("%s: freq qos update failed\n", __func__);
  1509			} else {
  1510				/*
  1511				 * Let the per-policy boost flag mirror the cpufreq_driver
  1512				 * boost if an illegal state occurs after hotplug
  1513				 */
  1514				if (policy->boost_enabled && !cpufreq_driver->boost_enabled) {
> 1515					pr_info("%s: per-policy boost flag mirror the cpufreq_driver
  1516						boost\n", __func__);
  1517					policy->boost_enabled = cpufreq_driver->boost_enabled;
  1518					ret = cpufreq_driver->set_boost(policy,
  1519								cpufreq_driver->boost_enabled);
  1520					if (ret) {
  1521						policy->boost_enabled = !policy->boost_enabled;
  1522						pr_err("%s: per-policy boost flag mirror the cpufreq_driver
  1523							boost failed\n", __func__);
  1524					}
  1525				}
  1526			}
  1527		}
  1528	
  1529		if (cpufreq_driver->get && has_target()) {
  1530			policy->cur = cpufreq_driver->get(policy->cpu);
  1531			if (!policy->cur) {
  1532				ret = -EIO;
  1533				pr_err("%s: ->get() failed\n", __func__);
  1534				goto out_destroy_policy;
  1535			}
  1536		}
  1537	
  1538		/*
  1539		 * Sometimes boot loaders set CPU frequency to a value outside of
  1540		 * frequency table present with cpufreq core. In such cases CPU might be
  1541		 * unstable if it has to run on that frequency for long duration of time
  1542		 * and so its better to set it to a frequency which is specified in
  1543		 * freq-table. This also makes cpufreq stats inconsistent as
  1544		 * cpufreq-stats would fail to register because current frequency of CPU
  1545		 * isn't found in freq-table.
  1546		 *
  1547		 * Because we don't want this change to effect boot process badly, we go
  1548		 * for the next freq which is >= policy->cur ('cur' must be set by now,
  1549		 * otherwise we will end up setting freq to lowest of the table as 'cur'
  1550		 * is initialized to zero).
  1551		 *
  1552		 * We are passing target-freq as "policy->cur - 1" otherwise
  1553		 * __cpufreq_driver_target() would simply fail, as policy->cur will be
  1554		 * equal to target-freq.
  1555		 */
  1556		if ((cpufreq_driver->flags & CPUFREQ_NEED_INITIAL_FREQ_CHECK)
  1557		    && has_target()) {
  1558			unsigned int old_freq = policy->cur;
  1559	
  1560			/* Are we running at unknown frequency ? */
  1561			ret = cpufreq_frequency_table_get_index(policy, old_freq);
  1562			if (ret == -EINVAL) {
  1563				ret = __cpufreq_driver_target(policy, old_freq - 1,
  1564							      CPUFREQ_RELATION_L);
  1565	
  1566				/*
  1567				 * Reaching here after boot in a few seconds may not
  1568				 * mean that system will remain stable at "unknown"
  1569				 * frequency for longer duration. Hence, a BUG_ON().
  1570				 */
  1571				BUG_ON(ret);
  1572				pr_info("%s: CPU%d: Running at unlisted initial frequency: %u KHz, changing to: %u KHz\n",
  1573					__func__, policy->cpu, old_freq, policy->cur);
  1574			}
  1575		}
  1576	
  1577		if (new_policy) {
  1578			ret = cpufreq_add_dev_interface(policy);
  1579			if (ret)
  1580				goto out_destroy_policy;
  1581	
  1582			cpufreq_stats_create_table(policy);
  1583	
  1584			write_lock_irqsave(&cpufreq_driver_lock, flags);
  1585			list_add(&policy->policy_list, &cpufreq_policy_list);
  1586			write_unlock_irqrestore(&cpufreq_driver_lock, flags);
  1587	
  1588			/*
  1589			 * Register with the energy model before
  1590			 * sugov_eas_rebuild_sd() is called, which will result
  1591			 * in rebuilding of the sched domains, which should only be done
  1592			 * once the energy model is properly initialized for the policy
  1593			 * first.
  1594			 *
  1595			 * Also, this should be called before the policy is registered
  1596			 * with cooling framework.
  1597			 */
  1598			if (cpufreq_driver->register_em)
  1599				cpufreq_driver->register_em(policy);
  1600		}
  1601	
  1602		ret = cpufreq_init_policy(policy);
  1603		if (ret) {
  1604			pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n",
  1605			       __func__, cpu, ret);
  1606			goto out_destroy_policy;
  1607		}
  1608	
  1609		up_write(&policy->rwsem);
  1610	
  1611		kobject_uevent(&policy->kobj, KOBJ_ADD);
  1612	
  1613		/* Callback for handling stuff after policy is ready */
  1614		if (cpufreq_driver->ready)
  1615			cpufreq_driver->ready(policy);
  1616	
  1617		/* Register cpufreq cooling only for a new policy */
  1618		if (new_policy && cpufreq_thermal_control_enabled(cpufreq_driver))
  1619			policy->cdev = of_cpufreq_cooling_register(policy);
  1620	
  1621		pr_debug("initialization complete\n");
  1622	
  1623		return 0;
  1624	
  1625	out_destroy_policy:
  1626		for_each_cpu(j, policy->real_cpus)
  1627			remove_cpu_dev_symlink(policy, j, get_cpu_device(j));
  1628	
  1629	out_offline_policy:
  1630		if (cpufreq_driver->offline)
  1631			cpufreq_driver->offline(policy);
  1632	
  1633	out_exit_policy:
  1634		if (cpufreq_driver->exit)
  1635			cpufreq_driver->exit(policy);
  1636	
  1637	out_free_policy:
  1638		cpumask_clear(policy->cpus);
  1639		up_write(&policy->rwsem);
  1640	
  1641		cpufreq_policy_free(policy);
  1642		return ret;
  1643	}
  1644
diff mbox series

Patch

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a45aac17c20f..1f067d91a0b0 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1495,6 +1495,35 @@  static int cpufreq_online(unsigned int cpu)
 
 		blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 				CPUFREQ_CREATE_POLICY, policy);
+	} else {
+		/*
+		 * Call freq_qos_update_request() for the per-policy boost flag mirror
+		 * the cpufreq_driver boost during hotplug online.
+		 * Register an online callback if the default mirroring of the global
+		 * boost setting is not intended.
+		 */
+		if (!cpufreq_driver->online) {
+			ret = freq_qos_update_request(policy->max_freq_req, policy->max);
+			if (ret)
+				pr_err("%s: freq qos update failed\n", __func__);
+		} else {
+			/*
+			 * Let the per-policy boost flag mirror the cpufreq_driver
+			 * boost if an illegal state occurs after hotplug
+			 */
+			if (policy->boost_enabled && !cpufreq_driver->boost_enabled) {
+				pr_info("%s: per-policy boost flag mirror the cpufreq_driver
+					boost\n", __func__);
+				policy->boost_enabled = cpufreq_driver->boost_enabled;
+				ret = cpufreq_driver->set_boost(policy,
+							cpufreq_driver->boost_enabled);
+				if (ret) {
+					policy->boost_enabled = !policy->boost_enabled;
+					pr_err("%s: per-policy boost flag mirror the cpufreq_driver
+						boost failed\n", __func__);
+				}
+			}
+		}
 	}
 
 	if (cpufreq_driver->get && has_target()) {