diff options
Diffstat (limited to 'arch/arm/oprofile/common.c')
| -rw-r--r-- | arch/arm/oprofile/common.c | 185 | 
1 files changed, 97 insertions, 88 deletions
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index e57dde88289..1415930ceee 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -10,74 +10,23 @@  #include <linux/init.h>  #include <linux/oprofile.h>  #include <linux/errno.h> -#include <asm/semaphore.h>  #include <linux/sysdev.h> +#include <asm/semaphore.h>  #include "op_counter.h"  #include "op_arm_model.h" -static struct op_arm_model_spec *pmu_model; -static int pmu_enabled; -static struct semaphore pmu_sem; - -static int pmu_start(void); -static int pmu_setup(void); -static void pmu_stop(void); -static int pmu_create_files(struct super_block *, struct dentry *); - -#ifdef CONFIG_PM -static int pmu_suspend(struct sys_device *dev, pm_message_t state) -{ -	if (pmu_enabled) -		pmu_stop(); -	return 0; -} - -static int pmu_resume(struct sys_device *dev) -{ -	if (pmu_enabled) -		pmu_start(); -	return 0; -} - -static struct sysdev_class oprofile_sysclass = { -	set_kset_name("oprofile"), -	.resume		= pmu_resume, -	.suspend	= pmu_suspend, -}; - -static struct sys_device device_oprofile = { -	.id		= 0, -	.cls		= &oprofile_sysclass, -}; - -static int __init init_driverfs(void) -{ -	int ret; - -	if (!(ret = sysdev_class_register(&oprofile_sysclass))) -		ret = sysdev_register(&device_oprofile); - -	return ret; -} - -static void  exit_driverfs(void) -{ -	sysdev_unregister(&device_oprofile); -	sysdev_class_unregister(&oprofile_sysclass); -} -#else -#define init_driverfs()	do { } while (0) -#define exit_driverfs() do { } while (0) -#endif /* CONFIG_PM */ +static struct op_arm_model_spec *op_arm_model; +static int op_arm_enabled; +static struct semaphore op_arm_sem;  struct op_counter_config counter_config[OP_MAX_COUNTER]; -static int pmu_create_files(struct super_block *sb, struct dentry *root) +static int op_arm_create_files(struct super_block *sb, struct dentry *root)  {  	unsigned int i; -	for (i = 0; i < pmu_model->num_counters; i++) { +	for (i = 0; i < op_arm_model->num_counters; i++) {  		struct dentry *dir;  		char buf[2]; @@ -94,63 +43,123 @@ static int pmu_create_files(struct super_block *sb, struct dentry *root)  	return 0;  } -static int pmu_setup(void) +static int op_arm_setup(void)  {  	int ret;  	spin_lock(&oprofilefs_lock); -	ret = pmu_model->setup_ctrs(); +	ret = op_arm_model->setup_ctrs();  	spin_unlock(&oprofilefs_lock);  	return ret;  } -static int pmu_start(void) +static int op_arm_start(void)  {  	int ret = -EBUSY; -	down(&pmu_sem); -	if (!pmu_enabled) { -		ret = pmu_model->start(); -		pmu_enabled = !ret; +	down(&op_arm_sem); +	if (!op_arm_enabled) { +		ret = op_arm_model->start(); +		op_arm_enabled = !ret;  	} -	up(&pmu_sem); +	up(&op_arm_sem);  	return ret;  } -static void pmu_stop(void) +static void op_arm_stop(void) +{ +	down(&op_arm_sem); +	if (op_arm_enabled) +		op_arm_model->stop(); +	op_arm_enabled = 0; +	up(&op_arm_sem); +} + +#ifdef CONFIG_PM +static int op_arm_suspend(struct sys_device *dev, pm_message_t state)  { -	down(&pmu_sem); -	if (pmu_enabled) -		pmu_model->stop(); -	pmu_enabled = 0; -	up(&pmu_sem); +	down(&op_arm_sem); +	if (op_arm_enabled) +		op_arm_model->stop(); +	up(&op_arm_sem); +	return 0;  } -int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec) +static int op_arm_resume(struct sys_device *dev)  { -	init_MUTEX(&pmu_sem); +	down(&op_arm_sem); +	if (op_arm_enabled && op_arm_model->start()) +		op_arm_enabled = 0; +	up(&op_arm_sem); +	return 0; +} + +static struct sysdev_class oprofile_sysclass = { +	set_kset_name("oprofile"), +	.resume		= op_arm_resume, +	.suspend	= op_arm_suspend, +}; -	if (spec->init() < 0) -		return -ENODEV; +static struct sys_device device_oprofile = { +	.id		= 0, +	.cls		= &oprofile_sysclass, +}; -	pmu_model = spec; -	init_driverfs(); -	ops->create_files = pmu_create_files; -	ops->setup = pmu_setup; -	ops->shutdown = pmu_stop; -	ops->start = pmu_start; -	ops->stop = pmu_stop; -	ops->cpu_type = pmu_model->name; -	printk(KERN_INFO "oprofile: using %s PMU\n", spec->name); +static int __init init_driverfs(void) +{ +	int ret; -	return 0; +	if (!(ret = sysdev_class_register(&oprofile_sysclass))) +		ret = sysdev_register(&device_oprofile); + +	return ret; +} + +static void  exit_driverfs(void) +{ +	sysdev_unregister(&device_oprofile); +	sysdev_class_unregister(&oprofile_sysclass); +} +#else +#define init_driverfs()	do { } while (0) +#define exit_driverfs() do { } while (0) +#endif /* CONFIG_PM */ + +int __init oprofile_arch_init(struct oprofile_operations *ops) +{ +	struct op_arm_model_spec *spec = NULL; +	int ret = -ENODEV; + +#ifdef CONFIG_CPU_XSCALE +	spec = &op_xscale_spec; +#endif + +	if (spec) { +		init_MUTEX(&op_arm_sem); + +		if (spec->init() < 0) +			return -ENODEV; + +		op_arm_model = spec; +		init_driverfs(); +		ops->create_files = op_arm_create_files; +		ops->setup = op_arm_setup; +		ops->shutdown = op_arm_stop; +		ops->start = op_arm_start; +		ops->stop = op_arm_stop; +		ops->cpu_type = op_arm_model->name; +		ops->backtrace = arm_backtrace; +		printk(KERN_INFO "oprofile: using %s\n", spec->name); +	} + +	return ret;  } -void pmu_exit(void) +void oprofile_arch_exit(void)  { -	if (pmu_model) { +	if (op_arm_model) {  		exit_driverfs(); -		pmu_model = NULL; +		op_arm_model = NULL;  	}  }  | 
