Skip to content

Commit

Permalink
Staging: hv: netvsc: Fix a bug in accounting transmit slots
Browse files Browse the repository at this point in the history
The transmit slots were manipulated without proper locking. Fix this bug by
making the variable tracking the transmit slots atomic.

This patch should be ported to prior stable kernels 2.6.32 and later.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
K. Y. Srinivasan authored and Greg Kroah-Hartman committed Jul 5, 2011
1 parent 46d2eb6 commit 9079ce6
Showing 1 changed file with 9 additions and 7 deletions.
16 changes: 9 additions & 7 deletions drivers/staging/hv/netvsc_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/init.h>
#include <linux/atomic.h>
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/device.h>
Expand All @@ -45,7 +46,7 @@
struct net_device_context {
/* point back to our device context */
struct hv_device *device_ctx;
unsigned long avail;
atomic_t avail;
struct delayed_work dwork;
};

Expand Down Expand Up @@ -118,8 +119,9 @@ static void netvsc_xmit_completion(void *context)

dev_kfree_skb_any(skb);

net_device_ctx->avail += num_pages;
if (net_device_ctx->avail >= 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);
}
}
Expand All @@ -133,7 +135,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. */
Expand Down Expand Up @@ -185,8 +187,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
net->stats.tx_bytes += skb->len;
net->stats.tx_packets++;

net_device_ctx->avail -= num_pages;
if (net_device_ctx->avail < 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 */
Expand Down Expand Up @@ -345,7 +347,7 @@ static int netvsc_probe(struct hv_device *dev)

net_device_ctx = netdev_priv(net);
net_device_ctx->device_ctx = dev;
net_device_ctx->avail = ring_size;
atomic_set(&net_device_ctx->avail, ring_size);
dev_set_drvdata(&dev->device, net);
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);

Expand Down

0 comments on commit 9079ce6

Please sign in to comment.