Skip to content

Commit 53e8269

Browse files
committed
Merge branch 'hv_netvsc-fix-races-during-shutdown-and-changes'
Stephen Hemminger says: ==================== hv_netvsc: fix races during shutdown and changes This set of patches fixes issues identified by Vitaly Kuznetsov and Mohammed Gamal related to state changes in Hyper-v network driver. A lot of the issues are because setting up the netvsc device requires a second step (in work queue) to get all the sub-channels running. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 68e2ffd + 7b2ee50 commit 53e8269

File tree

4 files changed

+204
-183
lines changed

4 files changed

+204
-183
lines changed

drivers/net/hyperv/hyperv_net.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ void netvsc_channel_cb(void *context);
212212
int netvsc_poll(struct napi_struct *napi, int budget);
213213

214214
void rndis_set_subchannel(struct work_struct *w);
215-
bool rndis_filter_opened(const struct netvsc_device *nvdev);
216215
int rndis_filter_open(struct netvsc_device *nvdev);
217216
int rndis_filter_close(struct netvsc_device *nvdev);
218217
struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,

drivers/net/hyperv/netvsc.c

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ static void free_netvsc_device(struct rcu_head *head)
9090
= container_of(head, struct netvsc_device, rcu);
9191
int i;
9292

93+
kfree(nvdev->extension);
94+
vfree(nvdev->recv_buf);
95+
vfree(nvdev->send_buf);
96+
kfree(nvdev->send_section_map);
97+
9398
for (i = 0; i < VRSS_CHANNEL_MAX; i++)
9499
vfree(nvdev->chan_table[i].mrc.slots);
95100

@@ -211,12 +216,6 @@ static void netvsc_teardown_gpadl(struct hv_device *device,
211216
net_device->recv_buf_gpadl_handle = 0;
212217
}
213218

214-
if (net_device->recv_buf) {
215-
/* Free up the receive buffer */
216-
vfree(net_device->recv_buf);
217-
net_device->recv_buf = NULL;
218-
}
219-
220219
if (net_device->send_buf_gpadl_handle) {
221220
ret = vmbus_teardown_gpadl(device->channel,
222221
net_device->send_buf_gpadl_handle);
@@ -231,12 +230,6 @@ static void netvsc_teardown_gpadl(struct hv_device *device,
231230
}
232231
net_device->send_buf_gpadl_handle = 0;
233232
}
234-
if (net_device->send_buf) {
235-
/* Free up the send buffer */
236-
vfree(net_device->send_buf);
237-
net_device->send_buf = NULL;
238-
}
239-
kfree(net_device->send_section_map);
240233
}
241234

242235
int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx)
@@ -562,26 +555,29 @@ void netvsc_device_remove(struct hv_device *device)
562555
= rtnl_dereference(net_device_ctx->nvdev);
563556
int i;
564557

565-
cancel_work_sync(&net_device->subchan_work);
566-
567558
netvsc_revoke_buf(device, net_device);
568559

569560
RCU_INIT_POINTER(net_device_ctx->nvdev, NULL);
570561

562+
/* And disassociate NAPI context from device */
563+
for (i = 0; i < net_device->num_chn; i++)
564+
netif_napi_del(&net_device->chan_table[i].napi);
565+
571566
/*
572567
* At this point, no one should be accessing net_device
573568
* except in here
574569
*/
575570
netdev_dbg(ndev, "net device safe to remove\n");
576571

572+
/* older versions require that buffer be revoked before close */
573+
if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_4)
574+
netvsc_teardown_gpadl(device, net_device);
575+
577576
/* Now, we can close the channel safely */
578577
vmbus_close(device->channel);
579578

580-
netvsc_teardown_gpadl(device, net_device);
581-
582-
/* And dissassociate NAPI context from device */
583-
for (i = 0; i < net_device->num_chn; i++)
584-
netif_napi_del(&net_device->chan_table[i].napi);
579+
if (net_device->nvsp_version >= NVSP_PROTOCOL_VERSION_4)
580+
netvsc_teardown_gpadl(device, net_device);
585581

586582
/* Release all resources */
587583
free_netvsc_device_rcu(net_device);
@@ -645,14 +641,18 @@ static void netvsc_send_tx_complete(struct netvsc_device *net_device,
645641
queue_sends =
646642
atomic_dec_return(&net_device->chan_table[q_idx].queue_sends);
647643

648-
if (net_device->destroy && queue_sends == 0)
649-
wake_up(&net_device->wait_drain);
644+
if (unlikely(net_device->destroy)) {
645+
if (queue_sends == 0)
646+
wake_up(&net_device->wait_drain);
647+
} else {
648+
struct netdev_queue *txq = netdev_get_tx_queue(ndev, q_idx);
650649

651-
if (netif_tx_queue_stopped(netdev_get_tx_queue(ndev, q_idx)) &&
652-
(hv_ringbuf_avail_percent(&channel->outbound) > RING_AVAIL_PERCENT_HIWATER ||
653-
queue_sends < 1)) {
654-
netif_tx_wake_queue(netdev_get_tx_queue(ndev, q_idx));
655-
ndev_ctx->eth_stats.wake_queue++;
650+
if (netif_tx_queue_stopped(txq) &&
651+
(hv_ringbuf_avail_percent(&channel->outbound) > RING_AVAIL_PERCENT_HIWATER ||
652+
queue_sends < 1)) {
653+
netif_tx_wake_queue(txq);
654+
ndev_ctx->eth_stats.wake_queue++;
655+
}
656656
}
657657
}
658658

0 commit comments

Comments
 (0)