diff options
author | Will Deacon <will.deacon@arm.com> | 2010-04-30 06:38:39 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-05-17 06:53:59 -0400 |
commit | d1e86d64bc48dedd0d68d182d0ce6951d8b4fd0d (patch) | |
tree | dda2df2133dc73a542d6c59df5da84f731ab1b85 | |
parent | fe166148f699cc7865ca07b6754872cfb5ebc312 (diff) |
ARM: 6074/1: oprofile: convert from sysdev to platform device
This is a reworking of an original patch posted by Aaro Koskinen:
oprofile does not work with PM, because sysdev_suspend() is done with
interrupts disabled and oprofile needs a mutex. Implementing oprofile
as a platform device solves this problem.
Cc: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/oprofile/common.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index aad83df89bac..0691176899ff 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c | |||
@@ -10,13 +10,14 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/cpumask.h> | 12 | #include <linux/cpumask.h> |
13 | #include <linux/err.h> | ||
13 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
16 | #include <linux/oprofile.h> | 17 | #include <linux/oprofile.h> |
17 | #include <linux/perf_event.h> | 18 | #include <linux/perf_event.h> |
19 | #include <linux/platform_device.h> | ||
18 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
19 | #include <linux/sysdev.h> | ||
20 | #include <asm/stacktrace.h> | 21 | #include <asm/stacktrace.h> |
21 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
22 | 23 | ||
@@ -227,7 +228,7 @@ static void op_arm_stop(void) | |||
227 | } | 228 | } |
228 | 229 | ||
229 | #ifdef CONFIG_PM | 230 | #ifdef CONFIG_PM |
230 | static int op_arm_suspend(struct sys_device *dev, pm_message_t state) | 231 | static int op_arm_suspend(struct platform_device *dev, pm_message_t state) |
231 | { | 232 | { |
232 | mutex_lock(&op_arm_mutex); | 233 | mutex_lock(&op_arm_mutex); |
233 | if (op_arm_enabled) | 234 | if (op_arm_enabled) |
@@ -236,7 +237,7 @@ static int op_arm_suspend(struct sys_device *dev, pm_message_t state) | |||
236 | return 0; | 237 | return 0; |
237 | } | 238 | } |
238 | 239 | ||
239 | static int op_arm_resume(struct sys_device *dev) | 240 | static int op_arm_resume(struct platform_device *dev) |
240 | { | 241 | { |
241 | mutex_lock(&op_arm_mutex); | 242 | mutex_lock(&op_arm_mutex); |
242 | if (op_arm_enabled && op_perf_start()) | 243 | if (op_arm_enabled && op_perf_start()) |
@@ -245,34 +246,42 @@ static int op_arm_resume(struct sys_device *dev) | |||
245 | return 0; | 246 | return 0; |
246 | } | 247 | } |
247 | 248 | ||
248 | static struct sysdev_class oprofile_sysclass = { | 249 | static struct platform_driver oprofile_driver = { |
249 | .name = "oprofile", | 250 | .driver = { |
251 | .name = "arm-oprofile", | ||
252 | }, | ||
250 | .resume = op_arm_resume, | 253 | .resume = op_arm_resume, |
251 | .suspend = op_arm_suspend, | 254 | .suspend = op_arm_suspend, |
252 | }; | 255 | }; |
253 | 256 | ||
254 | static struct sys_device device_oprofile = { | 257 | static struct platform_device *oprofile_pdev; |
255 | .id = 0, | ||
256 | .cls = &oprofile_sysclass, | ||
257 | }; | ||
258 | 258 | ||
259 | static int __init init_driverfs(void) | 259 | static int __init init_driverfs(void) |
260 | { | 260 | { |
261 | int ret; | 261 | int ret; |
262 | 262 | ||
263 | if (!(ret = sysdev_class_register(&oprofile_sysclass))) | 263 | ret = platform_driver_register(&oprofile_driver); |
264 | ret = sysdev_register(&device_oprofile); | 264 | if (ret) |
265 | goto out; | ||
266 | |||
267 | oprofile_pdev = platform_device_register_simple( | ||
268 | oprofile_driver.driver.name, 0, NULL, 0); | ||
269 | if (IS_ERR(oprofile_pdev)) { | ||
270 | ret = PTR_ERR(oprofile_pdev); | ||
271 | platform_driver_unregister(&oprofile_driver); | ||
272 | } | ||
265 | 273 | ||
274 | out: | ||
266 | return ret; | 275 | return ret; |
267 | } | 276 | } |
268 | 277 | ||
269 | static void exit_driverfs(void) | 278 | static void exit_driverfs(void) |
270 | { | 279 | { |
271 | sysdev_unregister(&device_oprofile); | 280 | platform_device_unregister(oprofile_pdev); |
272 | sysdev_class_unregister(&oprofile_sysclass); | 281 | platform_driver_unregister(&oprofile_driver); |
273 | } | 282 | } |
274 | #else | 283 | #else |
275 | #define init_driverfs() do { } while (0) | 284 | static int __init init_driverfs(void) { return 0; } |
276 | #define exit_driverfs() do { } while (0) | 285 | #define exit_driverfs() do { } while (0) |
277 | #endif /* CONFIG_PM */ | 286 | #endif /* CONFIG_PM */ |
278 | 287 | ||
@@ -353,6 +362,12 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
353 | return -ENOMEM; | 362 | return -ENOMEM; |
354 | } | 363 | } |
355 | 364 | ||
365 | ret = init_driverfs(); | ||
366 | if (ret) { | ||
367 | kfree(counter_config); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
356 | for_each_possible_cpu(cpu) { | 371 | for_each_possible_cpu(cpu) { |
357 | perf_events[cpu] = kcalloc(perf_num_counters, | 372 | perf_events[cpu] = kcalloc(perf_num_counters, |
358 | sizeof(struct perf_event *), GFP_KERNEL); | 373 | sizeof(struct perf_event *), GFP_KERNEL); |
@@ -365,7 +380,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
365 | } | 380 | } |
366 | } | 381 | } |
367 | 382 | ||
368 | init_driverfs(); | ||
369 | ops->backtrace = arm_backtrace; | 383 | ops->backtrace = arm_backtrace; |
370 | ops->create_files = op_arm_create_files; | 384 | ops->create_files = op_arm_create_files; |
371 | ops->setup = op_arm_setup; | 385 | ops->setup = op_arm_setup; |