aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2010-04-30 06:38:39 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-05-17 06:53:59 -0400
commitd1e86d64bc48dedd0d68d182d0ce6951d8b4fd0d (patch)
treedda2df2133dc73a542d6c59df5da84f731ab1b85
parentfe166148f699cc7865ca07b6754872cfb5ebc312 (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.c44
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
230static int op_arm_suspend(struct sys_device *dev, pm_message_t state) 231static 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
239static int op_arm_resume(struct sys_device *dev) 240static 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
248static struct sysdev_class oprofile_sysclass = { 249static 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
254static struct sys_device device_oprofile = { 257static struct platform_device *oprofile_pdev;
255 .id = 0,
256 .cls = &oprofile_sysclass,
257};
258 258
259static int __init init_driverfs(void) 259static 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
274out:
266 return ret; 275 return ret;
267} 276}
268 277
269static void exit_driverfs(void) 278static 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) 284static 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;