tizen 2.3 release
[framework/system/deviced.git] / src / pass / pass-core.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #include <stdbool.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/time.h>
23
24 #include "pass.h"
25 #include "pass-gov.h"
26 #include "pass-hotplug.h"
27
28 #include "core/device-notifier.h"
29 #include "core/config-parser.h"
30
31 #define PASS_CPU_STATS_MAX_COUNT        20
32
33 /*
34  * is_enabled - Check the state of PASS governor
35  * @policy: instance of pass_policy structure
36  *
37  * Return true if the state of PASS is PASS_GOV_START
38  * Return false if the state of PASS is PASS_GOV_STOP
39  */
40 static bool is_enabled(struct pass_policy *policy)
41 {
42         if (!policy)
43                 return false;
44
45         if (policy->gov_state != PASS_GOV_START)
46                 return false;
47
48         return true;
49 }
50
51 /****************************************************************************
52  *                             PASS Notifier                                *
53  * - DEVICE_NOTIFIER_PMQOS                                                  *
54  * - DEVICE_NOTIFIER_BOOTING_DONE                                           *
55  ****************************************************************************/
56 #define PASS_LOCK                       "Lock"
57 #define PASS_UNLOCK                     "Unlock"
58
59 static int pass_governor_change_level_scope(struct pass_policy *policy,
60                                             int min_level, int max_level);
61
62 /*
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.
66  */
67 static struct pass_policy *policy_pmqos;
68
69 /*
70  * is_pmqos_enabled - Check state of whether to support PM_QOS for scenario
71  * @policy: instance of pass_policy structure
72  *
73  * Return true if the state of PM_QOS is supported
74  * Return false if the state of PM_QOS isn't supported
75  */
76 static bool is_pmqos_enabled(struct pass_policy *policy)
77 {
78         if (!policy)
79                 return false;
80
81         if (!policy->scenario.list)
82                 return false;
83
84         if (policy->scenario.state != PASS_ON)
85                 return false;
86
87         return true;
88 }
89
90 /*
91  * is_scenario_locked - Check locked state of each scenario
92  * @policy: instance of pass_scenario structure
93  *
94  * Return true if scenario is locked and enabled
95  * Return false if scenario is unlocked or disabled
96  */
97
98 static bool is_scenario_locked(struct pass_scenario *scn)
99 {
100         if (!scn)
101                 return false;
102
103         if (!scn->locked || scn->state != PASS_ON)
104                 return false;
105
106         return true;
107 }
108
109 static enum pass_state is_pmqos_locked(char *data, char *name)
110 {
111         char *unlock = NULL;
112
113         if (!data)
114                 return PASS_OFF;
115
116         unlock = strstr(data, PASS_UNLOCK);
117         if (!unlock) {
118                 /* Lock scenario */
119                 strncpy(name, data, strlen(data) - strlen(PASS_LOCK));
120                 return PASS_ON;
121         } else {
122                 /* Unlock scenario */
123                 strncpy(name, data, strlen(data) - strlen(PASS_UNLOCK));
124                 return PASS_OFF;
125         }
126 }
127
128 static int find_scenario_index(struct pass_scenario_policy *scenario,
129                                char *name)
130 {
131         int index;
132
133         for (index = 0; index < scenario->num_scenarios; index++)
134                 if (MATCH(scenario->list[index].name, name))
135                         return index;
136
137         return -EINVAL;
138 }
139
140 /*
141  * pass_notifier_pmqos - Callback function of DEVICE_NOTIFIER_PMQOS notifier
142  * @data: the scenario name
143  */
144 static int pass_notifier_pmqos(void *data)
145 {
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;
153         int count = 0;
154         int index = -1;
155         int i;
156
157         if (!is_enabled(policy))
158                 return 0;
159
160         if (!is_pmqos_enabled(policy))
161                 return 0;
162
163         /*
164          * Parse scenario name(data) whether to include 'Lock' or 'Unlock'
165          * string and divide correct scenario name.
166          */
167         locked = is_pmqos_locked(data, name);
168         index = find_scenario_index(scenario, name);
169         if (index < 0) {
170                 _W("Unknown scenario (%s)\n", data);
171                 return -EINVAL;
172         }
173         scn = &scenario->list[index];
174
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",
178                                 name, scn->state);
179                 return 0;
180         }
181
182         /*
183          * Compare locked state of scenario with
184          * if state is same as existing state
185          */
186         if (scn->locked == locked) {
187                 _E("'%s' scenario is already %s\n",
188                                 name, locked ? "Locked" : "Unlocked");
189                 return 0;
190         }
191         scenario->list[index].locked = locked;
192
193         if (locked)
194                 scenario->list[index].locked_time = get_time_ms();
195
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];
199
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;
205                         count++;
206                 }
207
208                 /*
209                  * TODO: PASS have to control busfreq/gpufreq as same as cpufreq
210                  */
211         }
212
213         /*
214          * Restore default min/max level if all scenarios hasn't locked state.
215          */
216         if (!is_scenario_locked(scn) && !count) {
217                 cpufreq_min_level = policy->default_min_level;
218                 cpufreq_max_level = policy->default_max_level;
219         }
220
221         if (locked) {
222                 _I("Lock   '%s' scenario\n", name);
223         } else {
224                 int64_t locked_time =
225                         get_time_ms() - scenario->list[index].locked_time;
226                 scenario->list[index].locked_time = 0;
227
228                 _I("UnLock '%s' scenario (%lldms)\n", name, locked_time);
229         }
230
231         pass_governor_change_level_scope(policy, cpufreq_min_level,
232                                          cpufreq_max_level);
233
234         /* TODO: PASS have to control busfreq/gpufreq as same as cpufreq. */
235
236         return 0;
237 }
238
239 /*
240  * pass_notifier_booting_done - Callback function of DEVICE_NOTIFIER_BOOTING_
241  *                              DONE notifier
242  * @data: NULL, this parameter isn't used
243  */
244 static int pass_notifier_booting_done(void *data)
245 {
246         if (!policy_pmqos)
247                 return 0;
248
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);
252
253         return 0;
254 }
255
256 /*
257  * pass_notifier_init - Register notifiers and init
258  * @policy: the instance of pass_policy structure
259  */
260 static int pass_notifier_init(struct pass_policy *policy)
261 {
262         /* Register DEVICE_NOTIFIER_PMQOS */
263         register_notifier(DEVICE_NOTIFIER_PMQOS, pass_notifier_pmqos);
264
265         /* Register DEVICE_NOTIFIER_BOOTING_DONE */
266         register_notifier(DEVICE_NOTIFIER_BOOTING_DONE,
267                           pass_notifier_booting_done);
268
269         /*
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
273          * notifier feature.
274          */
275         policy_pmqos = policy;
276
277         return 0;
278 }
279
280 /*
281  * pass_notifier_exit - Un-register notifiers and exit
282  * @policy: the instance of pass_policy structure
283  */
284 static int pass_notifier_exit(struct pass_policy *policy)
285 {
286         /* Un-register DEVICE_NOTIFIER_PMQOS */
287         unregister_notifier(DEVICE_NOTIFIER_PMQOS, pass_notifier_pmqos);
288
289         /* Un-Register DEVICE_NOTIFIER_BOOTING_DONE */
290         unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE,
291                             pass_notifier_booting_done);
292
293         return 0;
294 }
295
296 /*****************************************************************************
297  *                            PASS CPU Hotplug                               *
298  ****************************************************************************/
299
300 /*
301  * pass_hotplug_set_online - Change the maximum number of online cpu
302  *
303  * @policy: the instance of struct pass_policy
304  * @max_online: the maximum number of online cpu
305  */
306 static void pass_hotplug_set_online(struct pass_policy *policy,
307                                         unsigned int online)
308 {
309         struct pass_table *table = policy->pass_table;
310         struct pass_hotplug *hotplug = policy->hotplug;
311         int num_online;
312         int i;
313
314         if (!hotplug || online == hotplug->online)
315                 return;
316
317         if (online > hotplug->max_online)
318                 online = hotplug->max_online;
319
320         if (online > hotplug->online)
321                 num_online = online;
322         else
323                 num_online = hotplug->online;
324
325         for (i = 0 ; i < policy->cpufreq.num_nr_cpus; i++) {
326                 if (i < online)
327                         set_cpu_online(hotplug->sequence[i], PASS_CPU_UP);
328                 else
329                         set_cpu_online(hotplug->sequence[i], PASS_CPU_DOWN);
330         }
331
332         /*
333         _I("- CPU %4s '%d->%d'Core\n",
334                 (hotplug->online > online ? "DOWN" : "UP"),
335                 hotplug->online, online);
336         */
337
338         hotplug->online = online;
339 }
340
341 /*
342  * pass_hotplug_stop - Stop PASS hotplug
343  *
344  * @policy: the instance of struct pass_policy
345  */
346 static void pass_hotplug_stop(struct pass_policy *policy)
347 {
348         struct pass_table *table = policy->pass_table;
349         int level = policy->max_level;
350
351         if (!policy->hotplug)
352                 return;
353
354         policy->hotplug->online = table[level].limit_max_cpu;
355         policy->hotplug->max_online = policy->cpufreq.num_nr_cpus;
356 }
357
358 static int pass_hotplug_dummy_governor(struct pass_policy *policy)
359 {
360         int level = policy->curr_level;
361
362         return policy->pass_table[level].limit_max_cpu;
363 }
364
365 /*
366  * Define PASS hotplug
367  *
368  * - Dummy hotplug
369  */
370 static struct pass_hotplug pass_hotplug_dummy = {
371         .name           = "pass_hotplug_dummy",
372         .governor       = pass_hotplug_dummy_governor,
373 };
374
375 /*
376  * pass_get_governor - Return specific hotplug instance according to type
377  *
378  * @type: the type of PASS hotplug
379  */
380 struct pass_hotplug* pass_get_hotplug(struct pass_policy *policy,
381                                         enum pass_gov_type type)
382 {
383         switch (type) {
384         case PASS_GOV_STEP:
385         case PASS_GOV_RADIATION:
386                 return &pass_hotplug_dummy;
387         default:
388                 _E("Unknown hotplug type");
389                 break;
390         };
391
392         return NULL;
393 }
394
395 /*****************************************************************************
396  *                              PASS governor                                *
397  ****************************************************************************/
398
399 /*
400  * pass_governor_change_level - Change maximum cpu frequency and number of online cpu
401  *
402  * @policy: the instance of struct pass_policy
403  * @level: the pass level
404  */
405 static int pass_governor_change_level(struct pass_policy *policy, int new_level)
406 {
407         struct pass_table *table = policy->pass_table;
408         struct pass_hotplug *hotplug = policy->hotplug;
409         int curr_level = policy->curr_level;
410         int limit_max_freq;
411         int curr_max_freq;
412         int curr_min_freq;
413         int limit_max_cpu;
414         int online;
415         int i;
416
417         if (new_level > policy->max_level)
418                 new_level = policy->max_level;
419
420         if (new_level < policy->min_level)
421                 new_level = policy->min_level;
422
423         if (new_level == curr_level)
424                 return 0;
425
426         /*
427          * Get maximum CPU frequency/the maximum number of online CPU
428          * according to PASS level.
429          */
430         limit_max_freq = table[new_level].limit_max_freq;
431         limit_max_cpu = table[new_level].limit_max_cpu;
432
433         policy->prev_level = policy->curr_level;
434         policy->curr_level = new_level;
435
436         /* Turn on/off CPUs according the maximum number of online CPU */
437         if (hotplug) {
438                 if (hotplug->max_online != limit_max_cpu)
439                         hotplug->max_online = limit_max_cpu;
440
441                 if (hotplug->governor)
442                         online = hotplug->governor(policy);
443                 else
444                         online = 1;
445
446                 curr_max_freq = get_cpufreq_scaling_max_freq();
447                 curr_min_freq = get_cpufreq_scaling_min_freq();
448
449                 set_cpufreq_scaling_min_freq(curr_max_freq);
450
451                 pass_hotplug_set_online(policy, online);
452
453                 set_cpufreq_scaling_min_freq(curr_min_freq);
454         }
455
456         /* Set maximum CPU frequency */
457         set_cpufreq_scaling_max_freq(limit_max_freq);
458
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);
462
463         return 0;
464 };
465
466 /*
467  * pass_governor_change_level_scope - Change the scope of cpufreq scaling
468  *
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
472  */
473 static int pass_governor_change_level_scope(struct pass_policy *policy,
474                                             int min_level, int max_level)
475 {
476         if (!policy)
477                 return -EINVAL;
478
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);
482                 return -EINVAL;
483         }
484
485         if (min_level == policy->min_level
486                 && max_level == policy->max_level)
487                 return 0;
488
489         /* Change minimum/maximum level of cpufreq scaling */
490         policy->min_level = min_level;
491         policy->max_level = max_level;
492
493         pass_governor_change_level(policy, policy->curr_level);
494
495         return 0;
496 }
497
498 /*
499  * pass_calculate_busy_cpu - Count a number of busy cpu among NR_CPUS by using
500  *                           runnable_avg_sum/runnable_avg_period
501  *
502  * @policy: the instance of struct pass_policy
503  */
504 static void pass_calculate_busy_cpu(struct pass_policy *policy)
505 {
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;
512         unsigned int load;
513         unsigned int sum_load;
514         unsigned int sum_runnable_load;
515         unsigned int nr_runnings;
516         int limit_max_cpu;
517         int i;
518         int j;
519
520         limit_max_cpu = table[level].limit_max_cpu;
521
522         for (i = 0; i < policy->num_pass_cpu_stats; i++) {
523                 cur_freq = stats[i].freq;
524                 nr_runnings = stats[i].nr_runnings;
525
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;
531
532                 busy_cpu = 0;
533                 sum_load = 0;
534                 sum_runnable_load = 0;
535
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];
541                         if (!load)
542                                 continue;
543
544                         cpu_threshold =
545                                 (unsigned int)(cur_freq * load)
546                                                 / policy->cpufreq.max_freq;
547                         if (load == 100
548                                 || cpu_threshold >= policy->pass_cpu_threshold)
549                                 busy_cpu++;
550                 }
551
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;
555                 if (nr_runnings) {
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;
560                 }
561         }
562 }
563
564 /*
565  * pass_governor_stop - Stop PASS governor through D-Bus
566  *
567  * @policy: the instance of struct pass_policy
568  */
569 static void pass_governor_stop(struct pass_policy *policy)
570 {
571         if (!policy->governor) {
572                 _E("cannot stop PASS governor");
573                 return;
574         }
575
576         if (policy->gov_state == PASS_GOV_STOP) {
577                 _E("PASS governor is already inactive state");
578                 return;
579         }
580
581         /* Restore maximum cpu freq/the number of online cpu */
582         pass_governor_change_level(policy, policy->num_levels - 1);
583
584         pass_hotplug_stop(policy);
585
586         if (policy->governor->gov_timer_id) {
587                 ecore_timer_del(policy->governor->gov_timer_id);
588                 policy->governor->gov_timer_id = NULL;
589         }
590
591         /* Set PASS state as PASS_GOV_STOP */
592         policy->gov_state = PASS_GOV_STOP;
593
594         _I("Stop PASS governor");
595 }
596
597 /*
598  * pass_governor_core_timer - Callback function of core timer for PASS governor
599  *
600  * @data: the instance of struct pass_policy
601  */
602 static Eina_Bool pass_governor_core_timer(void *data)
603 {
604         struct pass_policy *policy = (struct pass_policy *)data;
605         static int count = 0;
606         int level;
607         int online;
608         int ret;
609
610         if (!policy) {
611                 _E("cannot execute PASS core timer");
612                 return ECORE_CALLBACK_CANCEL;
613         }
614
615         /*
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)
620          */
621         ret = get_pass_cpu_stats(policy);
622         if (ret < 0) {
623                 if (count++ < PASS_CPU_STATS_MAX_COUNT)
624                         return ECORE_CALLBACK_RENEW;
625
626                 count = 0;
627
628                 _E("cannot read 'pass_cpu_stats' sysfs entry");
629                 pass_governor_stop(policy);
630
631                 return ECORE_CALLBACK_CANCEL;
632         }
633
634         /* Calculate the number of busy cpu */
635         pass_calculate_busy_cpu(policy);
636
637         /* Determine the amount of proper resource */
638         if (policy->governor->governor) {
639                 level = policy->governor->governor(policy);
640
641                 pass_governor_change_level(policy, level);
642         } else {
643                 _E("cannot execute governor function");
644                 pass_governor_stop(policy);
645                 return ECORE_CALLBACK_CANCEL;
646         }
647
648         /*
649          * Change the period of govenor timer according to PASS level
650          */
651         if (policy->pass_table[level].gov_timeout >= PASS_MIN_GOV_TIMEOUT &&
652                 (policy->governor->gov_timeout
653                  != policy->pass_table[level].gov_timeout)) {
654
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);
658
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);
664         }
665
666         return ECORE_CALLBACK_RENEW;
667 }
668
669 /*
670  * pass_governor_start - Start PASS governor through D-Bus
671  *
672  * @policy: the instance of struct pass_policy
673  */
674 static void pass_governor_start(struct pass_policy *policy)
675 {
676         if (!policy->governor) {
677                 _E("cannot start PASS governor");
678                 return;
679         }
680
681         if (is_enabled(policy)) {
682                 _E("PASS governor is already active state");
683                 return;
684         }
685
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,
690                                 (void *)policy);
691         if (!policy->governor->gov_timer_id) {
692                 _E("cannot add core timer for governor");
693                 pass_governor_stop(policy);
694                 return;
695         }
696
697         /*
698          * Set default pass level when starting pass
699          * - default pass level according to policy->init_level
700          */
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);
705
706         /* Set PASS state as PASS_GOV_START */
707         policy->gov_state = PASS_GOV_START;
708
709         _I("Start PASS governor");
710 }
711
712 /*
713  * pass_governor_init - Initialize PASS governor
714  *
715  * @policy: the instance of struct pass_policy
716  */
717 static int pass_governor_init(struct pass_policy *policy)
718 {
719         int max_level;
720         int ret;
721
722         if(policy->governor->gov_timeout < 0) {
723                 _E("invalid timeout value [%d]!",
724                         policy->governor->gov_timeout);
725                 pass_governor_stop(policy);
726                 return -EINVAL;
727         }
728
729         /* Set default PASS state */
730         policy->gov_state = PASS_GOV_STOP;
731
732         /* Initialize notifier */
733         pass_notifier_init(policy);
734
735         _I("Initialize PASS (Power Aware System Service)");
736
737         return 0;
738 }
739
740 /*
741  * pass_governor_exit - Exit PASS governor
742  */
743 static int pass_governor_exit(struct pass_policy *policy)
744 {
745         int i;
746
747         /* Exit notifier */
748         pass_notifier_exit(policy);
749
750         /*
751          * Stop core timer and
752          * Restore maximum online cpu/cpu frequency
753          */
754         pass_governor_stop(policy);
755
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);
761         }
762         free(policy->pass_cpu_stats);
763
764         if (policy->hotplug)
765                 free(policy->hotplug->sequence);
766
767         /* Set pass_policy structure as default value */
768         policy->pass_cpu_threshold = 0;
769         policy->up_threshold = 0;
770         policy->down_threshold = 0;
771
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;
777
778         policy->pass_table = NULL;
779         policy->num_pass_cpu_stats = 0;
780
781         policy->governor->gov_timeout = 0;
782
783         policy->governor = NULL;
784
785         _I("Exit PASS (Power Aware System Service)");
786
787         return 0;
788 }
789
790 /*
791  * pass_governor_update - Restart/Pause PASS governor
792  *
793  * @cond: the instance of struct pass_policy
794  */
795 static int pass_governor_update(struct pass_policy *policy,
796                         enum pass_gov_state state)
797 {
798         if (!policy) {
799                 _E("cannot update PASS governor");
800                 return -EINVAL;
801         }
802
803         switch (state) {
804         case PASS_GOV_START:
805                 pass_governor_start(policy);
806                 break;
807         case PASS_GOV_STOP:
808                 pass_governor_stop(policy);
809                 break;
810         default:
811                 _E("Unknown governor state");
812                 return -EINVAL;
813         }
814
815         return 0;
816 }
817
818 /*
819  * Define PASS governor
820  *
821  * - Step governor
822  * - Radiation governor
823  */
824 static struct pass_governor pass_gov_step = {
825         .name           = "pass_step",
826         .init           = pass_governor_init,
827         .exit           = pass_governor_exit,
828         .update         = pass_governor_update,
829
830         .governor       = pass_step_governor,
831 };
832
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,
838
839         .governor       = pass_radiation_governor,
840 };
841
842 /*
843  * pass_get_governor - Return specific governor instance according to type
844  *
845  * @type: the type of PASS governor
846  */
847 struct pass_governor* pass_get_governor(struct pass_policy *policy,
848                                                 enum pass_gov_type type)
849 {
850         switch (type) {
851         case PASS_GOV_STEP:
852                 return &pass_gov_step;
853         case PASS_GOV_RADIATION:
854                 return &pass_gov_radiation;
855         default:
856                 _E("Unknown governor type");
857                 break;
858         };
859
860         return NULL;
861 }