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