--- /dev/null
+From 3683f44c42e991d313dc301504ee0fca1aeb8580 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+Date: Sat, 3 May 2014 11:03:28 +0100
+Subject: ARM: stacktrace: avoid listing stacktrace functions in stacktrace
+
+From: Russell King <rmk+kernel@arm.linux.org.uk>
+
+commit 3683f44c42e991d313dc301504ee0fca1aeb8580 upstream.
+
+While debugging the FEC ethernet driver using stacktrace, it was noticed
+that the stacktraces always begin as follows:
+
+ [<c00117b4>] save_stack_trace_tsk+0x0/0x98
+ [<c0011870>] save_stack_trace+0x24/0x28
+ ...
+
+This is because the stack trace code includes the stack frames for itself.
+This is incorrect behaviour, and also leads to "skip" doing the wrong
+thing (which is the number of stack frames to avoid recording.)
+
+Perversely, it does the right thing when passed a non-current thread. Fix
+this by ensuring that we have a known constant number of frames above the
+main stack trace function, and always skip these.
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/kernel/stacktrace.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+--- a/arch/arm/kernel/stacktrace.c
++++ b/arch/arm/kernel/stacktrace.c
+@@ -83,13 +83,16 @@ static int save_trace(struct stackframe
+ return trace->nr_entries >= trace->max_entries;
+ }
+
+-void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
++/* This must be noinline to so that our skip calculation works correctly */
++static noinline void __save_stack_trace(struct task_struct *tsk,
++ struct stack_trace *trace, unsigned int nosched)
+ {
+ struct stack_trace_data data;
+ struct stackframe frame;
+
+ data.trace = trace;
+ data.skip = trace->skip;
++ data.no_sched_functions = nosched;
+
+ if (tsk != current) {
+ #ifdef CONFIG_SMP
+@@ -102,7 +105,6 @@ void save_stack_trace_tsk(struct task_st
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
+ return;
+ #else
+- data.no_sched_functions = 1;
+ frame.fp = thread_saved_fp(tsk);
+ frame.sp = thread_saved_sp(tsk);
+ frame.lr = 0; /* recovered from the stack */
+@@ -111,11 +113,12 @@ void save_stack_trace_tsk(struct task_st
+ } else {
+ register unsigned long current_sp asm ("sp");
+
+- data.no_sched_functions = 0;
++ /* We don't want this function nor the caller */
++ data.skip += 2;
+ frame.fp = (unsigned long)__builtin_frame_address(0);
+ frame.sp = current_sp;
+ frame.lr = (unsigned long)__builtin_return_address(0);
+- frame.pc = (unsigned long)save_stack_trace_tsk;
++ frame.pc = (unsigned long)__save_stack_trace;
+ }
+
+ walk_stackframe(&frame, save_trace, &data);
+@@ -123,9 +126,14 @@ void save_stack_trace_tsk(struct task_st
+ trace->entries[trace->nr_entries++] = ULONG_MAX;
+ }
+
++void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
++{
++ __save_stack_trace(tsk, trace, 1);
++}
++
+ void save_stack_trace(struct stack_trace *trace)
+ {
+- save_stack_trace_tsk(current, trace);
++ __save_stack_trace(current, trace, 0);
+ }
+ EXPORT_SYMBOL_GPL(save_stack_trace);
+ #endif