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 | } |