diff options
author | Arjan van de Ven <arjan@infradead.org> | 2006-07-03 03:24:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-03 18:26:58 -0400 |
commit | 6abd219c6eab92172038e4719e02905acb7b68d4 (patch) | |
tree | b9ab0e856e1acf921f86baaebf14c5f34aa21371 | |
parent | b02454f43578b24bc8b8ab54a239156841f56f6d (diff) |
[PATCH] bcm43xx: netlink deadlock fix
reported by Jure Repinc:
> > http://bugzilla.kernel.org/show_bug.cgi?id=6773
> > checked out dmesg output and found the message
> >
> > ======================================================
> > [ BUG: hard-safe -> hard-unsafe lock order detected! ]
> > ------------------------------------------------------
> >
> > starting at line 660 of the dmesg.txt that I will attach.
The patch below should fix the deadlock, albeit I suspect it's not the
"right" fix; the right fix may well be to move the rx processing in bcm43xx
to softirq context. [it's debatable, ipw2200 hit this exact same bug; at
some point it's better to bite the bullet and move this to the common layer
as my patch below does]
Make the nl_table_lock irq-safe; it's taken for read in various netlink
functions, including functions that several wireless drivers (ipw2200,
bcm43xx) want to call from hardirq context.
The deadlock was found by the lock validator.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Michael Buesch <mb@bu3sch.de>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: Jeff Garzik <jeff@garzik.org>
Acked-by: "David S. Miller" <davem@davemloft.net>
Cc: jamal <hadi@cyberus.ca>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | net/netlink/af_netlink.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 70cee82a98bf..55c0adc8f115 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -156,7 +156,7 @@ static void netlink_sock_destruct(struct sock *sk) | |||
156 | 156 | ||
157 | static void netlink_table_grab(void) | 157 | static void netlink_table_grab(void) |
158 | { | 158 | { |
159 | write_lock_bh(&nl_table_lock); | 159 | write_lock_irq(&nl_table_lock); |
160 | 160 | ||
161 | if (atomic_read(&nl_table_users)) { | 161 | if (atomic_read(&nl_table_users)) { |
162 | DECLARE_WAITQUEUE(wait, current); | 162 | DECLARE_WAITQUEUE(wait, current); |
@@ -166,9 +166,9 @@ static void netlink_table_grab(void) | |||
166 | set_current_state(TASK_UNINTERRUPTIBLE); | 166 | set_current_state(TASK_UNINTERRUPTIBLE); |
167 | if (atomic_read(&nl_table_users) == 0) | 167 | if (atomic_read(&nl_table_users) == 0) |
168 | break; | 168 | break; |
169 | write_unlock_bh(&nl_table_lock); | 169 | write_unlock_irq(&nl_table_lock); |
170 | schedule(); | 170 | schedule(); |
171 | write_lock_bh(&nl_table_lock); | 171 | write_lock_irq(&nl_table_lock); |
172 | } | 172 | } |
173 | 173 | ||
174 | __set_current_state(TASK_RUNNING); | 174 | __set_current_state(TASK_RUNNING); |
@@ -178,7 +178,7 @@ static void netlink_table_grab(void) | |||
178 | 178 | ||
179 | static __inline__ void netlink_table_ungrab(void) | 179 | static __inline__ void netlink_table_ungrab(void) |
180 | { | 180 | { |
181 | write_unlock_bh(&nl_table_lock); | 181 | write_unlock_irq(&nl_table_lock); |
182 | wake_up(&nl_table_wait); | 182 | wake_up(&nl_table_wait); |
183 | } | 183 | } |
184 | 184 | ||