Re: [PATCH net-next] hv_netvsc: Implement batching of receive completions

2016-08-19 Thread David Miller
From: Haiyang Zhang 
Date: Fri, 19 Aug 2016 14:47:09 -0700

> From: Haiyang Zhang 
> 
> The existing code uses busy retry when unable to send out receive
> completions due to full ring buffer. It also gives up retrying after limit
> is reached, and causes receive buffer slots not being recycled.
> This patch implements batching of receive completions. It also prevents
> dropping receive completions due to full ring buffer.
> 
> Signed-off-by: Haiyang Zhang 
> Reviewed-by: Stephen Hemminger 

Applied, thanks.


[PATCH net-next] hv_netvsc: Implement batching of receive completions

2016-08-19 Thread Haiyang Zhang
From: Haiyang Zhang 

The existing code uses busy retry when unable to send out receive
completions due to full ring buffer. It also gives up retrying after limit
is reached, and causes receive buffer slots not being recycled.
This patch implements batching of receive completions. It also prevents
dropping receive completions due to full ring buffer.

Signed-off-by: Haiyang Zhang 
Reviewed-by: Stephen Hemminger 
---
 drivers/net/hyperv/hyperv_net.h   |   17 
 drivers/net/hyperv/netvsc.c   |  170 ++---
 drivers/net/hyperv/rndis_filter.c |6 +-
 3 files changed, 160 insertions(+), 33 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index fa7b1e4..ce45d68 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -634,6 +634,20 @@ struct multi_send_data {
u32 count; /* counter of batched packets */
 };
 
+struct recv_comp_data {
+   u64 tid; /* transaction id */
+   u32 status;
+};
+
+/* Netvsc Receive Slots Max */
+#define NETVSC_RECVSLOT_MAX (NETVSC_RECEIVE_BUFFER_SIZE / ETH_DATA_LEN + 1)
+
+struct multi_recv_comp {
+   void *buf; /* queued receive completions */
+   u32 first; /* first data entry */
+   u32 next; /* next entry for writing */
+};
+
 struct netvsc_stats {
u64 packets;
u64 bytes;
@@ -736,6 +750,9 @@ struct netvsc_device {
u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
u32 pkt_align; /* alignment bytes, e.g. 8 */
 
+   struct multi_recv_comp mrc[VRSS_CHANNEL_MAX];
+   atomic_t num_outstanding_recvs;
+
atomic_t open_cnt;
 };
 
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 8078bc2..b15edfc 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -74,6 +74,9 @@ static struct netvsc_device *alloc_net_device(void)
return NULL;
}
 
+   net_device->mrc[0].buf = vzalloc(NETVSC_RECVSLOT_MAX *
+sizeof(struct recv_comp_data));
+
init_waitqueue_head(_device->wait_drain);
net_device->destroy = false;
atomic_set(_device->open_cnt, 0);
@@ -85,6 +88,11 @@ static struct netvsc_device *alloc_net_device(void)
 
 static void free_netvsc_device(struct netvsc_device *nvdev)
 {
+   int i;
+
+   for (i = 0; i < VRSS_CHANNEL_MAX; i++)
+   vfree(nvdev->mrc[i].buf);
+
kfree(nvdev->cb_buffer);
kfree(nvdev);
 }
@@ -107,7 +115,8 @@ static struct netvsc_device *get_inbound_net_device(struct 
hv_device *device)
goto get_in_err;
 
if (net_device->destroy &&
-   atomic_read(_device->num_outstanding_sends) == 0)
+   atomic_read(_device->num_outstanding_sends) == 0 &&
+   atomic_read(_device->num_outstanding_recvs) == 0)
net_device = NULL;
 
 get_in_err:
@@ -972,49 +981,121 @@ send_now:
return ret;
 }
 
-static void netvsc_send_recv_completion(struct hv_device *device,
-   struct vmbus_channel *channel,
-   struct netvsc_device *net_device,
-   u64 transaction_id, u32 status)
+static int netvsc_send_recv_completion(struct vmbus_channel *channel,
+  u64 transaction_id, u32 status)
 {
struct nvsp_message recvcompMessage;
-   int retries = 0;
int ret;
-   struct net_device *ndev = hv_get_drvdata(device);
 
recvcompMessage.hdr.msg_type =
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
 
recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status;
 
-retry_send_cmplt:
/* Send the completion */
ret = vmbus_sendpacket(channel, ,
-  sizeof(struct nvsp_message), transaction_id,
-  VM_PKT_COMP, 0);
-   if (ret == 0) {
-   /* success */
-   /* no-op */
-   } else if (ret == -EAGAIN) {
-   /* no more room...wait a bit and attempt to retry 3 times */
-   retries++;
-   netdev_err(ndev, "unable to send receive completion pkt"
-   " (tid %llx)...retrying %d\n", transaction_id, retries);
-
-   if (retries < 4) {
-   udelay(100);
-   goto retry_send_cmplt;
-   } else {
-   netdev_err(ndev, "unable to send receive "
-   "completion pkt (tid %llx)...give up 
retrying\n",
-   transaction_id);
-   }
-   } else {
-   netdev_err(ndev, "unable to send receive "
-   "completion pkt - %llx\n", transaction_id);
+  sizeof(struct nvsp_message_header) +