netpoll: private skb pool (rev3)
[powerpc.git] / net / core / netpoll.c
index 9308af0..4de62f1 100644 (file)
@@ -36,9 +36,7 @@
 #define MAX_QUEUE_DEPTH (MAX_SKBS / 2)
 #define MAX_RETRIES 20000
 
-static DEFINE_SPINLOCK(skb_list_lock);
-static int nr_skbs;
-static struct sk_buff *skbs;
+static struct sk_buff_head skb_pool;
 
 static DEFINE_SPINLOCK(queue_lock);
 static int queue_depth;
@@ -190,17 +188,15 @@ static void refill_skbs(void)
        struct sk_buff *skb;
        unsigned long flags;
 
-       spin_lock_irqsave(&skb_list_lock, flags);
-       while (nr_skbs < MAX_SKBS) {
+       spin_lock_irqsave(&skb_pool.lock, flags);
+       while (skb_pool.qlen < MAX_SKBS) {
                skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
                if (!skb)
                        break;
 
-               skb->next = skbs;
-               skbs = skb;
-               nr_skbs++;
+               __skb_queue_tail(&skb_pool, skb);
        }
-       spin_unlock_irqrestore(&skb_list_lock, flags);
+       spin_unlock_irqrestore(&skb_pool.lock, flags);
 }
 
 static void zap_completion_queue(void)
@@ -229,38 +225,25 @@ static void zap_completion_queue(void)
        put_cpu_var(softnet_data);
 }
 
-static struct sk_buff * find_skb(struct netpoll *np, int len, int reserve)
+static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
 {
-       int once = 1, count = 0;
-       unsigned long flags;
-       struct sk_buff *skb = NULL;
+       int count = 0;
+       struct sk_buff *skb;
 
        zap_completion_queue();
+       refill_skbs();
 repeat:
-       if (nr_skbs < MAX_SKBS)
-               refill_skbs();
 
        skb = alloc_skb(len, GFP_ATOMIC);
-
-       if (!skb) {
-               spin_lock_irqsave(&skb_list_lock, flags);
-               skb = skbs;
-               if (skb) {
-                       skbs = skb->next;
-                       skb->next = NULL;
-                       nr_skbs--;
-               }
-               spin_unlock_irqrestore(&skb_list_lock, flags);
-       }
+       if (!skb)
+               skb = skb_dequeue(&skb_pool);
 
        if(!skb) {
-               count++;
-               if (once && (count == 1000000)) {
-                       printk("out of netpoll skbs!\n");
-                       once = 0;
+               if (++count < 10) {
+                       netpoll_poll(np);
+                       goto repeat;
                }
-               netpoll_poll(np);
-               goto repeat;
+               return NULL;
        }
 
        atomic_set(&skb->users, 1);
@@ -340,6 +323,12 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
        udph->dest = htons(np->remote_port);
        udph->len = htons(udp_len);
        udph->check = 0;
+       udph->check = csum_tcpudp_magic(htonl(np->local_ip),
+                                       htonl(np->remote_ip),
+                                       udp_len, IPPROTO_UDP,
+                                       csum_partial((unsigned char *)udph, udp_len, 0));
+       if (udph->check == 0)
+               udph->check = -1;
 
        skb->nh.iph = iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
 
@@ -764,6 +753,12 @@ int netpoll_setup(struct netpoll *np)
        return -1;
 }
 
+static int __init netpoll_init(void) {
+       skb_queue_head_init(&skb_pool);
+       return 0;
+}
+core_initcall(netpoll_init);
+
 void netpoll_cleanup(struct netpoll *np)
 {
        struct netpoll_info *npinfo;