Commit 72a4cedb authored by Petr Machata's avatar Petr Machata Committed by Jakub Kicinski

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: default avatarPetr Machata <petrm@nvidia.com>
Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
Link: https://lore.kernel.org/r/962deb4367585d38250e80c685a34735c0c7f3ad.1701183892.git.petrm@nvidia.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent db3e541b
......@@ -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
......
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