mirror of https://gitee.com/openkylin/linux.git
Merge branch 'hv_netvsc-Fix-shutdown-issues-on-older-Windows-hosts'
Mohammed Gamal says:
====================
hv_netvsc: Fix shutdown issues on older Windows hosts
Guests running on WS2012 hosts would not shutdown when changing network
interface setting (e.g. Number of channels, MTU ... etc).
This patch series addresses these shutdown issues we enecountered with WS2012
hosts. It's essentialy a rework of the series sent in
https://lkml.org/lkml/2018/1/23/111 on top of latest upstream
====================
Fixes: 0ef58b0a05
("hv_netvsc: change GPAD teardown order on older versions")
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a2aeea1cc1
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue