@@ -2522,6 +2522,7 @@ static int netvsc_probe(struct hv_device *dev,
2522
2522
spin_lock_init (& net_device_ctx -> lock );
2523
2523
INIT_LIST_HEAD (& net_device_ctx -> reconfig_events );
2524
2524
INIT_DELAYED_WORK (& net_device_ctx -> vf_takeover , netvsc_vf_setup );
2525
+ INIT_DELAYED_WORK (& net_device_ctx -> vfns_work , netvsc_vfns_work );
2525
2526
2526
2527
net_device_ctx -> vf_stats
2527
2528
= netdev_alloc_pcpu_stats (struct netvsc_vf_pcpu_stats );
@@ -2666,6 +2667,8 @@ static void netvsc_remove(struct hv_device *dev)
2666
2667
cancel_delayed_work_sync (& ndev_ctx -> dwork );
2667
2668
2668
2669
rtnl_lock ();
2670
+ cancel_delayed_work_sync (& ndev_ctx -> vfns_work );
2671
+
2669
2672
nvdev = rtnl_dereference (ndev_ctx -> nvdev );
2670
2673
if (nvdev ) {
2671
2674
cancel_work_sync (& nvdev -> subchan_work );
@@ -2707,6 +2710,7 @@ static int netvsc_suspend(struct hv_device *dev)
2707
2710
cancel_delayed_work_sync (& ndev_ctx -> dwork );
2708
2711
2709
2712
rtnl_lock ();
2713
+ cancel_delayed_work_sync (& ndev_ctx -> vfns_work );
2710
2714
2711
2715
nvdev = rtnl_dereference (ndev_ctx -> nvdev );
2712
2716
if (nvdev == NULL ) {
@@ -2800,6 +2804,27 @@ static void netvsc_event_set_vf_ns(struct net_device *ndev)
2800
2804
}
2801
2805
}
2802
2806
2807
+ void netvsc_vfns_work (struct work_struct * w )
2808
+ {
2809
+ struct net_device_context * ndev_ctx =
2810
+ container_of (w , struct net_device_context , vfns_work .work );
2811
+ struct net_device * ndev ;
2812
+
2813
+ if (!rtnl_trylock ()) {
2814
+ schedule_delayed_work (& ndev_ctx -> vfns_work , 1 );
2815
+ return ;
2816
+ }
2817
+
2818
+ ndev = hv_get_drvdata (ndev_ctx -> device_ctx );
2819
+ if (!ndev )
2820
+ goto out ;
2821
+
2822
+ netvsc_event_set_vf_ns (ndev );
2823
+
2824
+ out :
2825
+ rtnl_unlock ();
2826
+ }
2827
+
2803
2828
/*
2804
2829
* On Hyper-V, every VF interface is matched with a corresponding
2805
2830
* synthetic interface. The synthetic interface is presented first
@@ -2810,10 +2835,12 @@ static int netvsc_netdev_event(struct notifier_block *this,
2810
2835
unsigned long event , void * ptr )
2811
2836
{
2812
2837
struct net_device * event_dev = netdev_notifier_info_to_dev (ptr );
2838
+ struct net_device_context * ndev_ctx ;
2813
2839
int ret = 0 ;
2814
2840
2815
2841
if (event_dev -> netdev_ops == & device_ops && event == NETDEV_REGISTER ) {
2816
- netvsc_event_set_vf_ns (event_dev );
2842
+ ndev_ctx = netdev_priv (event_dev );
2843
+ schedule_delayed_work (& ndev_ctx -> vfns_work , 0 );
2817
2844
return NOTIFY_DONE ;
2818
2845
}
2819
2846
0 commit comments