aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/oprofile/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/oprofile/common.c')
-rw-r--r--arch/arm/oprofile/common.c185
1 files changed, 97 insertions, 88 deletions
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index e57dde882898..1415930ceee1 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -10,74 +10,23 @@
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/oprofile.h> 11#include <linux/oprofile.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <asm/semaphore.h>
14#include <linux/sysdev.h> 13#include <linux/sysdev.h>
14#include <asm/semaphore.h>
15 15
16#include "op_counter.h" 16#include "op_counter.h"
17#include "op_arm_model.h" 17#include "op_arm_model.h"
18 18
19static struct op_arm_model_spec *pmu_model; 19static struct op_arm_model_spec *op_arm_model;
20static int pmu_enabled; 20static int op_arm_enabled;
21static struct semaphore pmu_sem; 21static struct semaphore op_arm_sem;
22
23static int pmu_start(void);
24static int pmu_setup(void);
25static void pmu_stop(void);
26static int pmu_create_files(struct super_block *, struct dentry *);
27
28#ifdef CONFIG_PM
29static int pmu_suspend(struct sys_device *dev, pm_message_t state)
30{
31 if (pmu_enabled)
32 pmu_stop();
33 return 0;
34}
35
36static int pmu_resume(struct sys_device *dev)
37{
38 if (pmu_enabled)
39 pmu_start();
40 return 0;
41}
42
43static struct sysdev_class oprofile_sysclass = {
44 set_kset_name("oprofile"),
45 .resume = pmu_resume,
46 .suspend = pmu_suspend,
47};
48
49static struct sys_device device_oprofile = {
50 .id = 0,
51 .cls = &oprofile_sysclass,
52};
53
54static int __init init_driverfs(void)
55{
56 int ret;
57
58 if (!(ret = sysdev_class_register(&oprofile_sysclass)))
59 ret = sysdev_register(&device_oprofile);
60
61 return ret;
62}
63
64static void exit_driverfs(void)
65{
66 sysdev_unregister(&device_oprofile);
67 sysdev_class_unregister(&oprofile_sysclass);
68}
69#else
70#define init_driverfs() do { } while (0)
71#define exit_driverfs() do { } while (0)
72#endif /* CONFIG_PM */
73 22
74struct op_counter_config counter_config[OP_MAX_COUNTER]; 23struct op_counter_config counter_config[OP_MAX_COUNTER];
75 24
76static int pmu_create_files(struct super_block *sb, struct dentry *root) 25static int op_arm_create_files(struct super_block *sb, struct dentry *root)
77{ 26{
78 unsigned int i; 27 unsigned int i;
79 28
80 for (i = 0; i < pmu_model->num_counters; i++) { 29 for (i = 0; i < op_arm_model->num_counters; i++) {
81 struct dentry *dir; 30 struct dentry *dir;
82 char buf[2]; 31 char buf[2];
83 32
@@ -94,63 +43,123 @@ static int pmu_create_files(struct super_block *sb, struct dentry *root)
94 return 0; 43 return 0;
95} 44}
96 45
97static int pmu_setup(void) 46static int op_arm_setup(void)
98{ 47{
99 int ret; 48 int ret;
100 49
101 spin_lock(&oprofilefs_lock); 50 spin_lock(&oprofilefs_lock);
102 ret = pmu_model->setup_ctrs(); 51 ret = op_arm_model->setup_ctrs();
103 spin_unlock(&oprofilefs_lock); 52 spin_unlock(&oprofilefs_lock);
104 return ret; 53 return ret;
105} 54}
106 55
107static int pmu_start(void) 56static int op_arm_start(void)
108{ 57{
109 int ret = -EBUSY; 58 int ret = -EBUSY;
110 59
111 down(&pmu_sem); 60 down(&op_arm_sem);
112 if (!pmu_enabled) { 61 if (!op_arm_enabled) {
113 ret = pmu_model->start(); 62 ret = op_arm_model->start();
114 pmu_enabled = !ret; 63 op_arm_enabled = !ret;
115 } 64 }
116 up(&pmu_sem); 65 up(&op_arm_sem);
117 return ret; 66 return ret;
118} 67}
119 68
120static void pmu_stop(void) 69static void op_arm_stop(void)
70{
71 down(&op_arm_sem);
72 if (op_arm_enabled)
73 op_arm_model->stop();
74 op_arm_enabled = 0;
75 up(&op_arm_sem);
76}
77
78#ifdef CONFIG_PM
79static int op_arm_suspend(struct sys_device *dev, pm_message_t state)
121{ 80{
122 down(&pmu_sem); 81 down(&op_arm_sem);
123 if (pmu_enabled) 82 if (op_arm_enabled)
124 pmu_model->stop(); 83 op_arm_model->stop();
125 pmu_enabled = 0; 84 up(&op_arm_sem);
126 up(&pmu_sem); 85 return 0;
127} 86}
128 87
129int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec) 88static int op_arm_resume(struct sys_device *dev)
130{ 89{
131 init_MUTEX(&pmu_sem); 90 down(&op_arm_sem);
91 if (op_arm_enabled && op_arm_model->start())
92 op_arm_enabled = 0;
93 up(&op_arm_sem);
94 return 0;
95}
96
97static struct sysdev_class oprofile_sysclass = {
98 set_kset_name("oprofile"),
99 .resume = op_arm_resume,
100 .suspend = op_arm_suspend,
101};
132 102
133 if (spec->init() < 0) 103static struct sys_device device_oprofile = {
134 return -ENODEV; 104 .id = 0,
105 .cls = &oprofile_sysclass,
106};
135 107
136 pmu_model = spec; 108static int __init init_driverfs(void)
137 init_driverfs(); 109{
138 ops->create_files = pmu_create_files; 110 int ret;
139 ops->setup = pmu_setup;
140 ops->shutdown = pmu_stop;
141 ops->start = pmu_start;
142 ops->stop = pmu_stop;
143 ops->cpu_type = pmu_model->name;
144 printk(KERN_INFO "oprofile: using %s PMU\n", spec->name);
145 111
146 return 0; 112 if (!(ret = sysdev_class_register(&oprofile_sysclass)))
113 ret = sysdev_register(&device_oprofile);
114
115 return ret;
116}
117
118static void exit_driverfs(void)
119{
120 sysdev_unregister(&device_oprofile);
121 sysdev_class_unregister(&oprofile_sysclass);
122}
123#else
124#define init_driverfs() do { } while (0)
125#define exit_driverfs() do { } while (0)
126#endif /* CONFIG_PM */
127
128int __init oprofile_arch_init(struct oprofile_operations *ops)
129{
130 struct op_arm_model_spec *spec = NULL;
131 int ret = -ENODEV;
132
133#ifdef CONFIG_CPU_XSCALE
134 spec = &op_xscale_spec;
135#endif
136
137 if (spec) {
138 init_MUTEX(&op_arm_sem);
139
140 if (spec->init() < 0)
141 return -ENODEV;
142
143 op_arm_model = spec;
144 init_driverfs();
145 ops->create_files = op_arm_create_files;
146 ops->setup = op_arm_setup;
147 ops->shutdown = op_arm_stop;
148 ops->start = op_arm_start;
149 ops->stop = op_arm_stop;
150 ops->cpu_type = op_arm_model->name;
151 ops->backtrace = arm_backtrace;
152 printk(KERN_INFO "oprofile: using %s\n", spec->name);
153 }
154
155 return ret;
147} 156}
148 157
149void pmu_exit(void) 158void oprofile_arch_exit(void)
150{ 159{
151 if (pmu_model) { 160 if (op_arm_model) {
152 exit_driverfs(); 161 exit_driverfs();
153 pmu_model = NULL; 162 op_arm_model = NULL;
154 } 163 }
155} 164}
156 165