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 <[email protected]>
---
drivers/cpufreq/cpufreq.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
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()) {
--
2.18.0
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/[email protected]/config)
compiler: sh4-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240612/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
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);
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
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/[email protected]/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/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
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
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki