summaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv/netvsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/hyperv/netvsc.c')
-rw-r--r--drivers/net/hyperv/netvsc.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 727762d0..ab9118d 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -80,8 +80,10 @@ static struct netvsc_device *alloc_net_device(void)
return net_device;
}
-static void free_netvsc_device(struct netvsc_device *nvdev)
+static void free_netvsc_device(struct rcu_head *head)
{
+ struct netvsc_device *nvdev
+ = container_of(head, struct netvsc_device, rcu);
int i;
for (i = 0; i < VRSS_CHANNEL_MAX; i++)
@@ -90,6 +92,10 @@ static void free_netvsc_device(struct netvsc_device *nvdev)
kfree(nvdev);
}
+static void free_netvsc_device_rcu(struct netvsc_device *nvdev)
+{
+ call_rcu(&nvdev->rcu, free_netvsc_device);
+}
static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
{
@@ -551,7 +557,7 @@ void netvsc_device_remove(struct hv_device *device)
netvsc_disconnect_vsp(device);
- net_device_ctx->nvdev = NULL;
+ RCU_INIT_POINTER(net_device_ctx->nvdev, NULL);
/*
* At this point, no one should be accessing net_device
@@ -566,7 +572,7 @@ void netvsc_device_remove(struct hv_device *device)
napi_disable(&net_device->chan_table[i].napi);
/* Release all resources */
- free_netvsc_device(net_device);
+ free_netvsc_device_rcu(net_device);
}
#define RING_AVAIL_PERCENT_HIWATER 20
@@ -1322,7 +1328,7 @@ int netvsc_device_add(struct hv_device *device,
*/
wmb();
- net_device_ctx->nvdev = net_device;
+ rcu_assign_pointer(net_device_ctx->nvdev, net_device);
/* Connect with the NetVsp */
ret = netvsc_connect_vsp(device);
@@ -1341,7 +1347,7 @@ close:
vmbus_close(device->channel);
cleanup:
- free_netvsc_device(net_device);
+ free_netvsc_device(&net_device->rcu);
return ret;
}
OpenPOWER on IntegriCloud