diff mbox series

[NET-PREV,39/51] netvsc: Make joined device to share master's nd_lock

Message ID 174265456307.356712.11381775975226010571.stgit@pro.pro (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series Kill rtnl_lock using fine-grained nd_lock | expand

Checks

Context Check Description
netdev/tree_selection success Guessing tree name failed - patch did not apply, async

Commit Message

Kirill Tkhai March 22, 2025, 2:42 p.m. UTC
We don't want to do that from netvsc_netdev_event() since
we want to make netdevice notifiers be called under nd_lock
in future.

Also see comments in patch introducing schedule_delayed_event()

Signed-off-by: Kirill Tkhai <tkhai@ya.ru>
---
 drivers/net/hyperv/netvsc_drv.c |   25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 44142245343d..be8038e6393f 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -2192,6 +2192,7 @@  static int netvsc_vf_join(struct net_device *vf_netdev,
 			  struct net_device *ndev, int context)
 {
 	struct net_device_context *ndev_ctx = netdev_priv(ndev);
+	struct nd_lock *nd_lock, *nd_lock2;
 	int ret;
 
 	ret = netdev_rx_handler_register(vf_netdev,
@@ -2203,8 +2204,12 @@  static int netvsc_vf_join(struct net_device *vf_netdev,
 		goto rx_handler_failed;
 	}
 
+	double_lock_netdev(ndev, &nd_lock, vf_netdev, &nd_lock2);
+	nd_lock_transfer_devices(&nd_lock, &nd_lock2);
+
 	ret = netdev_master_upper_dev_link(vf_netdev, ndev,
 					   NULL, NULL, NULL);
+	double_unlock_netdev(nd_lock, nd_lock2);
 	if (ret != 0) {
 		netdev_err(vf_netdev,
 			   "can not set master device %s (err = %d)\n",
@@ -2797,6 +2802,20 @@  static struct  hv_driver netvsc_drv = {
 	},
 };
 
+static void call_netvsc_register(struct net_device *dev)
+{
+	unsigned long event;
+
+	rtnl_lock();
+	netvsc_prepare_bonding(dev);
+	netvsc_register_vf(dev, VF_REG_IN_NOTIFIER);
+	event = NETDEV_GOING_DOWN;
+	if (netif_running(dev))
+		event = NETDEV_CHANGE;
+	netvsc_vf_changed(dev, event);
+	rtnl_unlock();
+}
+
 /*
  * On Hyper-V, every VF interface is matched with a corresponding
  * synthetic interface. The synthetic interface is presented first
@@ -2814,10 +2833,10 @@  static int netvsc_netdev_event(struct notifier_block *this,
 		return NOTIFY_DONE;
 
 	switch (event) {
-	case NETDEV_POST_INIT:
-		return netvsc_prepare_bonding(event_dev);
 	case NETDEV_REGISTER:
-		return netvsc_register_vf(event_dev, VF_REG_IN_NOTIFIER);
+		return schedule_delayed_event(event_dev,
+					      call_netvsc_register);
+		return NOTIFY_DONE;
 	case NETDEV_UNREGISTER:
 		return netvsc_unregister_vf(event_dev);
 	case NETDEV_UP: