Skip to content

Commit

Permalink
hv_netvsc: avoid retry on send during shutdown
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stephen Hemminger authored and David S. Miller committed Mar 5, 2018
1 parent 3cc81a9 commit 12f6966
Showing 1 changed file with 7 additions and 17 deletions.
24 changes: 7 additions & 17 deletions drivers/net/hyperv/netvsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -852,24 +852,15 @@ 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;

/* 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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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) {
Expand All @@ -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:
Expand Down

0 comments on commit 12f6966

Please sign in to comment.