diff options
Diffstat (limited to 'arch/arm/common/fiq_debugger.c')
-rw-r--r-- | arch/arm/common/fiq_debugger.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c index 4156a7f51d62..2f10fea529b1 100644 --- a/arch/arm/common/fiq_debugger.c +++ b/arch/arm/common/fiq_debugger.c @@ -454,15 +454,21 @@ static void fiq_debugger_help(struct fiq_debugger_state *state) #endif } -static void fiq_debugger_take_affinity(void *info) + +static void change_cpu_affinity(int fiq, int cpu) { - struct fiq_debugger_state *state = info; struct cpumask cpumask; cpumask_clear(&cpumask); - cpumask_set_cpu(get_cpu(), &cpumask); + cpumask_set_cpu(cpu, &cpumask); + irq_set_affinity(fiq, &cpumask); +} - irq_set_affinity(state->uart_irq, &cpumask); +static void fiq_debugger_take_affinity(void *info) +{ + struct fiq_debugger_state *state = info; + + change_cpu_affinity(state->uart_irq, get_cpu()); } static void fiq_debugger_switch_cpu(struct fiq_debugger_state *state, int cpu) @@ -739,11 +745,33 @@ static void fiq_debugger_fiq(struct fiq_glue_handler *h, unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu; bool need_irq; + unsigned int next_cpu; + static bool cpu0_again; + + /* + * 1st FIQ always goes to CPU0. We will change FIQ CPU affinity, if CPU0 + * enter the FIQ handler 2nd time, we know we have already done the + * stack dump for all CPUs and we can enter the debug console. + */ + if (cpu0_again) { + need_irq = fiq_debugger_handle_uart_interrupt(state, + this_cpu, regs, svc_sp); + if (need_irq) + fiq_debugger_force_irq(state); + return; + } + + fiq_debugger_dump_allregs(&state->output, regs); + fiq_debugger_dump_pc(&state->output, regs); + fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp); + /* let another online CPU handle the FIQ */ + next_cpu = cpumask_next(this_cpu, cpu_online_mask); + if (next_cpu >= nr_cpu_ids) { + next_cpu = 0; + cpu0_again = true; + } + change_cpu_affinity(state->fiq, next_cpu); - need_irq = fiq_debugger_handle_uart_interrupt(state, this_cpu, regs, - svc_sp); - if (need_irq) - fiq_debugger_force_irq(state); } #endif |