diff options
author | Neil Horman <nhorman@tuxdriver.com> | 2006-06-26 03:04:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-06-26 03:04:27 -0400 |
commit | 068c6e98bc7ec4419299b38cd40be26ebf4bdeda (patch) | |
tree | 4312d3449036c35d5fc8fd4f60f447200928e817 /include | |
parent | 8834807b43200b1658b49d3b779e74a4f77e4ffb (diff) |
[NET] netpoll: break recursive loop in netpoll rx path
The netpoll system currently has a rx to tx path via:
netpoll_rx
__netpoll_rx
arp_reply
netpoll_send_skb
dev->hard_start_tx
This rx->tx loop places network drivers at risk of inadvertently causing a
deadlock or BUG halt by recursively trying to acquire a spinlock that is
used in both their rx and tx paths (this problem was origionally reported
to me in the 3c59x driver, which shares a spinlock between the
boomerang_interrupt and boomerang_start_xmit routines).
This patch breaks this loop, by queueing arp frames, so that they can be
responded to after all receive operations have been completed. Tested by
myself and the reported with successful results.
Specifically it was tested with netdump. Heres the BZ with details:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=194055
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: Matt Mackall <mpm@selenic.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/netpoll.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index ca5a8733000f..1efe60c5c00c 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h | |||
@@ -31,6 +31,7 @@ struct netpoll_info { | |||
31 | int rx_flags; | 31 | int rx_flags; |
32 | spinlock_t rx_lock; | 32 | spinlock_t rx_lock; |
33 | struct netpoll *rx_np; /* netpoll that registered an rx_hook */ | 33 | struct netpoll *rx_np; /* netpoll that registered an rx_hook */ |
34 | struct sk_buff_head arp_tx; /* list of arp requests to reply to */ | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | void netpoll_poll(struct netpoll *np); | 37 | void netpoll_poll(struct netpoll *np); |