aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/netpoll.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/netpoll.c')
-rw-r--r--net/core/netpoll.c53
1 files changed, 21 insertions, 32 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 6589adb14cb..4de62f1f413 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -36,9 +36,7 @@
36#define MAX_QUEUE_DEPTH (MAX_SKBS / 2) 36#define MAX_QUEUE_DEPTH (MAX_SKBS / 2)
37#define MAX_RETRIES 20000 37#define MAX_RETRIES 20000
38 38
39static DEFINE_SPINLOCK(skb_list_lock); 39static struct sk_buff_head skb_pool;
40static int nr_skbs;
41static struct sk_buff *skbs;
42 40
43static DEFINE_SPINLOCK(queue_lock); 41static DEFINE_SPINLOCK(queue_lock);
44static int queue_depth; 42static int queue_depth;
@@ -190,17 +188,15 @@ static void refill_skbs(void)
190 struct sk_buff *skb; 188 struct sk_buff *skb;
191 unsigned long flags; 189 unsigned long flags;
192 190
193 spin_lock_irqsave(&skb_list_lock, flags); 191 spin_lock_irqsave(&skb_pool.lock, flags);
194 while (nr_skbs < MAX_SKBS) { 192 while (skb_pool.qlen < MAX_SKBS) {
195 skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC); 193 skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
196 if (!skb) 194 if (!skb)
197 break; 195 break;
198 196
199 skb->next = skbs; 197 __skb_queue_tail(&skb_pool, skb);
200 skbs = skb;
201 nr_skbs++;
202 } 198 }
203 spin_unlock_irqrestore(&skb_list_lock, flags); 199 spin_unlock_irqrestore(&skb_pool.lock, flags);
204} 200}
205 201
206static void zap_completion_queue(void) 202static void zap_completion_queue(void)
@@ -229,38 +225,25 @@ static void zap_completion_queue(void)
229 put_cpu_var(softnet_data); 225 put_cpu_var(softnet_data);
230} 226}
231 227
232static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve) 228static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
233{ 229{
234 int once = 1, count = 0; 230 int count = 0;
235 unsigned long flags; 231 struct sk_buff *skb;
236 struct sk_buff *skb = NULL;
237 232
238 zap_completion_queue(); 233 zap_completion_queue();
234 refill_skbs();
239repeat: 235repeat:
240 if (nr_skbs < MAX_SKBS)
241 refill_skbs();
242 236
243 skb = alloc_skb(len, GFP_ATOMIC); 237 skb = alloc_skb(len, GFP_ATOMIC);
244 238 if (!skb)
245 if (!skb) { 239 skb = skb_dequeue(&skb_pool);
246 spin_lock_irqsave(&skb_list_lock, flags);
247 skb = skbs;
248 if (skb) {
249 skbs = skb->next;
250 skb->next = NULL;
251 nr_skbs--;
252 }
253 spin_unlock_irqrestore(&skb_list_lock, flags);
254 }
255 240
256 if(!skb) { 241 if(!skb) {
257 count++; 242 if (++count < 10) {
258 if (once && (count == 1000000)) { 243 netpoll_poll(np);
259 printk("out of netpoll skbs!\n"); 244 goto repeat;
260 once = 0;
261 } 245 }
262 netpoll_poll(np); 246 return NULL;
263 goto repeat;
264 } 247 }
265 248
266 atomic_set(&skb->users, 1); 249 atomic_set(&skb->users, 1);
@@ -770,6 +753,12 @@ int netpoll_setup(struct netpoll *np)
770 return -1; 753 return -1;
771} 754}
772 755
756static int __init netpoll_init(void) {
757 skb_queue_head_init(&skb_pool);
758 return 0;
759}
760core_initcall(netpoll_init);
761
773void netpoll_cleanup(struct netpoll *np) 762void netpoll_cleanup(struct netpoll *np)
774{ 763{
775 struct netpoll_info *npinfo; 764 struct netpoll_info *npinfo;