Commit f84ad5cf authored by Jakub Kicinski's avatar Jakub Kicinski

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.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 55b24334 803ea346
...@@ -290,6 +290,13 @@ Description of the vnic counters: ...@@ -290,6 +290,13 @@ Description of the vnic counters:
- nic_receive_steering_discard - nic_receive_steering_discard
number of packets that completed RX flow number of packets that completed RX flow
steering but were discarded due to a mismatch in flow table. steering but were discarded due to a mismatch in flow table.
- generated_pkt_steering_fail
number of packets generated by the VNIC experiencing unexpected steering
failure (at any point in steering flow).
- handled_pkt_steering_fail
number of packets handled by the VNIC experiencing unexpected steering
failure (at any point in steering flow owned by the VNIC, including the FDB
for the eswitch owner).
User commands examples: User commands examples:
......
...@@ -30,45 +30,65 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev, ...@@ -30,45 +30,65 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev,
static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev); static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev);
static void mlx5_ib_num_ports_update(struct mlx5_core_dev *dev, u32 *num_ports)
{
struct mlx5_core_dev *peer_dev;
int i;
mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
u32 peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev);
if (mlx5_lag_is_mpesw(peer_dev))
*num_ports += peer_num_ports;
else
/* Only 1 ib port is the representor for all uplinks */
*num_ports += peer_num_ports - 1;
}
}
static int static int
mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{ {
u32 num_ports = mlx5_eswitch_get_total_vports(dev); u32 num_ports = mlx5_eswitch_get_total_vports(dev);
struct mlx5_core_dev *lag_master = dev;
const struct mlx5_ib_profile *profile; const struct mlx5_ib_profile *profile;
struct mlx5_core_dev *peer_dev; struct mlx5_core_dev *peer_dev;
struct mlx5_ib_dev *ibdev; struct mlx5_ib_dev *ibdev;
int second_uplink = false; int new_uplink = false;
u32 peer_num_ports;
int vport_index; int vport_index;
int ret; int ret;
int i;
vport_index = rep->vport_index; vport_index = rep->vport_index;
if (mlx5_lag_is_shared_fdb(dev)) { if (mlx5_lag_is_shared_fdb(dev)) {
peer_dev = mlx5_lag_get_peer_mdev(dev);
peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev);
if (mlx5_lag_is_master(dev)) { if (mlx5_lag_is_master(dev)) {
if (mlx5_lag_is_mpesw(dev)) mlx5_ib_num_ports_update(dev, &num_ports);
num_ports += peer_num_ports;
else
num_ports += peer_num_ports - 1;
} else { } else {
if (rep->vport == MLX5_VPORT_UPLINK) { if (rep->vport == MLX5_VPORT_UPLINK) {
if (!mlx5_lag_is_mpesw(dev)) if (!mlx5_lag_is_mpesw(dev))
return 0; return 0;
second_uplink = true; new_uplink = true;
} }
mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
u32 peer_n_ports = mlx5_eswitch_get_total_vports(peer_dev);
if (mlx5_lag_is_master(peer_dev))
lag_master = peer_dev;
else if (!mlx5_lag_is_mpesw(dev))
/* Only 1 ib port is the representor for all uplinks */
peer_n_ports--;
vport_index += peer_num_ports; if (mlx5_get_dev_index(peer_dev) < mlx5_get_dev_index(dev))
dev = peer_dev; vport_index += peer_n_ports;
}
} }
} }
if (rep->vport == MLX5_VPORT_UPLINK && !second_uplink) if (rep->vport == MLX5_VPORT_UPLINK && !new_uplink)
profile = &raw_eth_profile; profile = &raw_eth_profile;
else else
return mlx5_ib_set_vport_rep(dev, rep, vport_index); return mlx5_ib_set_vport_rep(lag_master, rep, vport_index);
ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev); ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev);
if (!ibdev) if (!ibdev)
...@@ -85,8 +105,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) ...@@ -85,8 +105,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
vport_index = rep->vport_index; vport_index = rep->vport_index;
ibdev->port[vport_index].rep = rep; ibdev->port[vport_index].rep = rep;
ibdev->port[vport_index].roce.netdev = ibdev->port[vport_index].roce.netdev =
mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport); mlx5_ib_get_rep_netdev(lag_master->priv.eswitch, rep->vport);
ibdev->mdev = dev; ibdev->mdev = lag_master;
ibdev->num_ports = num_ports; ibdev->num_ports = num_ports;
ret = __mlx5_ib_add(ibdev, profile); ret = __mlx5_ib_add(ibdev, profile);
...@@ -94,8 +114,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) ...@@ -94,8 +114,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
goto fail_add; goto fail_add;
rep->rep_data[REP_IB].priv = ibdev; rep->rep_data[REP_IB].priv = ibdev;
if (mlx5_lag_is_shared_fdb(dev)) if (mlx5_lag_is_shared_fdb(lag_master))
mlx5_ib_register_peer_vport_reps(dev); mlx5_ib_register_peer_vport_reps(lag_master);
return 0; return 0;
...@@ -118,23 +138,27 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep) ...@@ -118,23 +138,27 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep); struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep);
int vport_index = rep->vport_index; int vport_index = rep->vport_index;
struct mlx5_ib_port *port; struct mlx5_ib_port *port;
int i;
if (WARN_ON(!mdev)) if (WARN_ON(!mdev))
return; return;
if (!dev)
return;
if (mlx5_lag_is_shared_fdb(mdev) && if (mlx5_lag_is_shared_fdb(mdev) &&
!mlx5_lag_is_master(mdev)) { !mlx5_lag_is_master(mdev)) {
struct mlx5_core_dev *peer_mdev; if (rep->vport == MLX5_VPORT_UPLINK && !mlx5_lag_is_mpesw(mdev))
if (rep->vport == MLX5_VPORT_UPLINK)
return; return;
peer_mdev = mlx5_lag_get_peer_mdev(mdev); for (i = 0; i < dev->num_ports; i++) {
vport_index += mlx5_eswitch_get_total_vports(peer_mdev); if (dev->port[i].rep == rep)
break;
}
if (WARN_ON(i == dev->num_ports))
return;
vport_index = i;
} }
if (!dev)
return;
port = &dev->port[vport_index]; port = &dev->port[vport_index];
write_lock(&port->roce.netdev_lock); write_lock(&port->roce.netdev_lock);
port->roce.netdev = NULL; port->roce.netdev = NULL;
...@@ -143,13 +167,18 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep) ...@@ -143,13 +167,18 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep)
port->rep = NULL; port->rep = NULL;
if (rep->vport == MLX5_VPORT_UPLINK) { if (rep->vport == MLX5_VPORT_UPLINK) {
struct mlx5_core_dev *peer_mdev;
struct mlx5_eswitch *esw; if (mlx5_lag_is_shared_fdb(mdev) && !mlx5_lag_is_master(mdev))
return;
if (mlx5_lag_is_shared_fdb(mdev)) { if (mlx5_lag_is_shared_fdb(mdev)) {
peer_mdev = mlx5_lag_get_peer_mdev(mdev); struct mlx5_core_dev *peer_mdev;
esw = peer_mdev->priv.eswitch; struct mlx5_eswitch *esw;
mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) {
esw = peer_mdev->priv.eswitch;
mlx5_eswitch_unregister_vport_reps(esw, REP_IB);
}
} }
__mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX); __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
} }
...@@ -163,14 +192,14 @@ static const struct mlx5_eswitch_rep_ops rep_ops = { ...@@ -163,14 +192,14 @@ static const struct mlx5_eswitch_rep_ops rep_ops = {
static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev) static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev)
{ {
struct mlx5_core_dev *peer_mdev = mlx5_lag_get_peer_mdev(mdev); struct mlx5_core_dev *peer_mdev;
struct mlx5_eswitch *esw; struct mlx5_eswitch *esw;
int i;
if (!peer_mdev) mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) {
return; esw = peer_mdev->priv.eswitch;
mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
esw = peer_mdev->priv.eswitch; }
mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB);
} }
struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw, struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw,
......
...@@ -76,6 +76,16 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev, ...@@ -76,6 +76,16 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev,
if (err) if (err)
return err; return err;
err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail",
VNIC_ENV_GET64(&vnic, generated_pkt_steering_fail));
if (err)
return err;
err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail",
VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail));
if (err)
return err;
err = devlink_fmsg_obj_nest_end(fmsg); err = devlink_fmsg_obj_nest_end(fmsg);
if (err) if (err)
return err; return err;
......
...@@ -594,13 +594,6 @@ struct mlx5e_mpw_info { ...@@ -594,13 +594,6 @@ struct mlx5e_mpw_info {
#define MLX5E_MAX_RX_FRAGS 4 #define MLX5E_MAX_RX_FRAGS 4
/* a single cache unit is capable to serve one napi call (for non-striding rq)
* or a MPWQE (for striding rq).
*/
#define MLX5E_CACHE_UNIT (MLX5_MPWRQ_MAX_PAGES_PER_WQE > NAPI_POLL_WEIGHT ? \
MLX5_MPWRQ_MAX_PAGES_PER_WQE : NAPI_POLL_WEIGHT)
#define MLX5E_CACHE_SIZE (4 * roundup_pow_of_two(MLX5E_CACHE_UNIT))
struct mlx5e_rq; struct mlx5e_rq;
typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq*, struct mlx5_cqe64*); typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq*, struct mlx5_cqe64*);
typedef struct sk_buff * typedef struct sk_buff *
......
...@@ -25,8 +25,8 @@ struct mlx5e_tc_act_stats { ...@@ -25,8 +25,8 @@ struct mlx5e_tc_act_stats {
static const struct rhashtable_params act_counters_ht_params = { static const struct rhashtable_params act_counters_ht_params = {
.head_offset = offsetof(struct mlx5e_tc_act_stats, hash), .head_offset = offsetof(struct mlx5e_tc_act_stats, hash),
.key_offset = 0, .key_offset = offsetof(struct mlx5e_tc_act_stats, tc_act_cookie),
.key_len = offsetof(struct mlx5e_tc_act_stats, counter), .key_len = sizeof_field(struct mlx5e_tc_act_stats, tc_act_cookie),
.automatic_shrinking = true, .automatic_shrinking = true,
}; };
...@@ -169,14 +169,11 @@ mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle, ...@@ -169,14 +169,11 @@ mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle,
{ {
struct rhashtable *ht = &handle->ht; struct rhashtable *ht = &handle->ht;
struct mlx5e_tc_act_stats *item; struct mlx5e_tc_act_stats *item;
struct mlx5e_tc_act_stats key;
u64 pkts, bytes, lastused; u64 pkts, bytes, lastused;
int err = 0; int err = 0;
key.tc_act_cookie = fl_act->cookie;
rcu_read_lock(); rcu_read_lock();
item = rhashtable_lookup(ht, &key, act_counters_ht_params); item = rhashtable_lookup(ht, &fl_act->cookie, act_counters_ht_params);
if (!item) { if (!item) {
rcu_read_unlock(); rcu_read_unlock();
err = -ENOENT; err = -ENOENT;
......
...@@ -207,7 +207,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget) ...@@ -207,7 +207,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
} }
ch_stats->aff_change++; ch_stats->aff_change++;
aff_change = true; aff_change = true;
if (budget && work_done == budget) if (work_done == budget)
work_done--; work_done--;
} }
......
...@@ -1601,7 +1601,8 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) ...@@ -1601,7 +1601,8 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw)
idx++; idx++;
} }
if (mlx5_ecpf_vport_exists(dev)) { if (mlx5_ecpf_vport_exists(dev) ||
mlx5_core_is_ecpf_esw_manager(dev)) {
err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF); err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF);
if (err) if (err)
goto err; goto err;
......
...@@ -779,6 +779,13 @@ static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw) ...@@ -779,6 +779,13 @@ static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw)
return 0; return 0;
} }
static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw)
{
if (mlx5_esw_allowed(esw))
return esw->num_peers;
return 0;
}
static inline struct mlx5_flow_table * static inline struct mlx5_flow_table *
mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw)
{ {
...@@ -826,6 +833,8 @@ static inline void ...@@ -826,6 +833,8 @@ static inline void
mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
struct mlx5_eswitch *slave_esw) {} struct mlx5_eswitch *slave_esw) {}
static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; }
static inline int static inline int
mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw) mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
{ {
......
...@@ -2178,6 +2178,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, ...@@ -2178,6 +2178,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
"Failed setting eswitch to offloads"); "Failed setting eswitch to offloads");
esw->mode = MLX5_ESWITCH_LEGACY; esw->mode = MLX5_ESWITCH_LEGACY;
mlx5_rescan_drivers(esw->dev); mlx5_rescan_drivers(esw->dev);
return err;
} }
if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) { if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
if (mlx5_eswitch_inline_mode_get(esw, if (mlx5_eswitch_inline_mode_get(esw,
...@@ -2187,7 +2188,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, ...@@ -2187,7 +2188,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
"Inline mode is different between vports"); "Inline mode is different between vports");
} }
} }
return err; return 0;
} }
static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw, static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw,
......
...@@ -244,16 +244,22 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns, ...@@ -244,16 +244,22 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns,
ft->type == FS_FT_FDB && ft->type == FS_FT_FDB &&
mlx5_lag_is_shared_fdb(dev) && mlx5_lag_is_shared_fdb(dev) &&
mlx5_lag_is_master(dev)) { mlx5_lag_is_master(dev)) {
err = mlx5_cmd_set_slave_root_fdb(dev, struct mlx5_core_dev *peer_dev;
mlx5_lag_get_peer_mdev(dev), int i;
!disconnect, (!disconnect) ?
ft->id : 0); mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) {
if (err && !disconnect) { err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect,
MLX5_SET(set_flow_table_root_in, in, op_mod, 0); (!disconnect) ? ft->id : 0);
MLX5_SET(set_flow_table_root_in, in, table_id, if (err && !disconnect) {
ns->root_ft->id); MLX5_SET(set_flow_table_root_in, in, op_mod, 0);
mlx5_cmd_exec_in(dev, set_flow_table_root, in); MLX5_SET(set_flow_table_root_in, in, table_id,
ns->root_ft->id);
mlx5_cmd_exec_in(dev, set_flow_table_root, in);
}
if (err)
break;
} }
} }
return err; return err;
......
...@@ -512,8 +512,11 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev, ...@@ -512,8 +512,11 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
return; return;
if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) && if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) {
if (ldev->ports > 2)
ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS;
set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags); set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags);
}
} }
static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode, static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode,
...@@ -708,7 +711,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev) ...@@ -708,7 +711,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
return 0; return 0;
} }
#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2 #define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 4
bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
{ {
#ifdef CONFIG_MLX5_ESWITCH #ifdef CONFIG_MLX5_ESWITCH
...@@ -734,7 +737,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) ...@@ -734,7 +737,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode) if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode)
return false; return false;
if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports != MLX5_LAG_OFFLOADS_SUPPORTED_PORTS) if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports > MLX5_LAG_OFFLOADS_SUPPORTED_PORTS)
return false; return false;
#else #else
for (i = 0; i < ldev->ports; i++) for (i = 0; i < ldev->ports; i++)
...@@ -782,7 +785,6 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) ...@@ -782,7 +785,6 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
{ {
bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags); 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; struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
bool roce_lag; bool roce_lag;
int err; int err;
int i; int i;
...@@ -807,28 +809,35 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) ...@@ -807,28 +809,35 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
if (shared_fdb || roce_lag) if (shared_fdb || roce_lag)
mlx5_lag_add_devices(ldev); mlx5_lag_add_devices(ldev);
if (shared_fdb) { if (shared_fdb)
if (!(dev0->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) for (i = 0; i < ldev->ports; i++)
mlx5_eswitch_reload_reps(dev0->priv.eswitch); if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
if (!(dev1->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
mlx5_eswitch_reload_reps(dev1->priv.eswitch);
}
} }
bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
{ {
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; struct mlx5_core_dev *dev;
struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; int i;
if (is_mdev_switchdev_mode(dev0) && for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
is_mdev_switchdev_mode(dev1) && dev = ldev->pf[i].dev;
mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) && if (is_mdev_switchdev_mode(dev) &&
mlx5_eswitch_vport_match_metadata_enabled(dev1->priv.eswitch) && mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
mlx5_devcom_comp_is_ready(dev0->priv.devcom, MLX5_CAP_GEN(dev, lag_native_fdb_selection) &&
MLX5_DEVCOM_ESW_OFFLOADS) && MLX5_CAP_ESW(dev, root_ft_on_other_esw) &&
MLX5_CAP_GEN(dev1, lag_native_fdb_selection) && mlx5_eswitch_get_npeers(dev->priv.eswitch) ==
MLX5_CAP_ESW(dev1, root_ft_on_other_esw) && MLX5_CAP_GEN(dev, num_lag_ports) - 1)
MLX5_CAP_ESW(dev0, esw_shared_ingress_acl)) continue;
return false;
}
dev = ldev->pf[MLX5_LAG_P1].dev;
if (is_mdev_switchdev_mode(dev) &&
mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
mlx5_devcom_comp_is_ready(dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS) &&
MLX5_CAP_ESW(dev, esw_shared_ingress_acl) &&
mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1)
return true; return true;
return false; return false;
...@@ -865,7 +874,6 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond) ...@@ -865,7 +874,6 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
static void mlx5_do_bond(struct mlx5_lag *ldev) static void mlx5_do_bond(struct mlx5_lag *ldev)
{ {
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
struct lag_tracker tracker = { }; struct lag_tracker tracker = { };
bool do_bond, roce_lag; bool do_bond, roce_lag;
int err; int err;
...@@ -906,20 +914,24 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) ...@@ -906,20 +914,24 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
for (i = 1; i < ldev->ports; i++) for (i = 1; i < ldev->ports; i++)
mlx5_nic_vport_enable_roce(ldev->pf[i].dev); mlx5_nic_vport_enable_roce(ldev->pf[i].dev);
} else if (shared_fdb) { } else if (shared_fdb) {
int i;
dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0); mlx5_rescan_drivers_locked(dev0);
err = mlx5_eswitch_reload_reps(dev0->priv.eswitch); for (i = 0; i < ldev->ports; i++) {
if (!err) err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
err = mlx5_eswitch_reload_reps(dev1->priv.eswitch); if (err)
break;
}
if (err) { if (err) {
dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0); mlx5_rescan_drivers_locked(dev0);
mlx5_deactivate_lag(ldev); mlx5_deactivate_lag(ldev);
mlx5_lag_add_devices(ldev); mlx5_lag_add_devices(ldev);
mlx5_eswitch_reload_reps(dev0->priv.eswitch); for (i = 0; i < ldev->ports; i++)
mlx5_eswitch_reload_reps(dev1->priv.eswitch); mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
mlx5_core_err(dev0, "Failed to enable lag\n"); mlx5_core_err(dev0, "Failed to enable lag\n");
return; return;
} }
...@@ -1519,26 +1531,37 @@ u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev) ...@@ -1519,26 +1531,37 @@ u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev)
} }
EXPORT_SYMBOL(mlx5_lag_get_num_ports); EXPORT_SYMBOL(mlx5_lag_get_num_ports);
struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev) struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i)
{ {
struct mlx5_core_dev *peer_dev = NULL; struct mlx5_core_dev *peer_dev = NULL;
struct mlx5_lag *ldev; struct mlx5_lag *ldev;
unsigned long flags; unsigned long flags;
int idx;
spin_lock_irqsave(&lag_lock, flags); spin_lock_irqsave(&lag_lock, flags);
ldev = mlx5_lag_dev(dev); ldev = mlx5_lag_dev(dev);
if (!ldev) if (!ldev)
goto unlock; goto unlock;
peer_dev = ldev->pf[MLX5_LAG_P1].dev == dev ? if (*i == ldev->ports)
ldev->pf[MLX5_LAG_P2].dev : goto unlock;
ldev->pf[MLX5_LAG_P1].dev; for (idx = *i; idx < ldev->ports; idx++)
if (ldev->pf[idx].dev != dev)
break;
if (idx == ldev->ports) {
*i = idx;
goto unlock;
}
*i = idx + 1;
peer_dev = ldev->pf[idx].dev;
unlock: unlock:
spin_unlock_irqrestore(&lag_lock, flags); spin_unlock_irqrestore(&lag_lock, flags);
return peer_dev; return peer_dev;
} }
EXPORT_SYMBOL(mlx5_lag_get_peer_mdev); EXPORT_SYMBOL(mlx5_lag_get_next_peer_mdev);
int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
u64 *values, u64 *values,
......
...@@ -111,7 +111,6 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, ...@@ -111,7 +111,6 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
bool shared_fdb); bool shared_fdb);
int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
struct net_device *ndev); struct net_device *ndev);
bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev);
char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags); char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags);
void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports, void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
......
...@@ -14,6 +14,7 @@ static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev) ...@@ -14,6 +14,7 @@ static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev)
return ldev->mode == MLX5_LAG_MODE_MULTIPATH; return ldev->mode == MLX5_LAG_MODE_MULTIPATH;
} }
#define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2
static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
{ {
if (!mlx5_lag_is_ready(ldev)) if (!mlx5_lag_is_ready(ldev))
...@@ -22,6 +23,9 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) ...@@ -22,6 +23,9 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev)) if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev))
return false; return false;
if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS)
return false;
return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev, return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev,
ldev->pf[MLX5_LAG_P2].dev); ldev->pf[MLX5_LAG_P2].dev);
} }
......
...@@ -65,6 +65,7 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev) ...@@ -65,6 +65,7 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev)
return err; return err;
} }
#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 2
static int enable_mpesw(struct mlx5_lag *ldev) static int enable_mpesw(struct mlx5_lag *ldev)
{ {
struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
...@@ -74,6 +75,9 @@ static int enable_mpesw(struct mlx5_lag *ldev) ...@@ -74,6 +75,9 @@ static int enable_mpesw(struct mlx5_lag *ldev)
if (ldev->mode != MLX5_LAG_MODE_NONE) if (ldev->mode != MLX5_LAG_MODE_NONE)
return -EINVAL; return -EINVAL;
if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS)
return -EOPNOTSUPP;
if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS || if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS ||
!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) || !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) ||
!MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) || !MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) ||
......
...@@ -75,13 +75,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) ...@@ -75,13 +75,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev)
if (!mlx5_core_is_pf(dev)) if (!mlx5_core_is_pf(dev))
return NULL; return NULL;
if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED) if (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_DEVCOM_PORTS_SUPPORTED)
return NULL; return NULL;
mlx5_dev_list_lock(); mlx5_dev_list_lock();
sguid0 = mlx5_query_nic_system_image_guid(dev); sguid0 = mlx5_query_nic_system_image_guid(dev);
list_for_each_entry(iter, &devcom_list, list) { list_for_each_entry(iter, &devcom_list, list) {
struct mlx5_core_dev *tmp_dev = NULL; /* There is at least one device in iter */
struct mlx5_core_dev *tmp_dev;
idx = -1; idx = -1;
for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) { for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <linux/mlx5/driver.h> #include <linux/mlx5/driver.h>
#define MLX5_DEVCOM_PORTS_SUPPORTED 2 #define MLX5_DEVCOM_PORTS_SUPPORTED 4
enum mlx5_devcom_components { enum mlx5_devcom_components {
MLX5_DEVCOM_ESW_OFFLOADS, MLX5_DEVCOM_ESW_OFFLOADS,
......
...@@ -1174,7 +1174,13 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, ...@@ -1174,7 +1174,13 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
u64 *values, u64 *values,
int num_counters, int num_counters,
size_t *offsets); size_t *offsets);
struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev); struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i);
#define mlx5_lag_for_each_peer_mdev(dev, peer, i) \
for (i = 0, peer = mlx5_lag_get_next_peer_mdev(dev, &i); \
peer; \
peer = mlx5_lag_get_next_peer_mdev(dev, &i))
u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev); u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev);
struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev); struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev);
void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up); void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up);
......
...@@ -1755,7 +1755,9 @@ struct mlx5_ifc_cmd_hca_cap_bits { ...@@ -1755,7 +1755,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_at_328[0x2]; u8 reserved_at_328[0x2];
u8 relaxed_ordering_read[0x1]; u8 relaxed_ordering_read[0x1];
u8 log_max_pd[0x5]; u8 log_max_pd[0x5];
u8 reserved_at_330[0x9]; u8 reserved_at_330[0x7];
u8 vnic_env_cnt_steering_fail[0x1];
u8 reserved_at_338[0x1];
u8 q_counter_aggregation[0x1]; u8 q_counter_aggregation[0x1];
u8 q_counter_other_vport[0x1]; u8 q_counter_other_vport[0x1];
u8 log_max_xrcd[0x5]; u8 log_max_xrcd[0x5];
...@@ -3673,7 +3675,13 @@ struct mlx5_ifc_vnic_diagnostic_statistics_bits { ...@@ -3673,7 +3675,13 @@ struct mlx5_ifc_vnic_diagnostic_statistics_bits {
u8 eth_wqe_too_small[0x20]; u8 eth_wqe_too_small[0x20];
u8 reserved_at_220[0xdc0]; u8 reserved_at_220[0xc0];
u8 generated_pkt_steering_fail[0x40];
u8 handled_pkt_steering_fail[0x40];
u8 reserved_at_360[0xc80];
}; };
struct mlx5_ifc_traffic_counter_bits { struct mlx5_ifc_traffic_counter_bits {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment