Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mlx5-updates-2023-06-06' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2023-06-06

1) Support 4 ports VF LAG, part 2/2
2) Few extra trivial cleanup patches

Shay Drory Says:
================

Support 4 ports VF LAG, part 2/2

This series continues the series[1] "Support 4 ports VF LAG, part1/2".
This series adds support for 4 ports VF LAG (single FDB E-Switch).

This series of patches refactoring LAG code that make assumptions
about VF LAG supporting only two ports and then enable 4 ports VF LAG.

Patch 1:
- Fix for ib rep code
Patches 2-5:
- Refactors LAG layer.
Patches 6-7:
- Block LAG types which doesn't support 4 ports.
Patch 8:
- Enable 4 ports VF LAG.

This series specifically allows HCAs with 4 ports to create a VF LAG
with only 4 ports. It is not possible to create a VF LAG with 2 or 3
ports using HCAs that have 4 ports.

Currently, the Merged E-Switch feature only supports HCAs with 2 ports.
However, upcoming patches will introduce support for HCAs with 4 ports.

In order to activate VF LAG a user can execute:

devlink dev eswitch set pci/0000:08:00.0 mode switchdev
devlink dev eswitch set pci/0000:08:00.1 mode switchdev
devlink dev eswitch set pci/0000:08:00.2 mode switchdev
devlink dev eswitch set pci/0000:08:00.3 mode switchdev
ip link add name bond0 type bond
ip link set dev bond0 type bond mode 802.3ad
ip link set dev eth2 master bond0
ip link set dev eth3 master bond0
ip link set dev eth4 master bond0
ip link set dev eth5 master bond0

Where eth2, eth3, eth4 and eth5 are net-interfaces of pci/0000:08:00.0
pci/0000:08:00.1 pci/0000:08:00.2 pci/0000:08:00.3 respectively.

User can verify LAG state and type via debugfs:
/sys/kernel/debug/mlx5/0000\:08\:00.0/lag/state
/sys/kernel/debug/mlx5/0000\:08\:00.0/lag/type

[1]
https://lore.kernel.org/netdev/20230601060118.154015-1-saeed@kernel.org/T/#mf1d2083780970ba277bfe721554d4925f03f36d1

================

* tag 'mlx5-updates-2023-06-06' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux:
net/mlx5e: simplify condition after napi budget handling change
mlx5/core: E-Switch, Allocate ECPF vport if it's an eswitch manager
net/mlx5: Skip inline mode check after mlx5_eswitch_enable_locked() failure
net/mlx5e: TC, refactor access to hash key
net/mlx5e: Remove RX page cache leftovers
net/mlx5e: Expose catastrophic steering error counters
net/mlx5: Enable 4 ports VF LAG
net/mlx5: LAG, block multiport eswitch LAG in case ldev have more than 2 ports
net/mlx5: LAG, block multipath LAG in case ldev have more than 2 ports
net/mlx5: LAG, change mlx5_shared_fdb_supported() to static
net/mlx5: LAG, generalize handling of shared FDB
net/mlx5: LAG, check if all eswitches are paired for shared FDB
{net/RDMA}/mlx5: introduce lag_for_each_peer
RDMA/mlx5: Free second uplink ib port
====================

Link: https://lore.kernel.org/r/20230607210410.88209-1-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+202 -104
+7
Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst
··· 290 290 - nic_receive_steering_discard 291 291 number of packets that completed RX flow 292 292 steering but were discarded due to a mismatch in flow table. 293 + - generated_pkt_steering_fail 294 + number of packets generated by the VNIC experiencing unexpected steering 295 + failure (at any point in steering flow). 296 + - handled_pkt_steering_fail 297 + number of packets handled by the VNIC experiencing unexpected steering 298 + failure (at any point in steering flow owned by the VNIC, including the FDB 299 + for the eswitch owner). 293 300 294 301 User commands examples: 295 302
+68 -39
drivers/infiniband/hw/mlx5/ib_rep.c
··· 30 30 31 31 static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev); 32 32 33 + static void mlx5_ib_num_ports_update(struct mlx5_core_dev *dev, u32 *num_ports) 34 + { 35 + struct mlx5_core_dev *peer_dev; 36 + int i; 37 + 38 + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { 39 + u32 peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev); 40 + 41 + if (mlx5_lag_is_mpesw(peer_dev)) 42 + *num_ports += peer_num_ports; 43 + else 44 + /* Only 1 ib port is the representor for all uplinks */ 45 + *num_ports += peer_num_ports - 1; 46 + } 47 + } 48 + 33 49 static int 34 50 mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) 35 51 { 36 52 u32 num_ports = mlx5_eswitch_get_total_vports(dev); 53 + struct mlx5_core_dev *lag_master = dev; 37 54 const struct mlx5_ib_profile *profile; 38 55 struct mlx5_core_dev *peer_dev; 39 56 struct mlx5_ib_dev *ibdev; 40 - int second_uplink = false; 41 - u32 peer_num_ports; 57 + int new_uplink = false; 42 58 int vport_index; 43 59 int ret; 60 + int i; 44 61 45 62 vport_index = rep->vport_index; 46 63 47 64 if (mlx5_lag_is_shared_fdb(dev)) { 48 - peer_dev = mlx5_lag_get_peer_mdev(dev); 49 - peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev); 50 65 if (mlx5_lag_is_master(dev)) { 51 - if (mlx5_lag_is_mpesw(dev)) 52 - num_ports += peer_num_ports; 53 - else 54 - num_ports += peer_num_ports - 1; 55 - 66 + mlx5_ib_num_ports_update(dev, &num_ports); 56 67 } else { 57 68 if (rep->vport == MLX5_VPORT_UPLINK) { 58 69 if (!mlx5_lag_is_mpesw(dev)) 59 70 return 0; 60 - second_uplink = true; 71 + new_uplink = true; 61 72 } 73 + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { 74 + u32 peer_n_ports = mlx5_eswitch_get_total_vports(peer_dev); 62 75 63 - vport_index += peer_num_ports; 64 - dev = peer_dev; 76 + if (mlx5_lag_is_master(peer_dev)) 77 + lag_master = peer_dev; 78 + else if (!mlx5_lag_is_mpesw(dev)) 79 + /* Only 1 ib port is the representor for all uplinks */ 80 + peer_n_ports--; 81 + 82 + if (mlx5_get_dev_index(peer_dev) < mlx5_get_dev_index(dev)) 83 + vport_index += peer_n_ports; 84 + } 65 85 } 66 86 } 67 87 68 - if (rep->vport == MLX5_VPORT_UPLINK && !second_uplink) 88 + if (rep->vport == MLX5_VPORT_UPLINK && !new_uplink) 69 89 profile = &raw_eth_profile; 70 90 else 71 - return mlx5_ib_set_vport_rep(dev, rep, vport_index); 91 + return mlx5_ib_set_vport_rep(lag_master, rep, vport_index); 72 92 73 93 ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev); 74 94 if (!ibdev) ··· 105 85 vport_index = rep->vport_index; 106 86 ibdev->port[vport_index].rep = rep; 107 87 ibdev->port[vport_index].roce.netdev = 108 - mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport); 109 - ibdev->mdev = dev; 88 + mlx5_ib_get_rep_netdev(lag_master->priv.eswitch, rep->vport); 89 + ibdev->mdev = lag_master; 110 90 ibdev->num_ports = num_ports; 111 91 112 92 ret = __mlx5_ib_add(ibdev, profile); ··· 114 94 goto fail_add; 115 95 116 96 rep->rep_data[REP_IB].priv = ibdev; 117 - if (mlx5_lag_is_shared_fdb(dev)) 118 - mlx5_ib_register_peer_vport_reps(dev); 97 + if (mlx5_lag_is_shared_fdb(lag_master)) 98 + mlx5_ib_register_peer_vport_reps(lag_master); 119 99 120 100 return 0; 121 101 ··· 138 118 struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep); 139 119 int vport_index = rep->vport_index; 140 120 struct mlx5_ib_port *port; 121 + int i; 141 122 142 123 if (WARN_ON(!mdev)) 143 124 return; 144 125 145 - if (mlx5_lag_is_shared_fdb(mdev) && 146 - !mlx5_lag_is_master(mdev)) { 147 - struct mlx5_core_dev *peer_mdev; 148 - 149 - if (rep->vport == MLX5_VPORT_UPLINK) 150 - return; 151 - peer_mdev = mlx5_lag_get_peer_mdev(mdev); 152 - vport_index += mlx5_eswitch_get_total_vports(peer_mdev); 153 - } 154 - 155 126 if (!dev) 156 127 return; 128 + 129 + if (mlx5_lag_is_shared_fdb(mdev) && 130 + !mlx5_lag_is_master(mdev)) { 131 + if (rep->vport == MLX5_VPORT_UPLINK && !mlx5_lag_is_mpesw(mdev)) 132 + return; 133 + for (i = 0; i < dev->num_ports; i++) { 134 + if (dev->port[i].rep == rep) 135 + break; 136 + } 137 + if (WARN_ON(i == dev->num_ports)) 138 + return; 139 + vport_index = i; 140 + } 157 141 158 142 port = &dev->port[vport_index]; 159 143 write_lock(&port->roce.netdev_lock); ··· 167 143 port->rep = NULL; 168 144 169 145 if (rep->vport == MLX5_VPORT_UPLINK) { 170 - struct mlx5_core_dev *peer_mdev; 171 - struct mlx5_eswitch *esw; 146 + 147 + if (mlx5_lag_is_shared_fdb(mdev) && !mlx5_lag_is_master(mdev)) 148 + return; 172 149 173 150 if (mlx5_lag_is_shared_fdb(mdev)) { 174 - peer_mdev = mlx5_lag_get_peer_mdev(mdev); 175 - esw = peer_mdev->priv.eswitch; 176 - mlx5_eswitch_unregister_vport_reps(esw, REP_IB); 151 + struct mlx5_core_dev *peer_mdev; 152 + struct mlx5_eswitch *esw; 153 + 154 + mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) { 155 + esw = peer_mdev->priv.eswitch; 156 + mlx5_eswitch_unregister_vport_reps(esw, REP_IB); 157 + } 177 158 } 178 159 __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX); 179 160 } ··· 192 163 193 164 static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev) 194 165 { 195 - struct mlx5_core_dev *peer_mdev = mlx5_lag_get_peer_mdev(mdev); 166 + struct mlx5_core_dev *peer_mdev; 196 167 struct mlx5_eswitch *esw; 168 + int i; 197 169 198 - if (!peer_mdev) 199 - return; 200 - 201 - esw = peer_mdev->priv.eswitch; 202 - mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB); 170 + mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) { 171 + esw = peer_mdev->priv.eswitch; 172 + mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB); 173 + } 203 174 } 204 175 205 176 struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
+10
drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c
··· 76 76 if (err) 77 77 return err; 78 78 79 + err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail", 80 + VNIC_ENV_GET64(&vnic, generated_pkt_steering_fail)); 81 + if (err) 82 + return err; 83 + 84 + err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", 85 + VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); 86 + if (err) 87 + return err; 88 + 79 89 err = devlink_fmsg_obj_nest_end(fmsg); 80 90 if (err) 81 91 return err;
-7
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 594 594 595 595 #define MLX5E_MAX_RX_FRAGS 4 596 596 597 - /* a single cache unit is capable to serve one napi call (for non-striding rq) 598 - * or a MPWQE (for striding rq). 599 - */ 600 - #define MLX5E_CACHE_UNIT (MLX5_MPWRQ_MAX_PAGES_PER_WQE > NAPI_POLL_WEIGHT ? \ 601 - MLX5_MPWRQ_MAX_PAGES_PER_WQE : NAPI_POLL_WEIGHT) 602 - #define MLX5E_CACHE_SIZE (4 * roundup_pow_of_two(MLX5E_CACHE_UNIT)) 603 - 604 597 struct mlx5e_rq; 605 598 typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq*, struct mlx5_cqe64*); 606 599 typedef struct sk_buff *
+3 -6
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
··· 25 25 26 26 static const struct rhashtable_params act_counters_ht_params = { 27 27 .head_offset = offsetof(struct mlx5e_tc_act_stats, hash), 28 - .key_offset = 0, 29 - .key_len = offsetof(struct mlx5e_tc_act_stats, counter), 28 + .key_offset = offsetof(struct mlx5e_tc_act_stats, tc_act_cookie), 29 + .key_len = sizeof_field(struct mlx5e_tc_act_stats, tc_act_cookie), 30 30 .automatic_shrinking = true, 31 31 }; 32 32 ··· 169 169 { 170 170 struct rhashtable *ht = &handle->ht; 171 171 struct mlx5e_tc_act_stats *item; 172 - struct mlx5e_tc_act_stats key; 173 172 u64 pkts, bytes, lastused; 174 173 int err = 0; 175 174 176 - key.tc_act_cookie = fl_act->cookie; 177 - 178 175 rcu_read_lock(); 179 - item = rhashtable_lookup(ht, &key, act_counters_ht_params); 176 + item = rhashtable_lookup(ht, &fl_act->cookie, act_counters_ht_params); 180 177 if (!item) { 181 178 rcu_read_unlock(); 182 179 err = -ENOENT;
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
··· 207 207 } 208 208 ch_stats->aff_change++; 209 209 aff_change = true; 210 - if (budget && work_done == budget) 210 + if (work_done == budget) 211 211 work_done--; 212 212 } 213 213
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
··· 1601 1601 idx++; 1602 1602 } 1603 1603 1604 - if (mlx5_ecpf_vport_exists(dev)) { 1604 + if (mlx5_ecpf_vport_exists(dev) || 1605 + mlx5_core_is_ecpf_esw_manager(dev)) { 1605 1606 err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF); 1606 1607 if (err) 1607 1608 goto err;
+9
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 779 779 return 0; 780 780 } 781 781 782 + static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) 783 + { 784 + if (mlx5_esw_allowed(esw)) 785 + return esw->num_peers; 786 + return 0; 787 + } 788 + 782 789 static inline struct mlx5_flow_table * 783 790 mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) 784 791 { ··· 832 825 static inline void 833 826 mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, 834 827 struct mlx5_eswitch *slave_esw) {} 828 + 829 + static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; } 835 830 836 831 static inline int 837 832 mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 2178 2178 "Failed setting eswitch to offloads"); 2179 2179 esw->mode = MLX5_ESWITCH_LEGACY; 2180 2180 mlx5_rescan_drivers(esw->dev); 2181 + return err; 2181 2182 } 2182 2183 if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) { 2183 2184 if (mlx5_eswitch_inline_mode_get(esw, ··· 2188 2187 "Inline mode is different between vports"); 2189 2188 } 2190 2189 } 2191 - return err; 2190 + return 0; 2192 2191 } 2193 2192 2194 2193 static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw,
+15 -9
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
··· 244 244 ft->type == FS_FT_FDB && 245 245 mlx5_lag_is_shared_fdb(dev) && 246 246 mlx5_lag_is_master(dev)) { 247 - err = mlx5_cmd_set_slave_root_fdb(dev, 248 - mlx5_lag_get_peer_mdev(dev), 249 - !disconnect, (!disconnect) ? 250 - ft->id : 0); 251 - if (err && !disconnect) { 252 - MLX5_SET(set_flow_table_root_in, in, op_mod, 0); 253 - MLX5_SET(set_flow_table_root_in, in, table_id, 254 - ns->root_ft->id); 255 - mlx5_cmd_exec_in(dev, set_flow_table_root, in); 247 + struct mlx5_core_dev *peer_dev; 248 + int i; 249 + 250 + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { 251 + err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect, 252 + (!disconnect) ? ft->id : 0); 253 + if (err && !disconnect) { 254 + MLX5_SET(set_flow_table_root_in, in, op_mod, 0); 255 + MLX5_SET(set_flow_table_root_in, in, table_id, 256 + ns->root_ft->id); 257 + mlx5_cmd_exec_in(dev, set_flow_table_root, in); 258 + } 259 + if (err) 260 + break; 256 261 } 262 + 257 263 } 258 264 259 265 return err;
+56 -33
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
··· 512 512 return; 513 513 514 514 if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) && 515 - tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) 515 + tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) { 516 + if (ldev->ports > 2) 517 + ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS; 516 518 set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags); 519 + } 517 520 } 518 521 519 522 static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode, ··· 711 708 return 0; 712 709 } 713 710 714 - #define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2 711 + #define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 4 715 712 bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) 716 713 { 717 714 #ifdef CONFIG_MLX5_ESWITCH ··· 737 734 if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode) 738 735 return false; 739 736 740 - if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports != MLX5_LAG_OFFLOADS_SUPPORTED_PORTS) 737 + if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports > MLX5_LAG_OFFLOADS_SUPPORTED_PORTS) 741 738 return false; 742 739 #else 743 740 for (i = 0; i < ldev->ports; i++) ··· 785 782 { 786 783 bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags); 787 784 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; 788 - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; 789 785 bool roce_lag; 790 786 int err; 791 787 int i; ··· 809 807 if (shared_fdb || roce_lag) 810 808 mlx5_lag_add_devices(ldev); 811 809 812 - if (shared_fdb) { 813 - if (!(dev0->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) 814 - mlx5_eswitch_reload_reps(dev0->priv.eswitch); 815 - if (!(dev1->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) 816 - mlx5_eswitch_reload_reps(dev1->priv.eswitch); 817 - } 810 + if (shared_fdb) 811 + for (i = 0; i < ldev->ports; i++) 812 + if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) 813 + mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); 818 814 } 819 815 820 - bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) 816 + static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) 821 817 { 822 - struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; 823 - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; 818 + struct mlx5_core_dev *dev; 819 + int i; 824 820 825 - if (is_mdev_switchdev_mode(dev0) && 826 - is_mdev_switchdev_mode(dev1) && 827 - mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) && 828 - mlx5_eswitch_vport_match_metadata_enabled(dev1->priv.eswitch) && 829 - mlx5_devcom_comp_is_ready(dev0->priv.devcom, 830 - MLX5_DEVCOM_ESW_OFFLOADS) && 831 - MLX5_CAP_GEN(dev1, lag_native_fdb_selection) && 832 - MLX5_CAP_ESW(dev1, root_ft_on_other_esw) && 833 - MLX5_CAP_ESW(dev0, esw_shared_ingress_acl)) 821 + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) { 822 + dev = ldev->pf[i].dev; 823 + if (is_mdev_switchdev_mode(dev) && 824 + mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && 825 + MLX5_CAP_GEN(dev, lag_native_fdb_selection) && 826 + MLX5_CAP_ESW(dev, root_ft_on_other_esw) && 827 + mlx5_eswitch_get_npeers(dev->priv.eswitch) == 828 + MLX5_CAP_GEN(dev, num_lag_ports) - 1) 829 + continue; 830 + return false; 831 + } 832 + 833 + dev = ldev->pf[MLX5_LAG_P1].dev; 834 + if (is_mdev_switchdev_mode(dev) && 835 + mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && 836 + mlx5_devcom_comp_is_ready(dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS) && 837 + MLX5_CAP_ESW(dev, esw_shared_ingress_acl) && 838 + mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1) 834 839 return true; 835 840 836 841 return false; ··· 874 865 static void mlx5_do_bond(struct mlx5_lag *ldev) 875 866 { 876 867 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; 877 - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; 878 868 struct lag_tracker tracker = { }; 879 869 bool do_bond, roce_lag; 880 870 int err; ··· 914 906 for (i = 1; i < ldev->ports; i++) 915 907 mlx5_nic_vport_enable_roce(ldev->pf[i].dev); 916 908 } else if (shared_fdb) { 909 + int i; 910 + 917 911 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 918 912 mlx5_rescan_drivers_locked(dev0); 919 913 920 - err = mlx5_eswitch_reload_reps(dev0->priv.eswitch); 921 - if (!err) 922 - err = mlx5_eswitch_reload_reps(dev1->priv.eswitch); 914 + for (i = 0; i < ldev->ports; i++) { 915 + err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); 916 + if (err) 917 + break; 918 + } 923 919 924 920 if (err) { 925 921 dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 926 922 mlx5_rescan_drivers_locked(dev0); 927 923 mlx5_deactivate_lag(ldev); 928 924 mlx5_lag_add_devices(ldev); 929 - mlx5_eswitch_reload_reps(dev0->priv.eswitch); 930 - mlx5_eswitch_reload_reps(dev1->priv.eswitch); 925 + for (i = 0; i < ldev->ports; i++) 926 + mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); 931 927 mlx5_core_err(dev0, "Failed to enable lag\n"); 932 928 return; 933 929 } ··· 1531 1519 } 1532 1520 EXPORT_SYMBOL(mlx5_lag_get_num_ports); 1533 1521 1534 - struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev) 1522 + struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i) 1535 1523 { 1536 1524 struct mlx5_core_dev *peer_dev = NULL; 1537 1525 struct mlx5_lag *ldev; 1538 1526 unsigned long flags; 1527 + int idx; 1539 1528 1540 1529 spin_lock_irqsave(&lag_lock, flags); 1541 1530 ldev = mlx5_lag_dev(dev); 1542 1531 if (!ldev) 1543 1532 goto unlock; 1544 1533 1545 - peer_dev = ldev->pf[MLX5_LAG_P1].dev == dev ? 1546 - ldev->pf[MLX5_LAG_P2].dev : 1547 - ldev->pf[MLX5_LAG_P1].dev; 1534 + if (*i == ldev->ports) 1535 + goto unlock; 1536 + for (idx = *i; idx < ldev->ports; idx++) 1537 + if (ldev->pf[idx].dev != dev) 1538 + break; 1539 + 1540 + if (idx == ldev->ports) { 1541 + *i = idx; 1542 + goto unlock; 1543 + } 1544 + *i = idx + 1; 1545 + 1546 + peer_dev = ldev->pf[idx].dev; 1548 1547 1549 1548 unlock: 1550 1549 spin_unlock_irqrestore(&lag_lock, flags); 1551 1550 return peer_dev; 1552 1551 } 1553 - EXPORT_SYMBOL(mlx5_lag_get_peer_mdev); 1552 + EXPORT_SYMBOL(mlx5_lag_get_next_peer_mdev); 1554 1553 1555 1554 int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, 1556 1555 u64 *values,
-1
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
··· 111 111 bool shared_fdb); 112 112 int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, 113 113 struct net_device *ndev); 114 - bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev); 115 114 116 115 char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags); 117 116 void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
+4
drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
··· 14 14 return ldev->mode == MLX5_LAG_MODE_MULTIPATH; 15 15 } 16 16 17 + #define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2 17 18 static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) 18 19 { 19 20 if (!mlx5_lag_is_ready(ldev)) 20 21 return false; 21 22 22 23 if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev)) 24 + return false; 25 + 26 + if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS) 23 27 return false; 24 28 25 29 return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev,
+4
drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
··· 65 65 return err; 66 66 } 67 67 68 + #define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 2 68 69 static int enable_mpesw(struct mlx5_lag *ldev) 69 70 { 70 71 struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; ··· 74 73 75 74 if (ldev->mode != MLX5_LAG_MODE_NONE) 76 75 return -EINVAL; 76 + 77 + if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS) 78 + return -EOPNOTSUPP; 77 79 78 80 if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS || 79 81 !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) ||
+3 -2
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
··· 75 75 76 76 if (!mlx5_core_is_pf(dev)) 77 77 return NULL; 78 - if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED) 78 + if (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_DEVCOM_PORTS_SUPPORTED) 79 79 return NULL; 80 80 81 81 mlx5_dev_list_lock(); 82 82 sguid0 = mlx5_query_nic_system_image_guid(dev); 83 83 list_for_each_entry(iter, &devcom_list, list) { 84 - struct mlx5_core_dev *tmp_dev = NULL; 84 + /* There is at least one device in iter */ 85 + struct mlx5_core_dev *tmp_dev; 85 86 86 87 idx = -1; 87 88 for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
··· 6 6 7 7 #include <linux/mlx5/driver.h> 8 8 9 - #define MLX5_DEVCOM_PORTS_SUPPORTED 2 9 + #define MLX5_DEVCOM_PORTS_SUPPORTED 4 10 10 11 11 enum mlx5_devcom_components { 12 12 MLX5_DEVCOM_ESW_OFFLOADS,
+7 -1
include/linux/mlx5/driver.h
··· 1174 1174 u64 *values, 1175 1175 int num_counters, 1176 1176 size_t *offsets); 1177 - struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev); 1177 + struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i); 1178 + 1179 + #define mlx5_lag_for_each_peer_mdev(dev, peer, i) \ 1180 + for (i = 0, peer = mlx5_lag_get_next_peer_mdev(dev, &i); \ 1181 + peer; \ 1182 + peer = mlx5_lag_get_next_peer_mdev(dev, &i)) 1183 + 1178 1184 u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev); 1179 1185 struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); 1180 1186 void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up);
+10 -2
include/linux/mlx5/mlx5_ifc.h
··· 1755 1755 u8 reserved_at_328[0x2]; 1756 1756 u8 relaxed_ordering_read[0x1]; 1757 1757 u8 log_max_pd[0x5]; 1758 - u8 reserved_at_330[0x9]; 1758 + u8 reserved_at_330[0x7]; 1759 + u8 vnic_env_cnt_steering_fail[0x1]; 1760 + u8 reserved_at_338[0x1]; 1759 1761 u8 q_counter_aggregation[0x1]; 1760 1762 u8 q_counter_other_vport[0x1]; 1761 1763 u8 log_max_xrcd[0x5]; ··· 3675 3673 3676 3674 u8 eth_wqe_too_small[0x20]; 3677 3675 3678 - u8 reserved_at_220[0xdc0]; 3676 + u8 reserved_at_220[0xc0]; 3677 + 3678 + u8 generated_pkt_steering_fail[0x40]; 3679 + 3680 + u8 handled_pkt_steering_fail[0x40]; 3681 + 3682 + u8 reserved_at_360[0xc80]; 3679 3683 }; 3680 3684 3681 3685 struct mlx5_ifc_traffic_counter_bits {