@@ -667,18 +667,21 @@ int netvsc_recv_callback(struct hv_device *device_obj,
667
667
{
668
668
struct net_device * net = hv_get_drvdata (device_obj );
669
669
struct net_device_context * net_device_ctx = netdev_priv (net );
670
+ struct net_device * vf_netdev ;
670
671
struct sk_buff * skb ;
671
- struct sk_buff * vf_skb ;
672
672
struct netvsc_stats * rx_stats ;
673
673
u32 bytes_recvd = packet -> total_data_buflen ;
674
674
int ret = 0 ;
675
675
676
676
if (!net || net -> reg_state != NETREG_REGISTERED )
677
677
return NVSP_STAT_FAIL ;
678
678
679
- if (READ_ONCE (net_device_ctx -> vf_inject )) {
679
+ vf_netdev = rcu_dereference (net_device_ctx -> vf_netdev );
680
+ if (vf_netdev ) {
681
+ struct sk_buff * vf_skb ;
682
+
680
683
atomic_inc (& net_device_ctx -> vf_use_cnt );
681
- if (!READ_ONCE ( net_device_ctx -> vf_inject ) ) {
684
+ if (!net_device_ctx -> vf_inject ) {
682
685
/*
683
686
* We raced; just move on.
684
687
*/
@@ -694,13 +697,12 @@ int netvsc_recv_callback(struct hv_device *device_obj,
694
697
* the host). Deliver these via the VF interface
695
698
* in the guest.
696
699
*/
697
- vf_skb = netvsc_alloc_recv_skb (net_device_ctx -> vf_netdev ,
700
+ vf_skb = netvsc_alloc_recv_skb (vf_netdev ,
698
701
packet , csum_info , * data ,
699
702
vlan_tci );
700
703
if (vf_skb != NULL ) {
701
- ++ net_device_ctx -> vf_netdev -> stats .rx_packets ;
702
- net_device_ctx -> vf_netdev -> stats .rx_bytes +=
703
- bytes_recvd ;
704
+ ++ vf_netdev -> stats .rx_packets ;
705
+ vf_netdev -> stats .rx_bytes += bytes_recvd ;
704
706
netif_receive_skb (vf_skb );
705
707
} else {
706
708
++ net -> stats .rx_dropped ;
@@ -1232,7 +1234,7 @@ static struct net_device *get_netvsc_bymac(const u8 *mac)
1232
1234
return NULL ;
1233
1235
}
1234
1236
1235
- static struct net_device * get_netvsc_byref (const struct net_device * vf_netdev )
1237
+ static struct net_device * get_netvsc_byref (struct net_device * vf_netdev )
1236
1238
{
1237
1239
struct net_device * dev ;
1238
1240
@@ -1248,7 +1250,7 @@ static struct net_device *get_netvsc_byref(const struct net_device *vf_netdev)
1248
1250
if (net_device_ctx -> nvdev == NULL )
1249
1251
continue ; /* device is removed */
1250
1252
1251
- if (net_device_ctx -> vf_netdev == vf_netdev )
1253
+ if (rtnl_dereference ( net_device_ctx -> vf_netdev ) == vf_netdev )
1252
1254
return dev ; /* a match */
1253
1255
}
1254
1256
@@ -1275,7 +1277,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
1275
1277
1276
1278
net_device_ctx = netdev_priv (ndev );
1277
1279
netvsc_dev = net_device_ctx -> nvdev ;
1278
- if (!netvsc_dev || net_device_ctx -> vf_netdev )
1280
+ if (!netvsc_dev || rtnl_dereference ( net_device_ctx -> vf_netdev ) )
1279
1281
return NOTIFY_DONE ;
1280
1282
1281
1283
netdev_info (ndev , "VF registering: %s\n" , vf_netdev -> name );
@@ -1285,7 +1287,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
1285
1287
try_module_get (THIS_MODULE );
1286
1288
1287
1289
dev_hold (vf_netdev );
1288
- net_device_ctx -> vf_netdev = vf_netdev ;
1290
+ rcu_assign_pointer ( net_device_ctx -> vf_netdev , vf_netdev ) ;
1289
1291
return NOTIFY_OK ;
1290
1292
}
1291
1293
@@ -1379,7 +1381,8 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
1379
1381
1380
1382
netdev_info (ndev , "VF unregistering: %s\n" , vf_netdev -> name );
1381
1383
netvsc_inject_disable (net_device_ctx );
1382
- net_device_ctx -> vf_netdev = NULL ;
1384
+
1385
+ RCU_INIT_POINTER (net_device_ctx -> vf_netdev , NULL );
1383
1386
dev_put (vf_netdev );
1384
1387
module_put (THIS_MODULE );
1385
1388
return NOTIFY_OK ;
@@ -1433,8 +1436,6 @@ static int netvsc_probe(struct hv_device *dev,
1433
1436
INIT_LIST_HEAD (& net_device_ctx -> reconfig_events );
1434
1437
1435
1438
atomic_set (& net_device_ctx -> vf_use_cnt , 0 );
1436
- net_device_ctx -> vf_netdev = NULL ;
1437
- net_device_ctx -> vf_inject = false;
1438
1439
1439
1440
net -> netdev_ops = & device_ops ;
1440
1441
0 commit comments