diff options
author | Robin Getz <robin.getz@analog.com> | 2007-10-29 17:20:41 +0800 |
---|---|---|
committer | Bryan Wu <bryan.wu@analog.com> | 2007-10-29 17:20:41 +0800 |
commit | 885be03b069131d242506f0f717d38659b2bdb6c (patch) | |
tree | 52c1858645ee28b9d0bc7166744da3eef5bc6f1f /arch/blackfin/kernel/traps.c | |
parent | 64307f7db3690140a16c6748e65068f8a279877c (diff) | |
download | talos-obmc-linux-885be03b069131d242506f0f717d38659b2bdb6c.tar.gz talos-obmc-linux-885be03b069131d242506f0f717d38659b2bdb6c.zip |
Blackfin arch: fix bug: kernel prints out error message twice
This fixes two things:
- stop calling write_lock_irq/write_unlock_irq which can turn modify
irq levels
- don't calling mmput when handing exceptions - since this might_sleep,
which does a rti, and leaves us in kernel space (irq15, rather
than irq5).
Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index afd044e78af6..ce86659f9b65 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -54,12 +54,13 @@ void __init trap_init(void) int kstack_depth_to_print = 48; #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON -static int printk_address(unsigned long address) +static void printk_address(unsigned long address) { struct vm_list_struct *vml; struct task_struct *p; struct mm_struct *mm; - unsigned long offset; + unsigned long flags, offset; + unsigned int in_exception = bfin_read_IPEND() & 0x10; #ifdef CONFIG_KALLSYMS unsigned long symsize; @@ -75,9 +76,10 @@ static int printk_address(unsigned long address) /* yeah! kernel space! */ if (!modname) modname = delim = ""; - return printk("<0x%p> { %s%s%s%s + 0x%lx }", + printk("<0x%p> { %s%s%s%s + 0x%lx }", (void *)address, delim, modname, delim, symname, (unsigned long)offset); + return; } #endif @@ -86,9 +88,9 @@ static int printk_address(unsigned long address) * mappings of all our processes and see if we can't be a whee * bit more specific */ - write_lock_irq(&tasklist_lock); + write_lock_irqsave(&tasklist_lock, flags); for_each_process(p) { - mm = get_task_mm(p); + mm = (in_exception ? p->mm : get_task_mm(p)); if (!mm) continue; @@ -117,20 +119,24 @@ static int printk_address(unsigned long address) else offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); - write_unlock_irq(&tasklist_lock); - mmput(mm); - return printk("<0x%p> [ %s + 0x%lx ]", - (void *)address, name, offset); + printk("<0x%p> [ %s + 0x%lx ]", + (void *)address, name, offset); + if (!in_exception) + mmput(mm); + goto done; } vml = vml->next; } - mmput(mm); + if (!in_exception) + mmput(mm); } - write_unlock_irq(&tasklist_lock); /* we were unable to find this address anywhere */ - return printk("[<0x%p>]", (void *)address); + printk("[<0x%p>]", (void *)address); + +done: + write_unlock_irqrestore(&tasklist_lock, flags); } #endif |