Commit 315702e0 authored by Petr Machata's avatar Petr Machata Committed by Jakub Kicinski

mlxsw: spectrum_fid: Add hooks for RSP table maintenance

In the CFF flood mode, the driver has to allocate a table within PGT, which
holds flood vectors for router subport FIDs. For LAGs, these flood vectors
have to obviously be maintained dynamically as port membership in a LAG
changes. But even for physical ports, the flood vectors have to be kept
valid, and may not contain enabled bits corresponding to non-existent
ports. It is therefore not possible to precompute the port part of the RSP
table, it has to be maintained as ports come and go due to splits.

To support the RSP table maintenance, add to FID ops two new ops:
fid_port_init and fid_port_fini, for when a port comes to existence, or
joins a lag, and vice versa. Invoke these ops from
mlxsw_sp_port_fids_init() and mlxsw_sp_port_fids_fini(), which are called
when port is added and removed, respectively. Also add two new hooks for
LAG maintenance, mlxsw_sp_fid_port_join_lag() / _leave_lag() which
transitively call into the same ops.

Later patches will actually add the op implementations themselves, this
just adds the scaffolding.
Signed-off-by: default avatarPetr Machata <petrm@nvidia.com>
Reviewed-by: default avatarAmit Cohen <amcohen@nvidia.com>
Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
Link: https://lore.kernel.org/r/234398a23540317abb25f74f920a5c8121faecf0.1701183892.git.petrm@nvidia.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a59316ff
......@@ -4515,6 +4515,10 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port->lagged = 1;
lag->ref_count++;
err = mlxsw_sp_fid_port_join_lag(mlxsw_sp_port);
if (err)
goto err_fid_port_join_lag;
/* Port is no longer usable as a router interface */
if (mlxsw_sp_port->default_vlan->fid)
mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
......@@ -4534,6 +4538,8 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
err_replay:
mlxsw_sp_router_port_leave_lag(mlxsw_sp_port, lag_dev);
err_router_join:
mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port);
err_fid_port_join_lag:
lag->ref_count--;
mlxsw_sp_port->lagged = 0;
mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
......@@ -4569,6 +4575,8 @@ static void mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
*/
mlxsw_sp_port_lag_uppers_cleanup(mlxsw_sp_port, lag_dev);
mlxsw_sp_fid_port_leave_lag(mlxsw_sp_port);
if (lag->ref_count == 1)
mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
......
......@@ -1328,6 +1328,8 @@ struct mlxsw_sp_fid *mlxsw_sp_fid_dummy_get(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_fid_put(struct mlxsw_sp_fid *fid);
int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port);
void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port);
int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port);
void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port);
extern const struct mlxsw_sp_fid_core_ops mlxsw_sp1_fid_core_ops;
extern const struct mlxsw_sp_fid_core_ops mlxsw_sp2_fid_core_ops;
......
......@@ -103,6 +103,14 @@ struct mlxsw_sp_fid_ops {
const struct mlxsw_sp_flood_table *flood_table);
void (*fid_pack)(char *sfmr_pl, const struct mlxsw_sp_fid *fid,
enum mlxsw_reg_sfmr_op op);
/* These are specific to RFID families and we assume are only
* implemented by RFID families, if at all.
*/
int (*fid_port_init)(const struct mlxsw_sp_fid_family *fid_family,
const struct mlxsw_sp_port *mlxsw_sp_port);
void (*fid_port_fini)(const struct mlxsw_sp_fid_family *fid_family,
const struct mlxsw_sp_port *mlxsw_sp_port);
};
struct mlxsw_sp_fid_family {
......@@ -1836,9 +1844,34 @@ mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
kfree(fid_family);
}
static int mlxsw_sp_fid_port_init(const struct mlxsw_sp_port *mlxsw_sp_port)
{
const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_fid_family *rfid_family;
rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
if (rfid_family->ops->fid_port_init)
return rfid_family->ops->fid_port_init(rfid_family,
mlxsw_sp_port);
return 0;
}
static void mlxsw_sp_fid_port_fini(const struct mlxsw_sp_port *mlxsw_sp_port)
{
const enum mlxsw_sp_fid_type type_rfid = MLXSW_SP_FID_TYPE_RFID;
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_fid_family *rfid_family;
rfid_family = mlxsw_sp->fid_core->fid_family_arr[type_rfid];
if (rfid_family->ops->fid_port_fini)
rfid_family->ops->fid_port_fini(rfid_family, mlxsw_sp_port);
}
int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
int err;
/* Track number of FIDs configured on the port with mapping type
* PORT_VID_TO_FID, so that we know when to transition the port
......@@ -1846,16 +1879,39 @@ int mlxsw_sp_port_fids_init(struct mlxsw_sp_port *mlxsw_sp_port)
*/
mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
return mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
err = mlxsw_sp_fid_port_init(mlxsw_sp_port);
if (err)
return err;
err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false);
if (err)
goto err_vp_mode_set;
return 0;
err_vp_mode_set:
mlxsw_sp_fid_port_fini(mlxsw_sp_port);
return err;
}
void mlxsw_sp_port_fids_fini(struct mlxsw_sp_port *mlxsw_sp_port)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
mlxsw_sp_fid_port_fini(mlxsw_sp_port);
mlxsw_sp->fid_core->port_fid_mappings[mlxsw_sp_port->local_port] = 0;
}
int mlxsw_sp_fid_port_join_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
{
return mlxsw_sp_fid_port_init(mlxsw_sp_port);
}
void mlxsw_sp_fid_port_leave_lag(const struct mlxsw_sp_port *mlxsw_sp_port)
{
mlxsw_sp_fid_port_fini(mlxsw_sp_port);
}
static int
mlxsw_sp_fids_init(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_fid_family *fid_family_arr[])
......
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