asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
+static int call_trace = 1;
 ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
        return ebp;
 }
 
-static asmlinkage void show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
+static asmlinkage int show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
 {
+       int n = 0;
        int printed = 0; /* nr of entries already printed on current line */
 
        while (unwind(info) == 0 && UNW_PC(info)) {
+               ++n;
                printed = print_addr_and_symbol(UNW_PC(info), log_lvl, printed);
                if (arch_unw_user_mode(info))
                        break;
        }
        if (printed)
                printk("\n");
+       return n;
 }
 
 static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
                               unsigned long *stack, char *log_lvl)
 {
        unsigned long ebp;
-       struct unwind_frame_info info;
 
        if (!task)
                task = current;
 
-       if (regs) {
-               if (unwind_init_frame_info(&info, task, regs) == 0) {
-                       show_trace_unwind(&info, log_lvl);
-                       return;
+       if (call_trace >= 0) {
+               int unw_ret = 0;
+               struct unwind_frame_info info;
+
+               if (regs) {
+                       if (unwind_init_frame_info(&info, task, regs) == 0)
+                               unw_ret = show_trace_unwind(&info, log_lvl);
+               } else if (task == current)
+                       unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
+               else {
+                       if (unwind_init_blocked(&info, task) == 0)
+                               unw_ret = show_trace_unwind(&info, log_lvl);
                }
-       } else if (task == current) {
-               if (unwind_init_running(&info, show_trace_unwind, log_lvl) == 0)
-                       return;
-       } else {
-               if (unwind_init_blocked(&info, task) == 0) {
-                       show_trace_unwind(&info, log_lvl);
-                       return;
+               if (unw_ret > 0) {
+                       if (call_trace > 0)
+                               return;
+                       printk("%sLegacy call trace:\n", log_lvl);
                }
        }
 
        return 1;
 }
 __setup("kstack=", kstack_setup);
+
+static int __init call_trace_setup(char *s)
+{
+       if (strcmp(s, "old") == 0)
+               call_trace = -1;
+       else if (strcmp(s, "both") == 0)
+               call_trace = 0;
+       else if (strcmp(s, "new") == 0)
+               call_trace = 1;
+       return 1;
+}
+__setup("call_trace=", call_trace_setup);
 
 }
 
 static int kstack_depth_to_print = 10;
+static int call_trace = 1;
 
 #ifdef CONFIG_KALLSYMS
 #include <linux/kallsyms.h> 
        return NULL;
 }
 
-static void show_trace_unwind(struct unwind_frame_info *info, void *context)
+static int show_trace_unwind(struct unwind_frame_info *info, void *context)
 {
-       int i = 11;
+       int i = 11, n = 0;
 
        while (unwind(info) == 0 && UNW_PC(info)) {
+               ++n;
                if (i > 50) {
                        printk("\n       ");
                        i = 7;
                        break;
        }
        printk("\n");
+       return n;
 }
 
 /*
 {
        const unsigned cpu = safe_smp_processor_id();
        unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
-       int i;
+       int i = 11;
        unsigned used = 0;
-       struct unwind_frame_info info;
 
        printk("\nCall Trace:");
 
        if (!tsk)
                tsk = current;
 
-       if (regs) {
-               if (unwind_init_frame_info(&info, tsk, regs) == 0) {
-                       show_trace_unwind(&info, NULL);
-                       return;
+       if (call_trace >= 0) {
+               int unw_ret = 0;
+               struct unwind_frame_info info;
+
+               if (regs) {
+                       if (unwind_init_frame_info(&info, tsk, regs) == 0)
+                               unw_ret = show_trace_unwind(&info, NULL);
+               } else if (tsk == current)
+                       unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
+               else {
+                       if (unwind_init_blocked(&info, tsk) == 0)
+                               unw_ret = show_trace_unwind(&info, NULL);
                }
-       } else if (tsk == current) {
-               if (unwind_init_running(&info, show_trace_unwind, NULL) == 0)
-                       return;
-       } else {
-               if (unwind_init_blocked(&info, tsk) == 0) {
-                       show_trace_unwind(&info, NULL);
-                       return;
+               if (unw_ret > 0) {
+                       if (call_trace > 0)
+                               return;
+                       printk("Legacy call trace:");
+                       i = 18;
                }
        }
 
                } \
        } while (0)
 
-       for(i = 11; ; ) {
+       for(; ; ) {
                const char *id;
                unsigned long *estack_end;
                estack_end = in_exception_stack(cpu, (unsigned long)stack,
 }
 __setup("kstack=", kstack_setup);
 
+static int __init call_trace_setup(char *s)
+{
+       if (strcmp(s, "old") == 0)
+               call_trace = -1;
+       else if (strcmp(s, "both") == 0)
+               call_trace = 0;
+       else if (strcmp(s, "new") == 0)
+               call_trace = 1;
+       return 1;
+}
+__setup("call_trace=", call_trace_setup);
 
        info->regs.xes = __USER_DS;
 }
 
-extern asmlinkage void arch_unwind_init_running(struct unwind_frame_info *,
-                                                asmlinkage void (*callback)(struct unwind_frame_info *,
-                                                                            void *arg),
-                                                void *arg);
+extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
+                                               asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                                          void *arg),
+                                               void *arg);
 
 static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
 {
 
        info->regs.ss = __KERNEL_DS;
 }
 
-extern void arch_unwind_init_running(struct unwind_frame_info *,
-                                     void (*callback)(struct unwind_frame_info *,
-                                                      void *arg),
-                                     void *arg);
+extern int arch_unwind_init_running(struct unwind_frame_info *,
+                                    int (*callback)(struct unwind_frame_info *,
+                                                    void *arg),
+                                    void *arg);
 
 static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
 {
 
  * Prepare to unwind the currently running thread.
  */
 extern int unwind_init_running(struct unwind_frame_info *,
-                               asmlinkage void (*callback)(struct unwind_frame_info *,
-                                                           void *arg),
+                               asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                          void *arg),
                                void *arg);
 
 /*
 }
 
 static inline int unwind_init_running(struct unwind_frame_info *info,
-                                      asmlinkage void (*cb)(struct unwind_frame_info *,
-                                                            void *arg),
+                                      asmlinkage int (*cb)(struct unwind_frame_info *,
+                                                           void *arg),
                                       void *arg)
 {
        return -ENOSYS;
 
  * Prepare to unwind the currently running thread.
  */
 int unwind_init_running(struct unwind_frame_info *info,
-                        asmlinkage void (*callback)(struct unwind_frame_info *,
-                                                    void *arg),
+                        asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                   void *arg),
                         void *arg)
 {
        info->task = current;
-       arch_unwind_init_running(info, callback, arg);
 
-       return 0;
+       return arch_unwind_init_running(info, callback, arg);
 }
 EXPORT_SYMBOL(unwind_init_running);