Merge tag 'ceph-for-4.21-rc1' of git://github.com/ceph/ceph-client
[linux-2.6-microblaze.git] / arch / csky / kernel / process.c
index 8ed2002..e555740 100644 (file)
@@ -93,26 +93,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs)
 
 unsigned long get_wchan(struct task_struct *p)
 {
-       unsigned long esp, pc;
-       unsigned long stack_page;
+       unsigned long lr;
+       unsigned long *fp, *stack_start, *stack_end;
        int count = 0;
 
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
 
-       stack_page = (unsigned long)p;
-       esp = p->thread.esp0;
+       stack_start = (unsigned long *)end_of_stack(p);
+       stack_end = (unsigned long *)(task_stack_page(p) + THREAD_SIZE);
+
+       fp = (unsigned long *) thread_saved_fp(p);
        do {
-               if (esp < stack_page+sizeof(struct task_struct) ||
-                   esp >= 8184+stack_page)
+               if (fp < stack_start || fp > stack_end)
                        return 0;
-               /*FIXME: There's may be error here!*/
-               pc = ((unsigned long *)esp)[1];
-               /* FIXME: This depends on the order of these functions. */
-               if (!in_sched_functions(pc))
-                       return pc;
-               esp = *(unsigned long *) esp;
+#ifdef CONFIG_STACKTRACE
+               lr = fp[1];
+               fp = (unsigned long *)fp[0];
+#else
+               lr = *fp++;
+#endif
+               if (!in_sched_functions(lr) &&
+                   __kernel_text_address(lr))
+                       return lr;
        } while (count++ < 16);
+
        return 0;
 }
 EXPORT_SYMBOL(get_wchan);