diff options
author | Colin Cross <ccross@android.com> | 2010-10-07 17:35:27 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2010-10-07 17:35:27 -0700 |
commit | ecf1cce25ccc5bf6326ae00cf0675a4ff9a9ff2d (patch) | |
tree | 3c14e10326759a8521e6b33a090ecafb0812e4ec /arch/arm/common | |
parent | bb3212324ff996f4cd5e854d4bbd63858badc1df (diff) | |
parent | 6098ced7ab5faec700ebc8ecec81bdd624969a66 (diff) |
Merge branch 'android-2.6.36' into android-tegra-2.6.36
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/fiq_debugger.c | 42 | ||||
-rw-r--r-- | arch/arm/common/fiq_glue_setup.c | 30 |
2 files changed, 59 insertions, 13 deletions
diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c index 1ba345d441d0..330053856c76 100644 --- a/arch/arm/common/fiq_debugger.c +++ b/arch/arm/common/fiq_debugger.c @@ -44,6 +44,10 @@ #include "fiq_debugger_ringbuf.h" #define DEBUG_MAX 64 +#define MAX_UNHANDLED_FIQ_COUNT 1000000 + +#define THREAD_INFO(sp) ((struct thread_info *) \ + ((unsigned long)(sp) & ~(THREAD_SIZE - 1))) struct fiq_debugger_state { struct fiq_glue_handler handler; @@ -70,6 +74,9 @@ struct fiq_debugger_state { bool uart_clk_enabled; struct wake_lock debugger_wake_lock; bool console_enable; + int current_cpu; + atomic_t unhandled_fiq_count; + bool in_fiq; #ifdef CONFIG_FIQ_DEBUGGER_CONSOLE struct console console; @@ -388,8 +395,7 @@ void dump_stacktrace(struct fiq_debugger_state *state, struct pt_regs * const regs, unsigned int depth, void *ssp) { struct frame_tail *tail; - struct thread_info *real_thread_info = (struct thread_info *) - ((unsigned long)ssp & ~(THREAD_SIZE - 1)); + struct thread_info *real_thread_info = THREAD_INFO(ssp); struct stacktrace_state sts; sts.depth = depth; @@ -449,6 +455,15 @@ static void debug_exec(struct fiq_debugger_state *state, } else if (!strcmp(cmd, "console")) { state->console_enable = true; debug_printf(state, "console mode\n"); + } else if (!strcmp(cmd, "cpu")) { + debug_printf(state, "cpu %d\n", state->current_cpu); + } else if (!strncmp(cmd, "cpu ", 4)) { + unsigned long cpu = 0; + if (strict_strtoul(cmd + 4, 10, &cpu) == 0) + state->current_cpu = cpu; + else + debug_printf(state, "invalid cpu\n"); + debug_printf(state, "cpu %d\n", state->current_cpu); } else { if (state->debug_busy) { debug_printf(state, @@ -552,6 +567,26 @@ static void debug_fiq(struct fiq_glue_handler *h, void *regs, void *svc_sp) int c; static int last_c; int count = 0; + unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu; + + if (this_cpu != state->current_cpu) { + if (state->in_fiq) + return; + + if (atomic_inc_return(&state->unhandled_fiq_count) != + MAX_UNHANDLED_FIQ_COUNT) + return; + + debug_printf(state, "fiq_debugger: cpu %d not responding, " + "reverting to cpu %d\n", state->current_cpu, + this_cpu); + + atomic_set(&state->unhandled_fiq_count, 0); + state->current_cpu = this_cpu; + return; + } + + state->in_fiq = true; while ((c = debug_getc(state)) != FIQ_DEBUGGER_NO_CHAR) { count++; @@ -606,6 +641,9 @@ static void debug_fiq(struct fiq_glue_handler *h, void *regs, void *svc_sp) /* poke sleep timer if necessary */ if (state->debug_enable && !state->no_sleep) debug_force_irq(state); + + atomic_set(&state->unhandled_fiq_count, 0); + state->in_fiq = false; } static void debug_resume(struct fiq_glue_handler *h) diff --git a/arch/arm/common/fiq_glue_setup.c b/arch/arm/common/fiq_glue_setup.c index f878ea079b4d..4044c7db95c8 100644 --- a/arch/arm/common/fiq_glue_setup.c +++ b/arch/arm/common/fiq_glue_setup.c @@ -23,7 +23,7 @@ extern void fiq_glue_setup(void *func, void *data, void *sp); static struct fiq_handler fiq_debbuger_fiq_handler = { .name = "fiq_glue", }; -static __percpu void *fiq_stack; +DEFINE_PER_CPU(void *, fiq_stack); static struct fiq_glue_handler *current_handler; static DEFINE_MUTEX(fiq_glue_lock); @@ -31,12 +31,13 @@ static void fiq_glue_setup_helper(void *info) { struct fiq_glue_handler *handler = info; fiq_glue_setup(handler->fiq, handler, - __this_cpu_ptr(fiq_stack) + THREAD_START_SP); + __get_cpu_var(fiq_stack) + THREAD_START_SP); } int fiq_glue_register_handler(struct fiq_glue_handler *handler) { int ret; + int cpu; if (!handler || !handler->fiq) return -EINVAL; @@ -47,10 +48,14 @@ int fiq_glue_register_handler(struct fiq_glue_handler *handler) goto err_busy; } - fiq_stack = __alloc_percpu(THREAD_SIZE, L1_CACHE_BYTES); - if (WARN_ON(!fiq_stack)) { - ret = -ENOMEM; - goto err_alloc_fiq_stack; + for_each_possible_cpu(cpu) { + void *stack; + stack = (void *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); + if (WARN_ON(!stack)) { + ret = -ENOMEM; + goto err_alloc_fiq_stack; + } + per_cpu(fiq_stack, cpu) = stack; } ret = claim_fiq(&fiq_debbuger_fiq_handler); @@ -61,12 +66,15 @@ int fiq_glue_register_handler(struct fiq_glue_handler *handler) on_each_cpu(fiq_glue_setup_helper, handler, true); set_fiq_handler(&fiq_glue, &fiq_glue_end - &fiq_glue); + mutex_unlock(&fiq_glue_lock); + return 0; + err_claim_fiq: - if (ret) { - free_percpu(fiq_stack); - fiq_stack = NULL; - } err_alloc_fiq_stack: + for_each_possible_cpu(cpu) { + __free_pages(per_cpu(fiq_stack, cpu), THREAD_SIZE_ORDER); + per_cpu(fiq_stack, cpu) = NULL; + } err_busy: mutex_unlock(&fiq_glue_lock); return ret; @@ -85,7 +93,7 @@ void fiq_glue_resume(void) if (!current_handler) return; fiq_glue_setup(current_handler->fiq, current_handler, - __this_cpu_ptr(fiq_stack) + THREAD_START_SP); + __get_cpu_var(fiq_stack) + THREAD_START_SP); if (current_handler->resume) current_handler->resume(current_handler); } |