#define IRQ_CNT 256
#define CCCNT_WARN 1000
#define CPU 8
-static unsigned long t_base[IRQ_CNT];
-static unsigned long t_isr[IRQ_CNT];
-static unsigned long t_total[IRQ_CNT];
+static unsigned long long t_base[IRQ_CNT];
+static unsigned long long t_isr[IRQ_CNT];
+static unsigned long long t_total[IRQ_CNT];
static unsigned int cnt_total[IRQ_CNT];
static void *cpu_action[CPU];
static int cpu_irq[CPU] = {0};
static void *cpu_sirq[CPU] = {NULL};
/*irq disable trace*/
-#define LONG_IRQDIS (1000 * 1000000) /*500 ms*/
+#define LONG_IRQDIS (1000 * 1000000)/*1000 ms*/
#define OUT_WIN (500 * 1000000) /*500 ms*/
#define LONG_IDLE (5000000000) /*5 sec*/
#define ENTRY 10
-static unsigned long t_i_d[CPU];
+static unsigned long long t_i_d[CPU];
static int irq_flg;
static struct stack_trace irq_trace[CPU];
static unsigned long t_entrys[CPU][ENTRY];
-static unsigned long t_idle[CPU] = { 0 };
-static unsigned long t_d_out;
+static unsigned long long t_idle[CPU] = { 0 };
+static unsigned long long t_d_out;
static unsigned long isr_thr = LONG_ISR;
core_param(isr_thr, isr_thr, ulong, 0644);
static unsigned long out_thr = OUT_WIN;
core_param(out_thr, out_thr, ulong, 0644);
-void notrace isr_in_hook(unsigned int cpu, unsigned long *tin,
+void notrace isr_in_hook(unsigned int cpu, unsigned long long *tin,
unsigned int irq, void *act)
{
if (irq >= IRQ_CNT || !isr_check_en || oops_in_progress)
}
}
-void notrace isr_out_hook(unsigned int cpu, unsigned long tin, unsigned int irq)
+void notrace isr_out_hook(unsigned int cpu, unsigned long long tin,
+ unsigned int irq)
{
- unsigned long tout;
- unsigned int ratio = 0;
+ unsigned long long tout;
+ unsigned long long ratio = 0;
+ unsigned long long t_diff;
+ unsigned long long t_isr_tmp;
+ unsigned long long t_total_tmp;
if (!isr_check_en || oops_in_progress)
return;
t_total[irq] = (tout-t_base[irq]);
cnt_total[irq]++;
- if (tout > isr_thr + tin)
- pr_err("ISR_Long___ERR. irq:%d tout-tin:%ld ms\n",
- irq, (tout - tin) / ns2ms);
+ if (tout > isr_thr + tin) {
+ t_diff = tout - tin;
+ do_div(t_diff, ns2ms);
+ pr_err("ISR_Long___ERR. irq:%d tout-tin:%llu ms\n",
+ irq, t_diff);
+ }
if (t_total[irq] < CHK_WINDOW)
return;
- ratio = t_isr[irq] * 100 / t_total[irq];
- if (ratio >= 35) {
- pr_err("IRQRatio___ERR.irq:%d ratio:%d\n", irq, (int)ratio);
- pr_err("t_isr:%d t_total:%d, cnt:%d\n",
- (int)(t_isr[irq] / ns2ms),
- (int)(t_total[irq] / ns2ms),
- cnt_total[irq]);
+ if (t_isr[irq] * 100 >= 35 * t_total[irq]) {
+ t_isr_tmp = t_isr[irq];
+ do_div(t_isr_tmp, ns2ms);
+ t_total_tmp = t_total[irq];
+ do_div(t_total_tmp, ns2ms);
+ ratio = t_isr_tmp * 100;
+ do_div(ratio, t_total_tmp);
+ pr_err("IRQRatio___ERR.irq:%d ratio:%llu\n", irq, ratio);
+ pr_err("t_isr:%llu t_total:%llu, cnt:%d\n",
+ t_isr_tmp, t_total_tmp, cnt_total[irq]);
}
t_base[irq] = sched_clock();
t_isr[irq] = 0;
cpu_action[cpu] = NULL;
}
-void notrace sirq_in_hook(unsigned int cpu, unsigned long *tin, void *p)
+void notrace sirq_in_hook(unsigned int cpu, unsigned long long *tin, void *p)
{
cpu_sirq[cpu] = p;
*tin = sched_clock();
}
-void notrace sirq_out_hook(unsigned int cpu, unsigned long tin, void *p)
+void notrace sirq_out_hook(unsigned int cpu, unsigned long long tin, void *p)
{
- unsigned long tout = sched_clock();
+ unsigned long long tout = sched_clock();
+ unsigned long long t_diff;
if (cpu_sirq[cpu] && tin && (tout > tin + sirq_thr) &&
!oops_in_progress) {
- pr_err("SIRQLong___ERR. sirq:%p tout-tin:%ld ms\n",
- p, (tout - tin) / ns2ms);
+ t_diff = tout - tin;
+ do_div(t_diff, ns2ms);
+ pr_err("SIRQLong___ERR. sirq:%p tout-tin:%llu ms\n",
+ p, t_diff);
}
cpu_sirq[cpu] = NULL;
}
if (!irq_flg || !irq_check_en || oops_in_progress)
return;
+
if (arch_irqs_disabled_flags(flags))
return;
irq_trace[cpu].skip = 2;
irq_trace[cpu].nr_entries = 0;
t_i_d[cpu] = sched_clock();
+
save_stack_trace(&irq_trace[cpu]);
}
EXPORT_SYMBOL(irq_trace_start);
void notrace irq_trace_stop(unsigned long flag)
{
- unsigned long t_i_e, t;
+ unsigned long long t_i_e, t;
unsigned int cpu;
int softirq = 0;
static int out_cnt;
out_cnt++;
if (t_i_e >= t_d_out + out_thr) {
t_d_out = t_i_e;
- pr_err("\n\nDisIRQ___ERR:%ld ms <%ld %ld> %d:\n",
- t / ns2ms, t_i_e / ns2ms, t_i_d[cpu] / ns2ms,
- out_cnt);
+ do_div(t, ns2ms);
+ do_div(t_i_e, ns2ms);
+ do_div(t_i_d[cpu], ns2ms);
+ pr_err("\n\nDisIRQ___ERR:%llu ms <%llu %llu> %d:\n",
+ t, t_i_e, t_i_d[cpu], out_cnt);
print_stack_trace(&irq_trace[cpu], 0);
dump_stack();
}
{
}
-void notrace arch_cpu_idle_enter(void)
+void notrace __arch_cpu_idle_enter(void)
{
int cpu;
put_cpu();
t_idle[cpu] = local_clock();
}
-void notrace arch_cpu_idle_exit(void)
+void notrace __arch_cpu_idle_exit(void)
{
int cpu;
int cpu;
int virq = irq_check_en;
int visr = isr_check_en;
+ unsigned long long t_idle_diff;
+ unsigned long long t_idle_tmp;
+ unsigned long long t_i_diff;
+ unsigned long long t_i_tmp;
irq_flg = 0;
irq_check_en = 0;
pr_err("\n\n\nHARDLOCKUP____ERR.CPU[%d] <irqen:%d isren%d>START\n",
c, virq, visr);
for_each_online_cpu(cpu) {
- unsigned long t_cur = sched_clock();
+ unsigned long long t_cur = sched_clock();
struct task_struct *p = (cpu_rq(cpu)->curr);
int preempt = task_thread_info(p)->preempt_count;
(unsigned int)(preempt & SOFTIRQ_MASK));
if (t_i_d[cpu]) {
- pr_err("IRQ____ERR[%d]. <%ld %ld>.\n",
- cpu, t_i_d[cpu] / ns2ms,
- (t_cur-t_i_d[cpu]) / ns2ms);
+ t_i_diff = t_cur-t_i_d[cpu];
+ do_div(t_i_diff, ns2ms);
+ t_i_tmp = t_i_d[cpu];
+ do_div(t_i_tmp, ns2ms);
+ pr_err("IRQ____ERR[%d]. <%llu %llu>.\n",
+ cpu, t_i_tmp, t_i_diff);
print_stack_trace(&irq_trace[cpu], 0);
}
if (t_idle[cpu] && (t_idle[cpu] > LONG_IDLE + t_cur)) {
- pr_err("CPU[%d] IdleLong____ERR:%ld ms <%ld %ld>\n",
- cpu, (t_cur - t_idle[cpu]) / ns2ms,
- t_cur / ns2ms, t_idle[cpu] / ns2ms);
+ t_idle_diff = t_cur - t_idle[cpu];
+ do_div(t_idle_diff, ns2ms);
+ do_div(t_cur, ns2ms);
+ t_idle_tmp = t_idle[cpu];
+ do_div(t_idle_tmp, ns2ms);
+ pr_err("CPU[%d] IdleLong____ERR:%llu ms <%llu %llu>\n",
+ cpu, t_idle_diff, t_cur, t_idle_tmp);
}
dump_cpu_task(cpu);
lockup_hook(cpu);
--- /dev/null
+/*
+ * drivers/amlogic/debug/irqflags_debug_arm.h
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __ASM_IRQFLAGS_DEBUG_ARM_H
+#define __ASM_IRQFLAGS_DEBUG_ARM_H
+
+#ifdef __KERNEL__
+
+#include <linux/amlogic/debug_lockup.h>
+
+/*
+ * CPU interrupt mask handling.
+ */
+#ifdef CONFIG_CPU_V7M
+#define IRQMASK_REG_NAME_R "primask"
+#define IRQMASK_REG_NAME_W "primask"
+#define IRQMASK_I_BIT 1
+#else
+#define IRQMASK_REG_NAME_R "cpsr"
+#define IRQMASK_REG_NAME_W "cpsr_c"
+#define IRQMASK_I_BIT PSR_I_BIT
+#endif
+
+#if __LINUX_ARM_ARCH__ >= 6
+
+#define arch_local_irq_save arch_local_irq_save
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags;
+
+ asm volatile(
+ "mrs %0, " IRQMASK_REG_NAME_R " @ arch_local_irq_save\n"
+ "cpsid i"
+ : "=r" (flags) : : "memory", "cc");
+ irq_trace_start(flags);
+ return flags;
+}
+
+#define arch_local_irq_enable arch_local_irq_enable
+static inline void arch_local_irq_enable(void)
+{
+ irq_trace_stop(0);
+ asm volatile(
+ " cpsie i @ arch_local_irq_enable"
+ :
+ :
+ : "memory", "cc");
+}
+
+#define arch_local_irq_disable arch_local_irq_disable
+static inline void arch_local_irq_disable(void)
+{
+#if 0
+ asm volatile(
+ " cpsid i @ arch_local_irq_disable"
+ :
+ :
+ : "memory", "cc");
+#endif
+ arch_local_irq_save();
+}
+
+#define local_fiq_enable() __asm__("cpsie f @ __stf" : : : "memory", "cc")
+#define local_fiq_disable() __asm__("cpsid f @ __clf" : : : "memory", "cc")
+
+#ifndef CONFIG_CPU_V7M
+#define local_abt_enable() __asm__("cpsie a @ __sta" : : : "memory", "cc")
+#define local_abt_disable() __asm__("cpsid a @ __cla" : : : "memory", "cc")
+#else
+#define local_abt_enable() do { } while (0)
+#define local_abt_disable() do { } while (0)
+#endif
+#else
+
+/*
+ * Save the current interrupt enable state & disable IRQs
+ */
+#define arch_local_irq_save arch_local_irq_save
+static inline unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags, temp;
+
+ asm volatile(
+ " mrs %0, cpsr @ arch_local_irq_save\n"
+ " orr %1, %0, #128\n"
+ " msr cpsr_c, %1"
+ : "=r" (flags), "=r" (temp)
+ :
+ : "memory", "cc");
+ return flags;
+}
+
+/*
+ * Enable IRQs
+ */
+#define arch_local_irq_enable arch_local_irq_enable
+static inline void arch_local_irq_enable(void)
+{
+ unsigned long temp;
+
+ asm volatile(
+ " mrs %0, cpsr @ arch_local_irq_enable\n"
+ " bic %0, %0, #128\n"
+ " msr cpsr_c, %0"
+ : "=r" (temp)
+ :
+ : "memory", "cc");
+}
+
+/*
+ * Disable IRQs
+ */
+#define arch_local_irq_disable arch_local_irq_disable
+static inline void arch_local_irq_disable(void)
+{
+ unsigned long temp;
+
+ asm volatile(
+ " mrs %0, cpsr @ arch_local_irq_disable\n"
+ " orr %0, %0, #128\n"
+ " msr cpsr_c, %0"
+ : "=r" (temp)
+ :
+ : "memory", "cc");
+}
+
+/*
+ * Enable FIQs
+ */
+#define local_fiq_enable() \
+ ({ \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ stf\n" \
+" bic %0, %0, #64\n" \
+" msr cpsr_c, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory", "cc"); \
+ })
+
+/*
+ * Disable FIQs
+ */
+#define local_fiq_disable() \
+ ({ \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ clf\n" \
+" orr %0, %0, #64\n" \
+" msr cpsr_c, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory", "cc"); \
+ })
+
+#define local_abt_enable() do { } while (0)
+#define local_abt_disable() do { } while (0)
+#endif
+
+/*
+ * Save the current interrupt enable state.
+ */
+#define arch_local_save_flags arch_local_save_flags
+static inline unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ asm volatile(
+ "mrs %0, " IRQMASK_REG_NAME_R " @ local_save_flags"
+ : "=r" (flags) : : "memory", "cc");
+ return flags;
+}
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+#define arch_local_irq_restore arch_local_irq_restore
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+ irq_trace_stop(flags);
+ asm volatile(
+ "msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
+ :
+ : "r" (flags)
+ : "memory", "cc");
+}
+
+#define arch_irqs_disabled_flags arch_irqs_disabled_flags
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+ return flags & IRQMASK_I_BIT;
+}
+
+#include <asm-generic/irqflags.h>
+
+#endif /* ifdef __KERNEL__ */
+#endif /* ifndef __ASM_IRQFLAGS_DEBUG_ARM_H */