]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/staging/hv/netvsc_drv.c
Staging: hv: netvsc: Fix a bug in accounting transmit slots
[linux-imx.git] / drivers / staging / hv / netvsc_drv.c
index f1a7402f5d5b7e24e27f8ef6860b253ab5838e12..0ad89cca375ad171a9b1e6f3fd936a69784d95fd 100644 (file)
@@ -19,6 +19,7 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
 #include <linux/init.h>
+#include <linux/atomic.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/device.h>
@@ -45,7 +46,7 @@
 struct net_device_context {
        /* point back to our device context */
        struct vm_device *device_ctx;
-       unsigned long avail;
+       atomic_t avail;
        struct work_struct work;
 };
 
@@ -133,7 +134,9 @@ static void netvsc_xmit_completion(void *context)
 
                dev_kfree_skb_any(skb);
 
-               if ((net_device_ctx->avail += num_pages) >= PACKET_PAGES_HIWATER)
+               atomic_add(num_pages, &net_device_ctx->avail);
+               if (atomic_read(&net_device_ctx->avail) >=
+                               PACKET_PAGES_HIWATER)
                        netif_wake_queue(net);
        }
 
@@ -159,7 +162,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 
        /* Add 1 for skb->data and additional one for RNDIS */
        num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
-       if (num_pages > net_device_ctx->avail)
+       if (num_pages > atomic_read(&net_device_ctx->avail))
                return NETDEV_TX_BUSY;
 
        /* Allocate a netvsc packet based on # of frags. */
@@ -218,7 +221,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
                           net->stats.tx_packets,
                           net->stats.tx_bytes);
 
-               if ((net_device_ctx->avail -= num_pages) < PACKET_PAGES_LOWATER)
+               atomic_sub(num_pages, &net_device_ctx->avail);
+               if (atomic_read(&net_device_ctx->avail) < PACKET_PAGES_LOWATER)
                        netif_stop_queue(net);
        } else {
                /* we are shutting down or bus overloaded, just drop packet */
@@ -406,7 +410,7 @@ static int netvsc_probe(struct device *device)
 
        net_device_ctx = netdev_priv(net);
        net_device_ctx->device_ctx = device_ctx;
-       net_device_ctx->avail = ring_size;
+       atomic_set(&net_device_ctx->avail, ring_size);
        dev_set_drvdata(device, net);
        INIT_WORK(&net_device_ctx->work, netvsc_send_garp);