summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2018-03-03 00:49:01 +0300
committerDavid S. Miller <davem@davemloft.net>2018-03-05 06:18:20 +0300
commit12f69661a49446840d742d8feb593ace022d9f66 (patch)
tree917e1f0ea60e089aee8b0f3d9011a6e668953a05 /drivers
parent3cc81a9aac43829d86ebf775c388b42d770bc0ac (diff)
downloadlinux-12f69661a49446840d742d8feb593ace022d9f66.tar.xz
hv_netvsc: avoid retry on send during shutdown
Change the initialization order so that the device is ready to transmit (ie connect vsp is completed) before setting the internal reference to the device with RCU. This avoids any races on initialization and prevents retry issues on shutdown. Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/hyperv/netvsc.c24
1 files changed, 7 insertions, 17 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 17e529af79dc..686900d61374 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -852,13 +852,6 @@ int netvsc_send(struct net_device *ndev,
if (unlikely(!net_device || net_device->destroy))
return -ENODEV;
- /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get
- * here before the negotiation with the host is finished and
- * send_section_map may not be allocated yet.
- */
- if (unlikely(!net_device->send_section_map))
- return -EAGAIN;
-
nvchan = &net_device->chan_table[packet->q_idx];
packet->send_buf_index = NETVSC_INVALID_INDEX;
packet->cp_partial = false;
@@ -866,10 +859,8 @@ int netvsc_send(struct net_device *ndev,
/* Send control message directly without accessing msd (Multi-Send
* Data) field which may be changed during data packet processing.
*/
- if (!skb) {
- cur_send = packet;
- goto send_now;
- }
+ if (!skb)
+ return netvsc_send_pkt(device, packet, net_device, pb, skb);
/* batch packets in send buffer if possible */
msdp = &nvchan->msd;
@@ -953,7 +944,6 @@ int netvsc_send(struct net_device *ndev,
}
}
-send_now:
if (cur_send)
ret = netvsc_send_pkt(device, cur_send, net_device, pb, skb);
@@ -1306,11 +1296,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
napi_enable(&net_device->chan_table[0].napi);
- /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
- * populated.
- */
- rcu_assign_pointer(net_device_ctx->nvdev, net_device);
-
/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device, net_device, device_info);
if (ret != 0) {
@@ -1319,6 +1304,11 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
goto close;
}
+ /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
+ * populated.
+ */
+ rcu_assign_pointer(net_device_ctx->nvdev, net_device);
+
return net_device;
close: