diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index c9910c33e671..04f611e6f678 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -109,11 +109,11 @@ static void free_netvsc_device_rcu(struct netvsc_device *nvdev) call_rcu(&nvdev->rcu, free_netvsc_device); } -static void netvsc_revoke_buf(struct hv_device *device, - struct netvsc_device *net_device) +static void netvsc_revoke_recv_buf(struct hv_device *device, + struct netvsc_device *net_device, + struct net_device *ndev) { struct nvsp_message *revoke_packet; - struct net_device *ndev = hv_get_drvdata(device); int ret; /* @@ -157,6 +157,14 @@ static void netvsc_revoke_buf(struct hv_device *device, } net_device->recv_section_cnt = 0; } +} + +static void netvsc_revoke_send_buf(struct hv_device *device, + struct netvsc_device *net_device, + struct net_device *ndev) +{ + struct nvsp_message *revoke_packet; + int ret; /* Deal with the send buffer we may have setup. * If we got a send section size, it means we received a @@ -202,10 +210,10 @@ static void netvsc_revoke_buf(struct hv_device *device, } } -static void netvsc_teardown_gpadl(struct hv_device *device, - struct netvsc_device *net_device) +static void netvsc_teardown_recv_gpadl(struct hv_device *device, + struct netvsc_device *net_device, + struct net_device *ndev) { - struct net_device *ndev = hv_get_drvdata(device); int ret; if (net_device->recv_buf_gpadl_handle) { @@ -222,6 +230,13 @@ static void netvsc_teardown_gpadl(struct hv_device *device, } net_device->recv_buf_gpadl_handle = 0; } +} + +static void netvsc_teardown_send_gpadl(struct hv_device *device, + struct netvsc_device *net_device, + struct net_device *ndev) +{ + int ret; if (net_device->send_buf_gpadl_handle) { ret = vmbus_teardown_gpadl(device->channel, @@ -437,8 +452,10 @@ static int netvsc_init_buf(struct hv_device *device, goto exit; cleanup: - netvsc_revoke_buf(device, net_device); - netvsc_teardown_gpadl(device, net_device); + netvsc_revoke_recv_buf(device, net_device, ndev); + netvsc_revoke_send_buf(device, net_device, ndev); + netvsc_teardown_recv_gpadl(device, net_device, ndev); + netvsc_teardown_send_gpadl(device, net_device, ndev); exit: return ret; @@ -457,7 +474,6 @@ static int negotiate_nvsp_ver(struct hv_device *device, init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT; init_packet->msg.init_msg.init.min_protocol_ver = nvsp_ver; init_packet->msg.init_msg.init.max_protocol_ver = nvsp_ver; - trace_nvsp_send(ndev, init_packet); /* Send the init request */ @@ -575,7 +591,17 @@ void netvsc_device_remove(struct hv_device *device) = rtnl_dereference(net_device_ctx->nvdev); int i; - netvsc_revoke_buf(device, net_device); + /* + * Revoke receive buffer. If host is pre-Win2016 then tear down + * receive buffer GPADL. Do the same for send buffer. + */ + netvsc_revoke_recv_buf(device, net_device, ndev); + if (vmbus_proto_version < VERSION_WIN10) + netvsc_teardown_recv_gpadl(device, net_device, ndev); + + netvsc_revoke_send_buf(device, net_device, ndev); + if (vmbus_proto_version < VERSION_WIN10) + netvsc_teardown_send_gpadl(device, net_device, ndev); RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); @@ -589,15 +615,17 @@ void netvsc_device_remove(struct hv_device *device) */ netdev_dbg(ndev, "net device safe to remove\n"); - /* older versions require that buffer be revoked before close */ - if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_4) - netvsc_teardown_gpadl(device, net_device); - /* Now, we can close the channel safely */ vmbus_close(device->channel); - if (net_device->nvsp_version >= NVSP_PROTOCOL_VERSION_4) - netvsc_teardown_gpadl(device, net_device); + /* + * If host is Win2016 or higher then we do the GPADL tear down + * here after VMBus is closed. + */ + if (vmbus_proto_version >= VERSION_WIN10) { + netvsc_teardown_recv_gpadl(device, net_device, ndev); + netvsc_teardown_send_gpadl(device, net_device, ndev); + } /* Release all resources */ free_netvsc_device_rcu(net_device);