diff options
| author | Stuart Menefy <stuart.menefy@st.com> | 2009-07-29 10:01:24 -0400 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2009-07-29 10:01:24 -0400 |
| commit | fd78a76aefb5bf28a11d6960d29e03a11db62320 (patch) | |
| tree | 8dac39f13c9b3bdadda02594f49501b5522ecad7 | |
| parent | 82b242214b6f5b96eb9b76452ac6e2b67dd81abd (diff) | |
sh: Rework irqflags tracing to fix up CONFIG_PROVE_LOCKING.
This cleans up the irqflags tracing code quite a bit and ties it
in to various missing callsites that caused an imbalance when
CONFIG_PROVE_LOCKING was enabled.
Previously this was catching on:
987 #ifdef CONFIG_PROVE_LOCKING
988 DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
989 DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
990 #endif
991 retval = -EAGAIN;
with hardirqs being doubly enabled, and subsequently bailing out
with the following call trace:
Call trace:
[<88035224>] __lock_acquire+0x616/0x6a6
[<88015a8c>] do_fork+0xf8/0x2b0
[<880331ec>] trace_hardirqs_on_caller+0xd4/0x114
[<88241074>] _spin_unlock_irq+0x20/0x64
[<88035224>] __lock_acquire+0x616/0x6a6
[<8800386c>] kernel_thread+0x48/0x70
[<88024ecc>] ____call_usermodehelper+0x0/0x110
[<88024ecc>] ____call_usermodehelper+0x0/0x110
[<88003894>] kernel_thread_helper+0x0/0x14
[<88024bac>] __call_usermodehelper+0x38/0x70
[<88025dc0>] worker_thread+0x150/0x274
[<88035b9c>] lock_release+0x0/0x198
[<88024b74>] __call_usermodehelper+0x0/0x70
[<88028cf0>] autoremove_wake_function+0x0/0x30
[<88028bf2>] kthread+0x3e/0x70
[<88025c70>] worker_thread+0x0/0x274
[<8800389c>] kernel_thread_helper+0x8/0x14
[<88028bb4>] kthread+0x0/0x70
[<88003894>] kernel_thread_helper+0x0/0x14
Reported-by: Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Matt Fleming <matt@console-pimps.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
| -rw-r--r-- | arch/sh/Kconfig.debug | 2 | ||||
| -rw-r--r-- | arch/sh/include/asm/entry-macros.S | 72 | ||||
| -rw-r--r-- | arch/sh/kernel/entry-common.S | 63 | ||||
| -rw-r--r-- | arch/sh/kernel/io_trapped.c | 7 | ||||
| -rw-r--r-- | drivers/serial/sh-sci.c | 5 |
5 files changed, 96 insertions, 53 deletions
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index b440fd936714..a6dce41296e7 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug | |||
| @@ -38,7 +38,7 @@ config EARLY_SCIF_CONSOLE_PORT | |||
| 38 | default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \ | 38 | default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \ |
| 39 | CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \ | 39 | CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \ |
| 40 | CPU_SUBTYPE_SH7343 | 40 | CPU_SUBTYPE_SH7343 |
| 41 | default "0xffea0000" if CPU_SUBTYPE_SH7785 | 41 | default "0xffeb0000" if CPU_SUBTYPE_SH7785 |
| 42 | default "0xffeb0000" if CPU_SUBTYPE_SH7786 | 42 | default "0xffeb0000" if CPU_SUBTYPE_SH7786 |
| 43 | default "0xfffe8000" if CPU_SUBTYPE_SH7203 | 43 | default "0xfffe8000" if CPU_SUBTYPE_SH7203 |
| 44 | default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263 | 44 | default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263 |
diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S index 3a4752a65722..1bdd93891cd7 100644 --- a/arch/sh/include/asm/entry-macros.S +++ b/arch/sh/include/asm/entry-macros.S | |||
| @@ -31,6 +31,78 @@ | |||
| 31 | #endif | 31 | #endif |
| 32 | .endm | 32 | .endm |
| 33 | 33 | ||
| 34 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 35 | |||
| 36 | .macro TRACE_IRQS_ON | ||
| 37 | mov.l r0, @-r15 | ||
| 38 | mov.l r1, @-r15 | ||
| 39 | mov.l r2, @-r15 | ||
| 40 | mov.l r3, @-r15 | ||
| 41 | mov.l r4, @-r15 | ||
| 42 | mov.l r5, @-r15 | ||
| 43 | mov.l r6, @-r15 | ||
| 44 | mov.l r7, @-r15 | ||
| 45 | |||
| 46 | mov.l 7834f, r0 | ||
| 47 | jsr @r0 | ||
| 48 | nop | ||
| 49 | |||
| 50 | mov.l @r15+, r7 | ||
| 51 | mov.l @r15+, r6 | ||
| 52 | mov.l @r15+, r5 | ||
| 53 | mov.l @r15+, r4 | ||
| 54 | mov.l @r15+, r3 | ||
| 55 | mov.l @r15+, r2 | ||
| 56 | mov.l @r15+, r1 | ||
| 57 | mov.l @r15+, r0 | ||
| 58 | mov.l 7834f, r0 | ||
| 59 | |||
| 60 | bra 7835f | ||
| 61 | nop | ||
| 62 | .balign 4 | ||
| 63 | 7834: .long trace_hardirqs_on | ||
| 64 | 7835: | ||
| 65 | .endm | ||
| 66 | .macro TRACE_IRQS_OFF | ||
| 67 | |||
| 68 | mov.l r0, @-r15 | ||
| 69 | mov.l r1, @-r15 | ||
| 70 | mov.l r2, @-r15 | ||
| 71 | mov.l r3, @-r15 | ||
| 72 | mov.l r4, @-r15 | ||
| 73 | mov.l r5, @-r15 | ||
| 74 | mov.l r6, @-r15 | ||
| 75 | mov.l r7, @-r15 | ||
| 76 | |||
| 77 | mov.l 7834f, r0 | ||
| 78 | jsr @r0 | ||
| 79 | nop | ||
| 80 | |||
| 81 | mov.l @r15+, r7 | ||
| 82 | mov.l @r15+, r6 | ||
| 83 | mov.l @r15+, r5 | ||
| 84 | mov.l @r15+, r4 | ||
| 85 | mov.l @r15+, r3 | ||
| 86 | mov.l @r15+, r2 | ||
| 87 | mov.l @r15+, r1 | ||
| 88 | mov.l @r15+, r0 | ||
| 89 | mov.l 7834f, r0 | ||
| 90 | |||
| 91 | bra 7835f | ||
| 92 | nop | ||
| 93 | .balign 4 | ||
| 94 | 7834: .long trace_hardirqs_off | ||
| 95 | 7835: | ||
| 96 | .endm | ||
| 97 | |||
| 98 | #else | ||
| 99 | .macro TRACE_IRQS_ON | ||
| 100 | .endm | ||
| 101 | |||
| 102 | .macro TRACE_IRQS_OFF | ||
| 103 | .endm | ||
| 104 | #endif | ||
| 105 | |||
| 34 | #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) | 106 | #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) |
| 35 | # define PREF(x) pref @x | 107 | # define PREF(x) pref @x |
| 36 | #else | 108 | #else |
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index d62175650c54..fc26ccd82789 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | */ | 45 | */ |
| 46 | 46 | ||
| 47 | #if defined(CONFIG_PREEMPT) | 47 | #if defined(CONFIG_PREEMPT) |
| 48 | # define preempt_stop() cli | 48 | # define preempt_stop() cli ; TRACE_IRQS_OFF |
| 49 | #else | 49 | #else |
| 50 | # define preempt_stop() | 50 | # define preempt_stop() |
| 51 | # define resume_kernel __restore_all | 51 | # define resume_kernel __restore_all |
| @@ -55,11 +55,7 @@ | |||
| 55 | .align 2 | 55 | .align 2 |
| 56 | ENTRY(exception_error) | 56 | ENTRY(exception_error) |
| 57 | ! | 57 | ! |
| 58 | #ifdef CONFIG_TRACE_IRQFLAGS | 58 | TRACE_IRQS_ON |
| 59 | mov.l 2f, r0 | ||
| 60 | jsr @r0 | ||
| 61 | nop | ||
| 62 | #endif | ||
| 63 | sti | 59 | sti |
| 64 | mov.l 1f, r0 | 60 | mov.l 1f, r0 |
| 65 | jmp @r0 | 61 | jmp @r0 |
| @@ -67,22 +63,23 @@ ENTRY(exception_error) | |||
| 67 | 63 | ||
| 68 | .align 2 | 64 | .align 2 |
| 69 | 1: .long do_exception_error | 65 | 1: .long do_exception_error |
| 70 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 71 | 2: .long trace_hardirqs_on | ||
| 72 | #endif | ||
| 73 | 66 | ||
| 74 | .align 2 | 67 | .align 2 |
| 75 | ret_from_exception: | 68 | ret_from_exception: |
| 76 | preempt_stop() | 69 | preempt_stop() |
| 77 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 78 | mov.l 4f, r0 | ||
| 79 | jsr @r0 | ||
| 80 | nop | ||
| 81 | #endif | ||
| 82 | ENTRY(ret_from_irq) | 70 | ENTRY(ret_from_irq) |
| 83 | ! | 71 | ! |
| 84 | mov #OFF_SR, r0 | 72 | mov #OFF_SR, r0 |
| 85 | mov.l @(r0,r15), r0 ! get status register | 73 | mov.l @(r0,r15), r0 ! get status register |
| 74 | |||
| 75 | shlr2 r0 | ||
| 76 | and #0x3c, r0 | ||
| 77 | cmp/eq #0x3c, r0 | ||
| 78 | bt 9f | ||
| 79 | TRACE_IRQS_ON | ||
| 80 | 9: | ||
| 81 | mov #OFF_SR, r0 | ||
| 82 | mov.l @(r0,r15), r0 ! get status register | ||
| 86 | shll r0 | 83 | shll r0 |
| 87 | shll r0 ! kernel space? | 84 | shll r0 ! kernel space? |
| 88 | get_current_thread_info r8, r0 | 85 | get_current_thread_info r8, r0 |
| @@ -125,11 +122,7 @@ noresched: | |||
| 125 | ENTRY(resume_userspace) | 122 | ENTRY(resume_userspace) |
| 126 | ! r8: current_thread_info | 123 | ! r8: current_thread_info |
| 127 | cli | 124 | cli |
| 128 | #ifdef CONFIG_TRACE_IRQFLAGS | 125 | TRACE_IRQS_OfF |
| 129 | mov.l 5f, r0 | ||
| 130 | jsr @r0 | ||
| 131 | nop | ||
| 132 | #endif | ||
| 133 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 126 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
| 134 | tst #(_TIF_WORK_MASK & 0xff), r0 | 127 | tst #(_TIF_WORK_MASK & 0xff), r0 |
| 135 | bt/s __restore_all | 128 | bt/s __restore_all |
| @@ -156,11 +149,7 @@ work_resched: | |||
| 156 | jsr @r1 ! schedule | 149 | jsr @r1 ! schedule |
| 157 | nop | 150 | nop |
| 158 | cli | 151 | cli |
| 159 | #ifdef CONFIG_TRACE_IRQFLAGS | 152 | TRACE_IRQS_OFF |
| 160 | mov.l 5f, r0 | ||
| 161 | jsr @r0 | ||
| 162 | nop | ||
| 163 | #endif | ||
| 164 | ! | 153 | ! |
| 165 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 154 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
| 166 | tst #(_TIF_WORK_MASK & 0xff), r0 | 155 | tst #(_TIF_WORK_MASK & 0xff), r0 |
| @@ -172,10 +161,6 @@ work_resched: | |||
| 172 | 1: .long schedule | 161 | 1: .long schedule |
| 173 | 2: .long do_notify_resume | 162 | 2: .long do_notify_resume |
| 174 | 3: .long resume_userspace | 163 | 3: .long resume_userspace |
| 175 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 176 | 4: .long trace_hardirqs_on | ||
| 177 | 5: .long trace_hardirqs_off | ||
| 178 | #endif | ||
| 179 | 164 | ||
| 180 | .align 2 | 165 | .align 2 |
| 181 | syscall_exit_work: | 166 | syscall_exit_work: |
| @@ -184,11 +169,7 @@ syscall_exit_work: | |||
| 184 | tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0 | 169 | tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0 |
| 185 | bt/s work_pending | 170 | bt/s work_pending |
| 186 | tst #_TIF_NEED_RESCHED, r0 | 171 | tst #_TIF_NEED_RESCHED, r0 |
| 187 | #ifdef CONFIG_TRACE_IRQFLAGS | 172 | TRACE_IRQS_ON |
| 188 | mov.l 5f, r0 | ||
| 189 | jsr @r0 | ||
| 190 | nop | ||
| 191 | #endif | ||
| 192 | sti | 173 | sti |
| 193 | mov r15, r4 | 174 | mov r15, r4 |
| 194 | mov.l 8f, r0 ! do_syscall_trace_leave | 175 | mov.l 8f, r0 ! do_syscall_trace_leave |
| @@ -321,11 +302,7 @@ ENTRY(system_call) | |||
| 321 | bt/s debug_trap ! it's a debug trap.. | 302 | bt/s debug_trap ! it's a debug trap.. |
| 322 | nop | 303 | nop |
| 323 | 304 | ||
| 324 | #ifdef CONFIG_TRACE_IRQFLAGS | 305 | TRACE_IRQS_ON |
| 325 | mov.l 5f, r10 | ||
| 326 | jsr @r10 | ||
| 327 | nop | ||
| 328 | #endif | ||
| 329 | sti | 306 | sti |
| 330 | 307 | ||
| 331 | ! | 308 | ! |
| @@ -355,11 +332,7 @@ syscall_call: | |||
| 355 | ! | 332 | ! |
| 356 | syscall_exit: | 333 | syscall_exit: |
| 357 | cli | 334 | cli |
| 358 | #ifdef CONFIG_TRACE_IRQFLAGS | 335 | TRACE_IRQS_OFF |
| 359 | mov.l 6f, r0 | ||
| 360 | jsr @r0 | ||
| 361 | nop | ||
| 362 | #endif | ||
| 363 | ! | 336 | ! |
| 364 | get_current_thread_info r8, r0 | 337 | get_current_thread_info r8, r0 |
| 365 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 338 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
| @@ -377,9 +350,5 @@ syscall_exit: | |||
| 377 | #endif | 350 | #endif |
| 378 | 2: .long NR_syscalls | 351 | 2: .long NR_syscalls |
| 379 | 3: .long sys_call_table | 352 | 3: .long sys_call_table |
| 380 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 381 | 5: .long trace_hardirqs_on | ||
| 382 | 6: .long trace_hardirqs_off | ||
| 383 | #endif | ||
| 384 | 7: .long do_syscall_trace_enter | 353 | 7: .long do_syscall_trace_enter |
| 385 | 8: .long do_syscall_trace_leave | 354 | 8: .long do_syscall_trace_leave |
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c index 77dfecb64373..e27a19e1f46e 100644 --- a/arch/sh/kernel/io_trapped.c +++ b/arch/sh/kernel/io_trapped.c | |||
| @@ -112,14 +112,15 @@ void __iomem *match_trapped_io_handler(struct list_head *list, | |||
| 112 | struct trapped_io *tiop; | 112 | struct trapped_io *tiop; |
| 113 | struct resource *res; | 113 | struct resource *res; |
| 114 | int k, len; | 114 | int k, len; |
| 115 | unsigned long flags; | ||
| 115 | 116 | ||
| 116 | spin_lock_irq(&trapped_lock); | 117 | spin_lock_irqsave(&trapped_lock, flags); |
| 117 | list_for_each_entry(tiop, list, list) { | 118 | list_for_each_entry(tiop, list, list) { |
| 118 | voffs = 0; | 119 | voffs = 0; |
| 119 | for (k = 0; k < tiop->num_resources; k++) { | 120 | for (k = 0; k < tiop->num_resources; k++) { |
| 120 | res = tiop->resource + k; | 121 | res = tiop->resource + k; |
| 121 | if (res->start == offset) { | 122 | if (res->start == offset) { |
| 122 | spin_unlock_irq(&trapped_lock); | 123 | spin_unlock_irqrestore(&trapped_lock, flags); |
| 123 | return tiop->virt_base + voffs; | 124 | return tiop->virt_base + voffs; |
| 124 | } | 125 | } |
| 125 | 126 | ||
| @@ -127,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list, | |||
| 127 | voffs += roundup(len, PAGE_SIZE); | 128 | voffs += roundup(len, PAGE_SIZE); |
| 128 | } | 129 | } |
| 129 | } | 130 | } |
| 130 | spin_unlock_irq(&trapped_lock); | 131 | spin_unlock_irqrestore(&trapped_lock, flags); |
| 131 | return NULL; | 132 | return NULL; |
| 132 | } | 133 | } |
| 133 | EXPORT_SYMBOL_GPL(match_trapped_io_handler); | 134 | EXPORT_SYMBOL_GPL(match_trapped_io_handler); |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 8e2feb563347..4cbb87ad070a 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -662,10 +662,11 @@ static irqreturn_t sci_rx_interrupt(int irq, void *port) | |||
| 662 | static irqreturn_t sci_tx_interrupt(int irq, void *ptr) | 662 | static irqreturn_t sci_tx_interrupt(int irq, void *ptr) |
| 663 | { | 663 | { |
| 664 | struct uart_port *port = ptr; | 664 | struct uart_port *port = ptr; |
| 665 | unsigned long flags; | ||
| 665 | 666 | ||
| 666 | spin_lock_irq(&port->lock); | 667 | spin_lock_irqsave(&port->lock, flags); |
| 667 | sci_transmit_chars(port); | 668 | sci_transmit_chars(port); |
| 668 | spin_unlock_irq(&port->lock); | 669 | spin_unlock_irqrestore(&port->lock, flags); |
| 669 | 670 | ||
| 670 | return IRQ_HANDLED; | 671 | return IRQ_HANDLED; |
| 671 | } | 672 | } |
