Skip to content

Commit 72a4ced

Browse files
pmachatakuba-moo
authored andcommitted
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 <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Link: https://lore.kernel.org/r/962deb4367585d38250e80c685a34735c0c7f3ad.1701183892.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent db3e541 commit 72a4ced

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c

+231
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/refcount.h>
1212

1313
#include "spectrum.h"
14+
#include "spectrum_router.h"
1415
#include "reg.h"
1516

1617
struct mlxsw_sp_fid_family;
@@ -115,6 +116,7 @@ struct mlxsw_sp_fid_ops {
115116

116117
enum mlxsw_sp_fid_flood_profile_id {
117118
MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE = 1,
119+
MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
118120
};
119121

120122
struct mlxsw_sp_fid_flood_profile {
@@ -368,6 +370,36 @@ mlxsw_sp_fid_8021d_pgt_size(const struct mlxsw_sp_fid_family *fid_family,
368370
return 0;
369371
}
370372

373+
static unsigned int mlxsw_sp_fid_rfid_port_offset_cff(unsigned int local_port)
374+
{
375+
/* Port 0 is the CPU port. Since we never create RIFs based off that
376+
* port, we don't need to count it.
377+
*/
378+
return WARN_ON_ONCE(!local_port) ? 0 : local_port - 1;
379+
}
380+
381+
static int
382+
mlxsw_sp_fid_rfid_pgt_size_cff(const struct mlxsw_sp_fid_family *fid_family,
383+
u16 *p_pgt_size)
384+
{
385+
struct mlxsw_core *core = fid_family->mlxsw_sp->core;
386+
unsigned int max_ports;
387+
u16 pgt_size;
388+
u16 max_lags;
389+
int err;
390+
391+
max_ports = mlxsw_core_max_ports(core);
392+
393+
err = mlxsw_core_max_lag(core, &max_lags);
394+
if (err)
395+
return err;
396+
397+
pgt_size = (mlxsw_sp_fid_rfid_port_offset_cff(max_ports) + max_lags) *
398+
fid_family->flood_profile->nr_flood_tables;
399+
*p_pgt_size = pgt_size;
400+
return 0;
401+
}
402+
371403
static u16
372404
mlxsw_sp_fid_pgt_base_ctl(const struct mlxsw_sp_fid_family *fid_family,
373405
const struct mlxsw_sp_flood_table *flood_table)
@@ -519,6 +551,18 @@ static void mlxsw_sp_fid_fid_pack_cff(char *sfmr_pl,
519551
fid_family->flood_profile->profile_id);
520552
}
521553

554+
static u16 mlxsw_sp_fid_rfid_fid_offset_cff(struct mlxsw_sp *mlxsw_sp,
555+
u16 port_lag_id, bool is_lag)
556+
{
557+
u16 max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
558+
559+
if (is_lag)
560+
return mlxsw_sp_fid_rfid_port_offset_cff(max_ports) +
561+
port_lag_id;
562+
else
563+
return mlxsw_sp_fid_rfid_port_offset_cff(port_lag_id);
564+
}
565+
522566
static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
523567
{
524568
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 = {
12481292
.profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_BRIDGE,
12491293
};
12501294

1295+
static const struct mlxsw_sp_flood_table mlxsw_sp_fid_rsp_flood_tables_cff[] = {
1296+
{
1297+
.packet_type = MLXSW_SP_FLOOD_TYPE_UC,
1298+
.table_index = 0,
1299+
},
1300+
{
1301+
.packet_type = MLXSW_SP_FLOOD_TYPE_NOT_UC,
1302+
.table_index = 1,
1303+
},
1304+
};
1305+
1306+
static const
1307+
struct mlxsw_sp_fid_flood_profile mlxsw_sp_fid_rsp_flood_profile_cff = {
1308+
.flood_tables = mlxsw_sp_fid_rsp_flood_tables_cff,
1309+
.nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_rsp_flood_tables_cff),
1310+
.profile_id = MLXSW_SP_FID_FLOOD_PROFILE_ID_RSP,
1311+
};
1312+
12511313
static bool
12521314
mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg)
12531315
{
@@ -1271,6 +1333,29 @@ static int mlxsw_sp_fid_rfid_setup_ctl(struct mlxsw_sp_fid *fid,
12711333
return 0;
12721334
}
12731335

1336+
static int mlxsw_sp_fid_rfid_setup_cff(struct mlxsw_sp_fid *fid,
1337+
const void *arg)
1338+
{
1339+
struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
1340+
u16 rif_index = *(const u16 *)arg;
1341+
struct mlxsw_sp_rif *rif;
1342+
bool is_lag;
1343+
u16 port;
1344+
int err;
1345+
1346+
rif = mlxsw_sp_rif_by_index(mlxsw_sp, rif_index);
1347+
if (!rif)
1348+
return -ENOENT;
1349+
1350+
err = mlxsw_sp_rif_subport_port(rif, &port, &is_lag);
1351+
if (err)
1352+
return err;
1353+
1354+
fid->fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1355+
is_lag);
1356+
return 0;
1357+
}
1358+
12741359
static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
12751360
{
12761361
return mlxsw_sp_fid_op(fid, true);
@@ -1410,6 +1495,139 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_ctl = {
14101495
.fid_pack = mlxsw_sp_fid_pack_ctl,
14111496
};
14121497

1498+
static int
1499+
mlxsw_sp_fid_rfid_port_add_cff(struct mlxsw_sp *mlxsw_sp,
1500+
const struct mlxsw_sp_flood_table *flood_table,
1501+
u16 pgt_addr, u16 smpe, unsigned int local_port)
1502+
{
1503+
int err;
1504+
1505+
err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1506+
local_port, true);
1507+
if (err)
1508+
return err;
1509+
1510+
if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1511+
u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1512+
1513+
err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1514+
router_port, true);
1515+
if (err)
1516+
goto err_entry_port_set;
1517+
}
1518+
1519+
return 0;
1520+
1521+
err_entry_port_set:
1522+
mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1523+
false);
1524+
return err;
1525+
}
1526+
1527+
static void
1528+
mlxsw_sp_fid_rfid_port_del_cff(struct mlxsw_sp *mlxsw_sp,
1529+
const struct mlxsw_sp_flood_table *flood_table,
1530+
u16 pgt_addr, u16 smpe, u16 local_port)
1531+
{
1532+
if (flood_table->packet_type == MLXSW_SP_FLOOD_TYPE_NOT_UC) {
1533+
u16 router_port = mlxsw_sp_router_port(mlxsw_sp);
1534+
1535+
mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe,
1536+
router_port, false);
1537+
}
1538+
mlxsw_sp_pgt_entry_port_set(mlxsw_sp, pgt_addr, smpe, local_port,
1539+
false);
1540+
}
1541+
1542+
static int
1543+
mlxsw_sp_fid_rfid_port_memb_ft_cff(const struct mlxsw_sp_fid_family *fid_family,
1544+
const struct mlxsw_sp_flood_table *flood_table,
1545+
const struct mlxsw_sp_port *mlxsw_sp_port,
1546+
bool member)
1547+
{
1548+
struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
1549+
u16 local_port = mlxsw_sp_port->local_port;
1550+
u16 fid_pgt_base;
1551+
u16 fid_offset;
1552+
u16 pgt_addr;
1553+
u16 smpe;
1554+
u16 port;
1555+
1556+
/* In-PGT SMPE is only valid on Spectrum-1, CFF only on Spectrum>1. */
1557+
smpe = 0;
1558+
1559+
port = mlxsw_sp_port->lagged ? mlxsw_sp_port->lag_id : local_port;
1560+
fid_offset = mlxsw_sp_fid_rfid_fid_offset_cff(mlxsw_sp, port,
1561+
mlxsw_sp_port->lagged);
1562+
fid_pgt_base = mlxsw_sp_fid_off_pgt_base_cff(fid_family, fid_offset);
1563+
pgt_addr = fid_pgt_base + flood_table->table_index;
1564+
1565+
if (member)
1566+
return mlxsw_sp_fid_rfid_port_add_cff(mlxsw_sp, flood_table,
1567+
pgt_addr, smpe,
1568+
local_port);
1569+
1570+
mlxsw_sp_fid_rfid_port_del_cff(mlxsw_sp, flood_table, pgt_addr, smpe,
1571+
local_port);
1572+
return 0;
1573+
}
1574+
1575+
static int
1576+
mlxsw_sp_fid_rfid_port_memb_cff(const struct mlxsw_sp_fid_family *fid_family,
1577+
const struct mlxsw_sp_port *mlxsw_sp_port,
1578+
bool member)
1579+
{
1580+
int i;
1581+
1582+
for (i = 0; i < fid_family->flood_profile->nr_flood_tables; i++) {
1583+
const struct mlxsw_sp_flood_table *flood_table =
1584+
&fid_family->flood_profile->flood_tables[i];
1585+
int err;
1586+
1587+
err = mlxsw_sp_fid_rfid_port_memb_ft_cff(fid_family,
1588+
flood_table,
1589+
mlxsw_sp_port, member);
1590+
if (err)
1591+
return err;
1592+
}
1593+
1594+
return 0;
1595+
}
1596+
1597+
static int
1598+
mlxsw_sp_fid_rfid_port_init_cff(const struct mlxsw_sp_fid_family *fid_family,
1599+
const struct mlxsw_sp_port *mlxsw_sp_port)
1600+
{
1601+
return mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, true);
1602+
}
1603+
1604+
static void
1605+
mlxsw_sp_fid_rfid_port_fini_cff(const struct mlxsw_sp_fid_family *fid_family,
1606+
const struct mlxsw_sp_port *mlxsw_sp_port)
1607+
{
1608+
mlxsw_sp_fid_rfid_port_memb_cff(fid_family, mlxsw_sp_port, false);
1609+
}
1610+
1611+
static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops_cff = {
1612+
.setup = mlxsw_sp_fid_rfid_setup_cff,
1613+
.configure = mlxsw_sp_fid_rfid_configure,
1614+
.deconfigure = mlxsw_sp_fid_rfid_deconfigure,
1615+
.index_alloc = mlxsw_sp_fid_rfid_index_alloc,
1616+
.compare = mlxsw_sp_fid_rfid_compare,
1617+
.port_vid_map = mlxsw_sp_fid_rfid_port_vid_map,
1618+
.port_vid_unmap = mlxsw_sp_fid_rfid_port_vid_unmap,
1619+
.vni_set = mlxsw_sp_fid_rfid_vni_set,
1620+
.vni_clear = mlxsw_sp_fid_rfid_vni_clear,
1621+
.nve_flood_index_set = mlxsw_sp_fid_rfid_nve_flood_index_set,
1622+
.nve_flood_index_clear = mlxsw_sp_fid_rfid_nve_flood_index_clear,
1623+
.vid_to_fid_rif_update = mlxsw_sp_fid_rfid_vid_to_fid_rif_update,
1624+
.pgt_size = mlxsw_sp_fid_rfid_pgt_size_cff,
1625+
.fid_port_init = mlxsw_sp_fid_rfid_port_init_cff,
1626+
.fid_port_fini = mlxsw_sp_fid_rfid_port_fini_cff,
1627+
.fid_mid = mlxsw_sp_fid_fid_mid_cff,
1628+
.fid_pack = mlxsw_sp_fid_fid_pack_cff,
1629+
};
1630+
14131631
static int mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
14141632
{
14151633
fid->fid_offset = 0;
@@ -1726,10 +1944,22 @@ static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family_cff = {
17261944
.smpe_index_valid = true,
17271945
};
17281946

1947+
static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family_cff = {
1948+
.type = MLXSW_SP_FID_TYPE_RFID,
1949+
.fid_size = sizeof(struct mlxsw_sp_fid),
1950+
.start_index = MLXSW_SP_RFID_START,
1951+
.end_index = MLXSW_SP_RFID_END,
1952+
.flood_profile = &mlxsw_sp_fid_rsp_flood_profile_cff,
1953+
.rif_type = MLXSW_SP_RIF_TYPE_SUBPORT,
1954+
.ops = &mlxsw_sp_fid_rfid_ops_cff,
1955+
.smpe_index_valid = false,
1956+
};
1957+
17291958
static const struct mlxsw_sp_fid_family *mlxsw_sp2_fid_family_arr_cff[] = {
17301959
[MLXSW_SP_FID_TYPE_8021Q] = &mlxsw_sp2_fid_8021q_family_cff,
17311960
[MLXSW_SP_FID_TYPE_8021D] = &mlxsw_sp2_fid_8021d_family_cff,
17321961
[MLXSW_SP_FID_TYPE_DUMMY] = &mlxsw_sp2_fid_dummy_family,
1962+
[MLXSW_SP_FID_TYPE_RFID] = &mlxsw_sp_fid_rfid_family_cff,
17331963
};
17341964

17351965
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,
21802410
static const
21812411
struct mlxsw_sp_fid_flood_profile *mlxsw_sp_fid_flood_profiles[] = {
21822412
&mlxsw_sp_fid_8021d_flood_profile,
2413+
&mlxsw_sp_fid_rsp_flood_profile_cff,
21832414
};
21842415

21852416
static int

0 commit comments

Comments
 (0)