blob: f8bb6447b2d0624c2312257e7227cba4cc320f2d [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (C) 2018 MediaTek Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/sched/clock.h>
15#include <linux/fs.h>
16#include <linux/sched.h>
17#include <linux/module.h>
18#include <linux/device.h>
19#include <linux/miscdevice.h>
20#include <linux/kallsyms.h>
21#include <linux/syscore_ops.h>
22#include <linux/dma-mapping.h>
23#include "interface.h"
24#include "sampler.h"
25#include "util.h"
26
27#include "ondiemet.h"
28
29#include "met_drv.h"
30#include "met_tag.h"
31#include "met_kernel_symbol.h"
32#include "met_power.h"
33#include "met_api_tbl.h"
34#include "version.h"
35
36extern int enable_met_backlight_tag(void);
37extern int output_met_backlight_tag(int level);
38
39static int run = -1;
40static int sample_rate = 1000; /* Default: 1000 Hz */
41static int met_suspend_compensation_mode;
42static int met_suspend_compensation_flag;
43
44/*
45 * met_cpu_pmu_method:
46 * 0: MET pmu driver
47 * 1: perf APIs
48 */
49unsigned int met_cpu_pmu_method = 1;
50/*
51 * controls whether re-configuring pmu events after leaving cpu off state
52 */
53unsigned int met_cpu_pm_pmu_reconfig = 1;
54
55int met_hrtimer_expire; /* in ns */
56int met_timer_expire; /* in jiffies */
57unsigned int ctrl_flags;
58int met_mode;
59EXPORT_SYMBOL(met_mode);
60
61DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_nmi);
62EXPORT_SYMBOL(met_strbuf_nmi);
63
64DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_irq);
65EXPORT_SYMBOL(met_strbuf_irq);
66
67DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_sirq);
68EXPORT_SYMBOL(met_strbuf_sirq);
69
70DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf);
71EXPORT_SYMBOL(met_strbuf);
72
73static void calc_timer_value(int rate)
74{
75 sample_rate = rate;
76
77 if (rate == 0) {
78 met_hrtimer_expire = 0;
79 met_timer_expire = 0;
80 return;
81 }
82
83 met_hrtimer_expire = 1000000000 / rate;
84
85 /* Case 1: hrtimer < 1 OS tick, met_timer_expire = 1 OS tick */
86 if (rate > HZ)
87 met_timer_expire = 1;
88 /* Case 2: hrtimer > 1 OS tick, met_timer_expire is hrtimer + 1 OS tick */
89 else
90 met_timer_expire = (HZ / rate) + 1;
91
92 /* pr_debug("JBK HZ=%d, met_hrtimer_expire=%d ns, met_timer_expire=%d ticks\n", */
93 /* HZ, met_hrtimer_expire, met_timer_expire); */
94}
95
96int met_parse_num(const char *str, unsigned int *value, int len)
97{
98 int ret;
99
100 if (len <= 0)
101 return -1;
102
103 if ((len > 2) &&
104 ((str[0] == '0') &&
105 ((str[1] == 'x') || (str[1] == 'X')))) {
106 ret = kstrtoint(str, 16, value);
107 } else {
108 ret = kstrtoint(str, 10, value);
109 }
110
111 if (ret != 0)
112 return -1;
113
114 return 0;
115}
116
117void met_set_suspend_notify(int flag)
118{
119 if (met_suspend_compensation_mode == 1)
120 met_suspend_compensation_flag = flag;
121 else
122 met_suspend_compensation_flag = 0;
123}
124
125LIST_HEAD(met_list);
126static struct kobject *kobj_misc;
127static struct kobject *kobj_pmu;
128static struct kobject *kobj_bus;
129
130static ssize_t ver_show(struct device *dev, struct device_attribute *attr, char *buf);
131static DEVICE_ATTR(ver, 0444, ver_show, NULL);
132
133static ssize_t plf_show(struct device *dev, struct device_attribute *attr, char *buf);
134static DEVICE_ATTR(plf, 0444, plf_show, NULL);
135
136static ssize_t core_topology_show(struct device *dev, struct device_attribute *attr, char *buf);
137static DEVICE_ATTR(core_topology, 0444, core_topology_show, NULL);
138
139static ssize_t devices_show(struct device *dev, struct device_attribute *attr, char *buf);
140static DEVICE_ATTR(devices, 0444, devices_show, NULL);
141
142static ssize_t ctrl_show(struct device *dev, struct device_attribute *attr, char *buf);
143static ssize_t ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf,
144 size_t count);
145static DEVICE_ATTR(ctrl, 0664, ctrl_show, ctrl_store);
146
147static ssize_t spr_show(struct device *dev, struct device_attribute *attr, char *buf);
148static ssize_t spr_store(struct device *dev, struct device_attribute *attr, const char *buf,
149 size_t count);
150static DEVICE_ATTR(sample_rate, 0664, spr_show, spr_store);
151
152static ssize_t run_show(struct device *dev, struct device_attribute *attr, char *buf);
153static ssize_t run_store(struct device *dev, struct device_attribute *attr, const char *buf,
154 size_t count);
155static DEVICE_ATTR(run, 0664, run_show, run_store);
156
157static ssize_t ksym_show(struct device *dev, struct device_attribute *attr, char *buf);
158static ssize_t ksym_store(struct device *dev, struct device_attribute *attr, const char *buf,
159 size_t count);
160static DEVICE_ATTR(ksym, 0664, ksym_show, ksym_store);
161
162static ssize_t cpu_pmu_method_show(struct device *dev, struct device_attribute *attr, char *buf);
163static ssize_t cpu_pmu_method_store(struct device *dev, struct device_attribute *attr, const char *buf,
164 size_t count);
165static DEVICE_ATTR(cpu_pmu_method, 0664, cpu_pmu_method_show, cpu_pmu_method_store);
166
167static ssize_t cpu_pm_pmu_reconfig_show(struct device *dev,
168 struct device_attribute *attr,
169 char *buf);
170static ssize_t cpu_pm_pmu_reconfig_store(struct device *dev,
171 struct device_attribute *attr,
172 const char *buf,
173 size_t count);
174static DEVICE_ATTR(cpu_pm_pmu_reconfig,
175 0664,
176 cpu_pm_pmu_reconfig_show,
177 cpu_pm_pmu_reconfig_store);
178
179#ifdef PR_CPU_NOTIFY
180int met_cpu_notify;
181static ssize_t cpu_notify_show(struct device *dev, struct device_attribute *attr, char *buf);
182static ssize_t cpu_notify_store(struct device *dev, struct device_attribute *attr, const char *buf,
183 size_t count);
184static DEVICE_ATTR(cpu_notify, 0664, cpu_notify_show, cpu_notify_store);
185#endif
186
187#ifdef CONFIG_CPU_FREQ
188static ssize_t dvfs_show(struct device *dev, struct device_attribute *attr, char *buf);
189static ssize_t dvfs_store(struct device *dev, struct device_attribute *attr, const char *buf,
190 size_t count);
191static DEVICE_ATTR(dvfs, 0664, dvfs_show, dvfs_store);
192#endif
193
194static ssize_t suspend_compensation_enable_show(struct device *dev, struct device_attribute *attr, char *buf);
195static ssize_t suspend_compensation_enable_store(struct device *dev, struct device_attribute *attr,
196 const char *buf, size_t count);
197static DEVICE_ATTR(suspend_compensation_enable, 0664, suspend_compensation_enable_show,
198 suspend_compensation_enable_store);
199
200static ssize_t suspend_compensation_flag_show(struct device *dev, struct device_attribute *attr, char *buf);
201static DEVICE_ATTR(suspend_compensation_flag, 0444, suspend_compensation_flag_show, NULL);
202
203static ssize_t ipi_test_store(struct device *dev, struct device_attribute *attr, const char *buf,
204 size_t count);
205static DEVICE_ATTR(ipi_test, 0220, NULL, ipi_test_store);
206
207static const struct file_operations met_file_ops = {
208 .owner = THIS_MODULE
209};
210
211struct miscdevice met_device = {
212 .minor = MISC_DYNAMIC_MINOR,
213 .name = "met",
214 .mode = 0664,
215 .fops = &met_file_ops
216};
217EXPORT_SYMBOL(met_device);
218
219static int met_run(void)
220{
221 sampler_start();
222#ifdef MET_USER_EVENT_SUPPORT
223 bltab.flag &= (~MET_CLASS_ALL);
224#endif
225 ondiemet_start();
226 return 0;
227}
228
229static void met_stop(void)
230{
231#ifdef MET_USER_EVENT_SUPPORT
232 bltab.flag |= MET_CLASS_ALL;
233#endif
234 sampler_stop();
235 /* the met.ko will be use by script "cat ...", release it */
236 if ((ondiemet_module[ONDIEMET_SSPM] == 0) || (sspm_buffer_size == -1))
237 ondiemet_log_manager_stop();
238 ondiemet_stop();
239 ondiemet_extract();
240}
241
242static ssize_t ver_show(struct device *dev, struct device_attribute *attr, char *buf)
243{
244 int i;
245
246 mutex_lock(&dev->mutex);
247 i = snprintf(buf, PAGE_SIZE, "%s\n", MET_BACKEND_VERSION);
248 mutex_unlock(&dev->mutex);
249 return i;
250}
251
252static ssize_t devices_show(struct device *dev, struct device_attribute *attr, char *buf)
253{
254 int len, total_len = 0;
255 struct metdevice *c = NULL;
256
257 mutex_lock(&dev->mutex);
258 list_for_each_entry(c, &met_list, list) {
259 len = 0;
260 if (c->type == MET_TYPE_PMU)
261 len = snprintf(buf, PAGE_SIZE - total_len, "pmu/%s:0\n", c->name);
262 else if (c->type == MET_TYPE_BUS)
263 len = snprintf(buf, PAGE_SIZE - total_len, "bus/%s:0\n", c->name);
264 else if (c->type == MET_TYPE_MISC)
265 len = snprintf(buf, PAGE_SIZE - total_len, "misc/%s:0\n", c->name);
266
267 if (c->ondiemet_mode == 0) {
268 if (c->process_argument)
269 buf[len - 2]++;
270 } else if (c->ondiemet_mode == 1) {
271 if (c->ondiemet_process_argument)
272 buf[len - 2]++;
273 } else if (c->ondiemet_mode == 2) {
274 if (c->process_argument)
275 buf[len - 2]++;
276 if (c->ondiemet_process_argument)
277 buf[len - 2]++;
278 }
279
280 buf += len;
281 total_len += len;
282 }
283
284 mutex_unlock(&dev->mutex);
285 return total_len;
286}
287
288static char met_platform[16] = "none";
289static ssize_t plf_show(struct device *dev, struct device_attribute *attr, char *buf)
290{
291 int i;
292
293 mutex_lock(&dev->mutex);
294 i = snprintf(buf, PAGE_SIZE, "%s\n", met_platform);
295 mutex_unlock(&dev->mutex);
296 return i;
297}
298
299static char met_topology[64] = "none";
300static ssize_t core_topology_show(struct device *dev, struct device_attribute *attr, char *buf)
301{
302 int i;
303
304 mutex_lock(&dev->mutex);
305 i = snprintf(buf, PAGE_SIZE, "%s\n", met_topology);
306 mutex_unlock(&dev->mutex);
307 return i;
308}
309
310static ssize_t ctrl_show(struct device *dev, struct device_attribute *attr, char *buf)
311{
312 return snprintf(buf, PAGE_SIZE, "%d\n", ctrl_flags);
313}
314
315static ssize_t ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf,
316 size_t count)
317{
318 unsigned int value = 0;
319
320 if (met_parse_num(buf, &value, count) < 0)
321 return -EINVAL;
322
323 ctrl_flags = value;
324 return count;
325}
326
327static ssize_t cpu_pmu_method_show(struct device *dev, struct device_attribute *attr, char *buf)
328{
329 return snprintf(buf, PAGE_SIZE, "%d\n", met_cpu_pmu_method);
330}
331
332static ssize_t cpu_pmu_method_store(struct device *dev, struct device_attribute *attr, const char *buf,
333 size_t count)
334{
335 unsigned int value;
336
337 if (met_parse_num(buf, &value, count) < 0)
338 return -EINVAL;
339
340 met_cpu_pmu_method = value;
341 return count;
342}
343
344static ssize_t cpu_pm_pmu_reconfig_show(struct device *dev,
345 struct device_attribute *attr,
346 char *buf)
347{
348 return snprintf(buf, PAGE_SIZE, "%d\n", met_cpu_pm_pmu_reconfig);
349}
350
351static ssize_t cpu_pm_pmu_reconfig_store(struct device *dev,
352 struct device_attribute *attr,
353 const char *buf,
354 size_t count)
355{
356 unsigned int value;
357
358 if (met_parse_num(buf, &value, count) < 0)
359 return -EINVAL;
360
361 met_cpu_pm_pmu_reconfig = value;
362 return count;
363}
364
365static void _test_trace_ipi_raise(void *info)
366{
367 unsigned int *cpu = (unsigned int *)info;
368 void (*arch_send_call_function_single_ipi_sym)(int cpu) = NULL;
369
370 arch_send_call_function_single_ipi_sym = (void *)symbol_get(met_arch_send_call_function_single_ipi);
371 if (arch_send_call_function_single_ipi_sym)
372 arch_send_call_function_single_ipi_sym(*cpu);
373}
374
375
376static ssize_t ipi_test_store(struct device *dev, struct device_attribute *attr, const char *buf,
377 size_t count)
378{
379 int this_cpu = smp_processor_id();
380 unsigned int cpu = 0;
381 unsigned int value;
382
383 if (met_parse_num(buf, &value, count) < 0)
384 return -EINVAL;
385
386 cpu = value;
387 if (cpu == this_cpu)
388 _test_trace_ipi_raise(&cpu);
389 else
390 met_smp_call_function_single_symbol(cpu, _test_trace_ipi_raise, &cpu, 1);
391
392 return count;
393}
394
395
396#if defined(MET_BOOT_MSG)
397char met_boot_msg_tmp[256];
398char met_boot_msg[PAGE_SIZE];
399int met_boot_msg_idx;
400
401int pr_bootmsg(int str_len, char *str)
402{
403 if (met_boot_msg_idx+str_len+1 > PAGE_SIZE)
404 return -1;
405 memcpy(met_boot_msg+met_boot_msg_idx, str, str_len);
406 met_boot_msg_idx += str_len;
407 return 0;
408}
409
410static ssize_t bootmsg_show(struct device *dev, struct device_attribute *attr, char *buf)
411{
412 int i;
413
414 mutex_lock(&dev->mutex);
415 i = snprintf(buf, PAGE_SIZE, "%s\n", met_boot_msg);
416 mutex_unlock(&dev->mutex);
417 return i;
418}
419
420static DEVICE_ATTR_RO(bootmsg);
421EXPORT_SYMBOL(met_boot_msg_tmp);
422EXPORT_SYMBOL(pr_bootmsg);
423#endif
424
425static ssize_t spr_show(struct device *dev, struct device_attribute *attr, char *buf)
426{
427 int i;
428
429 mutex_lock(&dev->mutex);
430 i = snprintf(buf, PAGE_SIZE, "%d\n", sample_rate);
431 mutex_unlock(&dev->mutex);
432 return i;
433}
434
435static ssize_t spr_store(struct device *dev, struct device_attribute *attr, const char *buf,
436 size_t count)
437{
438 int value;
439 struct metdevice *c = NULL;
440
441 mutex_lock(&dev->mutex);
442
443 if ((run == 1) || (count == 0) || (buf == NULL)) {
444 mutex_unlock(&dev->mutex);
445 return -EINVAL;
446 }
447 if (kstrtoint(buf, 0, &value) != 0) {
448 mutex_unlock(&dev->mutex);
449 return -EINVAL;
450 }
451
452 if ((value < 0) || (value > 10000)) {
453 mutex_unlock(&dev->mutex);
454 return -EINVAL;
455 }
456
457 calc_timer_value(value);
458
459 list_for_each_entry(c, &met_list, list) {
460 if (c->polling_interval > 0)
461 c->polling_count_reload = ((c->polling_interval * sample_rate) - 1) / 1000;
462 else
463 c->polling_count_reload = 0;
464 }
465
466 mutex_unlock(&dev->mutex);
467
468 return count;
469}
470
471static ssize_t run_show(struct device *dev, struct device_attribute *attr, char *buf)
472{
473 int i;
474
475 mutex_lock(&dev->mutex);
476 i = snprintf(buf, PAGE_SIZE, "%d\n", run);
477 mutex_unlock(&dev->mutex);
478 return i;
479}
480
481static ssize_t run_store(struct device *dev, struct device_attribute *attr, const char *buf,
482 size_t count)
483{
484 int value;
485
486 mutex_lock(&dev->mutex);
487
488 if ((count == 0) || (buf == NULL)) {
489 mutex_unlock(&dev->mutex);
490 return -EINVAL;
491 }
492 if (kstrtoint(buf, 0, &value) != 0) {
493 mutex_unlock(&dev->mutex);
494 return -EINVAL;
495 }
496
497 switch (value) {
498 case 1:
499 if (run != 1) {
500 run = 1;
501 met_run();
502 }
503 break;
504 case 0:
505 if (run != 0) {
506 if (run == 1) {
507 met_stop();
508#ifdef MET_USER_EVENT_SUPPORT
509#ifdef CONFIG_MET_MODULE
510 met_save_dump_buffer_real("/data/trace.dump");
511#else
512 met_save_dump_buffer("/data/trace.dump");
513#endif
514#endif
515 run = 0;
516 } else
517 /* run == -1 */
518 run = 0;
519 }
520 break;
521 case -1:
522 if (run != -1) {
523 if (run == 1)
524 met_stop();
525
526 run = -1;
527 }
528 break;
529 default:
530 mutex_unlock(&dev->mutex);
531 return -EINVAL;
532 }
533
534 mutex_unlock(&dev->mutex);
535
536 return count;
537}
538
539static unsigned int met_ksym_addr;
540static char met_func_name[512];
541static ssize_t ksym_show(struct device *dev, struct device_attribute *attr, char *buf)
542{
543 int i;
544 int len = 0;
545 int idx = 0;
546
547 mutex_lock(&dev->mutex);
548 if (met_ksym_addr != 0)
549 len = sprint_symbol_no_offset(met_func_name, met_ksym_addr);
550 if (len != 0) {
551 for (idx = 0; idx < 512; idx++)
552 if (met_func_name[idx] == ' ')
553 met_func_name[idx] = '\0';
554 i = snprintf(buf, PAGE_SIZE, "%s\n", met_func_name);
555 } else
556 i = snprintf(buf, PAGE_SIZE, "ksymlookup fail(%x)\n", met_ksym_addr);
557
558 mutex_unlock(&dev->mutex);
559 return i;
560}
561
562static ssize_t ksym_store(struct device *dev, struct device_attribute *attr, const char *buf,
563 size_t count)
564{
565 mutex_lock(&dev->mutex);
566
567 if ((count == 0) || (buf == NULL)) {
568 mutex_unlock(&dev->mutex);
569 return -EINVAL;
570 }
571 if (kstrtoint(buf, 16, &met_ksym_addr) != 0) {
572 mutex_unlock(&dev->mutex);
573 return -EINVAL;
574 }
575
576 mutex_unlock(&dev->mutex);
577
578 return count;
579}
580
581#if defined(PR_CPU_NOTIFY)
582static ssize_t cpu_notify_show(struct device *dev, struct device_attribute *attr, char *buf)
583{
584 int i;
585
586 i = snprintf(buf, PAGE_SIZE, "%d\n", met_cpu_notify);
587 return i;
588}
589
590static ssize_t cpu_notify_store(struct device *dev, struct device_attribute *attr, const char *buf,
591 size_t count)
592{
593 if ((count == 0) || (buf == NULL))
594 return -EINVAL;
595
596 if (kstrtoint(buf, 0, &met_cpu_notify) != 0)
597 return -EINVAL;
598
599 return count;
600}
601#endif
602
603#ifdef CONFIG_CPU_FREQ
604static ssize_t dvfs_show(struct device *dev, struct device_attribute *attr, char *buf)
605{
606 int i;
607
608 i = snprintf(buf, PAGE_SIZE, "%d\n", 0);
609 return i;
610}
611
612static ssize_t dvfs_store(struct device *dev, struct device_attribute *attr, const char *buf,
613 size_t count)
614{
615 return count;
616}
617#endif
618
619static ssize_t suspend_compensation_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
620{
621 int ret;
622
623 ret = snprintf(buf, PAGE_SIZE, "%d\n", met_suspend_compensation_mode);
624
625 return ret;
626}
627
628static ssize_t suspend_compensation_enable_store(struct device *dev, struct device_attribute *attr,
629 const char *buf, size_t count)
630{
631 int value;
632
633 if ((count == 0) || (buf == NULL))
634 return -EINVAL;
635
636 if (kstrtoint(buf, 0, &value) != 0)
637 return -EINVAL;
638
639 if (value < 0)
640 return -EINVAL;
641
642 met_suspend_compensation_mode = value;
643
644 return count;
645}
646
647static ssize_t suspend_compensation_flag_show(struct device *dev, struct device_attribute *attr, char *buf)
648{
649 int ret;
650
651 ret = snprintf(buf, PAGE_SIZE, "%d\n", met_suspend_compensation_flag);
652
653 return ret;
654}
655
656static ssize_t hash_show(struct device *dev, struct device_attribute *attr, char *buf)
657{
658 return 0;
659}
660
661static ssize_t hash_store(struct device *dev, struct device_attribute *attr, const char *buf,
662 size_t count)
663{
664 return 0;
665}
666
667static DEVICE_ATTR(hash, 0664, hash_show, hash_store);
668
669static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
670{
671 struct metdevice *c = NULL;
672
673 list_for_each_entry(c, &met_list, list) {
674 if (c->kobj == kobj)
675 break;
676 }
677 if (c == NULL)
678 return -ENOENT;
679
680 return snprintf(buf, PAGE_SIZE, "%d\n", c->mode);
681}
682
683static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
684 size_t n)
685{
686 struct metdevice *c = NULL;
687
688 list_for_each_entry(c, &met_list, list) {
689 if (c->kobj == kobj)
690 break;
691 }
692 if (c == NULL)
693 return -ENOENT;
694
695 if (kstrtoint(buf, 0, &(c->mode)) != 0)
696 return -EINVAL;
697
698 return n;
699}
700
701static struct kobj_attribute mode_attr = __ATTR(mode, 0664, mode_show, mode_store);
702
703static ssize_t ondiemet_mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
704{
705 struct metdevice *c = NULL;
706
707 list_for_each_entry(c, &met_list, list) {
708 if (c->kobj == kobj)
709 break;
710 }
711 if (c == NULL)
712 return -ENOENT;
713
714 return snprintf(buf, PAGE_SIZE, "%d\n", c->ondiemet_mode);
715}
716
717static ssize_t ondiemet_mode_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
718 size_t n)
719{
720 struct metdevice *c = NULL;
721
722 list_for_each_entry(c, &met_list, list) {
723 if (c->kobj == kobj)
724 break;
725 }
726 if (c == NULL)
727 return -ENOENT;
728
729 if (kstrtoint(buf, 0, &(c->ondiemet_mode)) != 0)
730 return -EINVAL;
731
732 return n;
733}
734
735static struct kobj_attribute ondiemet_mode_attr = __ATTR(ondiemet_mode, 0664, ondiemet_mode_show, ondiemet_mode_store);
736
737static ssize_t polling_interval_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
738{
739 int interval = 1;
740 struct metdevice *c = NULL;
741
742 list_for_each_entry(c, &met_list, list) {
743 if (c->kobj == kobj)
744 break;
745 }
746 if (c == NULL)
747 return -ENOENT;
748
749 if (c->polling_interval)
750 interval = c->polling_interval;
751
752 return snprintf(buf, PAGE_SIZE, "%d\n", interval);
753}
754
755static ssize_t polling_interval_store(struct kobject *kobj, struct kobj_attribute *attr,
756 const char *buf, size_t n)
757{
758 struct metdevice *c = NULL;
759
760 list_for_each_entry(c, &met_list, list) {
761 if (c->kobj == kobj)
762 break;
763 }
764 if (c == NULL)
765 return -ENOENT;
766
767 if (kstrtoint(buf, 0, &(c->polling_interval)) != 0)
768 return -EINVAL;
769
770 if (c->polling_interval > 0)
771 c->polling_count_reload = ((c->polling_interval * sample_rate) - 1) / 1000;
772 else
773 c->polling_count_reload = 0;
774
775 return n;
776}
777
778static struct kobj_attribute polling_interval_attr =
779__ATTR(polling_ms, 0664, polling_interval_show, polling_interval_store);
780
781static ssize_t header_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
782{
783 struct metdevice *c = NULL;
784 ssize_t count = 0;
785
786 list_for_each_entry(c, &met_list, list) {
787 if (c->kobj == kobj)
788 break;
789 }
790 if (c == NULL)
791 return -ENOENT;
792
793 if (c->ondiemet_mode == 0) {
794 if ((c->mode) && (c->print_header))
795 return c->print_header(buf, PAGE_SIZE);
796 } else if (c->ondiemet_mode == 1) {
797 if ((c->mode) && (c->ondiemet_print_header))
798 return c->ondiemet_print_header(buf, PAGE_SIZE);
799 } else if (c->ondiemet_mode == 2) {
800 if ((c->mode) && (c->print_header))
801 count = c->print_header(buf, PAGE_SIZE);
802 if (count < PAGE_SIZE) {
803 if ((c->mode) && (c->ondiemet_print_header))
804 count += c->ondiemet_print_header(buf+count, PAGE_SIZE - count);
805 }
806 return count;
807 }
808
809 return 0;
810}
811
812static struct kobj_attribute header_attr = __ATTR(header, 0444, header_show, NULL);
813
814static ssize_t help_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
815{
816 struct metdevice *c = NULL;
817 ssize_t count = 0;
818
819 list_for_each_entry(c, &met_list, list) {
820 if (c->kobj == kobj)
821 break;
822 }
823 if (c == NULL)
824 return -ENOENT;
825
826 if (c->ondiemet_mode == 0) {
827 if (c->print_help)
828 return c->print_help(buf, PAGE_SIZE);
829 } else if (c->ondiemet_mode == 1) {
830 if (c->ondiemet_print_help)
831 return c->ondiemet_print_help(buf, PAGE_SIZE);
832 } else if (c->ondiemet_mode == 2) {
833 if (c->print_help)
834 count = c->print_help(buf, PAGE_SIZE);
835 if (count < PAGE_SIZE) {
836 if (c->ondiemet_print_help)
837 count += c->ondiemet_print_help(buf+count, PAGE_SIZE - count);
838 }
839 return count;
840 }
841
842 return 0;
843}
844
845static struct kobj_attribute help_attr = __ATTR(help, 0444, help_show, NULL);
846
847static int argu_status = -1;
848static ssize_t argu_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
849 size_t n)
850{
851 int ret = 0;
852 struct metdevice *c = NULL;
853
854 argu_status = -1;
855
856 list_for_each_entry(c, &met_list, list) {
857 if (c->kobj == kobj)
858 break;
859 }
860 if (c == NULL)
861 return -ENOENT;
862
863 if (c->ondiemet_mode == 0) {
864 if (c->process_argument)
865 ret = c->process_argument(buf, (int)n);
866 } else if (c->ondiemet_mode == 1) {
867 if (c->ondiemet_process_argument)
868 ret = c->ondiemet_process_argument(buf, (int)n);
869 } else if (c->ondiemet_mode == 2) {
870 if (c->process_argument)
871 ret = c->process_argument(buf, (int)n);
872 if (c->ondiemet_process_argument)
873 ret = c->ondiemet_process_argument(buf, (int)n);
874 }
875
876 if (ret != 0)
877 return -EINVAL;
878
879 argu_status = 0;
880 return n;
881}
882
883static ssize_t argu_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
884{
885 return snprintf(buf, PAGE_SIZE, "%d\n", argu_status);
886}
887
888static struct kobj_attribute argu_attr = __ATTR(argu, 0664, argu_show, argu_store);
889
890static ssize_t reset_store(struct kobject *kobj,
891 struct kobj_attribute *attr,
892 const char *buf,
893 size_t n)
894{
895 int ret = 0;
896 struct metdevice *c = NULL;
897
898 list_for_each_entry(c, &met_list, list) {
899 if (c->kobj == kobj)
900 break;
901 }
902 if (c == NULL)
903 return -ENOENT;
904
905 if (c->ondiemet_mode == 0) {
906 if (c->reset)
907 ret = c->reset();
908 else
909 c->mode = 0;
910 } else if (c->ondiemet_mode == 1) {
911 if (c->ondiemet_reset)
912 ret = c->ondiemet_reset();
913 } else if (c->ondiemet_mode == 2) {
914 if (c->reset)
915 ret = c->reset();
916 else
917 c->mode = 0;
918 if (c->ondiemet_reset)
919 ret = c->ondiemet_reset();
920 }
921
922 if (ret != 0)
923 return -EINVAL;
924
925 return n;
926}
927
928static struct kobj_attribute reset_attr = __ATTR(reset, 0220, NULL, reset_store);
929
930static ssize_t header_read_again_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
931{
932 struct metdevice *c = NULL;
933
934 list_for_each_entry(c, &met_list, list) {
935 if (c->kobj == kobj)
936 break;
937 }
938 if (c == NULL)
939 return -ENOENT;
940
941 return snprintf(buf, PAGE_SIZE, "%d\n", c->header_read_again);
942}
943
944static struct kobj_attribute header_read_again_attr = __ATTR(header_read_again, 0664, header_read_again_show, NULL);
945
946
947int met_register(struct metdevice *met)
948{
949 int ret, cpu;
950 struct metdevice *c;
951
952 list_for_each_entry(c, &met_list, list) {
953 if (!strcmp(c->name, met->name))
954 return -EEXIST;
955 }
956
957 PR_BOOTMSG("met_register %s ...\n", met->name);
958
959 INIT_LIST_HEAD(&met->list);
960
961 /* Allocate timer count for per CPU */
962 met->polling_count = alloc_percpu(int);
963 if (met->polling_count == NULL)
964 return -EINVAL;
965
966 for_each_possible_cpu(cpu)
967 *(per_cpu_ptr(met->polling_count, cpu)) = 0;
968
969 if (met->polling_interval > 0) {
970 ret = ((met->polling_interval * sample_rate) - 1) / 1000;
971 met->polling_count_reload = ret;
972 } else
973 met->polling_count_reload = 0;
974
975 met->kobj = NULL;
976
977 if (met->type == MET_TYPE_BUS)
978 met->kobj = kobject_create_and_add(met->name, kobj_bus);
979 else if (met->type == MET_TYPE_PMU)
980 met->kobj = kobject_create_and_add(met->name, kobj_pmu);
981 else if (met->type == MET_TYPE_MISC)
982 met->kobj = kobject_create_and_add(met->name, kobj_misc);
983 else {
984 ret = -EINVAL;
985 goto err_out;
986 }
987
988 if (met->kobj == NULL) {
989 ret = -EINVAL;
990 goto err_out;
991 }
992
993 if (met->create_subfs) {
994 ret = met->create_subfs(met->kobj);
995 if (ret)
996 goto err_out;
997 }
998
999 ret = sysfs_create_file(met->kobj, &mode_attr.attr);
1000 if (ret)
1001 goto err_out;
1002
1003
1004 ret = sysfs_create_file(met->kobj, &ondiemet_mode_attr.attr);
1005 if (ret)
1006 goto err_out;
1007
1008 ret = sysfs_create_file(met->kobj, &polling_interval_attr.attr);
1009 if (ret)
1010 goto err_out;
1011
1012 ret = sysfs_create_file(met->kobj, &header_read_again_attr.attr);
1013 if (ret)
1014 goto err_out;
1015
1016 if (met->print_header || met->ondiemet_print_header) {
1017 ret = sysfs_create_file(met->kobj, &header_attr.attr);
1018 if (ret)
1019 goto err_out;
1020 }
1021
1022 if (met->print_help || met->ondiemet_print_help) {
1023 ret = sysfs_create_file(met->kobj, &help_attr.attr);
1024 if (ret)
1025 goto err_out;
1026 }
1027
1028 if (met->process_argument || met->ondiemet_process_argument) {
1029 ret = sysfs_create_file(met->kobj, &argu_attr.attr);
1030 if (ret)
1031 goto err_out;
1032 }
1033
1034 if (met->reset) {
1035 ret = sysfs_create_file(met->kobj, &reset_attr.attr);
1036 if (ret)
1037 goto err_out;
1038 }
1039
1040 spin_lock_init(&met->my_lock);
1041
1042 list_add(&met->list, &met_list);
1043 return 0;
1044
1045 err_out:
1046
1047 if (met->polling_count)
1048 free_percpu(met->polling_count);
1049
1050 if (met->kobj) {
1051 kobject_del(met->kobj);
1052 kobject_put(met->kobj);
1053 met->kobj = NULL;
1054 }
1055
1056 return ret;
1057}
1058EXPORT_SYMBOL(met_register);
1059
1060int met_deregister(struct metdevice *met)
1061{
1062 struct metdevice *c = NULL;
1063
1064 list_for_each_entry(c, &met_list, list) {
1065 if (c == met)
1066 break;
1067 }
1068 if (c != met)
1069 return -ENOENT;
1070
1071 if (met->print_header || met->ondiemet_print_header)
1072 sysfs_remove_file(met->kobj, &header_attr.attr);
1073
1074 if (met->print_help || met->ondiemet_print_help)
1075 sysfs_remove_file(met->kobj, &help_attr.attr);
1076
1077 if (met->process_argument || met->ondiemet_process_argument)
1078 sysfs_remove_file(met->kobj, &argu_attr.attr);
1079
1080 sysfs_remove_file(met->kobj, &reset_attr.attr);
1081 sysfs_remove_file(met->kobj, &header_read_again_attr.attr);
1082 sysfs_remove_file(met->kobj, &polling_interval_attr.attr);
1083 sysfs_remove_file(met->kobj, &mode_attr.attr);
1084 sysfs_remove_file(met->kobj, &ondiemet_mode_attr.attr);
1085
1086 if (met->delete_subfs)
1087 met->delete_subfs();
1088
1089 kobject_del(met->kobj);
1090 kobject_put(met->kobj);
1091 met->kobj = NULL;
1092
1093 if (met->polling_count)
1094 free_percpu(met->polling_count);
1095
1096 list_del(&met->list);
1097 return 0;
1098}
1099EXPORT_SYMBOL(met_deregister);
1100
1101int met_set_platform(const char *plf_name, int flag)
1102{
1103 strncpy(met_platform, plf_name, sizeof(met_platform) - 1);
1104#if 0
1105 int ret;
1106
1107 if (flag) {
1108 ret = device_create_file(met_device.this_device, &dev_attr_plf);
1109 if (ret != 0) {
1110 pr_debug("can not create device file: plf\n");
1111 return ret;
1112 }
1113 strncpy(met_platform, plf_name, sizeof(met_platform) - 1);
1114 } else
1115 device_remove_file(met_device.this_device, &dev_attr_plf);
1116
1117#endif
1118 return 0;
1119}
1120EXPORT_SYMBOL(met_set_platform);
1121
1122int met_set_topology(const char *topology_name, int flag)
1123{
1124 strncpy(met_topology, topology_name, sizeof(met_topology) - 1);
1125#if 0
1126 int ret;
1127
1128 if (flag) {
1129 ret = device_create_file(met_device.this_device, &dev_attr_core_topology);
1130 if (ret != 0) {
1131 pr_debug("can not create device file: topology\n");
1132 return ret;
1133 }
1134 strncpy(met_topology, topology_name, sizeof(met_topology) - 1);
1135 } else {
1136 device_remove_file(met_device.this_device, &dev_attr_core_topology);
1137 }
1138#endif
1139 return 0;
1140}
1141EXPORT_SYMBOL(met_set_topology);
1142
1143#include "met_struct.h"
1144
1145void force_sample(void *unused)
1146{
1147 int cpu;
1148 unsigned long long stamp;
1149 struct metdevice *c;
1150 struct met_cpu_struct *met_cpu_ptr;
1151
1152 if ((run != 1) || (sample_rate == 0))
1153 return;
1154
1155 /* to avoid met tag is coming after __met_hrtimer_stop and before run=-1 */
1156 met_cpu_ptr = this_cpu_ptr(&met_cpu);
1157 if (met_cpu_ptr->work_enabled == 0)
1158 return;
1159
1160 cpu = smp_processor_id();
1161
1162 stamp = cpu_clock(cpu);
1163
1164 list_for_each_entry(c, &met_list, list) {
1165 if (c->ondiemet_mode == 0) {
1166 if ((c->mode != 0) && (c->tagged_polling != NULL))
1167 c->tagged_polling(stamp, 0);
1168 } else if (c->ondiemet_mode == 1) {
1169 if ((c->mode != 0) && (c->ondiemet_tagged_polling != NULL))
1170 c->ondiemet_tagged_polling(stamp, 0);
1171 } else if (c->ondiemet_mode == 2) {
1172 if ((c->mode != 0) && (c->tagged_polling != NULL))
1173 c->tagged_polling(stamp, 0);
1174 if ((c->mode != 0) && (c->ondiemet_tagged_polling != NULL))
1175 c->ondiemet_tagged_polling(stamp, 0);
1176 }
1177 }
1178}
1179
1180#define MET_SUSPEND_HAND
1181#ifdef MET_SUSPEND_HAND
1182static struct syscore_ops met_hrtimer_ops = {
1183 .suspend = met_hrtimer_suspend,
1184 .resume = met_hrtimer_resume,
1185};
1186#endif
1187
1188int fs_reg(void)
1189{
1190 int ret = 0;
1191
1192 ctrl_flags = 0;
1193 met_mode = 0;
1194
1195#ifdef MET_SUSPEND_HAND
1196 /* suspend/resume function handle register */
1197 register_syscore_ops(&met_hrtimer_ops);
1198#endif
1199
1200 calc_timer_value(sample_rate);
1201
1202 ret = misc_register(&met_device);
1203 if (ret != 0) {
1204 pr_debug("misc register failed\n");
1205 return ret;
1206 }
1207
1208 /* dma map config */
1209 /* arch_setup_dma_ops(met_device.this_device, 0, 0, NULL, false); */
1210 met_arch_setup_dma_ops_symbol(met_device.this_device);
1211
1212 ret = device_create_file(met_device.this_device, &dev_attr_ksym);
1213 if (ret != 0) {
1214 pr_debug("can not create device file: ksym\n");
1215 return ret;
1216 }
1217
1218 ret = device_create_file(met_device.this_device, &dev_attr_run);
1219 if (ret != 0) {
1220 pr_debug("can not create device file: run\n");
1221 return ret;
1222 }
1223
1224#if defined(PR_CPU_NOTIFY)
1225 ret = device_create_file(met_device.this_device, &dev_attr_cpu_notify);
1226 if (ret != 0) {
1227 pr_debug("can not create device file: cpu_notify\n");
1228 return ret;
1229 }
1230#endif
1231
1232#ifdef CONFIG_CPU_FREQ
1233 ret = device_create_file(met_device.this_device, &dev_attr_dvfs);
1234 if (ret != 0) {
1235 pr_debug("can not create device file: dvfs\n");
1236 return ret;
1237 }
1238#endif
1239
1240 ret = device_create_file(met_device.this_device, &dev_attr_suspend_compensation_enable);
1241 if (ret != 0) {
1242 pr_debug("can not create device file: suspend_compensation_enable\n");
1243 return ret;
1244 }
1245
1246 ret = device_create_file(met_device.this_device, &dev_attr_suspend_compensation_flag);
1247 if (ret != 0) {
1248 pr_debug("can not create device file: suspend_compensation_enable\n");
1249 return ret;
1250 }
1251
1252 ret = device_create_file(met_device.this_device, &dev_attr_ver);
1253 if (ret != 0) {
1254 pr_debug("can not create device file: ver\n");
1255 return ret;
1256 }
1257
1258 ret = device_create_file(met_device.this_device, &dev_attr_devices);
1259 if (ret != 0) {
1260 pr_debug("can not create device file: devices\n");
1261 return ret;
1262 }
1263
1264 ret = device_create_file(met_device.this_device, &dev_attr_ctrl);
1265 if (ret != 0) {
1266 pr_debug("can not create device file: ctrl\n");
1267 return ret;
1268 }
1269
1270 ret = device_create_file(met_device.this_device, &dev_attr_cpu_pmu_method);
1271 if (ret != 0) {
1272 pr_debug("can not create device file: cpu_pmu_method\n");
1273 return ret;
1274 }
1275
1276 ret = device_create_file(met_device.this_device, &dev_attr_cpu_pm_pmu_reconfig);
1277 if (ret != 0) {
1278 pr_debug("can not create device file: cpu_pm_pmu_reconfig\n");
1279 return ret;
1280 }
1281
1282#if defined(MET_BOOT_MSG)
1283 ret = device_create_file(met_device.this_device, &dev_attr_bootmsg);
1284 if (ret != 0) {
1285 pr_debug("can not create device file: bootmsg\n");
1286 return ret;
1287 }
1288#endif
1289
1290 ret = device_create_file(met_device.this_device, &dev_attr_sample_rate);
1291 if (ret != 0) {
1292 pr_debug("can not create device file: sample_rate\n");
1293 return ret;
1294 }
1295
1296 ret = device_create_file(met_device.this_device, &dev_attr_core_topology);
1297 if (ret != 0) {
1298 pr_debug("can not create device file: topology\n");
1299 return ret;
1300 }
1301
1302 ret = device_create_file(met_device.this_device, &dev_attr_plf);
1303 if (ret != 0) {
1304 pr_debug("can not create device file: plf\n");
1305 return ret;
1306 }
1307
1308 ret = device_create_file(met_device.this_device, &dev_attr_hash);
1309 if (ret != 0) {
1310 pr_debug("can not create device file: hash\n");
1311 return ret;
1312 }
1313
1314 ret = device_create_file(met_device.this_device, &dev_attr_ipi_test);
1315 if (ret != 0) {
1316 pr_debug("can not create device file: ipi_test\n");
1317 return ret;
1318 }
1319
1320 kobj_misc = kobject_create_and_add("misc", &met_device.this_device->kobj);
1321 if (kobj_misc == NULL) {
1322 pr_debug("can not create kobject: kobj_misc\n");
1323 return ret;
1324 }
1325
1326 kobj_pmu = kobject_create_and_add("pmu", &met_device.this_device->kobj);
1327 if (kobj_pmu == NULL) {
1328 pr_debug("can not create kobject: kobj_pmu\n");
1329 return ret;
1330 }
1331
1332 kobj_bus = kobject_create_and_add("bus", &met_device.this_device->kobj);
1333 if (kobj_bus == NULL) {
1334 pr_debug("can not create kobject: kobj_bus\n");
1335 return ret;
1336 }
1337
1338 met_register(&met_cookie);
1339 met_register(&met_cpupmu);
1340 met_register(&met_memstat);
1341 met_register(&met_switch);
1342#ifdef MET_EVENT_POWER_SUPPORT
1343 met_register(&met_trace_event);
1344 met_ext_api.met_pm_qos_update_request = pm_qos_update_request;
1345 met_ext_api.met_pm_qos_update_target = pm_qos_update_target;
1346#endif
1347
1348 met_register(&met_dummy_header);
1349
1350 met_register(&met_backlight);
1351 met_ext_api.enable_met_backlight_tag = enable_met_backlight_tag_real;
1352 met_ext_api.output_met_backlight_tag = output_met_backlight_tag_real;
1353
1354#ifdef MET_USER_EVENT_SUPPORT
1355 tag_reg((struct file_operations * const) met_device.fops, &met_device.this_device->kobj);
1356#endif
1357
1358 met_register(&met_stat);
1359
1360 ondiemet_log_manager_init(met_device.this_device);
1361 ondiemet_attr_init(met_device.this_device);
1362
1363 return ret;
1364}
1365
1366void fs_unreg(void)
1367{
1368 if (run == 1)
1369 met_stop();
1370
1371 run = -1;
1372
1373 met_deregister(&met_stat);
1374
1375#ifdef MET_USER_EVENT_SUPPORT
1376 tag_unreg();
1377#endif
1378
1379 met_deregister(&met_dummy_header);
1380#ifdef MET_EVENT_POWER_SUPPORT
1381 met_deregister(&met_trace_event);
1382 met_ext_api.met_pm_qos_update_request = NULL;
1383 met_ext_api.met_pm_qos_update_target = NULL;
1384#endif
1385 met_deregister(&met_switch);
1386 met_deregister(&met_memstat);
1387 met_deregister(&met_cpupmu);
1388 met_deregister(&met_cookie);
1389 met_deregister(&met_backlight);
1390 met_ext_api.enable_met_backlight_tag = NULL;
1391 met_ext_api.output_met_backlight_tag = NULL;
1392
1393 kobject_del(kobj_misc);
1394 kobject_put(kobj_misc);
1395 kobj_misc = NULL;
1396 kobject_del(kobj_pmu);
1397 kobject_put(kobj_pmu);
1398 kobj_pmu = NULL;
1399 kobject_del(kobj_bus);
1400 kobject_put(kobj_bus);
1401 kobj_bus = NULL;
1402
1403 device_remove_file(met_device.this_device, &dev_attr_ksym);
1404
1405 device_remove_file(met_device.this_device, &dev_attr_run);
1406#ifdef PR_CPU_NOTIFY
1407 device_remove_file(met_device.this_device, &dev_attr_cpu_notify);
1408#endif
1409#ifdef CONFIG_CPU_FREQ
1410 device_remove_file(met_device.this_device, &dev_attr_dvfs);
1411#endif
1412 device_remove_file(met_device.this_device, &dev_attr_suspend_compensation_enable);
1413 device_remove_file(met_device.this_device, &dev_attr_suspend_compensation_flag);
1414
1415 device_remove_file(met_device.this_device, &dev_attr_ver);
1416 device_remove_file(met_device.this_device, &dev_attr_devices);
1417 device_remove_file(met_device.this_device, &dev_attr_sample_rate);
1418
1419 device_remove_file(met_device.this_device, &dev_attr_ctrl);
1420 device_remove_file(met_device.this_device, &dev_attr_cpu_pmu_method);
1421 device_remove_file(met_device.this_device, &dev_attr_cpu_pm_pmu_reconfig);
1422
1423 device_remove_file(met_device.this_device, &dev_attr_core_topology);
1424 device_remove_file(met_device.this_device, &dev_attr_plf);
1425 device_remove_file(met_device.this_device, &dev_attr_hash);
1426 device_remove_file(met_device.this_device, &dev_attr_ipi_test);
1427
1428 ondiemet_log_manager_uninit(met_device.this_device);
1429 ondiemet_attr_uninit(met_device.this_device);
1430
1431 misc_deregister(&met_device);
1432#ifdef MET_SUSPEND_HAND
1433 /* suspend/resume function handle register */
1434 unregister_syscore_ops(&met_hrtimer_ops);
1435#endif
1436}
1437
1438unsigned int get_ctrl_flags(void)
1439{
1440 return ctrl_flags;
1441}