4 * @remark Copyright 2004 Oprofile Authors
5 * @remark Read the file COPYING
7 * @author Zwane Mwaikambo
10 #include <linux/init.h>
11 #include <linux/oprofile.h>
12 #include <linux/errno.h>
13 #include <linux/slab.h>
14 #include <linux/sysdev.h>
15 #include <linux/mutex.h>
17 #include "op_counter.h"
18 #include "op_arm_model.h"
20 static struct op_arm_model_spec
*op_arm_model
;
21 static int op_arm_enabled
;
22 static DEFINE_MUTEX(op_arm_mutex
);
24 struct op_counter_config
*counter_config
;
26 static int op_arm_create_files(struct super_block
*sb
, struct dentry
*root
)
30 for (i
= 0; i
< op_arm_model
->num_counters
; i
++) {
34 snprintf(buf
, sizeof buf
, "%d", i
);
35 dir
= oprofilefs_mkdir(sb
, root
, buf
);
36 oprofilefs_create_ulong(sb
, dir
, "enabled", &counter_config
[i
].enabled
);
37 oprofilefs_create_ulong(sb
, dir
, "event", &counter_config
[i
].event
);
38 oprofilefs_create_ulong(sb
, dir
, "count", &counter_config
[i
].count
);
39 oprofilefs_create_ulong(sb
, dir
, "unit_mask", &counter_config
[i
].unit_mask
);
40 oprofilefs_create_ulong(sb
, dir
, "kernel", &counter_config
[i
].kernel
);
41 oprofilefs_create_ulong(sb
, dir
, "user", &counter_config
[i
].user
);
47 static int op_arm_setup(void)
51 spin_lock(&oprofilefs_lock
);
52 ret
= op_arm_model
->setup_ctrs();
53 spin_unlock(&oprofilefs_lock
);
57 static int op_arm_start(void)
61 mutex_lock(&op_arm_mutex
);
62 if (!op_arm_enabled
) {
63 ret
= op_arm_model
->start();
64 op_arm_enabled
= !ret
;
66 mutex_unlock(&op_arm_mutex
);
70 static void op_arm_stop(void)
72 mutex_lock(&op_arm_mutex
);
76 mutex_unlock(&op_arm_mutex
);
80 static int op_arm_suspend(struct sys_device
*dev
, pm_message_t state
)
82 mutex_lock(&op_arm_mutex
);
85 mutex_unlock(&op_arm_mutex
);
89 static int op_arm_resume(struct sys_device
*dev
)
91 mutex_lock(&op_arm_mutex
);
92 if (op_arm_enabled
&& op_arm_model
->start())
94 mutex_unlock(&op_arm_mutex
);
98 static struct sysdev_class oprofile_sysclass
= {
100 .resume
= op_arm_resume
,
101 .suspend
= op_arm_suspend
,
104 static struct sys_device device_oprofile
= {
106 .cls
= &oprofile_sysclass
,
109 static int __init
init_driverfs(void)
113 if (!(ret
= sysdev_class_register(&oprofile_sysclass
)))
114 ret
= sysdev_register(&device_oprofile
);
119 static void exit_driverfs(void)
121 sysdev_unregister(&device_oprofile
);
122 sysdev_class_unregister(&oprofile_sysclass
);
125 #define init_driverfs() do { } while (0)
126 #define exit_driverfs() do { } while (0)
127 #endif /* CONFIG_PM */
129 int __init
oprofile_arch_init(struct oprofile_operations
*ops
)
131 struct op_arm_model_spec
*spec
= NULL
;
134 ops
->backtrace
= arm_backtrace
;
136 #ifdef CONFIG_CPU_XSCALE
137 spec
= &op_xscale_spec
;
140 #ifdef CONFIG_OPROFILE_ARMV6
141 spec
= &op_armv6_spec
;
144 #ifdef CONFIG_OPROFILE_MPCORE
145 spec
= &op_mpcore_spec
;
148 #ifdef CONFIG_OPROFILE_ARMV7
149 spec
= &op_armv7_spec
;
157 counter_config
= kcalloc(spec
->num_counters
, sizeof(struct op_counter_config
),
164 ops
->create_files
= op_arm_create_files
;
165 ops
->setup
= op_arm_setup
;
166 ops
->shutdown
= op_arm_stop
;
167 ops
->start
= op_arm_start
;
168 ops
->stop
= op_arm_stop
;
169 ops
->cpu_type
= op_arm_model
->name
;
170 printk(KERN_INFO
"oprofile: using %s\n", spec
->name
);
176 void oprofile_arch_exit(void)
182 kfree(counter_config
);