Merge branch 'mlxsw-unified-bridge-conversion-part-2'
Ido Schimmel says:
====================
mlxsw: Unified bridge conversion - part 2/6
This is the second part of the conversion of mlxsw to the unified bridge
model. Part 1 was merged in commit 4336487e30
("Merge branch
'mlxsw-unified-bridge-conversion-part-1'") which includes details about
the new model and the motivation behind the conversion.
This patchset does not begin the conversion, but rather prepares the code
base for it.
Patchset overview:
Patch #1 removes an unnecessary field from one of the FID families.
Patches #2-#7 make various improvements in the layer 2 multicast code,
making it more receptive towards upcoming changes.
Patches #8-#10 prepare the CONFIG_PROFILE command for the unified bridge
model. This command will be used to enable the new model in the last
patchset.
Patches #11-#13 perform small changes in the FID code, preparing it for
upcoming changes.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ffd3018bf7
@ -713,16 +713,25 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_flood_tables, 0x30, 16, 4);
|
||||
*/
|
||||
MLXSW_ITEM32(cmd_mbox, config_profile, max_vid_flood_tables, 0x30, 8, 4);
|
||||
|
||||
enum mlxsw_cmd_mbox_config_profile_flood_mode {
|
||||
/* Mixed mode, where:
|
||||
* max_flood_tables indicates the number of single-entry tables.
|
||||
* max_vid_flood_tables indicates the number of per-VID tables.
|
||||
* max_fid_offset_flood_tables indicates the number of FID-offset
|
||||
* tables. max_fid_flood_tables indicates the number of per-FID tables.
|
||||
* Reserved when unified bridge model is used.
|
||||
*/
|
||||
MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_MIXED = 3,
|
||||
/* Controlled flood tables. Reserved when legacy bridge model is
|
||||
* used.
|
||||
*/
|
||||
MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED = 4,
|
||||
};
|
||||
|
||||
/* cmd_mbox_config_profile_flood_mode
|
||||
* Flooding mode to use.
|
||||
* 0-2 - Backward compatible modes for SwitchX devices.
|
||||
* 3 - Mixed mode, where:
|
||||
* max_flood_tables indicates the number of single-entry tables.
|
||||
* max_vid_flood_tables indicates the number of per-VID tables.
|
||||
* max_fid_offset_flood_tables indicates the number of FID-offset tables.
|
||||
* max_fid_flood_tables indicates the number of per-FID tables.
|
||||
*/
|
||||
MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 2);
|
||||
MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 3);
|
||||
|
||||
/* cmd_mbox_config_profile_max_fid_offset_flood_tables
|
||||
* Maximum number of FID-offset flooding tables.
|
||||
|
@ -1551,6 +1551,14 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
|
||||
if (err)
|
||||
goto err_config_profile;
|
||||
|
||||
/* Some resources depend on unified bridge model, which is configured
|
||||
* as part of config_profile. Query the resources again to get correct
|
||||
* values.
|
||||
*/
|
||||
err = mlxsw_core_resources_query(mlxsw_core, mbox, res);
|
||||
if (err)
|
||||
goto err_requery_resources;
|
||||
|
||||
err = mlxsw_pci_aqs_init(mlxsw_pci, mbox);
|
||||
if (err)
|
||||
goto err_aqs_init;
|
||||
@ -1568,6 +1576,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
|
||||
err_request_eq_irq:
|
||||
mlxsw_pci_aqs_fini(mlxsw_pci);
|
||||
err_aqs_init:
|
||||
err_requery_resources:
|
||||
err_config_profile:
|
||||
err_cqe_v_check:
|
||||
err_query_resources:
|
||||
|
@ -3376,7 +3376,7 @@ static const struct mlxsw_config_profile mlxsw_sp1_config_profile = {
|
||||
.max_mid = MLXSW_SP_MID_MAX,
|
||||
.used_flood_tables = 1,
|
||||
.used_flood_mode = 1,
|
||||
.flood_mode = 3,
|
||||
.flood_mode = MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_MIXED,
|
||||
.max_fid_flood_tables = 3,
|
||||
.fid_flood_table_size = MLXSW_SP_FID_FLOOD_TABLE_SIZE,
|
||||
.used_max_ib_mc = 1,
|
||||
@ -3400,7 +3400,7 @@ static const struct mlxsw_config_profile mlxsw_sp2_config_profile = {
|
||||
.max_mid = MLXSW_SP_MID_MAX,
|
||||
.used_flood_tables = 1,
|
||||
.used_flood_mode = 1,
|
||||
.flood_mode = 3,
|
||||
.flood_mode = MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_MIXED,
|
||||
.max_fid_flood_tables = 3,
|
||||
.fid_flood_table_size = MLXSW_SP_FID_FLOOD_TABLE_SIZE,
|
||||
.used_max_ib_mc = 1,
|
||||
|
@ -1237,7 +1237,6 @@ int mlxsw_sp_setup_tc_block_qevent_mark(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
|
||||
/* spectrum_fid.c */
|
||||
bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index);
|
||||
bool mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid *fid);
|
||||
struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
|
||||
u16 fid_index);
|
||||
int mlxsw_sp_fid_nve_ifindex(const struct mlxsw_sp_fid *fid, int *nve_ifindex);
|
||||
|
@ -27,6 +27,7 @@ struct mlxsw_sp_fid {
|
||||
struct mlxsw_sp_rif *rif;
|
||||
refcount_t ref_count;
|
||||
u16 fid_index;
|
||||
u16 fid_offset;
|
||||
struct mlxsw_sp_fid_family *fid_family;
|
||||
struct rhash_head ht_node;
|
||||
|
||||
@ -102,7 +103,6 @@ struct mlxsw_sp_fid_family {
|
||||
enum mlxsw_sp_rif_type rif_type;
|
||||
const struct mlxsw_sp_fid_ops *ops;
|
||||
struct mlxsw_sp *mlxsw_sp;
|
||||
u8 lag_vid_valid:1;
|
||||
};
|
||||
|
||||
static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
|
||||
@ -137,11 +137,6 @@ bool mlxsw_sp_fid_is_dummy(struct mlxsw_sp *mlxsw_sp, u16 fid_index)
|
||||
return fid_family->start_index == fid_index;
|
||||
}
|
||||
|
||||
bool mlxsw_sp_fid_lag_vid_valid(const struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
return fid->fid_family->lag_vid_valid;
|
||||
}
|
||||
|
||||
struct mlxsw_sp_fid *mlxsw_sp_fid_lookup_by_index(struct mlxsw_sp *mlxsw_sp,
|
||||
u16 fid_index)
|
||||
{
|
||||
@ -206,7 +201,7 @@ int mlxsw_sp_fid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
|
||||
const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!ops->nve_flood_index_set || fid->nve_flood_index_valid))
|
||||
if (WARN_ON(fid->nve_flood_index_valid))
|
||||
return -EINVAL;
|
||||
|
||||
err = ops->nve_flood_index_set(fid, nve_flood_index);
|
||||
@ -224,7 +219,7 @@ void mlxsw_sp_fid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
|
||||
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
|
||||
const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
|
||||
|
||||
if (WARN_ON(!ops->nve_flood_index_clear || !fid->nve_flood_index_valid))
|
||||
if (WARN_ON(!fid->nve_flood_index_valid))
|
||||
return;
|
||||
|
||||
fid->nve_flood_index_valid = false;
|
||||
@ -244,7 +239,7 @@ int mlxsw_sp_fid_vni_set(struct mlxsw_sp_fid *fid, enum mlxsw_sp_nve_type type,
|
||||
struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
|
||||
int err;
|
||||
|
||||
if (WARN_ON(!ops->vni_set || fid->vni_valid))
|
||||
if (WARN_ON(fid->vni_valid))
|
||||
return -EINVAL;
|
||||
|
||||
fid->nve_type = type;
|
||||
@ -276,7 +271,7 @@ void mlxsw_sp_fid_vni_clear(struct mlxsw_sp_fid *fid)
|
||||
const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
|
||||
struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
|
||||
|
||||
if (WARN_ON(!ops->vni_clear || !fid->vni_valid))
|
||||
if (WARN_ON(!fid->vni_valid))
|
||||
return;
|
||||
|
||||
fid->vni_valid = false;
|
||||
@ -405,6 +400,7 @@ static void mlxsw_sp_fid_8021q_setup(struct mlxsw_sp_fid *fid, const void *arg)
|
||||
u16 vid = *(u16 *) arg;
|
||||
|
||||
mlxsw_sp_fid_8021q_fid(fid)->vid = vid;
|
||||
fid->fid_offset = 0;
|
||||
}
|
||||
|
||||
static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
|
||||
@ -424,13 +420,13 @@ static int mlxsw_sp_fid_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_vni_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
|
||||
__be32 vni, bool vni_valid, u32 nve_flood_index,
|
||||
bool nve_flood_index_valid)
|
||||
u16 fid_offset, __be32 vni, bool vni_valid,
|
||||
u32 nve_flood_index, bool nve_flood_index_valid)
|
||||
{
|
||||
char sfmr_pl[MLXSW_REG_SFMR_LEN];
|
||||
|
||||
mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid_index,
|
||||
0);
|
||||
fid_offset);
|
||||
mlxsw_reg_sfmr_vv_set(sfmr_pl, vni_valid);
|
||||
mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(vni));
|
||||
mlxsw_reg_sfmr_vtfp_set(sfmr_pl, nve_flood_index_valid);
|
||||
@ -459,20 +455,23 @@ static void mlxsw_sp_fid_8021d_setup(struct mlxsw_sp_fid *fid, const void *arg)
|
||||
int br_ifindex = *(int *) arg;
|
||||
|
||||
mlxsw_sp_fid_8021d_fid(fid)->br_ifindex = br_ifindex;
|
||||
fid->fid_offset = 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_8021d_configure(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
|
||||
|
||||
return mlxsw_sp_fid_op(fid_family->mlxsw_sp, fid->fid_index, 0, true);
|
||||
return mlxsw_sp_fid_op(fid_family->mlxsw_sp, fid->fid_index,
|
||||
fid->fid_offset, true);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fid_8021d_deconfigure(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
if (fid->vni_valid)
|
||||
mlxsw_sp_nve_fid_disable(fid->fid_family->mlxsw_sp, fid);
|
||||
mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
|
||||
mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index,
|
||||
fid->fid_offset, false);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_8021d_index_alloc(struct mlxsw_sp_fid *fid,
|
||||
@ -614,8 +613,9 @@ static int mlxsw_sp_fid_8021d_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
|
||||
{
|
||||
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
|
||||
|
||||
return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, vni,
|
||||
true, fid->nve_flood_index,
|
||||
return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
|
||||
fid->fid_offset, vni, true,
|
||||
fid->nve_flood_index,
|
||||
fid->nve_flood_index_valid);
|
||||
}
|
||||
|
||||
@ -623,8 +623,9 @@ static void mlxsw_sp_fid_8021d_vni_clear(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
|
||||
|
||||
mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, 0, false,
|
||||
fid->nve_flood_index, fid->nve_flood_index_valid);
|
||||
mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
|
||||
fid->fid_offset, 0, false, fid->nve_flood_index,
|
||||
fid->nve_flood_index_valid);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid,
|
||||
@ -633,16 +634,17 @@ static int mlxsw_sp_fid_8021d_nve_flood_index_set(struct mlxsw_sp_fid *fid,
|
||||
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
|
||||
|
||||
return mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
|
||||
fid->vni, fid->vni_valid, nve_flood_index,
|
||||
true);
|
||||
fid->fid_offset, fid->vni, fid->vni_valid,
|
||||
nve_flood_index, true);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fid_8021d_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
struct mlxsw_sp_fid_family *fid_family = fid->fid_family;
|
||||
|
||||
mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index, fid->vni,
|
||||
fid->vni_valid, 0, false);
|
||||
mlxsw_sp_fid_vni_op(fid_family->mlxsw_sp, fid->fid_index,
|
||||
fid->fid_offset, fid->vni, fid->vni_valid, 0,
|
||||
false);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -699,7 +701,6 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
|
||||
.nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
|
||||
.rif_type = MLXSW_SP_RIF_TYPE_FID,
|
||||
.ops = &mlxsw_sp_fid_8021d_ops,
|
||||
.lag_vid_valid = 1,
|
||||
};
|
||||
|
||||
static bool
|
||||
@ -748,9 +749,13 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
|
||||
.nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
|
||||
.rif_type = MLXSW_SP_RIF_TYPE_VLAN,
|
||||
.ops = &mlxsw_sp_fid_8021q_emu_ops,
|
||||
.lag_vid_valid = 1,
|
||||
};
|
||||
|
||||
static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
|
||||
{
|
||||
fid->fid_offset = 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_rfid_configure(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
/* rFIDs are allocated by the device during init */
|
||||
@ -815,13 +820,39 @@ mlxsw_sp_fid_rfid_port_vid_unmap(struct mlxsw_sp_fid *fid,
|
||||
mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_rfid_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fid_rfid_vni_clear(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_rfid_nve_flood_index_set(struct mlxsw_sp_fid *fid,
|
||||
u32 nve_flood_index)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fid_rfid_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_rfid_ops = {
|
||||
.setup = mlxsw_sp_fid_rfid_setup,
|
||||
.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,
|
||||
};
|
||||
|
||||
#define MLXSW_SP_RFID_BASE (15 * 1024)
|
||||
@ -836,16 +867,22 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
|
||||
.ops = &mlxsw_sp_fid_rfid_ops,
|
||||
};
|
||||
|
||||
static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
|
||||
{
|
||||
fid->fid_offset = 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_dummy_configure(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
|
||||
|
||||
return mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, true);
|
||||
return mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, fid->fid_offset, true);
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fid_dummy_deconfigure(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index, 0, false);
|
||||
mlxsw_sp_fid_op(fid->fid_family->mlxsw_sp, fid->fid_index,
|
||||
fid->fid_offset, false);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_dummy_index_alloc(struct mlxsw_sp_fid *fid,
|
||||
@ -862,11 +899,37 @@ static bool mlxsw_sp_fid_dummy_compare(const struct mlxsw_sp_fid *fid,
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_dummy_vni_set(struct mlxsw_sp_fid *fid, __be32 vni)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fid_dummy_vni_clear(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
static int mlxsw_sp_fid_dummy_nve_flood_index_set(struct mlxsw_sp_fid *fid,
|
||||
u32 nve_flood_index)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void mlxsw_sp_fid_dummy_nve_flood_index_clear(struct mlxsw_sp_fid *fid)
|
||||
{
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
|
||||
.setup = mlxsw_sp_fid_dummy_setup,
|
||||
.configure = mlxsw_sp_fid_dummy_configure,
|
||||
.deconfigure = mlxsw_sp_fid_dummy_deconfigure,
|
||||
.index_alloc = mlxsw_sp_fid_dummy_index_alloc,
|
||||
.compare = mlxsw_sp_fid_dummy_compare,
|
||||
.vni_set = mlxsw_sp_fid_dummy_vni_set,
|
||||
.vni_clear = mlxsw_sp_fid_dummy_vni_clear,
|
||||
.nve_flood_index_set = mlxsw_sp_fid_dummy_nve_flood_index_set,
|
||||
.nve_flood_index_clear = mlxsw_sp_fid_dummy_nve_flood_index_clear,
|
||||
};
|
||||
|
||||
static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
|
||||
@ -927,8 +990,7 @@ static struct mlxsw_sp_fid *mlxsw_sp_fid_get(struct mlxsw_sp *mlxsw_sp,
|
||||
fid->fid_index = fid_index;
|
||||
__set_bit(fid_index - fid_family->start_index, fid_family->fids_bitmap);
|
||||
|
||||
if (fid->fid_family->ops->setup)
|
||||
fid->fid_family->ops->setup(fid, arg);
|
||||
fid->fid_family->ops->setup(fid, arg);
|
||||
|
||||
err = fid->fid_family->ops->configure(fid);
|
||||
if (err)
|
||||
|
@ -111,10 +111,10 @@ static void
|
||||
mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
struct mlxsw_sp_bridge_port *bridge_port);
|
||||
|
||||
static void
|
||||
mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
static int
|
||||
mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_bridge_device
|
||||
*bridge_device);
|
||||
*bridge_device, bool mc_enabled);
|
||||
|
||||
static void
|
||||
mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
@ -642,6 +642,64 @@ err_port_bridge_vlan_flood_set:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_bridge_vlans_flood_set(struct mlxsw_sp_bridge_vlan *bridge_vlan,
|
||||
enum mlxsw_sp_flood_type packet_type,
|
||||
bool member)
|
||||
{
|
||||
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(mlxsw_sp_port_vlan, &bridge_vlan->port_vlan_list,
|
||||
bridge_vlan_node) {
|
||||
u16 local_port = mlxsw_sp_port_vlan->mlxsw_sp_port->local_port;
|
||||
|
||||
err = mlxsw_sp_fid_flood_set(mlxsw_sp_port_vlan->fid,
|
||||
packet_type, local_port, member);
|
||||
if (err)
|
||||
goto err_fid_flood_set;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_fid_flood_set:
|
||||
list_for_each_entry_continue_reverse(mlxsw_sp_port_vlan,
|
||||
&bridge_vlan->port_vlan_list,
|
||||
list) {
|
||||
u16 local_port = mlxsw_sp_port_vlan->mlxsw_sp_port->local_port;
|
||||
|
||||
mlxsw_sp_fid_flood_set(mlxsw_sp_port_vlan->fid, packet_type,
|
||||
local_port, !member);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_bridge_ports_flood_table_set(struct mlxsw_sp_bridge_port *bridge_port,
|
||||
enum mlxsw_sp_flood_type packet_type,
|
||||
bool member)
|
||||
{
|
||||
struct mlxsw_sp_bridge_vlan *bridge_vlan;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(bridge_vlan, &bridge_port->vlans_list, list) {
|
||||
err = mlxsw_sp_bridge_vlans_flood_set(bridge_vlan, packet_type,
|
||||
member);
|
||||
if (err)
|
||||
goto err_bridge_vlans_flood_set;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_bridge_vlans_flood_set:
|
||||
list_for_each_entry_continue_reverse(bridge_vlan,
|
||||
&bridge_port->vlans_list, list)
|
||||
mlxsw_sp_bridge_vlans_flood_set(bridge_vlan, packet_type,
|
||||
!member);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_port_bridge_vlan_learning_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
struct mlxsw_sp_bridge_vlan *bridge_vlan,
|
||||
@ -842,6 +900,7 @@ static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
struct net_device *orig_dev,
|
||||
bool mc_disabled)
|
||||
{
|
||||
enum mlxsw_sp_flood_type packet_type = MLXSW_SP_FLOOD_TYPE_MC;
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
struct mlxsw_sp_bridge_device *bridge_device;
|
||||
struct mlxsw_sp_bridge_port *bridge_port;
|
||||
@ -854,26 +913,40 @@ static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
if (!bridge_device)
|
||||
return 0;
|
||||
|
||||
if (bridge_device->multicast_enabled != !mc_disabled) {
|
||||
bridge_device->multicast_enabled = !mc_disabled;
|
||||
mlxsw_sp_bridge_mdb_mc_enable_sync(mlxsw_sp_port,
|
||||
bridge_device);
|
||||
}
|
||||
|
||||
list_for_each_entry(bridge_port, &bridge_device->ports_list, list) {
|
||||
enum mlxsw_sp_flood_type packet_type = MLXSW_SP_FLOOD_TYPE_MC;
|
||||
bool member = mlxsw_sp_mc_flood(bridge_port);
|
||||
|
||||
err = mlxsw_sp_bridge_port_flood_table_set(mlxsw_sp_port,
|
||||
bridge_port,
|
||||
packet_type, member);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (bridge_device->multicast_enabled == !mc_disabled)
|
||||
return 0;
|
||||
|
||||
bridge_device->multicast_enabled = !mc_disabled;
|
||||
err = mlxsw_sp_bridge_mdb_mc_enable_sync(mlxsw_sp, bridge_device,
|
||||
!mc_disabled);
|
||||
if (err)
|
||||
goto err_mc_enable_sync;
|
||||
|
||||
list_for_each_entry(bridge_port, &bridge_device->ports_list, list) {
|
||||
bool member = mlxsw_sp_mc_flood(bridge_port);
|
||||
|
||||
err = mlxsw_sp_bridge_ports_flood_table_set(bridge_port,
|
||||
packet_type,
|
||||
member);
|
||||
if (err)
|
||||
goto err_flood_table_set;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_flood_table_set:
|
||||
list_for_each_entry_continue_reverse(bridge_port,
|
||||
&bridge_device->ports_list, list) {
|
||||
bool member = mlxsw_sp_mc_flood(bridge_port);
|
||||
|
||||
mlxsw_sp_bridge_ports_flood_table_set(bridge_port, packet_type,
|
||||
!member);
|
||||
}
|
||||
mlxsw_sp_bridge_mdb_mc_enable_sync(mlxsw_sp, bridge_device,
|
||||
mc_disabled);
|
||||
err_mc_enable_sync:
|
||||
bridge_device->multicast_enabled = mc_disabled;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_smid_router_port_set(struct mlxsw_sp *mlxsw_sp,
|
||||
@ -1677,7 +1750,7 @@ mlxsw_sp_mc_get_mrouters_bitmap(unsigned long *flood_bitmap,
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
static int
|
||||
mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_mid *mid,
|
||||
struct mlxsw_sp_bridge_device *bridge_device)
|
||||
@ -1690,12 +1763,12 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
|
||||
mid_idx = find_first_zero_bit(mlxsw_sp->bridge->mids_bitmap,
|
||||
MLXSW_SP_MID_MAX);
|
||||
if (mid_idx == MLXSW_SP_MID_MAX)
|
||||
return false;
|
||||
return -ENOBUFS;
|
||||
|
||||
num_of_ports = mlxsw_core_max_ports(mlxsw_sp->core);
|
||||
flood_bitmap = bitmap_alloc(num_of_ports, GFP_KERNEL);
|
||||
if (!flood_bitmap)
|
||||
return false;
|
||||
return -ENOMEM;
|
||||
|
||||
bitmap_copy(flood_bitmap, mid->ports_in_mid, num_of_ports);
|
||||
mlxsw_sp_mc_get_mrouters_bitmap(flood_bitmap, bridge_device, mlxsw_sp);
|
||||
@ -1705,16 +1778,16 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
|
||||
bridge_device->mrouter);
|
||||
bitmap_free(flood_bitmap);
|
||||
if (err)
|
||||
return false;
|
||||
return err;
|
||||
|
||||
err = mlxsw_sp_port_mdb_op(mlxsw_sp, mid->addr, mid->fid, mid_idx,
|
||||
true);
|
||||
if (err)
|
||||
return false;
|
||||
return err;
|
||||
|
||||
set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
|
||||
mid->in_hw = true;
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_mc_remove_mdb_entry(struct mlxsw_sp *mlxsw_sp,
|
||||
@ -1736,6 +1809,7 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
|
||||
u16 fid)
|
||||
{
|
||||
struct mlxsw_sp_mid *mid;
|
||||
int err;
|
||||
|
||||
mid = kzalloc(sizeof(*mid), GFP_KERNEL);
|
||||
if (!mid)
|
||||
@ -1753,7 +1827,8 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
|
||||
if (!bridge_device->multicast_enabled)
|
||||
goto out;
|
||||
|
||||
if (!mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid, bridge_device))
|
||||
err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid, bridge_device);
|
||||
if (err)
|
||||
goto err_write_mdb_entry;
|
||||
|
||||
out:
|
||||
@ -1840,24 +1915,37 @@ err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
|
||||
struct mlxsw_sp_bridge_device
|
||||
*bridge_device)
|
||||
static int
|
||||
mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_bridge_device *bridge_device,
|
||||
bool mc_enabled)
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
struct mlxsw_sp_mid *mid;
|
||||
bool mc_enabled;
|
||||
|
||||
mc_enabled = bridge_device->multicast_enabled;
|
||||
int err;
|
||||
|
||||
list_for_each_entry(mid, &bridge_device->mids_list, list) {
|
||||
if (mc_enabled)
|
||||
err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid,
|
||||
bridge_device);
|
||||
else
|
||||
err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
|
||||
|
||||
if (err)
|
||||
goto err_mdb_entry_update;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_mdb_entry_update:
|
||||
list_for_each_entry_continue_reverse(mid, &bridge_device->mids_list,
|
||||
list) {
|
||||
if (mc_enabled)
|
||||
mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
|
||||
else
|
||||
mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid,
|
||||
bridge_device);
|
||||
else
|
||||
mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2730,8 +2818,7 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
|
||||
|
||||
bridge_device = bridge_port->bridge_device;
|
||||
vid = bridge_device->vlan_enabled ? mlxsw_sp_port_vlan->vid : 0;
|
||||
lag_vid = mlxsw_sp_fid_lag_vid_valid(mlxsw_sp_port_vlan->fid) ?
|
||||
mlxsw_sp_port_vlan->vid : 0;
|
||||
lag_vid = mlxsw_sp_port_vlan->vid;
|
||||
|
||||
do_fdb_op:
|
||||
err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
|
||||
|
Loading…
Reference in New Issue
Block a user