tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / power / load_analyzer_cputester.c
1 /* cpu tester */
2
3
4 int cpu_tester_en;
5
6 int cpufreq_tester_en;
7 int cpuidle_tester_en;
8 int cpuload_tester_en;
9
10 int cpu_idle_trace_en;
11
12 bool b_cpuload_work_queue_stop;
13
14 static struct workqueue_struct *cpu_tester_wq;
15
16 static struct workqueue_struct *cpu_load_wq[CPU_NUM];
17
18
19 struct delayed_work cpu_tester_work;
20 struct delayed_work cpu_idle_tester_work;
21 struct delayed_work cpu_freq_tester_work;
22 struct delayed_work cpu_load_tester_work[CPU_NUM];
23
24 int cpu_tester_get_cpu_idletest_list_num(void)
25 {
26         return (sizeof(cpu_idletest_list) / sizeof(struct cpu_test_list_tag)) -1;
27 }
28
29
30 int cpu_tester_get_cpu_freqtest_list_num(void)
31 {
32         return (sizeof(cpu_freqtest_list) / sizeof(struct cpu_test_list_tag)) -1;
33 }
34
35 int cpu_tester_get_cpu_test_freq_table_num(void)
36 {
37         return (sizeof(cpu_test_freq_table) / sizeof(struct cpu_test_freq_table_tag));
38 }
39
40
41 int cpu_tester_get_cpu_test_idle_table_num(void)
42 {
43         return (sizeof(cpu_test_idle_table) / sizeof(struct cpu_test_idle_table_tag));
44 }
45
46
47
48 int cpufreq_force_state = -1;;
49 static int cpufreq_force_set_read_sub(char *buf, int buf_size)
50 {
51         int ret = 0;
52
53         ret +=  snprintf(buf + ret, buf_size - ret, "%d\n", cpufreq_force_state);
54
55         return ret;
56 }
57
58 static ssize_t cpufreq_force_set_read(struct file *file,
59         char __user *buffer, size_t count, loff_t *ppos)
60 {
61         unsigned int size_for_copy;
62
63         size_for_copy = wrapper_for_debug_fs(buffer, count, ppos
64                                         ,cpufreq_force_set_read_sub);
65
66         return size_for_copy;
67 }
68
69 static ssize_t cpufreq_force_set_write(struct file *file,
70                                       const char __user *user_buf, size_t count,
71                                       loff_t *ppos)
72 {
73         struct cpufreq_policy *policy;
74
75         if (strstr(user_buf, "-1")!=NULL)
76                 cpufreq_force_state = -1;
77         else
78                 cpufreq_force_state = atoi(user_buf);
79
80         policy = cpufreq_cpu_get(0);
81         if (policy !=NULL) {
82                 __cpufreq_driver_target(policy, cpufreq_force_state, CPUFREQ_RELATION_L);
83                 cpufreq_cpu_put(policy);
84         }
85
86         return count;
87 }
88
89
90 int cpufreq_force_set(int *force_state, int target_freq)
91 {
92         if (cpufreq_force_state == -1) {
93                 *force_state = target_freq;
94         } else {
95                 *force_state = cpufreq_force_state;
96         }
97
98         return 0;
99 }
100
101
102
103 static int cpuidle_force_state = -1;;
104 static int cpuidle_force_set_read_sub(char *buf, int buf_size)
105 {
106         int ret = 0;
107
108         ret +=  snprintf(buf + ret, buf_size - ret, "%d\n", cpuidle_force_state);
109
110         return ret;
111 }
112
113 static ssize_t cpuidle_force_set_read(struct file *file,
114         char __user *buffer, size_t count, loff_t *ppos)
115 {
116         unsigned int size_for_copy;
117
118         size_for_copy = wrapper_for_debug_fs(buffer, count, ppos
119                                         ,cpuidle_force_set_read_sub);
120
121         return size_for_copy;
122 }
123
124 static ssize_t cpuidle_force_set_write(struct file *file,
125                                       const char __user *user_buf, size_t count,
126                                       loff_t *ppos)
127 {
128
129         if (strstr(user_buf, "-1")!=NULL)
130                 cpuidle_force_state = -1;
131         else
132                 cpuidle_force_state = atoi(user_buf);
133
134         return count;
135 }
136
137
138 int cpuidle_force_set(int *force_state, int next_state)
139 {
140
141         if (cpuidle_force_state == -1) {
142                 *force_state = next_state;
143         } else {
144                 *force_state = cpuidle_force_state;
145         }
146
147         return 0;
148 }
149
150 void cpu_idle_tester_work_start(struct work_struct *work)
151 {
152         static int cnt = -1;
153         int operating_msec;
154         int setting_value;
155
156         if (cpuidle_tester_en != 1)
157                 return;
158
159
160         if (cpu_idletest_list[++cnt].test_item == END_OF_LIST) {
161                 cnt = 0;
162         };
163
164         setting_value = cpu_idletest_list[cnt].setting_value;
165
166         if (setting_value == CPUIDLE_RANDOM)
167                 setting_value = jiffies % CPUIDLE_RANDOM;
168
169         cpuidle_force_state = setting_value;
170
171         operating_msec = cpu_idletest_list[cnt].test_time;
172
173         cpu_idletest_list[cnt].test_cnt++;
174
175         queue_delayed_work(cpu_tester_wq
176                         , &cpu_idle_tester_work, msecs_to_jiffies(operating_msec));
177 }
178
179 void cpu_freq_tester_work_start(struct work_struct *work)
180 {
181         static int cnt = -1;
182         int operating_msec;
183         struct cpufreq_policy *policy;
184         int setting_value;
185
186         if (cpufreq_tester_en != 1)
187                 return;
188
189         if (cpu_freqtest_list[++cnt].test_item == END_OF_LIST) {
190                 cnt = 0;
191         };
192
193         setting_value = cpu_freqtest_list[cnt].setting_value;
194
195         if (setting_value == CPUFREQ_RANDOM)
196                 setting_value = jiffies % CPUFREQ_RANDOM;
197
198         set_cpufreq_force_state(setting_value);
199
200         operating_msec = cpu_freqtest_list[cnt].test_time;
201
202         policy = cpufreq_cpu_get(0);
203         if (policy !=NULL) {
204                 __cpufreq_driver_target(policy, cpufreq_force_state, CPUFREQ_RELATION_L);
205                 cpufreq_cpu_put(policy);
206         }
207
208         cpu_freqtest_list[cnt].test_cnt++;
209
210         queue_delayed_work(cpu_tester_wq
211                         , &cpu_freq_tester_work, msecs_to_jiffies(operating_msec));
212 }
213
214 static int cpuload_working[CPU_NUM];
215
216 void cpu_load_tester_work_start(struct work_struct *work)
217 {
218         struct delayed_work *my_delayed_work;
219         int num;
220
221         if (cpuload_tester_en > 0) {
222                 mdelay(200);
223                 my_delayed_work= to_delayed_work(work);
224                 num = my_delayed_work -&(cpu_load_tester_work[0]);
225
226                 if (cpuload_working[num] == 1) {
227                         if (cpu_online(num)) {
228                                 queue_delayed_work_on(num, cpu_load_wq[num]
229                                                         , to_delayed_work(work), 0);
230                         } else {
231                                 queue_delayed_work(cpu_load_wq[num]
232                                                         , to_delayed_work(work), 0);
233                         }
234                 }
235         }
236 }
237
238 void cpu_tester_work_start(struct work_struct *work)
239 {
240         int i, cpuload_new_off, cpuload_new_on;
241         int cpu_freq_table_num, cpu_idle_table_num;
242         static int pre_cpuload_tester_en = 0;
243
244         if ((cpufreq_tester_en) && (!delayed_work_pending(&cpu_freq_tester_work))){
245                 cpu_freq_table_num = cpu_tester_get_cpu_test_freq_table_num();
246                 for(i =0; i<cpu_freq_table_num; i++) {
247                         cpu_test_freq_table[i].enter_count = 0;
248                         cpu_test_freq_table[i].exit_count = 0;
249                 }
250                 queue_delayed_work(cpu_tester_wq
251                         , &cpu_freq_tester_work, (1)*HZ);
252
253         }
254
255         if ((cpuidle_tester_en) && (!delayed_work_pending(&cpu_idle_tester_work))){
256                 cpu_idle_table_num = cpu_tester_get_cpu_test_idle_table_num();
257                 for(i =0; i<cpu_idle_table_num; i++) {
258                         cpu_test_idle_table[i].enter_count = 0;
259                         cpu_test_idle_table[i].exit_count = 0;
260                 }
261                 queue_delayed_work(cpu_tester_wq
262                                         , &cpu_idle_tester_work, (1)*HZ);
263         }
264
265         cpuload_new_off = pre_cpuload_tester_en - cpuload_tester_en;
266         cpuload_new_on = cpuload_tester_en - pre_cpuload_tester_en;
267
268         pr_info("cpuload_new_off=%d cpuload_new_on=%d\n", cpuload_new_off, cpuload_new_on);
269
270         if (cpuload_new_on > 0){
271                 for (i = pre_cpuload_tester_en ; i < cpuload_tester_en ; i ++) {
272                         cpuload_working[i] = 1;
273                         if (!delayed_work_pending(&cpu_load_tester_work[i])) {
274                                 queue_delayed_work(cpu_load_wq[i]
275                                                         , &(cpu_load_tester_work[i]), HZ/100);
276                         }
277                 }
278         } else if (cpuload_new_off > 0) {
279                 for (i=1; cpuload_new_off--; i++) {
280                         cpuload_working[pre_cpuload_tester_en-i] = 0;
281                 }
282         }
283
284         pre_cpuload_tester_en = cpuload_tester_en;
285 }
286
287
288 static int cpu_tester_state_read_sub(char *buf, int buf_size)
289 {
290         int ret = 0, i = 0;
291         char cpuidle_state_name[10] = {0, };
292         char cpufreq_state_name[10] = {0, };
293
294         int cpu_idletest_list_num, cpu_freqtest_list_num;
295
296         cpu_idletest_list_num = cpu_tester_get_cpu_idletest_list_num();
297         cpu_freqtest_list_num = cpu_tester_get_cpu_freqtest_list_num();
298
299         ret +=  snprintf(buf + ret, buf_size - ret
300                 , "========= CPU FREQ TEST =========\n"
301                   "   CPUFREQ  TEST_COUNT\n");
302
303
304         for(i = 0; i < cpu_freqtest_list_num; i++) {
305                 cpu_tester_enum_to_str(cpufreq_state_name
306                                 , CPU_FREQ_TEST, cpu_freqtest_list[i].setting_value);
307
308                 ret +=  snprintf(buf + ret, buf_size - ret
309                         , "%10s\t%d\n"
310                         , cpufreq_state_name
311                         , cpu_freqtest_list[i].test_cnt);
312         }
313         ret +=  snprintf(buf + ret, buf_size - ret
314                 , "\n");
315
316         ret +=  snprintf(buf + ret, buf_size - ret
317                 , "========= CPU IDLE TEST =========\n"
318                   "   CPUIDLE  TEST_COUNT\n");
319
320         for(i = 0; i < cpu_idletest_list_num; i++) {
321                 cpu_tester_enum_to_str(cpuidle_state_name
322                                 , CPU_IDLE_TEST, cpu_idletest_list[i].setting_value);
323
324                 ret +=  snprintf(buf + ret, buf_size - ret
325                         , "%10s\t%d\n"
326                         , cpuidle_state_name
327                         , cpu_idletest_list[i].test_cnt);
328         }
329
330         ret +=  snprintf(buf + ret, buf_size - ret, "\n");
331
332
333         return ret;
334 }
335
336 static ssize_t cpu_tester_state_read(struct file *file,
337         char __user *buffer, size_t count, loff_t *ppos)
338 {
339         unsigned int size_for_copy;
340
341         size_for_copy = wrapper_for_debug_fs(buffer, count, ppos
342                                         ,cpu_tester_state_read_sub);
343
344         return size_for_copy;
345 }
346
347
348 static int cpu_test_result_read_sub(char *buf, int buf_size)
349 {
350         int ret = 0, i = 0;
351         int cpu_freq_table_num, cpu_idle_table_num;
352         char cpuidle_state_name[10] = {0, };
353         char cpufreq_state_name[10] = {0, };
354
355         cpu_freq_table_num = cpu_tester_get_cpu_test_freq_table_num();
356         cpu_idle_table_num = cpu_tester_get_cpu_test_idle_table_num();
357
358         ret +=  snprintf(buf + ret, buf_size - ret
359                 , "========= CPU FREQ TEST =========\n"
360                   "   CPUFREQ  TEST_COUNT\n");
361
362
363         for(i = 0; i < cpu_freq_table_num; i++) {
364                 cpu_tester_enum_to_str(cpufreq_state_name
365                                 , CPU_FREQ_TEST, cpu_test_freq_table[i].cpufreq);
366
367                 ret +=  snprintf(buf + ret, buf_size - ret
368                         , "%10s\t%d\n"
369                         , cpufreq_state_name
370                         , cpu_test_freq_table[i].exit_count);
371         }
372         ret +=  snprintf(buf + ret, buf_size - ret
373                 , "\n");
374
375         ret +=  snprintf(buf + ret, buf_size - ret
376                 , "========= CPU IDLE TEST =========\n"
377                   "   CPUIDLE  TEST_COUNT\n");
378
379         for(i = 0; i < cpu_idle_table_num; i++) {
380                 cpu_tester_enum_to_str(cpuidle_state_name
381                                 , CPU_IDLE_TEST, cpu_test_idle_table[i].cpuidle);
382
383                 ret +=  snprintf(buf + ret, buf_size - ret
384                         , "%10s\t%d\n"
385                         , cpuidle_state_name
386                         , cpu_test_idle_table[i].exit_count);
387         }
388
389         ret +=  snprintf(buf + ret, buf_size - ret, "\n");
390
391
392         return ret;
393 }
394
395 static ssize_t cpu_test_result_read(struct file *file,
396         char __user *buffer, size_t count, loff_t *ppos)
397 {
398         unsigned int size_for_copy;
399
400         size_for_copy = wrapper_for_debug_fs(buffer, count, ppos
401                                         ,cpu_test_result_read_sub);
402
403         return size_for_copy;
404 }
405
406
407 static int cpu_tester_en_read_sub(char *buf, int buf_size)
408 {
409         int ret = 0;
410
411         ret +=  snprintf(buf + ret, buf_size - ret
412                 , "cpufreq:%d cpuidle:%d cpuload:%d\n"
413                         , cpufreq_tester_en, cpuidle_tester_en, cpuload_tester_en);
414
415         return ret;
416 }
417
418 static ssize_t cpu_tester_en_read(struct file *file,
419         char __user *buffer, size_t count, loff_t *ppos)
420 {
421         unsigned int size_for_copy;
422
423         size_for_copy = wrapper_for_debug_fs(buffer, count, ppos
424                                         ,cpu_tester_en_read_sub);
425
426         return size_for_copy;
427 }
428
429
430
431 int cpu_tester_check_onoff(char *str, char *tagname)
432 {
433         char *p_tagstart;
434         int tagname_size;
435         int onoff = -1;
436
437         tagname_size = strlen(tagname);
438
439         p_tagstart = strstr(str, tagname);
440
441         if (p_tagstart != NULL)
442                 onoff = atoi(p_tagstart + tagname_size);
443
444         return onoff;
445 }
446
447 static ssize_t cpu_tester_en_write(struct file *file,
448                                       const char __user *user_buf, size_t count,
449                                       loff_t *ppos)
450 {
451         int cpufreq_input, cpuidle_input, cpuload_input, all_input;
452         bool b_cpufreq_result = 0, b_cpuidle_result = 0, b_cpu_all_result = 0;
453
454         /* STEP 1 : Get input value */
455         cpufreq_input = cpu_tester_check_onoff((char *)user_buf, "cpufreq:");
456         cpuidle_input = cpu_tester_check_onoff((char *)user_buf, "cpuidle:");
457         cpuload_input = cpu_tester_check_onoff((char *)user_buf, "cpuload:");
458         all_input = cpu_tester_check_onoff((char *)user_buf, "all:");
459
460         pr_info("cpufreq_input=%d cpuidle_input=%d cpuload_input=%d all_input=%d\n"
461                                 , cpufreq_input, cpuidle_input, cpuload_input, all_input);
462
463         /* STEP 2 : checking need to print result or not*/
464         if ((all_input == 0) || (all_input ==1) || (all_input == -1)) {
465                 if ((cpu_tester_en == 1) && (all_input == 0)) {
466                         b_cpu_all_result = 1;
467                 }
468                 if ((all_input == 0) || (all_input ==1)) {
469                         cpufreq_input = all_input;
470                         cpuidle_input = all_input;
471                 }
472                 cpu_tester_en = all_input;
473         } else {
474                 goto fail;
475         }
476
477         if ((cpufreq_input == 0) || (cpufreq_input ==1) || (cpufreq_input == -1)) {
478                 if ((cpufreq_tester_en == 1) && (cpufreq_input == 0)) {
479                         b_cpufreq_result = 1;
480                 }
481                 if (cpufreq_input == 0)
482                         cpufreq_force_state =-1;
483                 cpufreq_tester_en = cpufreq_input;
484         } else {
485                 goto fail;
486         }
487
488         if ((cpuidle_input == 0) || (cpuidle_input ==1) || (cpuidle_input == -1)) {
489                 if ((cpuidle_tester_en == 1) && (cpuidle_input == 0)) {
490                         b_cpuidle_result = 1;
491                 }
492                 if (cpuidle_input == 0)
493                         cpuidle_force_state =-1;
494
495                 cpuidle_tester_en = cpuidle_input;
496         } else {
497                 goto fail;
498         }
499
500         if ((cpuload_input >=  -1) && (cpuload_input <= CPU_NUM)) {
501                 if ((cpuload_input >= 0) && (cpuload_input <= CPU_NUM))
502                         cpuload_tester_en = cpuload_input;
503         } else {
504                 pr_err("cpuload is wrong %d", cpuload_input);
505                 goto fail;
506         }
507
508         /* STEP 3 : print result to kernel log */
509         if ((b_cpufreq_result == 1) || (b_cpuidle_result == 1) || (b_cpu_all_result == 1)) {
510                 #define BUF_SIZE (1024 * 1024)
511                 char *buf;
512
513                 buf = vmalloc(BUF_SIZE);
514                 cpu_test_result_read_sub(buf, BUF_SIZE);
515                 cpu_print_buf_to_klog(buf);
516                 vfree(buf);
517         }
518
519         /* STEP 4 : cpu tester workqueue start  */
520         cpu_tester_work_start(NULL);
521
522 fail:
523
524         return count;
525 }
526
527 static const struct file_operations cpuidle_force_state_fops = {
528         .owner = THIS_MODULE,
529         .read = cpuidle_force_set_read,
530         .write =cpuidle_force_set_write,
531 };
532
533 static const struct file_operations cpufreq_force_state_fops = {
534         .owner = THIS_MODULE,
535         .read = cpufreq_force_set_read,
536         .write =cpufreq_force_set_write,
537 };
538
539 static const struct file_operations cpu_test_result_fops = {
540         .owner = THIS_MODULE,
541         .read = cpu_test_result_read,
542 };
543
544
545 static const struct file_operations cpu_tester_state_fops = {
546         .owner = THIS_MODULE,
547         .read = cpu_tester_state_read,
548 };
549
550
551 static const struct file_operations cpu_tester_en_fops = {
552         .owner = THIS_MODULE,
553         .read = cpu_tester_en_read,
554         .write =cpu_tester_en_write,
555 };
556
557 static int cpu_idle_test_read_sub(char *buf, int buf_size)
558 {
559         int ret = 0, i = 0;
560         char cpuidle_state_name[10] = {0, };
561         int cpu_idle_table_num;
562
563         cpu_idle_table_num = cpu_tester_get_cpu_test_idle_table_num();
564
565         ret +=  snprintf(buf + ret, buf_size - ret
566                 , "========= CPU IDLE STATUS COUNT =========\n"
567                   "   CPUIDLE  COUNT\n");
568
569         for(i = 0; i < cpu_idle_table_num; i++) {
570                 cpu_tester_enum_to_str(cpuidle_state_name
571                         , CPU_IDLE_TEST, cpu_test_idle_table[i].cpuidle);
572
573                 ret +=  snprintf(buf + ret, buf_size - ret
574                         , "%10s\t%d\n"
575                         , cpuidle_state_name
576                         , cpu_test_idle_table[i].exit_count);
577         }
578
579         ret +=  snprintf(buf + ret, buf_size - ret, "\n");
580
581         return ret;
582 }
583
584 static ssize_t cpu_idle_trace_en_read(struct file *file,
585         char __user *buffer, size_t count, loff_t *ppos)
586 {
587         unsigned int size_for_copy;
588
589         size_for_copy = wrapper_for_debug_fs(buffer, count, ppos
590                                         ,cpu_idle_test_read_sub);
591
592         return size_for_copy;
593 }
594
595 static ssize_t cpu_idle_trace_en_write(struct file *file,
596                                       const char __user *user_buf, size_t count,
597                                       loff_t *ppos)
598 {
599         bool input;
600         int i;
601         int cpu_idle_table_num;
602
603         input = (atoi(user_buf) > 0);
604
605         if (input && !cpu_idle_trace_en) {
606                 cpu_idle_table_num = cpu_tester_get_cpu_test_idle_table_num();
607                 for (i = 0; i < cpu_idle_table_num; ++i) {
608                         cpu_test_idle_table[i].enter_count = 0;
609                         cpu_test_idle_table[i].exit_count = 0;
610                 }
611         }
612
613         cpu_idle_trace_en = input;
614
615         return count;
616 }
617
618
619 static const struct file_operations cpu_trace_idle_fops = {
620         .owner = THIS_MODULE,
621         .read = cpu_idle_trace_en_read,
622         .write =cpu_idle_trace_en_write,
623 };
624
625
626 void debugfs_cpu_tester(struct dentry *d)
627 {
628         if (!debugfs_create_file("cpuidle_force_state", 0600
629                 , d, NULL,&cpuidle_force_state_fops))   \
630                         pr_err("%s : debugfs_create_file, error\n", "cpuidle_force_state");
631
632         if (!debugfs_create_file("cpufreq_force_state", 0600
633                 , d, NULL,&cpufreq_force_state_fops))   \
634                         pr_err("%s : debugfs_create_file, error\n", "cpufreq_force_state");
635
636         if (!debugfs_create_file("cpu_tester_state", 0600
637                 , d, NULL,&cpu_tester_state_fops))   \
638                         pr_err("%s : debugfs_create_file, error\n", "cpu_tester_state");
639
640         if (!debugfs_create_file("test_result", 0600
641                 , d, NULL,&cpu_test_result_fops))   \
642                         pr_err("%s : debugfs_create_file, error\n", "cpu_test_result");
643
644         if (!debugfs_create_file("cpu_tester_en", 0600
645                 , d, NULL,&cpu_tester_en_fops))   \
646                         pr_err("%s : debugfs_create_file, error\n", "cpu_tester_en");
647
648         if (!debugfs_create_file("cpu_idle_trace_en", 0600
649                 , d, NULL,&cpu_trace_idle_fops))   \
650                         pr_err("%s : debugfs_create_file, error\n", "cpu_idle_trace_en");
651
652 }
653
654