diff options
author | Drew Richardson <drew.richardson@arm.com> | 2011-11-29 12:00:00 -0800 |
---|---|---|
committer | Drew Richardson <drew.richardson@arm.com> | 2014-12-19 15:22:16 -0800 |
commit | 689b7539711ab098911503808cc3e24307d9bcf7 (patch) | |
tree | eded88dc8c354b94a0b930d3c44f9da2348a4ace /driver/gator_main.c | |
parent | 24395bff3db9e12e6f406ad783ecc9bcde626253 (diff) |
gator: Version 5.85.8
Signed-off-by: Drew Richardson <drew.richardson@arm.com>
Diffstat (limited to 'driver/gator_main.c')
-rw-r--r-- | driver/gator_main.c | 91 |
1 files changed, 58 insertions, 33 deletions
diff --git a/driver/gator_main.c b/driver/gator_main.c index 91744ad..36e951b 100644 --- a/driver/gator_main.c +++ b/driver/gator_main.c @@ -7,7 +7,7 @@ * */ -static unsigned long gator_protocol_version = 6; +static unsigned long gator_protocol_version = 7; #include <linux/slab.h> #include <linux/cpu.h> @@ -17,6 +17,8 @@ static unsigned long gator_protocol_version = 6; #include <linux/hardirq.h> #include <linux/highmem.h> #include <linux/pagemap.h> +#include <linux/suspend.h> +#include <asm/stacktrace.h> #include <asm/uaccess.h> #include "gator.h" @@ -51,7 +53,7 @@ static unsigned long gator_protocol_version = 6; /****************************************************************************** * DEFINES ******************************************************************************/ -#define TIMER_BUFFER_SIZE_DEFAULT (256*1024) +#define TIMER_BUFFER_SIZE_DEFAULT (512*1024) #define EVENT_BUFFER_SIZE_DEFAULT (128*1024) #define NO_COOKIE 0UL @@ -267,11 +269,12 @@ static void gator_add_trace(int cpu, int buftype, unsigned int address) static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs) { - struct module *mod; - unsigned int addr, cookie = 0; int inKernel = regs ? !user_mode(regs) : 1; unsigned long exec_cookie = inKernel ? NO_COOKIE : get_exec_cookie(cpu, buftype, current); + if (!regs) + return; + gator_buffer_write_packed_int(cpu, buftype, MESSAGE_START_BACKTRACE); gator_buffer_write_packed_int64(cpu, buftype, gator_get_time()); gator_buffer_write_packed_int(cpu, buftype, exec_cookie); @@ -279,25 +282,15 @@ static void gator_add_sample(int cpu, int buftype, struct pt_regs * const regs) gator_buffer_write_packed_int(cpu, buftype, (unsigned int)current->pid); gator_buffer_write_packed_int(cpu, buftype, inKernel); - // get_irq_regs() will return NULL outside of IRQ context (e.g. nested IRQ) - if (regs) { - if (inKernel) { - addr = PC_REG; - mod = __module_address(addr); - if (mod) { - cookie = get_cookie(cpu, buftype, current, NULL, mod, true); - addr = addr - (unsigned long)mod->module_core; - } - gator_buffer_write_packed_int(cpu, buftype, addr & ~1); - gator_buffer_write_packed_int(cpu, buftype, cookie); - } else { - // Cookie+PC - gator_add_trace(cpu, buftype, PC_REG); - - // Backtrace - if (gator_backtrace_depth) - arm_backtrace_eabi(cpu, buftype, regs, gator_backtrace_depth); - } + if (inKernel) { + kernel_backtrace(cpu, buftype, regs); + } else { + // Cookie+PC + gator_add_trace(cpu, buftype, PC_REG); + + // Backtrace + if (gator_backtrace_depth) + arm_backtrace_eabi(cpu, buftype, regs, gator_backtrace_depth); } gator_buffer_write_packed_int(cpu, buftype, MESSAGE_END_BACKTRACE); @@ -352,11 +345,12 @@ static void gator_timer_interrupt(void) } } else if (gi->read64) { len = gi->read64(&buffer64); - if (len > 0) + if (len > 0) { gator_buffer_write_packed_int(cpu, buftype, len); for (i = 0; i < len; i++) { gator_buffer_write_packed_int64(cpu, buftype, buffer64[i]); } + } } } gator_buffer_write_packed_int(cpu, buftype, 0); @@ -460,29 +454,28 @@ static uint64_t gator_get_time(void) struct timespec ts; uint64_t timestamp; - ktime_get_ts(&ts); + getnstimeofday(&ts); timestamp = timespec_to_ns(&ts); return timestamp; } /****************************************************************************** - * cpu online notifier + * cpu online and pm notifiers ******************************************************************************/ -static int __cpuinit gator_cpu_notify(struct notifier_block *self, - unsigned long action, void *hcpu) +static int __cpuinit gator_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; switch (action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - smp_call_function_single(cpu, __gator_timer_online, NULL, 1); - break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: smp_call_function_single(cpu, __gator_timer_offline, NULL, 1); break; + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + smp_call_function_single(cpu, __gator_timer_online, NULL, 1); + break; } return NOTIFY_OK; @@ -492,13 +485,45 @@ static struct notifier_block __refdata gator_cpu_notifier = { .notifier_call = gator_cpu_notify, }; +// n.b. calling "on_each_cpu" only runs on those that are online +// Registered linux events are not disabled, so their counters will continue to collect +static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) +{ + switch (event) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + unregister_hotcpu_notifier(&gator_cpu_notifier); + unregister_scheduler_tracepoints(); + on_each_cpu(trace_sched_insert_idle, NULL, 1); + on_each_cpu(__gator_timer_offline, NULL, 1); + break; + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + on_each_cpu(__gator_timer_online, NULL, 1); + register_scheduler_tracepoints(); + register_hotcpu_notifier(&gator_cpu_notifier); + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block gator_pm_notifier = { + .notifier_call = gator_pm_notify, +}; + static int gator_notifier_start(void) { - return register_hotcpu_notifier(&gator_cpu_notifier); + int retval; + retval = register_hotcpu_notifier(&gator_cpu_notifier); + if (retval == 0) + retval = register_pm_notifier(&gator_pm_notifier); + return retval; } static void gator_notifier_stop(void) { + unregister_pm_notifier(&gator_pm_notifier); unregister_hotcpu_notifier(&gator_cpu_notifier); } |