diff mbox series

[azure,4.13] hv_netvsc: netvsc_teardown_gpadl() split

Message ID 1513093487-11937-1-git-send-email-marcelo.cerri@canonical.com
State New
Headers show
Series [azure,4.13] hv_netvsc: netvsc_teardown_gpadl() split | expand

Commit Message

Marcelo Henrique Cerri Dec. 12, 2017, 3:44 p.m. UTC
From: Vitaly Kuznetsov <vkuznets@redhat.com>

BugLink: http://bugs.launchpad.net/bugs/1735546

It was found that in some cases host refuses to teardown GPADL for send/
receive buffers (probably when some work with these buffere is scheduled or
ongoing). Change the teardown logic to be:
1) Send NVSP_MSG1_TYPE_REVOKE_* messages
2) Close the channel
3) Teardown GPADLs.
This seems to work reliably.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(cherry picked from commit 0cf737808ae7cb25e952be619db46b9147a92f46)
Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
---
 drivers/net/hyperv/netvsc.c | 69 +++++++++++++++++++++++----------------------
 1 file changed, 36 insertions(+), 33 deletions(-)

Comments

Thadeu Lima de Souza Cascardo Dec. 12, 2017, 8:29 p.m. UTC | #1
On Tue, Dec 12, 2017 at 01:44:47PM -0200, Marcelo Henrique Cerri wrote:
> From: Vitaly Kuznetsov <vkuznets@redhat.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1735546
> 

What are the test results here? Looking at the bug, I didn't see
anything about this patch.

> It was found that in some cases host refuses to teardown GPADL for send/
> receive buffers (probably when some work with these buffere is scheduled or
> ongoing). Change the teardown logic to be:
> 1) Send NVSP_MSG1_TYPE_REVOKE_* messages
> 2) Close the channel
> 3) Teardown GPADLs.
> This seems to work reliably.
> 
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> (cherry picked from commit 0cf737808ae7cb25e952be619db46b9147a92f46)
> Signed-off-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Marcelo Henrique Cerri Dec. 12, 2017, 8:33 p.m. UTC | #2
Sorry. Without the patch, in a 4.13 kernel modprobe freezes when
reloading the network driver (hv_netvsc). This patch fixes the problem.
Marcelo Henrique Cerri Dec. 12, 2017, 8:34 p.m. UTC | #3
The patch was tested on both azure and hyper-v with positive results.
Thadeu Lima de Souza Cascardo Dec. 12, 2017, 8:41 p.m. UTC | #4
Good test results.

Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Benjamin M Romer Dec. 12, 2017, 8:50 p.m. UTC | #5
Acked-by: Benjamin M Romer <benjamin.romer@canonical.com>
diff mbox series

Patch

diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 411eb0df553f..3df419ff8fd3 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -98,12 +98,11 @@  static void free_netvsc_device_rcu(struct netvsc_device *nvdev)
 	call_rcu(&nvdev->rcu, free_netvsc_device);
 }
 
-static void netvsc_destroy_buf(struct hv_device *device)
+static void netvsc_revoke_buf(struct hv_device *device,
+			      struct netvsc_device *net_device)
 {
 	struct nvsp_message *revoke_packet;
 	struct net_device *ndev = hv_get_drvdata(device);
-	struct net_device_context *ndc = netdev_priv(ndev);
-	struct netvsc_device *net_device = rtnl_dereference(ndc->nvdev);
 	int ret;
 
 	/*
@@ -145,28 +144,6 @@  static void netvsc_destroy_buf(struct hv_device *device)
 		}
 	}
 
-	/* Teardown the gpadl on the vsp end */
-	if (net_device->recv_buf_gpadl_handle) {
-		ret = vmbus_teardown_gpadl(device->channel,
-					   net_device->recv_buf_gpadl_handle);
-
-		/* If we failed here, we might as well return and have a leak
-		 * rather than continue and a bugchk
-		 */
-		if (ret != 0) {
-			netdev_err(ndev,
-				   "unable to teardown receive buffer's gpadl\n");
-			return;
-		}
-		net_device->recv_buf_gpadl_handle = 0;
-	}
-
-	if (net_device->recv_buf) {
-		/* Free up the receive buffer */
-		vfree(net_device->recv_buf);
-		net_device->recv_buf = NULL;
-	}
-
 	/* Deal with the send buffer we may have setup.
 	 * If we got a  send section size, it means we received a
 	 * NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE msg (ie sent
@@ -206,7 +183,35 @@  static void netvsc_destroy_buf(struct hv_device *device)
 			return;
 		}
 	}
-	/* Teardown the gpadl on the vsp end */
+}
+
+static void netvsc_teardown_gpadl(struct hv_device *device,
+				  struct netvsc_device *net_device)
+{
+	struct net_device *ndev = hv_get_drvdata(device);
+	int ret;
+
+	if (net_device->recv_buf_gpadl_handle) {
+		ret = vmbus_teardown_gpadl(device->channel,
+					   net_device->recv_buf_gpadl_handle);
+
+		/* If we failed here, we might as well return and have a leak
+		 * rather than continue and a bugchk
+		 */
+		if (ret != 0) {
+			netdev_err(ndev,
+				   "unable to teardown receive buffer's gpadl\n");
+			return;
+		}
+		net_device->recv_buf_gpadl_handle = 0;
+	}
+
+	if (net_device->recv_buf) {
+		/* Free up the receive buffer */
+		vfree(net_device->recv_buf);
+		net_device->recv_buf = NULL;
+	}
+
 	if (net_device->send_buf_gpadl_handle) {
 		ret = vmbus_teardown_gpadl(device->channel,
 					   net_device->send_buf_gpadl_handle);
@@ -411,7 +416,8 @@  static int netvsc_init_buf(struct hv_device *device,
 	goto exit;
 
 cleanup:
-	netvsc_destroy_buf(device);
+	netvsc_revoke_buf(device, net_device);
+	netvsc_teardown_gpadl(device, net_device);
 
 exit:
 	return ret;
@@ -539,11 +545,6 @@  static int netvsc_connect_vsp(struct hv_device *device,
 	return ret;
 }
 
-static void netvsc_disconnect_vsp(struct hv_device *device)
-{
-	netvsc_destroy_buf(device);
-}
-
 /*
  * netvsc_device_remove - Callback when the root bus device is removed
  */
@@ -555,7 +556,7 @@  void netvsc_device_remove(struct hv_device *device)
 		= rtnl_dereference(net_device_ctx->nvdev);
 	int i;
 
-	netvsc_disconnect_vsp(device);
+	netvsc_revoke_buf(device, net_device);
 
 	RCU_INIT_POINTER(net_device_ctx->nvdev, NULL);
 
@@ -568,6 +569,8 @@  void netvsc_device_remove(struct hv_device *device)
 	/* Now, we can close the channel safely */
 	vmbus_close(device->channel);
 
+	netvsc_teardown_gpadl(device, net_device);
+
 	/* And dissassociate NAPI context from device */
 	for (i = 0; i < net_device->num_chn; i++)
 		netif_napi_del(&net_device->chan_table[i].napi);