diff options
author | Haiyang Zhang <haiyangz@microsoft.com> | 2011-12-02 11:56:25 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-09 16:26:50 -0800 |
commit | 1d06825b0ede541f63b5577435abd2fc649a9b5e (patch) | |
tree | f3b72c945f340d1f6e81ec124a8fb352d9de747f /drivers/net/hyperv/netvsc.c | |
parent | 9d41c5bb07ad97b7777283d7922292f456ba4bfd (diff) | |
download | op-kernel-dev-1d06825b0ede541f63b5577435abd2fc649a9b5e.zip op-kernel-dev-1d06825b0ede541f63b5577435abd2fc649a9b5e.tar.gz |
net/hyperv: Fix the stop/wake queue mechanism
The ring buffer is only used to pass meta data for outbound packets. The
actual payload is accessed by DMA from the host. So the stop/wake queue
mechanism based on counting and comparing number of pages sent v.s. number
of pages in the ring buffer is wrong. Also, there is a race condition in
the stop/wake queue calls, which can stop xmit queue forever.
The new stop/wake queue mechanism is based on the actual bytes used by
outbound packets in the ring buffer. The check for number of outstanding
sends after stop queue prevents the race condition that can cause wake
queue happening earlier than stop queue.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reported-by: Long Li <longli@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/net/hyperv/netvsc.c')
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 4a807e4..b6ac152 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -435,6 +435,9 @@ static void netvsc_send_completion(struct hv_device *device, nvsc_packet->completion.send.send_completion_ctx); atomic_dec(&net_device->num_outstanding_sends); + + if (netif_queue_stopped(ndev)) + netif_wake_queue(ndev); } else { netdev_err(ndev, "Unknown send completion packet type- " "%d received!!\n", nvsp_packet->hdr.msg_type); @@ -485,11 +488,16 @@ int netvsc_send(struct hv_device *device, } - if (ret != 0) + if (ret == 0) { + atomic_inc(&net_device->num_outstanding_sends); + } else if (ret == -EAGAIN) { + netif_stop_queue(ndev); + if (atomic_read(&net_device->num_outstanding_sends) < 1) + netif_wake_queue(ndev); + } else { netdev_err(ndev, "Unable to send packet %p ret %d\n", packet, ret); - else - atomic_inc(&net_device->num_outstanding_sends); + } return ret; } |