return sp & ~0xf;
 }
 #endif
+
+unsigned long get_wchan(struct task_struct *p)
+{
+       unsigned long stack_page, sp, ip;
+       bool seen_sched = 0;
+
+       if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
+               return 0;
+
+       stack_page = (unsigned long) task_stack_page(p);
+       /* Bail if the process has no kernel stack for some reason */
+       if (stack_page == 0)
+               return 0;
+
+       sp = p->thread.switch_buf->JB_SP;
+       /*
+        * Bail if the stack pointer is below the bottom of the kernel
+        * stack for some reason
+        */
+       if (sp < stack_page)
+               return 0;
+
+       while (sp < stack_page + THREAD_SIZE) {
+               ip = *((unsigned long *) sp);
+               if (in_sched_functions(ip))
+                       /* Ignore everything until we're above the scheduler */
+                       seen_sched = 1;
+               else if (kernel_text_address(ip) && seen_sched)
+                       return ip;
+
+               sp += sizeof(unsigned long);
+       }
+
+       return 0;
+}
 
 
 
 #define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf)
-#define get_wchan(p) (0)
+extern unsigned long get_wchan(struct task_struct *p);
 
 #endif