]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/mlx5: LAG, Support LAG over Multi-Host NICs
authorRongwei Liu <rongweil@nvidia.com>
Thu, 19 Dec 2024 17:58:32 +0000 (19:58 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 23 Dec 2024 18:34:45 +0000 (10:34 -0800)
New multi-host NICs provide each host with partial ports,
allowing each host to maintain its unique LAG configuration.

On these multi-host NICs, the 'native_port_num' capability
is no longer continuous on each host and can exceed the
'num_lag_ports' capability. Therefore, it is necessary to
skip the PFs with ldev->pf[i].dev == NULL when querying/modifying
the lag devices' information.
There is no need to check dev.native_port_num against ldev->ports.

Signed-off-by: Rongwei Liu <rongweil@nvidia.com>
Reviewed-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20241219175841.1094544-3-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
drivers/net/ethernet/mellanox/mlx5/core/main.c

index ed539ac4fef187607cd662e8e56f9e224f9fe9c6..cea5aa314f6c5f78763bbb79d5b48785cb6cdc2f 100644 (file)
@@ -76,23 +76,30 @@ static u8 lag_active_port_bits(struct mlx5_lag *ldev)
        return active_port;
 }
 
-static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, int mode,
-                              unsigned long flags)
+static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
+                              int mode, unsigned long flags)
 {
        bool fdb_sel_mode = test_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE,
                                     &flags);
        int port_sel_mode = get_port_sel_mode(mode, flags);
        u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};
+       u8 *ports = ldev->v2p_map;
+       int idx0, idx1;
        void *lag_ctx;
 
        lag_ctx = MLX5_ADDR_OF(create_lag_in, in, ctx);
        MLX5_SET(create_lag_in, in, opcode, MLX5_CMD_OP_CREATE_LAG);
        MLX5_SET(lagc, lag_ctx, fdb_selection_mode, fdb_sel_mode);
+       idx0 = mlx5_lag_get_dev_index_by_seq(ldev, 0);
+       idx1 = mlx5_lag_get_dev_index_by_seq(ldev, 1);
+
+       if (idx0 < 0 || idx1 < 0)
+               return -EINVAL;
 
        switch (port_sel_mode) {
        case MLX5_LAG_PORT_SELECT_MODE_QUEUE_AFFINITY:
-               MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
-               MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
+               MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[idx0]);
+               MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[idx1]);
                break;
        case MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT:
                if (!MLX5_CAP_PORT_SELECTION(dev, port_select_flow_table_bypass))
@@ -114,12 +121,18 @@ static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
 {
        u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};
        void *lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);
+       int idx0, idx1;
+
+       idx0 = mlx5_lag_get_dev_index_by_seq(ldev, 0);
+       idx1 = mlx5_lag_get_dev_index_by_seq(ldev, 1);
+       if (idx0 < 0 || idx1 < 0)
+               return -EINVAL;
 
        MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
        MLX5_SET(modify_lag_in, in, field_select, 0x1);
 
-       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
-       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
+       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[idx0]);
+       MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[idx1]);
 
        return mlx5_cmd_exec_in(dev, modify_lag, in);
 }
@@ -287,6 +300,48 @@ int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
        return -ENOENT;
 }
 
+int mlx5_lag_get_dev_index_by_seq(struct mlx5_lag *ldev, int seq)
+{
+       int i, num = 0;
+
+       if (!ldev)
+               return -ENOENT;
+
+       mlx5_ldev_for_each(i, 0, ldev) {
+               if (num == seq)
+                       return i;
+               num++;
+       }
+       return -ENOENT;
+}
+
+int mlx5_lag_num_devs(struct mlx5_lag *ldev)
+{
+       int i, num = 0;
+
+       if (!ldev)
+               return 0;
+
+       mlx5_ldev_for_each(i, 0, ldev) {
+               (void)i;
+               num++;
+       }
+       return num;
+}
+
+int mlx5_lag_num_netdevs(struct mlx5_lag *ldev)
+{
+       int i, num = 0;
+
+       if (!ldev)
+               return 0;
+
+       mlx5_ldev_for_each(i, 0, ldev)
+               if (ldev->pf[i].netdev)
+                       num++;
+       return num;
+}
+
 static bool __mlx5_lag_is_roce(struct mlx5_lag *ldev)
 {
        return ldev->mode == MLX5_LAG_MODE_ROCE;
@@ -423,10 +478,15 @@ static int mlx5_cmd_modify_active_port(struct mlx5_core_dev *dev, u8 ports)
 
 static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
 {
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       struct mlx5_core_dev *dev0;
        u8 active_ports;
        int ret;
 
+       if (idx < 0)
+               return -EINVAL;
+
+       dev0 = ldev->pf[idx].dev;
        if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) {
                ret = mlx5_lag_port_sel_modify(ldev, ports);
                if (ret ||
@@ -445,7 +505,7 @@ static struct net_device *mlx5_lag_active_backup_get_netdev(struct mlx5_core_dev
        struct net_device *ndev = NULL;
        struct mlx5_lag *ldev;
        unsigned long flags;
-       int i;
+       int i, last_idx;
 
        spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
@@ -456,8 +516,12 @@ static struct net_device *mlx5_lag_active_backup_get_netdev(struct mlx5_core_dev
        mlx5_ldev_for_each(i, 0, ldev)
                if (ldev->tracker.netdev_state[i].tx_enabled)
                        ndev = ldev->pf[i].netdev;
-       if (!ndev)
-               ndev = ldev->pf[ldev->ports - 1].netdev;
+       if (!ndev) {
+               last_idx = mlx5_lag_get_dev_index_by_seq(ldev, ldev->ports - 1);
+               if (last_idx < 0)
+                       goto unlock;
+               ndev = ldev->pf[last_idx].netdev;
+       }
 
        if (ndev)
                dev_hold(ndev);
@@ -471,13 +535,18 @@ unlock:
 void mlx5_modify_lag(struct mlx5_lag *ldev,
                     struct lag_tracker *tracker)
 {
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        u8 ports[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS] = {};
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       struct mlx5_core_dev *dev0;
        int idx;
        int err;
        int i;
        int j;
 
+       if (first_idx < 0)
+               return;
+
+       dev0 = ldev->pf[first_idx].dev;
        mlx5_infer_tx_affinity_mapping(tracker, ldev, ldev->buckets, ports);
 
        mlx5_ldev_for_each(i, 0, ldev) {
@@ -518,8 +587,13 @@ void mlx5_modify_lag(struct mlx5_lag *ldev,
 static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
                                           unsigned long *flags)
 {
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       struct mlx5_core_dev *dev0;
 
+       if (first_idx < 0)
+               return -EINVAL;
+
+       dev0 = ldev->pf[first_idx].dev;
        if (!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table)) {
                if (ldev->ports > 2)
                        return -EINVAL;
@@ -539,11 +613,13 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
                                                enum mlx5_lag_mode mode,
                                                unsigned long *flags)
 {
-       struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       struct lag_func *dev0;
 
-       if (mode == MLX5_LAG_MODE_MPESW)
+       if (first_idx < 0 || mode == MLX5_LAG_MODE_MPESW)
                return;
 
+       dev0 = &ldev->pf[first_idx];
        if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
            tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) {
                if (ldev->ports > 2)
@@ -588,12 +664,18 @@ char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
 
 static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev)
 {
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
-       struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
-       int err;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       struct mlx5_eswitch *master_esw;
+       struct mlx5_core_dev *dev0;
        int i, j;
+       int err;
 
-       mlx5_ldev_for_each(i, 1, ldev) {
+       if (first_idx < 0)
+               return -EINVAL;
+
+       dev0 = ldev->pf[first_idx].dev;
+       master_esw = dev0->priv.eswitch;
+       mlx5_ldev_for_each(i, first_idx + 1, ldev) {
                struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch;
 
                err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw,
@@ -603,7 +685,7 @@ static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev)
        }
        return 0;
 err:
-       mlx5_ldev_for_each_reverse(j, i, 1, ldev)
+       mlx5_ldev_for_each_reverse(j, i, first_idx + 1, ldev)
                mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
                                                         ldev->pf[j].dev->priv.eswitch);
        return err;
@@ -615,16 +697,21 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
                           unsigned long flags)
 {
        bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
+       struct mlx5_core_dev *dev0;
        int err;
 
+       if (first_idx < 0)
+               return -EINVAL;
+
+       dev0 = ldev->pf[first_idx].dev;
        if (tracker)
                mlx5_lag_print_mapping(dev0, ldev, tracker, flags);
        mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
                       shared_fdb, mlx5_get_str_port_sel_mode(mode, flags));
 
-       err = mlx5_cmd_create_lag(dev0, ldev->v2p_map, mode, flags);
+       err = mlx5_cmd_create_lag(dev0, ldev, mode, flags);
        if (err) {
                mlx5_core_err(dev0,
                              "Failed to create LAG (%d)\n",
@@ -656,11 +743,16 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
                      enum mlx5_lag_mode mode,
                      bool shared_fdb)
 {
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        bool roce_lag = mode == MLX5_LAG_MODE_ROCE;
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       struct mlx5_core_dev *dev0;
        unsigned long flags = 0;
        int err;
 
+       if (first_idx < 0)
+               return -EINVAL;
+
+       dev0 = ldev->pf[first_idx].dev;
        err = mlx5_lag_set_flags(ldev, mode, tracker, shared_fdb, &flags);
        if (err)
                return err;
@@ -704,20 +796,26 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
 
 int mlx5_deactivate_lag(struct mlx5_lag *ldev)
 {
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
-       struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
        bool roce_lag = __mlx5_lag_is_roce(ldev);
        unsigned long flags = ldev->mode_flags;
+       struct mlx5_eswitch *master_esw;
+       struct mlx5_core_dev *dev0;
        int err;
        int i;
 
+       if (first_idx < 0)
+               return -EINVAL;
+
+       dev0 = ldev->pf[first_idx].dev;
+       master_esw = dev0->priv.eswitch;
        ldev->mode = MLX5_LAG_MODE_NONE;
        ldev->mode_flags = 0;
        mlx5_lag_mp_reset(ldev);
 
        if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) {
-               mlx5_ldev_for_each(i, 1, ldev)
+               mlx5_ldev_for_each(i, first_idx + 1, ldev)
                        mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
                                                                 ldev->pf[i].dev->priv.eswitch);
                clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
@@ -749,6 +847,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
 
 bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
 {
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
 #ifdef CONFIG_MLX5_ESWITCH
        struct mlx5_core_dev *dev;
        u8 mode;
@@ -756,9 +855,8 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
        bool roce_support;
        int i;
 
-       for (i = 0; i < ldev->ports; i++)
-               if (!ldev->pf[i].dev)
-                       return false;
+       if (first_idx < 0 || mlx5_lag_num_devs(ldev) != ldev->ports)
+               return false;
 
 #ifdef CONFIG_MLX5_ESWITCH
        mlx5_ldev_for_each(i, 0, ldev) {
@@ -767,7 +865,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
                        return false;
        }
 
-       dev = ldev->pf[MLX5_LAG_P1].dev;
+       dev = ldev->pf[first_idx].dev;
        mode = mlx5_eswitch_mode(dev);
        mlx5_ldev_for_each(i, 0, ldev)
                if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode)
@@ -778,8 +876,8 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
                if (mlx5_sriov_is_enabled(ldev->pf[i].dev))
                        return false;
 #endif
-       roce_support = mlx5_get_roce_state(ldev->pf[MLX5_LAG_P1].dev);
-       mlx5_ldev_for_each(i, MLX5_LAG_P2, ldev)
+       roce_support = mlx5_get_roce_state(ldev->pf[first_idx].dev);
+       mlx5_ldev_for_each(i, first_idx + 1, ldev)
                if (mlx5_get_roce_state(ldev->pf[i].dev) != roce_support)
                        return false;
 
@@ -817,11 +915,16 @@ void mlx5_lag_remove_devices(struct mlx5_lag *ldev)
 void mlx5_disable_lag(struct mlx5_lag *ldev)
 {
        bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       struct mlx5_core_dev *dev0;
        bool roce_lag;
        int err;
        int i;
 
+       if (idx < 0)
+               return;
+
+       dev0 = ldev->pf[idx].dev;
        roce_lag = __mlx5_lag_is_roce(ldev);
 
        if (shared_fdb) {
@@ -831,7 +934,7 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
                        dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
                        mlx5_rescan_drivers_locked(dev0);
                }
-               mlx5_ldev_for_each(i, MLX5_LAG_P2, ldev)
+               mlx5_ldev_for_each(i, idx + 1, ldev)
                        mlx5_nic_vport_disable_roce(ldev->pf[i].dev);
        }
 
@@ -850,10 +953,14 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
 
 static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
 {
+       int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        struct mlx5_core_dev *dev;
        int i;
 
-       mlx5_ldev_for_each(i, MLX5_LAG_P1 + 1, ldev) {
+       if (idx < 0)
+               return false;
+
+       mlx5_ldev_for_each(i, idx + 1, ldev) {
                dev = ldev->pf[i].dev;
                if (is_mdev_switchdev_mode(dev) &&
                    mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
@@ -865,7 +972,7 @@ static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
                return false;
        }
 
-       dev = ldev->pf[MLX5_LAG_P1].dev;
+       dev = ldev->pf[idx].dev;
        if (is_mdev_switchdev_mode(dev) &&
            mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
            mlx5_esw_offloads_devcom_is_ready(dev->priv.eswitch) &&
@@ -906,13 +1013,18 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
 
 static void mlx5_do_bond(struct mlx5_lag *ldev)
 {
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        struct lag_tracker tracker = { };
+       struct mlx5_core_dev *dev0;
        struct net_device *ndev;
        bool do_bond, roce_lag;
        int err;
        int i;
 
+       if (idx < 0)
+               return;
+
+       dev0 = ldev->pf[idx].dev;
        if (!mlx5_lag_is_ready(ldev)) {
                do_bond = false;
        } else {
@@ -945,7 +1057,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
                } else if (roce_lag) {
                        dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
                        mlx5_rescan_drivers_locked(dev0);
-                       mlx5_ldev_for_each(i, MLX5_LAG_P2, ldev) {
+                       mlx5_ldev_for_each(i, idx + 1, ldev) {
                                if (mlx5_get_roce_state(ldev->pf[i].dev))
                                        mlx5_nic_vport_enable_roce(ldev->pf[i].dev);
                        }
@@ -1380,7 +1492,7 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
                         struct net_device *netdev)
 {
        struct mlx5_lag *ldev;
-       int i;
+       int num = 0;
 
        ldev = mlx5_lag_dev(dev);
        if (!ldev)
@@ -1388,11 +1500,8 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
 
        mutex_lock(&ldev->lock);
        mlx5_ldev_add_netdev(ldev, dev, netdev);
-       for (i = 0; i < ldev->ports; i++)
-               if (!ldev->pf[i].netdev)
-                       break;
-
-       if (i >= ldev->ports)
+       num = mlx5_lag_num_netdevs(ldev);
+       if (num >= ldev->ports)
                set_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
        mutex_unlock(&ldev->lock);
        mlx5_queue_bond_work(ldev, 0);
@@ -1469,11 +1578,12 @@ bool mlx5_lag_is_master(struct mlx5_core_dev *dev)
        struct mlx5_lag *ldev;
        unsigned long flags;
        bool res = false;
+       int idx;
 
        spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
-       res = ldev && __mlx5_lag_is_active(ldev) &&
-               dev == ldev->pf[MLX5_LAG_P1].dev;
+       idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       res = ldev && __mlx5_lag_is_active(ldev) && idx >= 0 && dev == ldev->pf[idx].dev;
        spin_unlock_irqrestore(&lag_lock, flags);
 
        return res;
index 1dada791815e4e6b459056896e53c632d6025b68..01cf7236694715619d81d9ef2fb107c2bfb02012 100644 (file)
@@ -136,4 +136,7 @@ static inline bool mlx5_lag_is_supported(struct mlx5_core_dev *dev)
 
 int mlx5_get_pre_ldev_func(struct mlx5_lag *ldev, int start_idx, int end_idx);
 int mlx5_get_next_ldev_func(struct mlx5_lag *ldev, int start_idx);
+int mlx5_lag_get_dev_index_by_seq(struct mlx5_lag *ldev, int seq);
+int mlx5_lag_num_devs(struct mlx5_lag *ldev);
+int mlx5_lag_num_netdevs(struct mlx5_lag *ldev);
 #endif /* __MLX5_LAG_H__ */
index 40406d04adc9858d7546967c1f9f9c5a8c6d962c..aee17fcf3b36c3dcfbdf7dd00ca7fd17cae00681 100644 (file)
@@ -17,7 +17,10 @@ static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev)
 #define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2
 static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
 {
-       if (!mlx5_lag_is_ready(ldev))
+       int idx0 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       int idx1 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P2);
+
+       if (idx0 < 0 || idx1 < 0 || !mlx5_lag_is_ready(ldev))
                return false;
 
        if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev))
@@ -26,8 +29,8 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
        if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS)
                return false;
 
-       return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev,
-                                        ldev->pf[MLX5_LAG_P2].dev);
+       return mlx5_esw_multipath_prereq(ldev->pf[idx0].dev,
+                                        ldev->pf[idx1].dev);
 }
 
 bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev)
@@ -50,43 +53,45 @@ bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev)
 static void mlx5_lag_set_port_affinity(struct mlx5_lag *ldev,
                                       enum mlx5_lag_port_affinity port)
 {
+       int idx0 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       int idx1 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P2);
        struct lag_tracker tracker = {};
 
-       if (!__mlx5_lag_is_multipath(ldev))
+       if (idx0 < 0 || idx1 < 0 || !__mlx5_lag_is_multipath(ldev))
                return;
 
        switch (port) {
        case MLX5_LAG_NORMAL_AFFINITY:
-               tracker.netdev_state[MLX5_LAG_P1].tx_enabled = true;
-               tracker.netdev_state[MLX5_LAG_P2].tx_enabled = true;
-               tracker.netdev_state[MLX5_LAG_P1].link_up = true;
-               tracker.netdev_state[MLX5_LAG_P2].link_up = true;
+               tracker.netdev_state[idx0].tx_enabled = true;
+               tracker.netdev_state[idx1].tx_enabled = true;
+               tracker.netdev_state[idx0].link_up = true;
+               tracker.netdev_state[idx1].link_up = true;
                break;
        case MLX5_LAG_P1_AFFINITY:
-               tracker.netdev_state[MLX5_LAG_P1].tx_enabled = true;
-               tracker.netdev_state[MLX5_LAG_P1].link_up = true;
-               tracker.netdev_state[MLX5_LAG_P2].tx_enabled = false;
-               tracker.netdev_state[MLX5_LAG_P2].link_up = false;
+               tracker.netdev_state[idx0].tx_enabled = true;
+               tracker.netdev_state[idx0].link_up = true;
+               tracker.netdev_state[idx1].tx_enabled = false;
+               tracker.netdev_state[idx1].link_up = false;
                break;
        case MLX5_LAG_P2_AFFINITY:
-               tracker.netdev_state[MLX5_LAG_P1].tx_enabled = false;
-               tracker.netdev_state[MLX5_LAG_P1].link_up = false;
-               tracker.netdev_state[MLX5_LAG_P2].tx_enabled = true;
-               tracker.netdev_state[MLX5_LAG_P2].link_up = true;
+               tracker.netdev_state[idx0].tx_enabled = false;
+               tracker.netdev_state[idx0].link_up = false;
+               tracker.netdev_state[idx1].tx_enabled = true;
+               tracker.netdev_state[idx1].link_up = true;
                break;
        default:
-               mlx5_core_warn(ldev->pf[MLX5_LAG_P1].dev,
+               mlx5_core_warn(ldev->pf[idx0].dev,
                               "Invalid affinity port %d", port);
                return;
        }
 
-       if (tracker.netdev_state[MLX5_LAG_P1].tx_enabled)
-               mlx5_notifier_call_chain(ldev->pf[MLX5_LAG_P1].dev->priv.events,
+       if (tracker.netdev_state[idx0].tx_enabled)
+               mlx5_notifier_call_chain(ldev->pf[idx0].dev->priv.events,
                                         MLX5_DEV_EVENT_PORT_AFFINITY,
                                         (void *)0);
 
-       if (tracker.netdev_state[MLX5_LAG_P2].tx_enabled)
-               mlx5_notifier_call_chain(ldev->pf[MLX5_LAG_P2].dev->priv.events,
+       if (tracker.netdev_state[idx1].tx_enabled)
+               mlx5_notifier_call_chain(ldev->pf[idx1].dev->priv.events,
                                         MLX5_DEV_EVENT_PORT_AFFINITY,
                                         (void *)0);
 
@@ -150,11 +155,15 @@ mlx5_lag_get_next_fib_dev(struct mlx5_lag *ldev,
 static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
                                     struct fib_entry_notifier_info *fen_info)
 {
+       int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        struct net_device *nh_dev0, *nh_dev1;
        struct fib_info *fi = fen_info->fi;
        struct lag_mp *mp = &ldev->lag_mp;
        int i, dev_idx = 0;
 
+       if (idx < 0)
+               return;
+
        /* Handle delete event */
        if (event == FIB_EVENT_ENTRY_DEL) {
                /* stop track */
@@ -180,7 +189,7 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
        }
 
        if (nh_dev0 == nh_dev1) {
-               mlx5_core_warn(ldev->pf[MLX5_LAG_P1].dev,
+               mlx5_core_warn(ldev->pf[idx].dev,
                               "Multipath offload doesn't support routes with multiple nexthops of the same device");
                return;
        }
index 1123c8afcf9efc5c28cef70dc0ddab6b49caa41e..ffac0bd6c8952fe8362e9dc3695992add2e08b92 100644 (file)
@@ -68,13 +68,15 @@ err_metadata:
 #define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 4
 static int enable_mpesw(struct mlx5_lag *ldev)
 {
-       struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+       int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       struct mlx5_core_dev *dev0;
        int err;
        int i;
 
-       if (ldev->mode != MLX5_LAG_MODE_NONE)
+       if (idx < 0 || ldev->mode != MLX5_LAG_MODE_NONE)
                return -EINVAL;
 
+       dev0 = ldev->pf[idx].dev;
        if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS)
                return -EOPNOTSUPP;
 
index f98f0735fce0f7111471688897916adcb557f930..22241f52716ce5fd0670338e0c338dfcff5c61a0 100644 (file)
@@ -39,13 +39,18 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
                                          struct mlx5_lag_definer *lag_definer,
                                          u8 *ports)
 {
-       struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        struct mlx5_flow_table_attr ft_attr = {};
        struct mlx5_flow_destination dest = {};
        MLX5_DECLARE_FLOW_ACT(flow_act);
        struct mlx5_flow_namespace *ns;
+       struct mlx5_core_dev *dev;
        int err, i, j, k, idx;
 
+       if (first_idx < 0)
+               return -EINVAL;
+
+       dev = ldev->pf[first_idx].dev;
        ft_attr.max_fte = ldev->ports * ldev->buckets;
        ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER;
 
@@ -293,11 +298,16 @@ static struct mlx5_lag_definer *
 mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash,
                        enum mlx5_traffic_types tt, bool tunnel, u8 *ports)
 {
-       struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        struct mlx5_lag_definer *lag_definer;
+       struct mlx5_core_dev *dev;
        u32 *match_definer_mask;
        int format_id, err;
 
+       if (first_idx < 0)
+               return ERR_PTR(-EINVAL);
+
+       dev = ldev->pf[first_idx].dev;
        lag_definer = kzalloc(sizeof(*lag_definer), GFP_KERNEL);
        if (!lag_definer)
                return ERR_PTR(-ENOMEM);
@@ -339,12 +349,15 @@ free_lag_definer:
 static void mlx5_lag_destroy_definer(struct mlx5_lag *ldev,
                                     struct mlx5_lag_definer *lag_definer)
 {
-       struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
-       int idx;
-       int i;
-       int j;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+       struct mlx5_core_dev *dev;
+       int idx, i, j;
 
-       mlx5_ldev_for_each(i, 0, ldev) {
+       if (first_idx < 0)
+               return;
+
+       dev = ldev->pf[first_idx].dev;
+       mlx5_ldev_for_each(i, first_idx, ldev) {
                for (j = 0; j < ldev->buckets; j++) {
                        idx = i * ldev->buckets + j;
                        mlx5_del_flow_rules(lag_definer->rules[idx]);
@@ -499,10 +512,15 @@ static void mlx5_lag_set_outer_ttc_params(struct mlx5_lag *ldev,
 
 static int mlx5_lag_create_ttc_table(struct mlx5_lag *ldev)
 {
-       struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
        struct ttc_params ttc_params = {};
+       struct mlx5_core_dev *dev;
 
+       if (first_idx < 0)
+               return -EINVAL;
+
+       dev = ldev->pf[first_idx].dev;
        mlx5_lag_set_outer_ttc_params(ldev, &ttc_params);
        port_sel->outer.ttc = mlx5_create_ttc_table(dev, &ttc_params);
        return PTR_ERR_OR_ZERO(port_sel->outer.ttc);
@@ -510,10 +528,15 @@ static int mlx5_lag_create_ttc_table(struct mlx5_lag *ldev)
 
 static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev)
 {
-       struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+       int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
        struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
        struct ttc_params ttc_params = {};
+       struct mlx5_core_dev *dev;
+
+       if (first_idx < 0)
+               return -EINVAL;
 
+       dev = ldev->pf[first_idx].dev;
        mlx5_lag_set_inner_ttc_params(ldev, &ttc_params);
        port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params);
        return PTR_ERR_OR_ZERO(port_sel->inner.ttc);
index 220a9ac75c8ba0256f78a0293ef4f65f5e4d48ea..869bfecdd8ffa4ca651c711d13fa78c2aa3b9574 100644 (file)
@@ -664,6 +664,10 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
                MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_current_uc_list,
                         ilog2(max_uc_list));
 
+       /* enable absolute native port num */
+       if (MLX5_CAP_GEN_MAX(dev, abs_native_port_num))
+               MLX5_SET(cmd_hca_cap, set_hca_cap, abs_native_port_num, 1);
+
        return set_caps(dev, set_ctx, MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE);
 }