]> bbs.cooldavid.org Git - net-next-2.6.git/blame - arch/arm/oprofile/common.c
[ARM] Yet more asm/apm-emulation.h stuff
[net-next-2.6.git] / arch / arm / oprofile / common.c
CommitLineData
1da177e4
LT
1/**
2 * @file common.c
3 *
4 * @remark Copyright 2004 Oprofile Authors
5 * @remark Read the file COPYING
6 *
7 * @author Zwane Mwaikambo
8 */
9
10#include <linux/init.h>
11#include <linux/oprofile.h>
12#include <linux/errno.h>
ae92dc9f 13#include <linux/slab.h>
1da177e4 14#include <linux/sysdev.h>
93ad7949 15#include <linux/mutex.h>
1da177e4
LT
16
17#include "op_counter.h"
18#include "op_arm_model.h"
19
55f05234
RK
20static struct op_arm_model_spec *op_arm_model;
21static int op_arm_enabled;
93ad7949 22static DEFINE_MUTEX(op_arm_mutex);
1da177e4 23
ae92dc9f 24struct op_counter_config *counter_config;
1da177e4 25
55f05234 26static int op_arm_create_files(struct super_block *sb, struct dentry *root)
1da177e4
LT
27{
28 unsigned int i;
29
55f05234 30 for (i = 0; i < op_arm_model->num_counters; i++) {
1da177e4 31 struct dentry *dir;
ae92dc9f 32 char buf[4];
1da177e4
LT
33
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);
42 }
43
44 return 0;
45}
46
55f05234 47static int op_arm_setup(void)
1da177e4
LT
48{
49 int ret;
50
51 spin_lock(&oprofilefs_lock);
55f05234 52 ret = op_arm_model->setup_ctrs();
1da177e4
LT
53 spin_unlock(&oprofilefs_lock);
54 return ret;
55}
56
55f05234 57static int op_arm_start(void)
1da177e4
LT
58{
59 int ret = -EBUSY;
60
93ad7949 61 mutex_lock(&op_arm_mutex);
55f05234
RK
62 if (!op_arm_enabled) {
63 ret = op_arm_model->start();
64 op_arm_enabled = !ret;
1da177e4 65 }
93ad7949 66 mutex_unlock(&op_arm_mutex);
1da177e4
LT
67 return ret;
68}
69
55f05234 70static void op_arm_stop(void)
1da177e4 71{
93ad7949 72 mutex_lock(&op_arm_mutex);
55f05234
RK
73 if (op_arm_enabled)
74 op_arm_model->stop();
75 op_arm_enabled = 0;
93ad7949 76 mutex_unlock(&op_arm_mutex);
1da177e4
LT
77}
78
b5893c56 79#ifdef CONFIG_PM
55f05234 80static int op_arm_suspend(struct sys_device *dev, pm_message_t state)
b5893c56 81{
93ad7949 82 mutex_lock(&op_arm_mutex);
55f05234
RK
83 if (op_arm_enabled)
84 op_arm_model->stop();
93ad7949 85 mutex_unlock(&op_arm_mutex);
b5893c56
RK
86 return 0;
87}
88
55f05234 89static int op_arm_resume(struct sys_device *dev)
b5893c56 90{
93ad7949 91 mutex_lock(&op_arm_mutex);
55f05234
RK
92 if (op_arm_enabled && op_arm_model->start())
93 op_arm_enabled = 0;
93ad7949 94 mutex_unlock(&op_arm_mutex);
b5893c56
RK
95 return 0;
96}
97
98static struct sysdev_class oprofile_sysclass = {
99 set_kset_name("oprofile"),
55f05234
RK
100 .resume = op_arm_resume,
101 .suspend = op_arm_suspend,
b5893c56
RK
102};
103
104static struct sys_device device_oprofile = {
105 .id = 0,
106 .cls = &oprofile_sysclass,
107};
108
109static int __init init_driverfs(void)
110{
111 int ret;
112
113 if (!(ret = sysdev_class_register(&oprofile_sysclass)))
114 ret = sysdev_register(&device_oprofile);
115
116 return ret;
117}
118
119static void exit_driverfs(void)
120{
121 sysdev_unregister(&device_oprofile);
122 sysdev_class_unregister(&oprofile_sysclass);
123}
124#else
125#define init_driverfs() do { } while (0)
126#define exit_driverfs() do { } while (0)
127#endif /* CONFIG_PM */
128
c6b9dafc 129int __init oprofile_arch_init(struct oprofile_operations *ops)
1da177e4 130{
c6b9dafc
RK
131 struct op_arm_model_spec *spec = NULL;
132 int ret = -ENODEV;
133
134#ifdef CONFIG_CPU_XSCALE
135 spec = &op_xscale_spec;
136#endif
137
2d9e1ae0
RK
138#ifdef CONFIG_OPROFILE_ARMV6
139 spec = &op_armv6_spec;
140#endif
141
10c03f69
RK
142#ifdef CONFIG_OPROFILE_MPCORE
143 spec = &op_mpcore_spec;
144#endif
145
c6b9dafc 146 if (spec) {
7610dfa3
RD
147 ret = spec->init();
148 if (ret < 0)
149 return ret;
c6b9dafc 150
58e9ff56 151 counter_config = kcalloc(spec->num_counters, sizeof(struct op_counter_config),
ae92dc9f
RK
152 GFP_KERNEL);
153 if (!counter_config)
154 return -ENOMEM;
155
c6b9dafc
RK
156 op_arm_model = spec;
157 init_driverfs();
158 ops->create_files = op_arm_create_files;
159 ops->setup = op_arm_setup;
160 ops->shutdown = op_arm_stop;
161 ops->start = op_arm_start;
162 ops->stop = op_arm_stop;
163 ops->cpu_type = op_arm_model->name;
164 ops->backtrace = arm_backtrace;
165 printk(KERN_INFO "oprofile: using %s\n", spec->name);
166 }
1da177e4 167
c6b9dafc 168 return ret;
1da177e4
LT
169}
170
c6b9dafc 171void oprofile_arch_exit(void)
1da177e4 172{
55f05234 173 if (op_arm_model) {
1da177e4 174 exit_driverfs();
55f05234 175 op_arm_model = NULL;
1da177e4 176 }
ae92dc9f 177 kfree(counter_config);
1da177e4 178}