diff options
author | Matt Mackall <mpm@selenic.com> | 2005-08-11 22:27:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-08-11 22:27:43 -0400 |
commit | 53fb95d3c14290fd6ee808b221e35493f096246f (patch) | |
tree | 146c31c79bbc66d8fde3afa5ae37a04b63041eba /include/linux/netpoll.h | |
parent | 2652076507b662fc88ba16c27b59c7bdd9ccd956 (diff) |
[NETPOLL]: fix initialization/NAPI race
This fixes a race during initialization with the NAPI softirq
processing by using an RCU approach.
This race was discovered when refill_skbs() was added to
the setup code.
Signed-off-by: Matt Mackall <mpm@selenic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/netpoll.h')
-rw-r--r-- | include/linux/netpoll.h | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index be68d94b03d5..5ade54a78dbb 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/rcupdate.h> | ||
12 | #include <linux/list.h> | 13 | #include <linux/list.h> |
13 | 14 | ||
14 | struct netpoll; | 15 | struct netpoll; |
@@ -61,25 +62,31 @@ static inline int netpoll_rx(struct sk_buff *skb) | |||
61 | return ret; | 62 | return ret; |
62 | } | 63 | } |
63 | 64 | ||
64 | static inline void netpoll_poll_lock(struct net_device *dev) | 65 | static inline void *netpoll_poll_lock(struct net_device *dev) |
65 | { | 66 | { |
67 | rcu_read_lock(); /* deal with race on ->npinfo */ | ||
66 | if (dev->npinfo) { | 68 | if (dev->npinfo) { |
67 | spin_lock(&dev->npinfo->poll_lock); | 69 | spin_lock(&dev->npinfo->poll_lock); |
68 | dev->npinfo->poll_owner = smp_processor_id(); | 70 | dev->npinfo->poll_owner = smp_processor_id(); |
71 | return dev->npinfo; | ||
69 | } | 72 | } |
73 | return NULL; | ||
70 | } | 74 | } |
71 | 75 | ||
72 | static inline void netpoll_poll_unlock(struct net_device *dev) | 76 | static inline void netpoll_poll_unlock(void *have) |
73 | { | 77 | { |
74 | if (dev->npinfo) { | 78 | struct netpoll_info *npi = have; |
75 | dev->npinfo->poll_owner = -1; | 79 | |
76 | spin_unlock(&dev->npinfo->poll_lock); | 80 | if (npi) { |
81 | npi->poll_owner = -1; | ||
82 | spin_unlock(&npi->poll_lock); | ||
77 | } | 83 | } |
84 | rcu_read_unlock(); | ||
78 | } | 85 | } |
79 | 86 | ||
80 | #else | 87 | #else |
81 | #define netpoll_rx(a) 0 | 88 | #define netpoll_rx(a) 0 |
82 | #define netpoll_poll_lock(a) | 89 | #define netpoll_poll_lock(a) 0 |
83 | #define netpoll_poll_unlock(a) | 90 | #define netpoll_poll_unlock(a) |
84 | #endif | 91 | #endif |
85 | 92 | ||