Commit d360d565 authored by Akinobu Mita's avatar Akinobu Mita Committed by Linus Torvalds

[PATCH] oprofile: falling back on timer interrupt mode

When some hardware setups or architectures do not allow OProfile to use
performance counters, OProfile operates in timer mode.

But, from 2.6.11-rc1, we need to specify the module parameter "timer=1" to
work on timer interrupt mode.  Change things so that we detect the absence of
the high-resolution timer and fall back to timer-based profiling
automatically.

Furthermore we can easily get oops by reading /dev/oprofile/cpu_type.
Signed-off-by: default avatarAkinobu Mita <amgta@yacht.ocn.ne.jp>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3680d547
......@@ -138,7 +138,7 @@ op_axp_create_files(struct super_block * sb, struct dentry * root)
return 0;
}
void __init
int __init
oprofile_arch_init(struct oprofile_operations *ops)
{
struct op_axp_model *lmodel = NULL;
......@@ -166,7 +166,7 @@ oprofile_arch_init(struct oprofile_operations *ops)
}
if (!lmodel)
return;
return -ENODEV;
model = lmodel;
ops->create_files = op_axp_create_files;
......@@ -178,6 +178,8 @@ oprofile_arch_init(struct oprofile_operations *ops)
printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
lmodel->cpu_type);
return 0;
}
......
......@@ -105,12 +105,13 @@ static void pmu_stop(void)
up(&pmu_sem);
}
void __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec)
int __init
pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec)
{
init_MUTEX(&pmu_sem);
if (spec->init() < 0)
return;
return -ENODEV;
pmu_model = spec;
init_driverfs();
......@@ -121,6 +122,8 @@ void __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *
ops->stop = pmu_stop;
ops->cpu_type = pmu_model->name;
printk(KERN_INFO "oprofile: using %s PMU\n", spec->name);
return 0;
}
void pmu_exit(void)
......
......@@ -12,11 +12,15 @@
#include <linux/errno.h>
#include "op_arm_model.h"
void __init oprofile_arch_init(struct oprofile_operations *ops)
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
int ret = -ENODEV;
#ifdef CONFIG_CPU_XSCALE
pmu_init(ops, &op_xscale_spec);
ret = pmu_init(ops, &op_xscale_spec);
#endif
return ret;
}
void oprofile_arch_exit(void)
......
......@@ -21,7 +21,7 @@ extern void nmi_exit(void);
extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
void __init oprofile_arch_init(struct oprofile_operations * ops)
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
int ret;
......@@ -35,6 +35,8 @@ void __init oprofile_arch_init(struct oprofile_operations * ops)
ret = nmi_timer_init(ops);
#endif
ops->backtrace = x86_backtrace;
return ret;
}
......
......@@ -16,13 +16,17 @@ extern int perfmon_init(struct oprofile_operations * ops);
extern void perfmon_exit(void);
extern void ia64_backtrace(struct pt_regs * const regs, unsigned int depth);
void __init oprofile_arch_init(struct oprofile_operations * ops)
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
int ret = -ENODEV;
#ifdef CONFIG_PERFMON
/* perfmon_init() can fail, but we have no way to report it */
perfmon_init(ops);
ret = perfmon_init(ops);
#endif
ops->backtrace = ia64_backtrace;
return ret;
}
......
......@@ -12,8 +12,9 @@
#include <linux/errno.h>
#include <linux/init.h>
void __init oprofile_arch_init(struct oprofile_operations * ops)
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
return -ENODEV;
}
void oprofile_arch_exit(void)
......
......@@ -12,8 +12,9 @@
#include <linux/kernel.h>
#include <linux/oprofile.h>
void __init oprofile_arch_init(struct oprofile_operations * ops)
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
return -ENODEV;
}
......
......@@ -125,7 +125,7 @@ static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
return 0;
}
void __init oprofile_arch_init(struct oprofile_operations *ops)
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
unsigned int pvr;
......@@ -170,7 +170,7 @@ void __init oprofile_arch_init(struct oprofile_operations *ops)
break;
default:
return;
return -ENODEV;
}
ops->create_files = op_ppc64_create_files;
......@@ -181,6 +181,8 @@ void __init oprofile_arch_init(struct oprofile_operations *ops)
printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
ops->cpu_type);
return 0;
}
void oprofile_arch_exit(void)
......
......@@ -12,8 +12,9 @@
#include <linux/init.h>
#include <linux/errno.h>
void __init oprofile_arch_init(struct oprofile_operations* ops)
int __init oprofile_arch_init(struct oprofile_operations* ops)
{
return -ENODEV;
}
void oprofile_arch_exit(void)
......
......@@ -12,8 +12,9 @@
#include <linux/init.h>
#include <linux/errno.h>
void __init oprofile_arch_init(struct oprofile_operations *ops)
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
return -ENODEV;
}
void oprofile_arch_exit(void)
......
......@@ -12,8 +12,9 @@
#include <linux/errno.h>
#include <linux/init.h>
void __init oprofile_arch_init(struct oprofile_operations * ops)
int __init oprofile_arch_init(struct oprofile_operations * ops)
{
return -ENODEV;
}
......
......@@ -153,11 +153,11 @@ int oprofile_set_backtrace(unsigned long val)
static int __init oprofile_init(void)
{
int err = 0;
int err;
oprofile_arch_init(&oprofile_ops);
err = oprofile_arch_init(&oprofile_ops);
if (timer) {
if (err < 0 || timer) {
printk(KERN_INFO "oprofile: using timer interrupt.\n");
oprofile_timer_init(&oprofile_ops);
}
......
......@@ -48,7 +48,7 @@ struct oprofile_operations {
*
* If an error occurs, the fields should be left untouched.
*/
void oprofile_arch_init(struct oprofile_operations * ops);
int oprofile_arch_init(struct oprofile_operations * ops);
/**
* One-time exit/cleanup for the arch.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment