@@ -2528,6 +2528,7 @@ static int netvsc_probe(struct hv_device *dev,
2528
2528
spin_lock_init (& net_device_ctx -> lock );
2529
2529
INIT_LIST_HEAD (& net_device_ctx -> reconfig_events );
2530
2530
INIT_DELAYED_WORK (& net_device_ctx -> vf_takeover , netvsc_vf_setup );
2531
+ INIT_DELAYED_WORK (& net_device_ctx -> vfns_work , netvsc_vfns_work );
2531
2532
2532
2533
net_device_ctx -> vf_stats
2533
2534
= netdev_alloc_pcpu_stats (struct netvsc_vf_pcpu_stats );
@@ -2670,6 +2671,8 @@ static void netvsc_remove(struct hv_device *dev)
2670
2671
cancel_delayed_work_sync (& ndev_ctx -> dwork );
2671
2672
2672
2673
rtnl_lock ();
2674
+ cancel_delayed_work_sync (& ndev_ctx -> vfns_work );
2675
+
2673
2676
nvdev = rtnl_dereference (ndev_ctx -> nvdev );
2674
2677
if (nvdev ) {
2675
2678
cancel_work_sync (& nvdev -> subchan_work );
@@ -2711,6 +2714,7 @@ static int netvsc_suspend(struct hv_device *dev)
2711
2714
cancel_delayed_work_sync (& ndev_ctx -> dwork );
2712
2715
2713
2716
rtnl_lock ();
2717
+ cancel_delayed_work_sync (& ndev_ctx -> vfns_work );
2714
2718
2715
2719
nvdev = rtnl_dereference (ndev_ctx -> nvdev );
2716
2720
if (nvdev == NULL ) {
@@ -2804,6 +2808,27 @@ static void netvsc_event_set_vf_ns(struct net_device *ndev)
2804
2808
}
2805
2809
}
2806
2810
2811
+ void netvsc_vfns_work (struct work_struct * w )
2812
+ {
2813
+ struct net_device_context * ndev_ctx =
2814
+ container_of (w , struct net_device_context , vfns_work .work );
2815
+ struct net_device * ndev ;
2816
+
2817
+ if (!rtnl_trylock ()) {
2818
+ schedule_delayed_work (& ndev_ctx -> vfns_work , 1 );
2819
+ return ;
2820
+ }
2821
+
2822
+ ndev = hv_get_drvdata (ndev_ctx -> device_ctx );
2823
+ if (!ndev )
2824
+ goto out ;
2825
+
2826
+ netvsc_event_set_vf_ns (ndev );
2827
+
2828
+ out :
2829
+ rtnl_unlock ();
2830
+ }
2831
+
2807
2832
/*
2808
2833
* On Hyper-V, every VF interface is matched with a corresponding
2809
2834
* synthetic interface. The synthetic interface is presented first
@@ -2814,10 +2839,12 @@ static int netvsc_netdev_event(struct notifier_block *this,
2814
2839
unsigned long event , void * ptr )
2815
2840
{
2816
2841
struct net_device * event_dev = netdev_notifier_info_to_dev (ptr );
2842
+ struct net_device_context * ndev_ctx ;
2817
2843
int ret = 0 ;
2818
2844
2819
2845
if (event_dev -> netdev_ops == & device_ops && event == NETDEV_REGISTER ) {
2820
- netvsc_event_set_vf_ns (event_dev );
2846
+ ndev_ctx = netdev_priv (event_dev );
2847
+ schedule_delayed_work (& ndev_ctx -> vfns_work , 0 );
2821
2848
return NOTIFY_DONE ;
2822
2849
}
2823
2850
0 commit comments