]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
[karo-tx-linux.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_router.c
index c70c59181014d96ce169231000eed109644b0c79..33cec1cc164259ad9d7dd022a811e957447a61ff 100644 (file)
@@ -3098,7 +3098,9 @@ static int mlxsw_sp_inetaddr_vport_event(struct net_device *l3_dev,
 static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
                                        unsigned long event)
 {
-       if (netif_is_bridge_port(port_dev) || netif_is_lag_port(port_dev))
+       if (netif_is_bridge_port(port_dev) ||
+           netif_is_lag_port(port_dev) ||
+           netif_is_ovs_port(port_dev))
                return 0;
 
        return mlxsw_sp_inetaddr_vport_event(port_dev, port_dev, event, 1);
@@ -3343,6 +3345,21 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
        return 0;
 }
 
+static int __mlxsw_sp_inetaddr_event(struct net_device *dev,
+                                    unsigned long event)
+{
+       if (mlxsw_sp_port_dev_check(dev))
+               return mlxsw_sp_inetaddr_port_event(dev, event);
+       else if (netif_is_lag_master(dev))
+               return mlxsw_sp_inetaddr_lag_event(dev, event);
+       else if (netif_is_bridge_master(dev))
+               return mlxsw_sp_inetaddr_bridge_event(dev, dev, event);
+       else if (is_vlan_dev(dev))
+               return mlxsw_sp_inetaddr_vlan_event(dev, event);
+       else
+               return 0;
+}
+
 int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
                            unsigned long event, void *ptr)
 {
@@ -3360,15 +3377,7 @@ int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
        if (!mlxsw_sp_rif_should_config(rif, ifa->ifa_dev, event))
                goto out;
 
-       if (mlxsw_sp_port_dev_check(dev))
-               err = mlxsw_sp_inetaddr_port_event(dev, event);
-       else if (netif_is_lag_master(dev))
-               err = mlxsw_sp_inetaddr_lag_event(dev, event);
-       else if (netif_is_bridge_master(dev))
-               err = mlxsw_sp_inetaddr_bridge_event(dev, dev, event);
-       else if (is_vlan_dev(dev))
-               err = mlxsw_sp_inetaddr_vlan_event(dev, event);
-
+       err = __mlxsw_sp_inetaddr_event(dev, event);
 out:
        return notifier_from_errno(err);
 }
@@ -3431,71 +3440,53 @@ err_rif_edit:
        return err;
 }
 
-int mlxsw_sp_vport_vrf_join(struct mlxsw_sp_port *mlxsw_sp_vport)
+static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
+                                 struct net_device *l3_dev)
 {
-       struct mlxsw_sp_fid *f = mlxsw_sp_vport_fid_get(mlxsw_sp_vport);
-       struct net_device *dev = mlxsw_sp_vport->dev;
+       struct mlxsw_sp_rif *rif;
 
-       /* In case vPort already has a RIF, then we need to drop it.
-        * A new one will be created using the VRF's VR.
+       /* If netdev is already associated with a RIF, then we need to
+        * destroy it and create a new one with the new virtual router ID.
         */
-       if (f && f->rif)
-               mlxsw_sp_vport_rif_sp_leave(mlxsw_sp_vport);
-
-       return mlxsw_sp_vport_rif_sp_join(mlxsw_sp_vport, dev);
-}
-
-void mlxsw_sp_vport_vrf_leave(struct mlxsw_sp_port *mlxsw_sp_vport)
-{
-       mlxsw_sp_vport_rif_sp_leave(mlxsw_sp_vport);
-}
-
-int mlxsw_sp_port_vrf_join(struct mlxsw_sp_port *mlxsw_sp_port)
-{
-       struct mlxsw_sp_port *mlxsw_sp_vport;
-
-       mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, 1);
-       if (WARN_ON(!mlxsw_sp_vport))
-               return -EINVAL;
+       rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
+       if (rif)
+               __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
 
-       return mlxsw_sp_vport_vrf_join(mlxsw_sp_vport);
+       return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP);
 }
 
-void mlxsw_sp_port_vrf_leave(struct mlxsw_sp_port *mlxsw_sp_port)
+static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
+                                   struct net_device *l3_dev)
 {
-       struct mlxsw_sp_port *mlxsw_sp_vport;
+       struct mlxsw_sp_rif *rif;
 
-       mlxsw_sp_vport = mlxsw_sp_port_vport_find(mlxsw_sp_port, 1);
-       if (WARN_ON(!mlxsw_sp_vport))
+       rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
+       if (!rif)
                return;
-
-       mlxsw_sp_vport_vrf_leave(mlxsw_sp_vport);
+       __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
 }
 
-int mlxsw_sp_bridge_vrf_join(struct mlxsw_sp *mlxsw_sp,
-                            struct net_device *l3_dev)
+int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
+                                struct netdev_notifier_changeupper_info *info)
 {
-       struct mlxsw_sp_fid *f;
-
-       f = mlxsw_sp_bridge_fid_get(mlxsw_sp, l3_dev);
-       if (WARN_ON(!f))
-               return -EINVAL;
-
-       if (f->rif)
-               mlxsw_sp_rif_bridge_destroy(mlxsw_sp, f->rif);
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
+       int err = 0;
 
-       return mlxsw_sp_rif_bridge_create(mlxsw_sp, l3_dev, f);
-}
+       if (!mlxsw_sp)
+               return 0;
 
-void mlxsw_sp_bridge_vrf_leave(struct mlxsw_sp *mlxsw_sp,
-                              struct net_device *l3_dev)
-{
-       struct mlxsw_sp_fid *f;
+       switch (event) {
+       case NETDEV_PRECHANGEUPPER:
+               return 0;
+       case NETDEV_CHANGEUPPER:
+               if (info->linking)
+                       err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev);
+               else
+                       mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
+               break;
+       }
 
-       f = mlxsw_sp_bridge_fid_get(mlxsw_sp, l3_dev);
-       if (WARN_ON(!f))
-               return;
-       mlxsw_sp_rif_bridge_destroy(mlxsw_sp, f->rif);
+       return err;
 }
 
 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)