change usb control process name to usb-server
[framework/system/system-server.git] / ss_cpu_handler.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 */
16
17
18 #include <fcntl.h>
19
20 #include "ss_device_plugin.h"
21 #include "ss_log.h"
22 #include "include/ss_data.h"
23 #include "vconf.h"
24
25 #define DEFAULT_MAX_CPU_FREQ            1200000
26 #define DEFAULT_MIN_CPU_FREQ            100000
27 #define POWER_SAVING_CPUFREQ            800000
28
29 static int max_cpu_freq_limit = -1;
30 static int min_cpu_freq_limit = -1;
31 static int cur_max_cpu_freq = INT_MAX;
32 static int cur_min_cpu_freq = INT_MIN;
33
34 static Eina_List *max_cpu_freq_list;
35 static Eina_List *min_cpu_freq_list;
36
37 struct cpu_freq_entry {
38         int pid;
39         int freq;
40 };
41
42 static void __set_freq_limit();
43 static int __is_entry_enble(int pid);
44 static int __remove_entry_from_max_cpu_freq_list(int pid);
45 static int __remove_entry_from_min_cpu_freq_list(int pid);
46 static int __add_entry_to_max_cpu_freq_list(int pid, int freq);
47 static int __add_entry_to_min_cpu_freq_list(int pid, int freq);
48 static int __write_max_cpu_freq(int freq);
49 static int __write_min_cpu_freq(int freq);
50
51 int set_max_frequency_action(int argc, char **argv)
52 {
53         int r = -1;
54         
55         if (argc < 2)
56                 return -1;
57
58         r = __add_entry_to_max_cpu_freq_list(atoi(argv[0]), atoi(argv[1]));
59         if (r < 0) {
60                 PRT_TRACE_ERR("Add entry failed");
61                 return -1;
62         }
63
64         r = __write_max_cpu_freq(cur_max_cpu_freq);
65         if (r < 0) {
66                 PRT_TRACE_ERR("Write entry failed");
67                 return -1;
68         }
69
70         return 0;
71 }
72
73 int set_min_frequency_action(int argc, char **argv)
74 {
75         int r = -1;
76         
77         if (argc < 2)
78                 return -1;
79
80         r = __add_entry_to_min_cpu_freq_list(atoi(argv[0]), atoi(argv[1]));
81         if (r < 0) {
82                 PRT_TRACE_ERR("Add entry failed");
83                 return -1;
84         }
85         
86         r = __write_min_cpu_freq(cur_min_cpu_freq);
87         if (r < 0) {
88                 PRT_TRACE_ERR("Write entry failed");
89                 return -1;
90         }
91
92         return 0;
93 }
94
95 int release_max_frequency_action(int argc, char **argv)
96 {
97         int r = -1;
98         if (argc < 1)
99                 return -1;
100         
101         r = __remove_entry_from_max_cpu_freq_list(atoi(argv[0]));
102         if (r < 0) {
103                 PRT_TRACE_ERR("Remove entry failed");
104                 return -1;
105         }
106
107         if (cur_max_cpu_freq == INT_MAX)
108                 cur_max_cpu_freq = max_cpu_freq_limit;
109
110         r = __write_max_cpu_freq(cur_max_cpu_freq);
111         if (r < 0) {
112                 PRT_TRACE_ERR("Write freq failed");
113                 return -1;
114         }
115
116         return 0;
117 }
118
119 int release_min_frequency_action(int argc, char **argv)
120 {
121         int r = -1;
122
123         if (argc < 1)
124                 return -1;
125
126         r = __remove_entry_from_min_cpu_freq_list(atoi(argv[0]));
127         if (r < 0) {
128                 PRT_TRACE_ERR("Remove entry failed");
129                 return -1;
130         }
131
132         if (cur_min_cpu_freq == INT_MIN)
133                 cur_min_cpu_freq = min_cpu_freq_limit;
134
135         r = __write_min_cpu_freq(cur_min_cpu_freq);
136         if (r < 0) {
137                 PRT_TRACE_ERR("Write entry failed");
138                 return -1;
139         }
140
141         return 0;
142 }
143
144 static int power_saving_cb(keynode_t *key_nodes, void *data)
145 {
146         int ret = -1;
147         int power_saving_stat = -1;
148         int power_saving_cpu_stat = -1;
149
150         power_saving_stat = vconf_keynode_get_bool(key_nodes);
151         if (power_saving_stat == 1) {
152                 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, &power_saving_cpu_stat);
153                 if (power_saving_cpu_stat == 1) {
154                         ret = __add_entry_to_max_cpu_freq_list(getpid(), POWER_SAVING_CPUFREQ);
155                         if (ret < 0) {
156                                 PRT_TRACE_ERR("Add entry failed");
157                                 return -1;
158                         }
159                 }
160         } else {
161                 ret = __remove_entry_from_max_cpu_freq_list(getpid());
162                 if (ret < 0) {
163                         PRT_TRACE_ERR("Remove entry failed");
164                         return -1;
165                 }
166                 if (cur_max_cpu_freq == INT_MIN)
167                         cur_max_cpu_freq = max_cpu_freq_limit;
168         }
169         ret = __write_max_cpu_freq(cur_max_cpu_freq);
170         if (ret < 0) {
171                 PRT_TRACE_ERR("Write failed");
172                 return -1;
173         }
174
175         return 0;
176 }
177
178 static int power_saving_cpu_cb(keynode_t *key_nodes, void *data)
179 {
180         int ret = -1;
181         int power_saving_stat = -1;
182         int power_saving_cpu_stat = -1;
183
184         vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
185         if (power_saving_stat == 1) {
186                 power_saving_cpu_stat = vconf_keynode_get_bool(key_nodes);
187                 if (power_saving_cpu_stat == 1) {
188                         ret = __add_entry_to_max_cpu_freq_list(getpid(), POWER_SAVING_CPUFREQ);
189                         if (ret < 0) {
190                                 PRT_TRACE_ERR("Add entry failed");
191                                 return -1;
192                         }
193                 } else {
194                         ret = __remove_entry_from_max_cpu_freq_list(getpid());
195                         if (ret < 0) {
196                                 PRT_TRACE_ERR("Remove entry failed");
197                                 return -1;
198                         }
199                         if (cur_max_cpu_freq == INT_MAX)
200                                 cur_max_cpu_freq = max_cpu_freq_limit;
201                 }
202                 ret = __write_max_cpu_freq(cur_max_cpu_freq);
203                 if (ret < 0) {
204                         PRT_TRACE_ERR("Write failed");
205                         return -1;
206                 }
207         }
208
209         return 0;
210 }
211
212 int ss_cpu_handler_init(void)
213 {
214         __set_freq_limit();
215         
216         ss_action_entry_add_internal(PREDEF_SET_MAX_FREQUENCY, set_max_frequency_action, NULL, NULL);
217         ss_action_entry_add_internal(PREDEF_SET_MIN_FREQUENCY, set_min_frequency_action, NULL, NULL);
218         ss_action_entry_add_internal(PREDEF_RELEASE_MAX_FREQUENCY, release_max_frequency_action, NULL, NULL);
219         ss_action_entry_add_internal(PREDEF_RELEASE_MIN_FREQUENCY, release_min_frequency_action, NULL, NULL);
220
221         vconf_notify_key_changed(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, (void *)power_saving_cb, NULL);
222         vconf_notify_key_changed(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, (void *)power_saving_cpu_cb, NULL);
223
224         return 0;
225 }
226
227 static void __set_freq_limit()
228 {
229         int ret;
230
231         ret = plugin_intf->OEM_sys_get_cpufreq_cpuinfo_max_freq(&max_cpu_freq_limit);
232         if (ret < 0) {
233                 PRT_TRACE_ERR("get cpufreq cpuinfo max readerror: %s", strerror(errno));
234                 max_cpu_freq_limit = DEFAULT_MAX_CPU_FREQ;
235         }
236
237         ret = plugin_intf->OEM_sys_get_cpufreq_cpuinfo_min_freq(&min_cpu_freq_limit);
238         if (ret < 0) {
239                 PRT_TRACE_ERR("get cpufreq cpuinfo min readerror: %s", strerror(errno));
240                 min_cpu_freq_limit = DEFAULT_MIN_CPU_FREQ;
241         }
242
243         /* check power saving */
244         int power_saving_stat = -1;
245         int power_saving_cpu_stat = -1;
246         vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
247         if (power_saving_stat == 1)
248                 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_CPU, &power_saving_cpu_stat);
249         if (power_saving_cpu_stat == 1) {
250                 ret = __add_entry_to_max_cpu_freq_list(getpid(), POWER_SAVING_CPUFREQ);
251                 if (ret < 0) {
252                         PRT_TRACE_ERR("Add entry failed");
253                         return;
254                 }
255                 ret = __write_max_cpu_freq(cur_max_cpu_freq);
256                 if (ret < 0) {
257                         PRT_TRACE_ERR("Write entry failed");
258                         return;
259                 }
260         }
261 }
262
263 static int __is_entry_enable(int pid)
264 {
265         char pid_path[PATH_MAX];
266         
267         snprintf(pid_path, PATH_MAX, "/proc/%d", pid);
268         if (access(pid_path, F_OK) < 0) {
269                 return 0;
270         }
271
272         return 1;
273 }
274
275 static int __remove_entry_from_max_cpu_freq_list(int pid)
276 {
277         Eina_List *tmp;
278         Eina_List *tmp_next;
279         struct cpu_freq_entry *entry;
280
281         cur_max_cpu_freq = INT_MAX;
282
283         EINA_LIST_FOREACH_SAFE(max_cpu_freq_list, tmp, tmp_next, entry) {
284                 if (entry != NULL) {
285                         if ((!__is_entry_enable(entry->pid)) || (entry->pid == pid)) {
286                                 max_cpu_freq_list = eina_list_remove(max_cpu_freq_list, entry);
287                                 free(entry);
288                                 continue;
289                         }
290
291                         if (entry->freq < cur_max_cpu_freq) {
292                                 cur_max_cpu_freq = entry->freq;
293                         }
294                 }
295         }
296
297         return 0;
298 }
299
300 static int __remove_entry_from_min_cpu_freq_list(int pid)
301 {
302         Eina_List *tmp;
303         Eina_List *tmp_next;
304         struct cpu_freq_entry *entry;
305
306         cur_min_cpu_freq = INT_MIN;
307
308         EINA_LIST_FOREACH_SAFE(min_cpu_freq_list, tmp, tmp_next, entry) {
309                 if (entry != NULL) {
310                         if ((!__is_entry_enable(entry->pid)) || (entry->pid == pid)) {
311                                 min_cpu_freq_list = eina_list_remove(min_cpu_freq_list, entry);
312                                 free(entry);
313                                 continue;
314                         }
315
316                         if (entry->freq > cur_min_cpu_freq) {
317                                 cur_min_cpu_freq = entry->freq;
318                         }
319
320                 }
321         }
322
323         return 0;
324 }
325
326 static int __add_entry_to_max_cpu_freq_list(int pid, int freq)
327 {
328         int r = -1;
329         struct cpu_freq_entry *entry;
330         
331         r = __remove_entry_from_max_cpu_freq_list(pid);
332         if (r < 0) {
333                 PRT_TRACE_ERR("Remove duplicated entry failed");
334         }
335
336         if (freq < cur_max_cpu_freq) {
337                 cur_max_cpu_freq = freq;
338         }
339
340         entry = malloc(sizeof(struct cpu_freq_entry));
341         if (!entry) {
342                 PRT_TRACE_ERR("Malloc failed");
343                 return -1;
344         }
345         
346         entry->pid = pid;
347         entry->freq = freq;
348
349         max_cpu_freq_list = eina_list_prepend(max_cpu_freq_list, entry);
350         if (!max_cpu_freq_list) {
351                 PRT_TRACE_ERR("eina_list_prepend failed");
352                 return -1;
353         }
354
355         return 0;
356 }
357
358 static int __add_entry_to_min_cpu_freq_list(int pid, int freq)
359 {
360         int r = -1;
361         struct cpu_freq_entry *entry;
362         
363         r = __remove_entry_from_min_cpu_freq_list(pid);
364         if (r < 0) {
365                 PRT_TRACE_ERR("Remove duplicated entry failed");
366         }
367
368         if (freq > cur_min_cpu_freq) {
369                 cur_min_cpu_freq = freq;
370         }
371
372         entry = malloc(sizeof(struct cpu_freq_entry));
373         if (!entry) {
374                 PRT_TRACE_ERR("Malloc failed");
375                 return -1;
376         }
377         
378         entry->pid = pid;
379         entry->freq = freq;
380
381         min_cpu_freq_list = eina_list_prepend(min_cpu_freq_list, entry);
382         if (!min_cpu_freq_list) {
383                 PRT_TRACE_ERR("eina_list_prepend failed");
384                 return -1;
385         }
386         
387         return 0;
388 }
389
390 static int __write_max_cpu_freq(int freq)
391 {
392         int ret;
393
394         ret = plugin_intf->OEM_sys_set_cpufreq_scaling_max_freq(freq);
395         if (ret < 0) {
396                 PRT_TRACE_ERR("set cpufreq max freq write error: %s", strerror(errno));
397                 return -1;
398         }
399         
400         return 0;
401 }
402
403 static int __write_min_cpu_freq(int freq)
404 {
405         int ret;
406
407         ret = plugin_intf->OEM_sys_set_cpufreq_scaling_min_freq(freq);
408         if (ret < 0) {
409                 PRT_TRACE_ERR("set cpufreq min freq write error: %s", strerror(errno));
410                 return -1;
411         }
412         
413         return 0;
414 }