]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - drivers/infiniband/hw/mlx5/main.c
Merge tag 'mm-stable-2023-02-20-13-37' of git://git.kernel.org/pub/scm/linux/kernel...
[thirdparty/linux.git] / drivers / infiniband / hw / mlx5 / main.c
index e3c97aa2c46cd25e80af748eb633fc29f4eb7f37..471c3455dfebd2aaa7ab58f8e743897a883ae3b4 100644 (file)
@@ -3012,26 +3012,63 @@ static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev)
        }
 }
 
-static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u32 port_num)
+static void mlx5_netdev_notifier_register(struct mlx5_roce *roce,
+                                         struct net_device *netdev)
 {
        int err;
 
-       dev->port[port_num].roce.nb.notifier_call = mlx5_netdev_event;
-       err = register_netdevice_notifier(&dev->port[port_num].roce.nb);
-       if (err) {
-               dev->port[port_num].roce.nb.notifier_call = NULL;
-               return err;
-       }
+       if (roce->tracking_netdev)
+               return;
+       roce->tracking_netdev = netdev;
+       roce->nb.notifier_call = mlx5_netdev_event;
+       err = register_netdevice_notifier_dev_net(netdev, &roce->nb, &roce->nn);
+       WARN_ON(err);
+}
 
-       return 0;
+static void mlx5_netdev_notifier_unregister(struct mlx5_roce *roce)
+{
+       if (!roce->tracking_netdev)
+               return;
+       unregister_netdevice_notifier_dev_net(roce->tracking_netdev, &roce->nb,
+                                             &roce->nn);
+       roce->tracking_netdev = NULL;
 }
 
-static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev, u32 port_num)
+static int mlx5e_mdev_notifier_event(struct notifier_block *nb,
+                                    unsigned long event, void *data)
 {
-       if (dev->port[port_num].roce.nb.notifier_call) {
-               unregister_netdevice_notifier(&dev->port[port_num].roce.nb);
-               dev->port[port_num].roce.nb.notifier_call = NULL;
+       struct mlx5_roce *roce = container_of(nb, struct mlx5_roce, mdev_nb);
+       struct net_device *netdev = data;
+
+       switch (event) {
+       case MLX5_DRIVER_EVENT_UPLINK_NETDEV:
+               if (netdev)
+                       mlx5_netdev_notifier_register(roce, netdev);
+               else
+                       mlx5_netdev_notifier_unregister(roce);
+               break;
+       default:
+               return NOTIFY_DONE;
        }
+
+       return NOTIFY_OK;
+}
+
+static void mlx5_mdev_netdev_track(struct mlx5_ib_dev *dev, u32 port_num)
+{
+       struct mlx5_roce *roce = &dev->port[port_num].roce;
+
+       roce->mdev_nb.notifier_call = mlx5e_mdev_notifier_event;
+       mlx5_blocking_notifier_register(dev->mdev, &roce->mdev_nb);
+       mlx5_core_uplink_netdev_event_replay(dev->mdev);
+}
+
+static void mlx5_mdev_netdev_untrack(struct mlx5_ib_dev *dev, u32 port_num)
+{
+       struct mlx5_roce *roce = &dev->port[port_num].roce;
+
+       mlx5_blocking_notifier_unregister(dev->mdev, &roce->mdev_nb);
+       mlx5_netdev_notifier_unregister(roce);
 }
 
 static int mlx5_enable_eth(struct mlx5_ib_dev *dev)
@@ -3138,7 +3175,7 @@ static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,
        if (mpi->mdev_events.notifier_call)
                mlx5_notifier_unregister(mpi->mdev, &mpi->mdev_events);
        mpi->mdev_events.notifier_call = NULL;
-       mlx5_remove_netdev_notifier(ibdev, port_num);
+       mlx5_mdev_netdev_untrack(ibdev, port_num);
        spin_lock(&port->mp.mpi_lock);
 
        comps = mpi->mdev_refcnt;
@@ -3196,12 +3233,7 @@ static bool mlx5_ib_bind_slave_port(struct mlx5_ib_dev *ibdev,
        if (err)
                goto unbind;
 
-       err = mlx5_add_netdev_notifier(ibdev, port_num);
-       if (err) {
-               mlx5_ib_err(ibdev, "failed adding netdev notifier for port %u\n",
-                           port_num + 1);
-               goto unbind;
-       }
+       mlx5_mdev_netdev_track(ibdev, port_num);
 
        mpi->mdev_events.notifier_call = mlx5_ib_event_slave_port;
        mlx5_notifier_register(mpi->mdev, &mpi->mdev_events);
@@ -3909,9 +3941,7 @@ static int mlx5_ib_roce_init(struct mlx5_ib_dev *dev)
                port_num = mlx5_core_native_port_num(dev->mdev) - 1;
 
                /* Register only for native ports */
-               err = mlx5_add_netdev_notifier(dev, port_num);
-               if (err)
-                       return err;
+               mlx5_mdev_netdev_track(dev, port_num);
 
                err = mlx5_enable_eth(dev);
                if (err)
@@ -3920,7 +3950,7 @@ static int mlx5_ib_roce_init(struct mlx5_ib_dev *dev)
 
        return 0;
 cleanup:
-       mlx5_remove_netdev_notifier(dev, port_num);
+       mlx5_mdev_netdev_untrack(dev, port_num);
        return err;
 }
 
@@ -3938,7 +3968,7 @@ static void mlx5_ib_roce_cleanup(struct mlx5_ib_dev *dev)
                mlx5_disable_eth(dev);
 
                port_num = mlx5_core_native_port_num(dev->mdev) - 1;
-               mlx5_remove_netdev_notifier(dev, port_num);
+               mlx5_mdev_netdev_untrack(dev, port_num);
        }
 }