4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
26 #include "pass-hotplug.h"
28 #include "core/device-notifier.h"
29 #include "core/config-parser.h"
31 #define PASS_CPU_STATS_MAX_COUNT 20
34 * is_enabled - Check the state of PASS governor
35 * @policy: instance of pass_policy structure
37 * Return true if the state of PASS is PASS_GOV_START
38 * Return false if the state of PASS is PASS_GOV_STOP
40 static bool is_enabled(struct pass_policy *policy)
45 if (policy->gov_state != PASS_GOV_START)
51 /****************************************************************************
53 * - DEVICE_NOTIFIER_PMQOS *
54 * - DEVICE_NOTIFIER_BOOTING_DONE *
55 ****************************************************************************/
56 #define PASS_LOCK "Lock"
57 #define PASS_UNLOCK "Unlock"
59 static int pass_governor_change_level_scope(struct pass_policy *policy,
60 int min_level, int max_level);
63 * FIXME: Current notifier of deviced didn't pass separate user_data parameter
64 * on callback function. So, PASS must need global pass_policy instance. This
65 * code must be modified after changing deviced's notifier feature.
67 static struct pass_policy *policy_pmqos;
70 * is_pmqos_enabled - Check state of whether to support PM_QOS for scenario
71 * @policy: instance of pass_policy structure
73 * Return true if the state of PM_QOS is supported
74 * Return false if the state of PM_QOS isn't supported
76 static bool is_pmqos_enabled(struct pass_policy *policy)
81 if (!policy->scenario.list)
84 if (policy->scenario.state != PASS_ON)
91 * is_scenario_locked - Check locked state of each scenario
92 * @policy: instance of pass_scenario structure
94 * Return true if scenario is locked and enabled
95 * Return false if scenario is unlocked or disabled
98 static bool is_scenario_locked(struct pass_scenario *scn)
103 if (!scn->locked || scn->state != PASS_ON)
109 static enum pass_state is_pmqos_locked(char *data, char *name)
116 unlock = strstr(data, PASS_UNLOCK);
119 strncpy(name, data, strlen(data) - strlen(PASS_LOCK));
122 /* Unlock scenario */
123 strncpy(name, data, strlen(data) - strlen(PASS_UNLOCK));
128 static int find_scenario_index(struct pass_scenario_policy *scenario,
133 for (index = 0; index < scenario->num_scenarios; index++)
134 if (MATCH(scenario->list[index].name, name))
141 * pass_notifier_pmqos - Callback function of DEVICE_NOTIFIER_PMQOS notifier
142 * @data: the scenario name
144 static int pass_notifier_pmqos(void *data)
146 struct pass_policy *policy = policy_pmqos;
147 struct pass_scenario_policy *scenario = &policy->scenario;
148 struct pass_scenario *scn = NULL;
149 enum pass_state locked = PASS_UNUSED;
150 char name[PASS_NAME_LEN] = {""};
151 unsigned int cpufreq_min_level = 0;
152 unsigned int cpufreq_max_level = 0;
157 if (!is_enabled(policy))
160 if (!is_pmqos_enabled(policy))
164 * Parse scenario name(data) whether to include 'Lock' or 'Unlock'
165 * string and divide correct scenario name.
167 locked = is_pmqos_locked(data, name);
168 index = find_scenario_index(scenario, name);
170 _W("Unknown scenario (%s)\n", data);
173 scn = &scenario->list[index];
175 /* Check the state of each scenario whether to support or not */
176 if (scn->state != PASS_ON) {
177 _W("cannot support '%s' scenario (support=%d)\n",
183 * Compare locked state of scenario with
184 * if state is same as existing state
186 if (scn->locked == locked) {
187 _E("'%s' scenario is already %s\n",
188 name, locked ? "Locked" : "Unlocked");
191 scenario->list[index].locked = locked;
194 scenario->list[index].locked_time = get_time_ms();
196 /* Change scaling scope according to scenario's level */
197 for (i = 0; i < scenario->num_scenarios; i++) {
198 struct pass_scenario *scn = &scenario->list[i];
200 if (is_scenario_locked(scn)) {
201 if (scn->cpufreq_min_level > cpufreq_min_level)
202 cpufreq_min_level = scn->cpufreq_min_level;
203 if (scn->cpufreq_max_level > cpufreq_max_level)
204 cpufreq_max_level = scn->cpufreq_max_level;
209 * TODO: PASS have to control busfreq/gpufreq as same as cpufreq
214 * Restore default min/max level if all scenarios hasn't locked state.
216 if (!is_scenario_locked(scn) && !count) {
217 cpufreq_min_level = policy->default_min_level;
218 cpufreq_max_level = policy->default_max_level;
222 _I("Lock '%s' scenario\n", name);
224 int64_t locked_time =
225 get_time_ms() - scenario->list[index].locked_time;
226 scenario->list[index].locked_time = 0;
228 _I("UnLock '%s' scenario (%lldms)\n", name, locked_time);
231 pass_governor_change_level_scope(policy, cpufreq_min_level,
234 /* TODO: PASS have to control busfreq/gpufreq as same as cpufreq. */
240 * pass_notifier_booting_done - Callback function of DEVICE_NOTIFIER_BOOTING_
242 * @data: NULL, this parameter isn't used
244 static int pass_notifier_booting_done(void *data)
249 /* Start PASS governor if 'pass_support' in pass.conf is true */
250 if (policy_pmqos->state == PASS_ON && policy_pmqos->governor)
251 policy_pmqos->governor->update(policy_pmqos, PASS_GOV_START);
257 * pass_notifier_init - Register notifiers and init
258 * @policy: the instance of pass_policy structure
260 static int pass_notifier_init(struct pass_policy *policy)
262 /* Register DEVICE_NOTIFIER_PMQOS */
263 register_notifier(DEVICE_NOTIFIER_PMQOS, pass_notifier_pmqos);
265 /* Register DEVICE_NOTIFIER_BOOTING_DONE */
266 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE,
267 pass_notifier_booting_done);
270 * FIXME: Current notifier of deviced didn't pass separate user_data
271 * parameter on callback function. So, PASS must need global pass_policy
272 * instance. This code must be modified after changing deviced's
275 policy_pmqos = policy;
281 * pass_notifier_exit - Un-register notifiers and exit
282 * @policy: the instance of pass_policy structure
284 static int pass_notifier_exit(struct pass_policy *policy)
286 /* Un-register DEVICE_NOTIFIER_PMQOS */
287 unregister_notifier(DEVICE_NOTIFIER_PMQOS, pass_notifier_pmqos);
289 /* Un-Register DEVICE_NOTIFIER_BOOTING_DONE */
290 unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE,
291 pass_notifier_booting_done);
296 /*****************************************************************************
298 ****************************************************************************/
301 * pass_hotplug_set_online - Change the maximum number of online cpu
303 * @policy: the instance of struct pass_policy
304 * @max_online: the maximum number of online cpu
306 static void pass_hotplug_set_online(struct pass_policy *policy,
309 struct pass_table *table = policy->pass_table;
310 struct pass_hotplug *hotplug = policy->hotplug;
314 if (!hotplug || online == hotplug->online)
317 if (online > hotplug->max_online)
318 online = hotplug->max_online;
320 if (online > hotplug->online)
323 num_online = hotplug->online;
325 for (i = 0 ; i < policy->cpufreq.num_nr_cpus; i++) {
327 set_cpu_online(hotplug->sequence[i], PASS_CPU_UP);
329 set_cpu_online(hotplug->sequence[i], PASS_CPU_DOWN);
333 _I("- CPU %4s '%d->%d'Core\n",
334 (hotplug->online > online ? "DOWN" : "UP"),
335 hotplug->online, online);
338 hotplug->online = online;
342 * pass_hotplug_stop - Stop PASS hotplug
344 * @policy: the instance of struct pass_policy
346 static void pass_hotplug_stop(struct pass_policy *policy)
348 struct pass_table *table = policy->pass_table;
349 int level = policy->max_level;
351 if (!policy->hotplug)
354 policy->hotplug->online = table[level].limit_max_cpu;
355 policy->hotplug->max_online = policy->cpufreq.num_nr_cpus;
358 static int pass_hotplug_dummy_governor(struct pass_policy *policy)
360 int level = policy->curr_level;
362 return policy->pass_table[level].limit_max_cpu;
366 * Define PASS hotplug
370 static struct pass_hotplug pass_hotplug_dummy = {
371 .name = "pass_hotplug_dummy",
372 .governor = pass_hotplug_dummy_governor,
376 * pass_get_governor - Return specific hotplug instance according to type
378 * @type: the type of PASS hotplug
380 struct pass_hotplug* pass_get_hotplug(struct pass_policy *policy,
381 enum pass_gov_type type)
385 case PASS_GOV_RADIATION:
386 return &pass_hotplug_dummy;
388 _E("Unknown hotplug type");
395 /*****************************************************************************
397 ****************************************************************************/
400 * pass_governor_change_level - Change maximum cpu frequency and number of online cpu
402 * @policy: the instance of struct pass_policy
403 * @level: the pass level
405 static int pass_governor_change_level(struct pass_policy *policy, int new_level)
407 struct pass_table *table = policy->pass_table;
408 struct pass_hotplug *hotplug = policy->hotplug;
409 int curr_level = policy->curr_level;
417 if (new_level > policy->max_level)
418 new_level = policy->max_level;
420 if (new_level < policy->min_level)
421 new_level = policy->min_level;
423 if (new_level == curr_level)
427 * Get maximum CPU frequency/the maximum number of online CPU
428 * according to PASS level.
430 limit_max_freq = table[new_level].limit_max_freq;
431 limit_max_cpu = table[new_level].limit_max_cpu;
433 policy->prev_level = policy->curr_level;
434 policy->curr_level = new_level;
436 /* Turn on/off CPUs according the maximum number of online CPU */
438 if (hotplug->max_online != limit_max_cpu)
439 hotplug->max_online = limit_max_cpu;
441 if (hotplug->governor)
442 online = hotplug->governor(policy);
446 curr_max_freq = get_cpufreq_scaling_max_freq();
447 curr_min_freq = get_cpufreq_scaling_min_freq();
449 set_cpufreq_scaling_min_freq(curr_max_freq);
451 pass_hotplug_set_online(policy, online);
453 set_cpufreq_scaling_min_freq(curr_min_freq);
456 /* Set maximum CPU frequency */
457 set_cpufreq_scaling_max_freq(limit_max_freq);
459 _I("Level %4s '%d->%d' : '%d'Hz/'%d'Core\n",
460 (curr_level > new_level ? "DOWN" : "UP"),
461 curr_level, new_level, limit_max_freq, limit_max_cpu);
467 * pass_governor_change_level_scope - Change the scope of cpufreq scaling
469 * @policy: the instance of struct pass_policy
470 * @min_level: the minimum level of cpufreq scaling
471 * @max_level: the maximum level of cpufreq scaling
473 static int pass_governor_change_level_scope(struct pass_policy *policy,
474 int min_level, int max_level)
479 if (min_level > max_level) {
480 _E("min_level(%d) have to be smaller than max_level(%d)\n",
481 min_level, max_level);
485 if (min_level == policy->min_level
486 && max_level == policy->max_level)
489 /* Change minimum/maximum level of cpufreq scaling */
490 policy->min_level = min_level;
491 policy->max_level = max_level;
493 pass_governor_change_level(policy, policy->curr_level);
499 * pass_calculate_busy_cpu - Count a number of busy cpu among NR_CPUS by using
500 * runnable_avg_sum/runnable_avg_period
502 * @policy: the instance of struct pass_policy
504 static void pass_calculate_busy_cpu(struct pass_policy *policy)
506 struct pass_cpu_stats *stats = policy->pass_cpu_stats;
507 struct pass_table *table = policy->pass_table;
508 unsigned int level = policy->curr_level;
509 unsigned int cpu_threshold = 0;
510 unsigned int busy_cpu;
511 unsigned int cur_freq;
513 unsigned int sum_load;
514 unsigned int sum_runnable_load;
515 unsigned int nr_runnings;
520 limit_max_cpu = table[level].limit_max_cpu;
522 for (i = 0; i < policy->num_pass_cpu_stats; i++) {
523 cur_freq = stats[i].freq;
524 nr_runnings = stats[i].nr_runnings;
526 stats[i].num_busy_cpu = 0;
527 stats[i].avg_load = 0;
528 stats[i].avg_runnable_load = 0;
529 stats[i].avg_thread_load = 0;
530 stats[i].avg_thread_runnable_load = 0;
534 sum_runnable_load = 0;
536 /* Calculate the number of busy cpu */
537 for (j = 0; j < policy->cpufreq.num_nr_cpus; j++) {
538 load = stats[i].load[j];
539 sum_load += stats[i].load[j];
540 sum_runnable_load += stats[i].runnable_load[j];
545 (unsigned int)(cur_freq * load)
546 / policy->cpufreq.max_freq;
548 || cpu_threshold >= policy->pass_cpu_threshold)
552 stats[i].num_busy_cpu = busy_cpu;
553 stats[i].avg_load = sum_load / limit_max_cpu;
554 stats[i].avg_runnable_load = sum_runnable_load / limit_max_cpu;
556 stats[i].avg_thread_load
557 = (sum_load * 100) / nr_runnings;
558 stats[i].avg_thread_runnable_load
559 = (sum_runnable_load * 100) / nr_runnings;
565 * pass_governor_stop - Stop PASS governor through D-Bus
567 * @policy: the instance of struct pass_policy
569 static void pass_governor_stop(struct pass_policy *policy)
571 if (!policy->governor) {
572 _E("cannot stop PASS governor");
576 if (policy->gov_state == PASS_GOV_STOP) {
577 _E("PASS governor is already inactive state");
581 /* Restore maximum cpu freq/the number of online cpu */
582 pass_governor_change_level(policy, policy->num_levels - 1);
584 pass_hotplug_stop(policy);
586 if (policy->governor->gov_timer_id) {
587 ecore_timer_del(policy->governor->gov_timer_id);
588 policy->governor->gov_timer_id = NULL;
591 /* Set PASS state as PASS_GOV_STOP */
592 policy->gov_state = PASS_GOV_STOP;
594 _I("Stop PASS governor");
598 * pass_governor_core_timer - Callback function of core timer for PASS governor
600 * @data: the instance of struct pass_policy
602 static Eina_Bool pass_governor_core_timer(void *data)
604 struct pass_policy *policy = (struct pass_policy *)data;
605 static int count = 0;
611 _E("cannot execute PASS core timer");
612 return ECORE_CALLBACK_CANCEL;
616 * Collect data related to system state
617 * - current cpu frequency
618 * - the number of nr_running
619 * - cpu load (= runnable_avg_sum * 100 / runnable_avg_period)
621 ret = get_pass_cpu_stats(policy);
623 if (count++ < PASS_CPU_STATS_MAX_COUNT)
624 return ECORE_CALLBACK_RENEW;
628 _E("cannot read 'pass_cpu_stats' sysfs entry");
629 pass_governor_stop(policy);
631 return ECORE_CALLBACK_CANCEL;
634 /* Calculate the number of busy cpu */
635 pass_calculate_busy_cpu(policy);
637 /* Determine the amount of proper resource */
638 if (policy->governor->governor) {
639 level = policy->governor->governor(policy);
641 pass_governor_change_level(policy, level);
643 _E("cannot execute governor function");
644 pass_governor_stop(policy);
645 return ECORE_CALLBACK_CANCEL;
649 * Change the period of govenor timer according to PASS level
651 if (policy->pass_table[level].gov_timeout >= PASS_MIN_GOV_TIMEOUT &&
652 (policy->governor->gov_timeout
653 != policy->pass_table[level].gov_timeout)) {
655 _I("Change the period of governor timer from %fs to %fs\n",
656 policy->governor->gov_timeout,
657 policy->pass_table[level].gov_timeout);
659 policy->governor->gov_timeout =
660 policy->pass_table[level].gov_timeout;
661 ecore_timer_interval_set(policy->governor->gov_timer_id,
662 policy->governor->gov_timeout);
663 ecore_timer_reset(policy->governor->gov_timer_id);
666 return ECORE_CALLBACK_RENEW;
670 * pass_governor_start - Start PASS governor through D-Bus
672 * @policy: the instance of struct pass_policy
674 static void pass_governor_start(struct pass_policy *policy)
676 if (!policy->governor) {
677 _E("cannot start PASS governor");
681 if (is_enabled(policy)) {
682 _E("PASS governor is already active state");
686 /* Create the core timer of PASS governor */
687 policy->governor->gov_timer_id = ecore_timer_add(
688 policy->governor->gov_timeout,
689 (Ecore_Task_Cb)pass_governor_core_timer,
691 if (!policy->governor->gov_timer_id) {
692 _E("cannot add core timer for governor");
693 pass_governor_stop(policy);
698 * Set default pass level when starting pass
699 * - default pass level according to policy->init_level
701 policy->curr_level = -1;
702 if (policy->init_level > policy->max_level)
703 policy->init_level = policy->max_level;
704 pass_governor_change_level(policy, policy->init_level);
706 /* Set PASS state as PASS_GOV_START */
707 policy->gov_state = PASS_GOV_START;
709 _I("Start PASS governor");
713 * pass_governor_init - Initialize PASS governor
715 * @policy: the instance of struct pass_policy
717 static int pass_governor_init(struct pass_policy *policy)
722 if(policy->governor->gov_timeout < 0) {
723 _E("invalid timeout value [%d]!",
724 policy->governor->gov_timeout);
725 pass_governor_stop(policy);
729 /* Set default PASS state */
730 policy->gov_state = PASS_GOV_STOP;
732 /* Initialize notifier */
733 pass_notifier_init(policy);
735 _I("Initialize PASS (Power Aware System Service)");
741 * pass_governor_exit - Exit PASS governor
743 static int pass_governor_exit(struct pass_policy *policy)
748 pass_notifier_exit(policy);
751 * Stop core timer and
752 * Restore maximum online cpu/cpu frequency
754 pass_governor_stop(policy);
756 /* Free allocated memory */
757 for (i = 0; i < policy->num_pass_cpu_stats; i++) {
758 free(policy->pass_cpu_stats[i].load);
759 free(policy->pass_cpu_stats[i].nr_running);
760 free(policy->pass_cpu_stats[i].runnable_load);
762 free(policy->pass_cpu_stats);
765 free(policy->hotplug->sequence);
767 /* Set pass_policy structure as default value */
768 policy->pass_cpu_threshold = 0;
769 policy->up_threshold = 0;
770 policy->down_threshold = 0;
772 policy->prev_level = 0;
773 policy->curr_level = 0;
774 policy->min_level = 0;
775 policy->max_level = 0;
776 policy->level_up_threshold = 0;
778 policy->pass_table = NULL;
779 policy->num_pass_cpu_stats = 0;
781 policy->governor->gov_timeout = 0;
783 policy->governor = NULL;
785 _I("Exit PASS (Power Aware System Service)");
791 * pass_governor_update - Restart/Pause PASS governor
793 * @cond: the instance of struct pass_policy
795 static int pass_governor_update(struct pass_policy *policy,
796 enum pass_gov_state state)
799 _E("cannot update PASS governor");
805 pass_governor_start(policy);
808 pass_governor_stop(policy);
811 _E("Unknown governor state");
819 * Define PASS governor
822 * - Radiation governor
824 static struct pass_governor pass_gov_step = {
826 .init = pass_governor_init,
827 .exit = pass_governor_exit,
828 .update = pass_governor_update,
830 .governor = pass_step_governor,
833 static struct pass_governor pass_gov_radiation = {
834 .name = "pass_radiation",
835 .init = pass_governor_init,
836 .exit = pass_governor_exit,
837 .update = pass_governor_update,
839 .governor = pass_radiation_governor,
843 * pass_get_governor - Return specific governor instance according to type
845 * @type: the type of PASS governor
847 struct pass_governor* pass_get_governor(struct pass_policy *policy,
848 enum pass_gov_type type)
852 return &pass_gov_step;
853 case PASS_GOV_RADIATION:
854 return &pass_gov_radiation;
856 _E("Unknown governor type");