diff options
Diffstat (limited to 'arch/sh/oprofile/common.c')
-rw-r--r-- | arch/sh/oprofile/common.c | 142 |
1 files changed, 27 insertions, 115 deletions
diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c index 44f4e31c6d63..b4c2d2b946dd 100644 --- a/arch/sh/oprofile/common.c +++ b/arch/sh/oprofile/common.c @@ -1,7 +1,7 @@ /* * arch/sh/oprofile/init.c * - * Copyright (C) 2003 - 2008 Paul Mundt + * Copyright (C) 2003 - 2010 Paul Mundt * * Based on arch/mips/oprofile/common.c: * @@ -17,136 +17,48 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/smp.h> +#include <linux/perf_event.h> +#include <linux/slab.h> #include <asm/processor.h> -#include "op_impl.h" - -extern struct op_sh_model op_model_sh7750_ops __weak; -extern struct op_sh_model op_model_sh4a_ops __weak; - -static struct op_sh_model *model; - -static struct op_counter_config ctr[20]; extern void sh_backtrace(struct pt_regs * const regs, unsigned int depth); -static int op_sh_setup(void) -{ - /* Pre-compute the values to stuff in the hardware registers. */ - model->reg_setup(ctr); - - /* Configure the registers on all cpus. */ - on_each_cpu(model->cpu_setup, NULL, 1); - - return 0; -} - -static int op_sh_create_files(struct super_block *sb, struct dentry *root) -{ - int i, ret = 0; - - for (i = 0; i < model->num_counters; i++) { - struct dentry *dir; - char buf[4]; - - snprintf(buf, sizeof(buf), "%d", i); - dir = oprofilefs_mkdir(sb, root, buf); - - ret |= oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled); - ret |= oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event); - ret |= oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel); - ret |= oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user); - - if (model->create_files) - ret |= model->create_files(sb, dir); - else - ret |= oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count); - - /* Dummy entries */ - ret |= oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask); - } - - return ret; -} - -static int op_sh_start(void) -{ - /* Enable performance monitoring for all counters. */ - on_each_cpu(model->cpu_start, NULL, 1); - - return 0; -} +#ifdef CONFIG_HW_PERF_EVENTS +/* + * This will need to be reworked when multiple PMUs are supported. + */ +static char *sh_pmu_op_name; -static void op_sh_stop(void) +char *op_name_from_perf_id(void) { - /* Disable performance monitoring for all counters. */ - on_each_cpu(model->cpu_stop, NULL, 1); + return sh_pmu_op_name; } int __init oprofile_arch_init(struct oprofile_operations *ops) { - struct op_sh_model *lmodel = NULL; - int ret; - - /* - * Always assign the backtrace op. If the counter initialization - * fails, we fall back to the timer which will still make use of - * this. - */ ops->backtrace = sh_backtrace; - switch (current_cpu_data.type) { - /* SH-4 types */ - case CPU_SH7750: - case CPU_SH7750S: - lmodel = &op_model_sh7750_ops; - break; - - /* SH-4A types */ - case CPU_SH7763: - case CPU_SH7770: - case CPU_SH7780: - case CPU_SH7781: - case CPU_SH7785: - case CPU_SH7786: - case CPU_SH7723: - case CPU_SH7724: - case CPU_SHX3: - lmodel = &op_model_sh4a_ops; - break; - - /* SH4AL-DSP types */ - case CPU_SH7343: - case CPU_SH7722: - case CPU_SH7366: - lmodel = &op_model_sh4a_ops; - break; - } - - if (!lmodel) + if (perf_num_counters() == 0) return -ENODEV; - if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER)) - return -ENODEV; - - ret = lmodel->init(); - if (unlikely(ret != 0)) - return ret; - - model = lmodel; - - ops->setup = op_sh_setup; - ops->create_files = op_sh_create_files; - ops->start = op_sh_start; - ops->stop = op_sh_stop; - ops->cpu_type = lmodel->cpu_type; - printk(KERN_INFO "oprofile: using %s performance monitoring.\n", - lmodel->cpu_type); + sh_pmu_op_name = kasprintf(GFP_KERNEL, "%s/%s", + UTS_MACHINE, perf_pmu_name()); + if (unlikely(!sh_pmu_op_name)) + return -ENOMEM; - return 0; + return oprofile_perf_init(ops); } -void oprofile_arch_exit(void) +void __exit oprofile_arch_exit(void) { - if (model && model->exit) - model->exit(); + oprofile_perf_exit(); + kfree(sh_pmu_op_name); +} +#else +int __init oprofile_arch_init(struct oprofile_operations *ops) +{ + ops->backtrace = sh_backtrace; + return -ENODEV; } +void __exit oprofile_arch_exit(void) {} +#endif /* CONFIG_HW_PERF_EVENTS */ |