diff options
Diffstat (limited to 'arch/sh/oprofile/common.c')
-rw-r--r-- | arch/sh/oprofile/common.c | 120 |
1 files changed, 27 insertions, 93 deletions
diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c index ac604937f3ee..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,114 +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" - -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; - /* - * XXX - * - * All of the SH7750/SH-4A counters have been converted to perf, - * this infrastructure hook is left for other users until they've - * had a chance to convert over, at which point all of this - * will be deleted. - */ - - if (!lmodel) - return -ENODEV; - if (!(current_cpu_data.flags & CPU_HAS_PERF_COUNTER)) + if (perf_num_counters() == 0) return -ENODEV; - ret = lmodel->init(); - if (unlikely(ret != 0)) - return ret; + sh_pmu_op_name = kasprintf(GFP_KERNEL, "%s/%s", + UTS_MACHINE, perf_pmu_name()); + if (unlikely(!sh_pmu_op_name)) + return -ENOMEM; - 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); - - 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 */ |