[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <962deb4367585d38250e80c685a34735c0c7f3ad.1701183892.git.petrm@nvidia.com>
Date: Tue, 28 Nov 2023 16:50:49 +0100
From: Petr Machata <petrm@...dia.com>
To: "David S. Miller" <davem@...emloft.net>, Eric Dumazet
<edumazet@...gle.com>, Jakub Kicinski <kuba@...nel.org>, Paolo Abeni
<pabeni@...hat.com>, <netdev@...r.kernel.org>
CC: Ido Schimmel <idosch@...dia.com>, Petr Machata <petrm@...dia.com>, "Amit
Cohen" <amcohen@...dia.com>, <mlxsw@...dia.com>
Subject: [PATCH net-next 16/17] mlxsw: spectrum_fid: Add support for rFID family in CFF flood mode
In this patch, add the artifacts for the rFID family that works in CFF
flood mode.
The same that was said about PGT organization and lookup in bridge FID
families applies for the rFID family as well. The main difference lies in
the fact that in the controlled flood mode, the FW was taking care of
maintaining the PGT tables for rFIDs. In CFF mode, the responsibility
shifts to the driver.
All rFIDs are based off either a front panel port, or a LAG port. For those
based off ports, we need to maintain at worst one PGT block for each port,
for those based off LAGs, one PGT block per LAG. This reflects in the
pgt_size callback, which determines the PGT footprint based on number of
ports and the LAG capacity.
A number of FIDs may end up using the same PGT base. Unlike with bridges,
where membership of a port in a given FID is highly dynamic, an rFID based
of a port will just always need to flood to that port.
Both the port and the LAG subtables need to be actively maintained. To that
end, the CFF rFID family implements fid_port_init and fid_port_fini
callbacks, which toggle the necessary bits.
Both FID-MID translation and SFMR packing then point into either the port
or the LAG subtable, to the block that corresponds to a given port or a
given LAG, depending on what port the RIF bound to the rFID uses.
As in the previous patch, the way CFF flood mode organizes PGT accesses
allows for much more smarts and dynamism. As in the previous patch, we
rather aim to keep things simple and static.
Signed-off-by: Petr Machata <petrm@...dia.com>
Reviewed-by: Ido Schimmel <idosch@...dia.com>
---
.../ethernet/mellanox/mlxsw/spectrum_fid.c | 231 ++++++++++++++++++
1 file changed, 231 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index 696a7ed30709..401117086235 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -11,6 +11,7 @@
#include <linux/refcount.h>
#include "spectrum.h"
+#include "spectrum_router.h"
#include "reg.h"
struct mlxsw_sp_fid_family;
@@ -115,6 +116,7 @@ struct mlxsw_sp_fid_ops {
enum mlxsw_sp_fid_flood_profile_id {
MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1,
+ MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
};
struct mlxsw_sp_fid_flood_profile {
@@ -368,6 +370,36 @@ mlxsw_sp_fid_8021d_pgt_size(const struct mlxsw_sp_fid_family *fid_family,
return 0;
}
+static unsigned int mlxsw_sp_fid_rfid_port_offset_cff(unsigned int local_port)
+{
+ /* Port 0 is the CPU port. Since we never create RIFs based off that
+ * port, we don't need to count it.
+ */
+ return WARN_ON_ONCE(!local_port) ? 0 : local_port - 1;
+}
+
+static int
+mlxsw_sp_fid_rfid_pgt_size_cff(const struct mlxsw_sp_fid_family *fid_family,
+ u16 *p_pgt_size)
+{
+ struct mlxsw_core *core = fid_family->mlxsw_sp->core;
+ unsigned int max_ports;
+ u16 pgt_size;
+ u16 max_lags;
+ int err;
+
+ max_ports = mlxsw_core_max_ports(core);
+
+ err = mlxsw_core_max_lag(core, &max_lags);
+ if (err)
+ return err;
+
+ pgt_size = (mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + max_lags) *
+ fid_family->flood_profile->nr_flood_tables;
+ *p_pgt_size = pgt_size;
+ return 0;
+}
+
static u16
mlxsw_sp_fid_pgt_base_ctl(const struct mlxsw_sp_fid_family *fid_family,
const struct mlxsw_sp_flood_table *flood_table)
@@ -519,6 +551,18 @@ static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl,
fid_family->flood_profile->profile_id);
}
+static u16 mlxsw_sp_fid_rfid_fid_offset_cff(struct mlxsw_sp *mlxsw_sp,
+ u16 port_lag_id, bool is_lag)
+{
+ u16 max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
+
+ if (is_lag)
+ return mlxsw_sp_fid_rfid_port_offset_cff(max_ports) +
+ port_lag_id;
+ else
+ return mlxsw_sp_fid_rfid_port_offset_cff(port_lag_id);
+}
+
static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
{
struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
@@ -1248,6 +1292,24 @@ struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_8021d_flood_profile = {
.profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE,
};
+static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = {
+ {
+ .packet_type = MLXSW_SP_FLOOD_TYPE_UC,
+ .table_index = 0,
+ },
+ {
+ .packet_type = MLXSW_SP_FLOOD_TYPE_NOT_UC,
+ .table_index = 1,
+ },
+};
+
+static const
+struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = {
+ .flood_tables = mlxsw_sp_fid_rsp_flood_tables_cff,
+ .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff),
+ .profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
+};
+
static bool
mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
{
@@ -1271,6 +1333,29 @@ static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid,
return 0;
}
+static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid,
+ const void *arg)
+{
+ struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
+ u16 rif_index = *(const u16 *)arg;
+ struct mlxsw_sp_rif *rif;
+ bool is_lag;
+ u16 port;
+ int err;
+
+ rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index);
+ if (!rif)
+ return -ENOENT;
+
+ err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag);
+ if (err)
+ return err;
+
+ fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
+ is_lag);
+ return 0;
+}
+
static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
{
return mlxsw_sp_fid_op(fid, true);
@@ -1410,6 +1495,139 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = {
.fid_pack = mlxsw_sp_fid_pack_ctl,
};
+static int
+mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp,
+ const struct mlxsw_sp_flood_table *flood_table,
+ u16 pgt_addr, u16 smpe, unsigned int local_port)
+{
+ int err;
+
+ err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
+ local_port, true);
+ if (err)
+ return err;
+
+ if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
+ u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
+
+ err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
+ router_port, true);
+ if (err)
+ goto err_entry_port_set;
+ }
+
+ return 0;
+
+err_entry_port_set:
+ mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
+ false);
+ return err;
+}
+
+static void
+mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp,
+ const struct mlxsw_sp_flood_table *flood_table,
+ u16 pgt_addr, u16 smpe, u16 local_port)
+{
+ if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
+ u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
+
+ mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
+ router_port, false);
+ }
+ mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
+ false);
+}
+
+static int
+mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family,
+ const struct mlxsw_sp_flood_table *flood_table,
+ const struct mlxsw_sp_port *mlxsw_sp_port,
+ bool member)
+{
+ struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
+ u16 local_port = mlxsw_sp_port->local_port;
+ u16 fid_pgt_base;
+ u16 fid_offset;
+ u16 pgt_addr;
+ u16 smpe;
+ u16 port;
+
+ /* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */
+ smpe = 0;
+
+ port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port;
+ fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
+ mlxsw_sp_port->lagged);
+ fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset);
+ pgt_addr = fid_pgt_base + flood_table->table_index;
+
+ if (member)
+ return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table,
+ pgt_addr, smpe,
+ local_port);
+
+ mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe,
+ local_port);
+ return 0;
+}
+
+static int
+mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family,
+ const struct mlxsw_sp_port *mlxsw_sp_port,
+ bool member)
+{
+ int i;
+
+ for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
+ const struct mlxsw_sp_flood_table *flood_table =
+ &fid_family->flood_profile->flood_tables[i];
+ int err;
+
+ err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family,
+ flood_table,
+ mlxsw_sp_port, member);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int
+mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family,
+ const struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true);
+}
+
+static void
+mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family,
+ const struct mlxsw_sp_port *mlxsw_sp_port)
+{
+ mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false);
+}
+
+static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = {
+ .setup = mlxsw_sp_fid_rfid_setup_cff,
+ .configure = mlxsw_sp_fid_rfid_configure,
+ .deconfigure = mlxsw_sp_fid_rfid_deconfigure,
+ .index_alloc = mlxsw_sp_fid_rfid_index_alloc,
+ .compare = mlxsw_sp_fid_rfid_compare,
+ .port_vid_map = mlxsw_sp_fid_rfid_port_vid_map,
+ .port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap,
+ .vni_set = mlxsw_sp_fid_rfid_vni_set,
+ .vni_clear = mlxsw_sp_fid_rfid_vni_clear,
+ .nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set,
+ .nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear,
+ .vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
+ .pgt_size = mlxsw_sp_fid_rfid_pgt_size_cff,
+ .fid_port_init = mlxsw_sp_fid_rfid_port_init_cff,
+ .fid_port_fini = mlxsw_sp_fid_rfid_port_fini_cff,
+ .fid_mid = mlxsw_sp_fid_fid_mid_cff,
+ .fid_pack = mlxsw_sp_fid_fid_pack_cff,
+};
+
static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
{
fid->fid_offset = 0;
@@ -1726,10 +1944,22 @@ static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = {
.smpe_index_valid = true,
};
+static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = {
+ .type = MLXSW_SP_FID_TYPE_RFID,
+ .fid_size = sizeof(struct mlxsw_sp_fid),
+ .start_index = MLXSW_SP_RFID_START,
+ .end_index = MLXSW_SP_RFID_END,
+ .flood_profile = &mlxsw_sp_fid_rsp_flood_profile_cff,
+ .rif_type = MLXSW_SP_RIF_TYPE_SUBPORT,
+ .ops = &mlxsw_sp_fid_rfid_ops_cff,
+ .smpe_index_valid = false,
+};
+
static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = {
[MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_cff,
[MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_cff,
[MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family,
+ [MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_cff,
};
static struct mlxsw_sp_fid *mlxsw_sp_fid_lookup(struct mlxsw_sp *mlxsw_sp,
@@ -2180,6 +2410,7 @@ mlxsw_sp2_fids_init_flood_profile(struct mlxsw_sp *mlxsw_sp,
static const
struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = {
&mlxsw_sp_fid_8021d_flood_profile,
+ &mlxsw_sp_fid_rsp_flood_profile_cff,
};
static int
--
2.41.0
Powered by blists - more mailing lists