Staging: hv: handle skb allocation failure
authorStephen Hemminger <shemminger@vyatta.com>
Wed, 10 Mar 2010 01:42:17 +0000 (17:42 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 11 May 2010 18:35:34 +0000 (11:35 -0700)
Some fixes to receive handling:
  * Dieing with assertion failure when running out of memory is not ok
  * Use newer alloc function to get aligned skb
  * Dropped statistic is supposed to be incremented only by
    driver it was responsible for the drop.

Compile tested only.

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Cc: Hank Janssen <hjanssen@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/hv/netvsc_drv.c

index e87a7c2..51a56e2 100644 (file)
@@ -294,7 +294,6 @@ static int netvsc_recv_callback(struct hv_device *device_obj,
        struct net_device_context *net_device_ctx;
        struct sk_buff *skb;
        void *data;
-       int ret;
        int i;
        unsigned long flags;
 
@@ -308,12 +307,12 @@ static int netvsc_recv_callback(struct hv_device *device_obj,
 
        net_device_ctx = netdev_priv(net);
 
-       /* Allocate a skb - TODO preallocate this */
-       /* Pad 2-bytes to align IP header to 16 bytes */
-       skb = dev_alloc_skb(packet->TotalDataBufferLength + 2);
-       ASSERT(skb);
-       skb_reserve(skb, 2);
-       skb->dev = net;
+       /* Allocate a skb - TODO direct I/O to pages? */
+       skb = netdev_alloc_skb_ip_align(net, packet->TotalDataBufferLength);
+       if (unlikely(!skb)) {
+               ++net->stats.rx_dropped;
+               return 0;
+       }
 
        /* for kmap_atomic */
        local_irq_save(flags);
@@ -338,25 +337,18 @@ static int netvsc_recv_callback(struct hv_device *device_obj,
        local_irq_restore(flags);
 
        skb->protocol = eth_type_trans(skb, net);
-
        skb->ip_summed = CHECKSUM_NONE;
 
+       net->stats.rx_packets++;
+       net->stats.rx_bytes += skb->len;
+
        /*
         * Pass the skb back up. Network stack will deallocate the skb when it
-        * is done
+        * is done.
+        * TODO - use NAPI?
         */
-       ret = netif_rx(skb);
-
-       switch (ret) {
-       case NET_RX_DROP:
-               net->stats.rx_dropped++;
-               break;
-       default:
-               net->stats.rx_packets++;
-               net->stats.rx_bytes += skb->len;
-               break;
+       netif_rx(skb);
 
-       }
        DPRINT_DBG(NETVSC_DRV, "# of recvs %lu total size %lu",
                   net->stats.rx_packets, net->stats.rx_bytes);