Commit ffd3018b authored by David S. Miller's avatar David S. Miller

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 4336487e ("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: default avatarDavid S. Miller <davem@davemloft.net>
parents a80d8fb7 048fcbb7
......@@ -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);
/* cmd_mbox_config_profile_flood_mode
* Flooding mode to use.
* 0-2 - Backward compatible modes for SwitchX devices.
* 3 - Mixed mode, where:
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.
* 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.
*/
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,7 +990,6 @@ 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);
err = fid->fid_family->ops->configure(fid);
......
......@@ -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 @@ mlxsw_sp_bridge_port_flood_table_set(struct mlxsw_sp_port *mlxsw_sp_port,
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) {
if (bridge_device->multicast_enabled == !mc_disabled)
return 0;
bridge_device->multicast_enabled = !mc_disabled;
mlxsw_sp_bridge_mdb_mc_enable_sync(mlxsw_sp_port,
bridge_device);
}
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) {
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);
err = mlxsw_sp_bridge_ports_flood_table_set(bridge_port,
packet_type,
member);
if (err)
return err;
goto err_flood_table_set;
}
bridge_device->multicast_enabled = !mc_disabled;
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 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
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)
mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid,
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);
}
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,
......
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