summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlxsw
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw')
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/cmd.h43
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.c178
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c70
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h15
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_env.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_thermal.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/i2c.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c37
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h20
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c95
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c30
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c69
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c2
22 files changed, 376 insertions, 260 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h
index 09bef04b11..e827c78be1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h
@@ -276,6 +276,12 @@ MLXSW_ITEM32(cmd_mbox, query_fw, fw_month, 0x14, 8, 8);
*/
MLXSW_ITEM32(cmd_mbox, query_fw, fw_day, 0x14, 0, 8);
+/* cmd_mbox_query_fw_lag_mode_support
+ * 0: CONFIG_PROFILE.lag_mode is not supported by FW
+ * 1: CONFIG_PROFILE.lag_mode is supported by FW
+ */
+MLXSW_ITEM32(cmd_mbox, query_fw, lag_mode_support, 0x18, 1, 1);
+
/* cmd_mbox_query_fw_clr_int_base_offset
* Clear Interrupt register's offset from clr_int_bar register
* in PCI address space.
@@ -659,42 +665,48 @@ MLXSW_ITEM32(cmd_mbox, config_profile,
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_ar_sec, 0x0C, 15, 1);
-/* cmd_mbox_config_set_ubridge
+/* cmd_mbox_config_profile_set_ubridge
* Capability bit. Setting a bit to 1 configures the profile
* according to the mailbox contents.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_ubridge, 0x0C, 22, 1);
-/* cmd_mbox_config_set_kvd_linear_size
+/* cmd_mbox_config_profile_set_kvd_linear_size
* Capability bit. Setting a bit to 1 configures the profile
* according to the mailbox contents.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_linear_size, 0x0C, 24, 1);
-/* cmd_mbox_config_set_kvd_hash_single_size
+/* cmd_mbox_config_profile_set_kvd_hash_single_size
* Capability bit. Setting a bit to 1 configures the profile
* according to the mailbox contents.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_single_size, 0x0C, 25, 1);
-/* cmd_mbox_config_set_kvd_hash_double_size
+/* cmd_mbox_config_profile_set_kvd_hash_double_size
* Capability bit. Setting a bit to 1 configures the profile
* according to the mailbox contents.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_double_size, 0x0C, 26, 1);
-/* cmd_mbox_config_set_cqe_version
+/* cmd_mbox_config_profile_set_cqe_version
* Capability bit. Setting a bit to 1 configures the profile
* according to the mailbox contents.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_version, 0x08, 0, 1);
-/* cmd_mbox_config_set_cqe_time_stamp_type
+/* cmd_mbox_config_profile_set_cqe_time_stamp_type
* Capability bit. Setting a bit to 1 configures the profile
* according to the mailbox contents.
*/
MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_time_stamp_type, 0x08, 2, 1);
+/* cmd_mbox_config_profile_set_lag_mode
+ * Capability bit. Setting a bit to 1 configures the lag_mode
+ * according to the mailbox contents.
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile, set_lag_mode, 0x08, 7, 1);
+
/* cmd_mbox_config_profile_max_vepa_channels
* Maximum number of VEPA channels per port (0 through 16)
* 0 - multi-channel VEPA is disabled
@@ -840,6 +852,21 @@ MLXSW_ITEM32(cmd_mbox, config_profile, arn, 0x50, 31, 1);
*/
MLXSW_ITEM32(cmd_mbox, config_profile, ubridge, 0x50, 4, 1);
+enum mlxsw_cmd_mbox_config_profile_lag_mode {
+ /* FW manages PGT LAG table */
+ MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_FW,
+ /* SW manages PGT LAG table */
+ MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW,
+};
+
+/* cmd_mbox_config_profile_lag_mode
+ * LAG mode
+ * Configured if set_lag_mode is set
+ * Supported from Spectrum-2 and above.
+ * Supported only when ubridge = 1
+ */
+MLXSW_ITEM32(cmd_mbox, config_profile, lag_mode, 0x50, 3, 1);
+
/* cmd_mbox_config_kvd_linear_size
* KVD Linear Size
* Valid for Spectrum only
@@ -847,7 +874,7 @@ MLXSW_ITEM32(cmd_mbox, config_profile, ubridge, 0x50, 4, 1);
*/
MLXSW_ITEM32(cmd_mbox, config_profile, kvd_linear_size, 0x54, 0, 24);
-/* cmd_mbox_config_kvd_hash_single_size
+/* cmd_mbox_config_profile_kvd_hash_single_size
* KVD Hash single-entries size
* Valid for Spectrum only
* Allowed values are 128*N where N=0 or higher
@@ -856,7 +883,7 @@ MLXSW_ITEM32(cmd_mbox, config_profile, kvd_linear_size, 0x54, 0, 24);
*/
MLXSW_ITEM32(cmd_mbox, config_profile, kvd_hash_single_size, 0x58, 0, 24);
-/* cmd_mbox_config_kvd_hash_double_size
+/* cmd_mbox_config_profile_kvd_hash_double_size
* KVD Hash double-entries size (units of single-size entries)
* Valid for Spectrum only
* Allowed values are 128*N where N=0 or higher
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index 1ccf3b73ed..f23421f038 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -204,6 +204,13 @@ int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag)
}
EXPORT_SYMBOL(mlxsw_core_max_lag);
+enum mlxsw_cmd_mbox_config_profile_lag_mode
+mlxsw_core_lag_mode(struct mlxsw_core *mlxsw_core)
+{
+ return mlxsw_core->bus->lag_mode(mlxsw_core->bus_priv);
+}
+EXPORT_SYMBOL(mlxsw_core_lag_mode);
+
void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
{
return mlxsw_core->driver_priv;
@@ -1792,122 +1799,78 @@ static void mlxsw_core_health_listener_func(const struct mlxsw_reg_info *reg,
static const struct mlxsw_listener mlxsw_core_health_listener =
MLXSW_CORE_EVENTL(mlxsw_core_health_listener_func, MFDE);
-static int
+static void
mlxsw_core_health_fw_fatal_dump_fatal_cause(const char *mfde_pl,
struct devlink_fmsg *fmsg)
{
u32 val, tile_v;
- int err;
val = mlxsw_reg_mfde_fatal_cause_id_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "cause_id", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "cause_id", val);
tile_v = mlxsw_reg_mfde_fatal_cause_tile_v_get(mfde_pl);
if (tile_v) {
val = mlxsw_reg_mfde_fatal_cause_tile_index_get(mfde_pl);
- err = devlink_fmsg_u8_pair_put(fmsg, "tile_index", val);
- if (err)
- return err;
+ devlink_fmsg_u8_pair_put(fmsg, "tile_index", val);
}
-
- return 0;
}
-static int
+static void
mlxsw_core_health_fw_fatal_dump_fw_assert(const char *mfde_pl,
struct devlink_fmsg *fmsg)
{
u32 val, tile_v;
- int err;
val = mlxsw_reg_mfde_fw_assert_var0_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "var0", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "var0", val);
val = mlxsw_reg_mfde_fw_assert_var1_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "var1", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "var1", val);
val = mlxsw_reg_mfde_fw_assert_var2_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "var2", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "var2", val);
val = mlxsw_reg_mfde_fw_assert_var3_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "var3", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "var3", val);
val = mlxsw_reg_mfde_fw_assert_var4_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "var4", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "var4", val);
val = mlxsw_reg_mfde_fw_assert_existptr_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "existptr", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "existptr", val);
val = mlxsw_reg_mfde_fw_assert_callra_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "callra", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "callra", val);
val = mlxsw_reg_mfde_fw_assert_oe_get(mfde_pl);
- err = devlink_fmsg_bool_pair_put(fmsg, "old_event", val);
- if (err)
- return err;
+ devlink_fmsg_bool_pair_put(fmsg, "old_event", val);
tile_v = mlxsw_reg_mfde_fw_assert_tile_v_get(mfde_pl);
if (tile_v) {
val = mlxsw_reg_mfde_fw_assert_tile_index_get(mfde_pl);
- err = devlink_fmsg_u8_pair_put(fmsg, "tile_index", val);
- if (err)
- return err;
+ devlink_fmsg_u8_pair_put(fmsg, "tile_index", val);
}
val = mlxsw_reg_mfde_fw_assert_ext_synd_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "ext_synd", val);
- if (err)
- return err;
-
- return 0;
+ devlink_fmsg_u32_pair_put(fmsg, "ext_synd", val);
}
-static int
+static void
mlxsw_core_health_fw_fatal_dump_kvd_im_stop(const char *mfde_pl,
struct devlink_fmsg *fmsg)
{
u32 val;
- int err;
val = mlxsw_reg_mfde_kvd_im_stop_oe_get(mfde_pl);
- err = devlink_fmsg_bool_pair_put(fmsg, "old_event", val);
- if (err)
- return err;
+ devlink_fmsg_bool_pair_put(fmsg, "old_event", val);
val = mlxsw_reg_mfde_kvd_im_stop_pipes_mask_get(mfde_pl);
- return devlink_fmsg_u32_pair_put(fmsg, "pipes_mask", val);
+ devlink_fmsg_u32_pair_put(fmsg, "pipes_mask", val);
}
-static int
+static void
mlxsw_core_health_fw_fatal_dump_crspace_to(const char *mfde_pl,
struct devlink_fmsg *fmsg)
{
u32 val;
- int err;
val = mlxsw_reg_mfde_crspace_to_log_address_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "log_address", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "log_address", val);
val = mlxsw_reg_mfde_crspace_to_oe_get(mfde_pl);
- err = devlink_fmsg_bool_pair_put(fmsg, "old_event", val);
- if (err)
- return err;
+ devlink_fmsg_bool_pair_put(fmsg, "old_event", val);
val = mlxsw_reg_mfde_crspace_to_log_id_get(mfde_pl);
- err = devlink_fmsg_u8_pair_put(fmsg, "log_irisc_id", val);
- if (err)
- return err;
+ devlink_fmsg_u8_pair_put(fmsg, "log_irisc_id", val);
val = mlxsw_reg_mfde_crspace_to_log_ip_get(mfde_pl);
- err = devlink_fmsg_u64_pair_put(fmsg, "log_ip", val);
- if (err)
- return err;
-
- return 0;
+ devlink_fmsg_u64_pair_put(fmsg, "log_ip", val);
}
static int mlxsw_core_health_fw_fatal_dump(struct devlink_health_reporter *reporter,
@@ -1918,24 +1881,17 @@ static int mlxsw_core_health_fw_fatal_dump(struct devlink_health_reporter *repor
char *val_str;
u8 event_id;
u32 val;
- int err;
if (!priv_ctx)
/* User-triggered dumps are not possible */
return -EOPNOTSUPP;
val = mlxsw_reg_mfde_irisc_id_get(mfde_pl);
- err = devlink_fmsg_u8_pair_put(fmsg, "irisc_id", val);
- if (err)
- return err;
- err = devlink_fmsg_arr_pair_nest_start(fmsg, "event");
- if (err)
- return err;
+ devlink_fmsg_u8_pair_put(fmsg, "irisc_id", val);
+ devlink_fmsg_arr_pair_nest_start(fmsg, "event");
event_id = mlxsw_reg_mfde_event_id_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "id", event_id);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "id", event_id);
switch (event_id) {
case MLXSW_REG_MFDE_EVENT_ID_CRSPACE_TO:
val_str = "CR space timeout";
@@ -1955,24 +1911,13 @@ static int mlxsw_core_health_fw_fatal_dump(struct devlink_health_reporter *repor
default:
val_str = NULL;
}
- if (val_str) {
- err = devlink_fmsg_string_pair_put(fmsg, "desc", val_str);
- if (err)
- return err;
- }
-
- err = devlink_fmsg_arr_pair_nest_end(fmsg);
- if (err)
- return err;
-
- err = devlink_fmsg_arr_pair_nest_start(fmsg, "severity");
- if (err)
- return err;
+ if (val_str)
+ devlink_fmsg_string_pair_put(fmsg, "desc", val_str);
+ devlink_fmsg_arr_pair_nest_end(fmsg);
+ devlink_fmsg_arr_pair_nest_start(fmsg, "severity");
val = mlxsw_reg_mfde_severity_get(mfde_pl);
- err = devlink_fmsg_u8_pair_put(fmsg, "id", val);
- if (err)
- return err;
+ devlink_fmsg_u8_pair_put(fmsg, "id", val);
switch (val) {
case MLXSW_REG_MFDE_SEVERITY_FATL:
val_str = "Fatal";
@@ -1986,15 +1931,9 @@ static int mlxsw_core_health_fw_fatal_dump(struct devlink_health_reporter *repor
default:
val_str = NULL;
}
- if (val_str) {
- err = devlink_fmsg_string_pair_put(fmsg, "desc", val_str);
- if (err)
- return err;
- }
-
- err = devlink_fmsg_arr_pair_nest_end(fmsg);
- if (err)
- return err;
+ if (val_str)
+ devlink_fmsg_string_pair_put(fmsg, "desc", val_str);
+ devlink_fmsg_arr_pair_nest_end(fmsg);
val = mlxsw_reg_mfde_method_get(mfde_pl);
switch (val) {
@@ -2007,16 +1946,11 @@ static int mlxsw_core_health_fw_fatal_dump(struct devlink_health_reporter *repor
default:
val_str = NULL;
}
- if (val_str) {
- err = devlink_fmsg_string_pair_put(fmsg, "method", val_str);
- if (err)
- return err;
- }
+ if (val_str)
+ devlink_fmsg_string_pair_put(fmsg, "method", val_str);
val = mlxsw_reg_mfde_long_process_get(mfde_pl);
- err = devlink_fmsg_bool_pair_put(fmsg, "long_process", val);
- if (err)
- return err;
+ devlink_fmsg_bool_pair_put(fmsg, "long_process", val);
val = mlxsw_reg_mfde_command_type_get(mfde_pl);
switch (val) {
@@ -2032,29 +1966,25 @@ static int mlxsw_core_health_fw_fatal_dump(struct devlink_health_reporter *repor
default:
val_str = NULL;
}
- if (val_str) {
- err = devlink_fmsg_string_pair_put(fmsg, "command_type", val_str);
- if (err)
- return err;
- }
+ if (val_str)
+ devlink_fmsg_string_pair_put(fmsg, "command_type", val_str);
val = mlxsw_reg_mfde_reg_attr_id_get(mfde_pl);
- err = devlink_fmsg_u32_pair_put(fmsg, "reg_attr_id", val);
- if (err)
- return err;
+ devlink_fmsg_u32_pair_put(fmsg, "reg_attr_id", val);
switch (event_id) {
case MLXSW_REG_MFDE_EVENT_ID_CRSPACE_TO:
- return mlxsw_core_health_fw_fatal_dump_crspace_to(mfde_pl,
- fmsg);
+ mlxsw_core_health_fw_fatal_dump_crspace_to(mfde_pl, fmsg);
+ break;
case MLXSW_REG_MFDE_EVENT_ID_KVD_IM_STOP:
- return mlxsw_core_health_fw_fatal_dump_kvd_im_stop(mfde_pl,
- fmsg);
+ mlxsw_core_health_fw_fatal_dump_kvd_im_stop(mfde_pl, fmsg);
+ break;
case MLXSW_REG_MFDE_EVENT_ID_FW_ASSERT:
- return mlxsw_core_health_fw_fatal_dump_fw_assert(mfde_pl, fmsg);
+ mlxsw_core_health_fw_fatal_dump_fw_assert(mfde_pl, fmsg);
+ break;
case MLXSW_REG_MFDE_EVENT_ID_FATAL_CAUSE:
- return mlxsw_core_health_fw_fatal_dump_fatal_cause(mfde_pl,
- fmsg);
+ mlxsw_core_health_fw_fatal_dump_fatal_cause(mfde_pl, fmsg);
+ break;
}
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index e5474d3e34..764d14bd5b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -36,6 +36,8 @@ struct mlxsw_fw_rev;
unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core);
int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag);
+enum mlxsw_cmd_mbox_config_profile_lag_mode
+mlxsw_core_lag_mode(struct mlxsw_core *mlxsw_core);
void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core);
@@ -335,6 +337,7 @@ struct mlxsw_config_profile {
u8 kvd_hash_single_parts;
u8 kvd_hash_double_parts;
u8 cqe_time_stamp_type;
+ bool lag_mode_prefer_sw;
struct mlxsw_swid_config swid_config[MLXSW_CONFIG_PROFILE_SWID_COUNT];
};
@@ -485,6 +488,7 @@ struct mlxsw_bus {
u32 (*read_frc_l)(void *bus_priv);
u32 (*read_utc_sec)(void *bus_priv);
u32 (*read_utc_nsec)(void *bus_priv);
+ enum mlxsw_cmd_mbox_config_profile_lag_mode (*lag_mode)(void *bus_priv);
u8 features;
};
@@ -624,7 +628,7 @@ struct mlxsw_linecards {
struct mlxsw_linecard_types_info *types_info;
struct list_head event_ops_list;
struct mutex event_ops_list_lock; /* Locks accesses to event ops list */
- struct mlxsw_linecard linecards[];
+ struct mlxsw_linecard linecards[] __counted_by(count);
};
static inline struct mlxsw_linecard *
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
index 70f9b5e85a..0d5e6f9b46 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
@@ -32,8 +32,7 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x18, 0, 8),
MLXSW_AFK_ELEMENT_INFO_U32(IP_ECN, 0x18, 9, 2),
MLXSW_AFK_ELEMENT_INFO_U32(IP_DSCP, 0x18, 11, 6),
- MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_MSB, 0x18, 17, 4),
- MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_LSB, 0x18, 21, 8),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER, 0x18, 17, 12),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_96_127, 0x20, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_64_95, 0x24, 4),
MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP_32_63, 0x28, 4),
@@ -44,6 +43,9 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_0_31, 0x3C, 4),
MLXSW_AFK_ELEMENT_INFO_U32(FDB_MISS, 0x40, 0, 1),
MLXSW_AFK_ELEMENT_INFO_U32(L4_PORT_RANGE, 0x40, 1, 16),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_0_3, 0x40, 17, 4),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_4_7, 0x40, 21, 4),
+ MLXSW_AFK_ELEMENT_INFO_U32(VIRT_ROUTER_MSB, 0x40, 25, 4),
};
struct mlxsw_afk {
@@ -136,6 +138,7 @@ mlxsw_afk_key_info_find(struct mlxsw_afk *mlxsw_afk,
struct mlxsw_afk_picker {
DECLARE_BITMAP(element, MLXSW_AFK_ELEMENT_MAX);
+ DECLARE_BITMAP(chosen_element, MLXSW_AFK_ELEMENT_MAX);
unsigned int total;
};
@@ -206,7 +209,7 @@ static int mlxsw_afk_picker_key_info_add(struct mlxsw_afk *mlxsw_afk,
if (key_info->blocks_count == mlxsw_afk->max_blocks)
return -EINVAL;
- for_each_set_bit(element, picker[block_index].element,
+ for_each_set_bit(element, picker[block_index].chosen_element,
MLXSW_AFK_ELEMENT_MAX) {
key_info->element_to_block[element] = key_info->blocks_count;
mlxsw_afk_element_usage_add(&key_info->elusage, element);
@@ -218,11 +221,43 @@ static int mlxsw_afk_picker_key_info_add(struct mlxsw_afk *mlxsw_afk,
return 0;
}
+static int mlxsw_afk_keys_fill(struct mlxsw_afk *mlxsw_afk,
+ unsigned long *chosen_blocks_bm,
+ struct mlxsw_afk_picker *picker,
+ struct mlxsw_afk_key_info *key_info)
+{
+ int i, err;
+
+ /* First fill only key blocks with high_entropy. */
+ for_each_set_bit(i, chosen_blocks_bm, mlxsw_afk->blocks_count) {
+ if (!mlxsw_afk->blocks[i].high_entropy)
+ continue;
+
+ err = mlxsw_afk_picker_key_info_add(mlxsw_afk, picker, i,
+ key_info);
+ if (err)
+ return err;
+ __clear_bit(i, chosen_blocks_bm);
+ }
+
+ /* Fill the rest of key blocks. */
+ for_each_set_bit(i, chosen_blocks_bm, mlxsw_afk->blocks_count) {
+ err = mlxsw_afk_picker_key_info_add(mlxsw_afk, picker, i,
+ key_info);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int mlxsw_afk_picker(struct mlxsw_afk *mlxsw_afk,
struct mlxsw_afk_key_info *key_info,
struct mlxsw_afk_element_usage *elusage)
{
+ DECLARE_BITMAP(elusage_chosen, MLXSW_AFK_ELEMENT_MAX) = {0};
struct mlxsw_afk_picker *picker;
+ unsigned long *chosen_blocks_bm;
enum mlxsw_afk_element element;
int err;
@@ -230,6 +265,12 @@ static int mlxsw_afk_picker(struct mlxsw_afk *mlxsw_afk,
if (!picker)
return -ENOMEM;
+ chosen_blocks_bm = bitmap_zalloc(mlxsw_afk->blocks_count, GFP_KERNEL);
+ if (!chosen_blocks_bm) {
+ err = -ENOMEM;
+ goto err_bitmap_alloc;
+ }
+
/* Since the same elements could be present in multiple blocks,
* we must find out optimal block list in order to make the
* block count as low as possible.
@@ -254,15 +295,26 @@ static int mlxsw_afk_picker(struct mlxsw_afk *mlxsw_afk,
err = block_index;
goto out;
}
- err = mlxsw_afk_picker_key_info_add(mlxsw_afk, picker,
- block_index, key_info);
- if (err)
- goto out;
+
+ __set_bit(block_index, chosen_blocks_bm);
+
+ bitmap_copy(picker[block_index].chosen_element,
+ picker[block_index].element, MLXSW_AFK_ELEMENT_MAX);
+
+ bitmap_or(elusage_chosen, elusage_chosen,
+ picker[block_index].chosen_element,
+ MLXSW_AFK_ELEMENT_MAX);
+
mlxsw_afk_picker_subtract_hits(mlxsw_afk, picker, block_index);
- } while (!mlxsw_afk_key_info_elements_eq(key_info, elusage));
- err = 0;
+ } while (!bitmap_equal(elusage_chosen, elusage->usage,
+ MLXSW_AFK_ELEMENT_MAX));
+
+ err = mlxsw_afk_keys_fill(mlxsw_afk, chosen_blocks_bm, picker,
+ key_info);
out:
+ bitmap_free(chosen_blocks_bm);
+err_bitmap_alloc:
kfree(picker);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
index 2eac7582c3..98a0559817 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
@@ -33,10 +33,12 @@ enum mlxsw_afk_element {
MLXSW_AFK_ELEMENT_IP_TTL_,
MLXSW_AFK_ELEMENT_IP_ECN,
MLXSW_AFK_ELEMENT_IP_DSCP,
- MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
- MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER,
MLXSW_AFK_ELEMENT_FDB_MISS,
MLXSW_AFK_ELEMENT_L4_PORT_RANGE,
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_3,
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_4_7,
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
MLXSW_AFK_ELEMENT_MAX,
};
@@ -117,6 +119,7 @@ struct mlxsw_afk_block {
u16 encoding; /* block ID */
struct mlxsw_afk_element_inst *instances;
unsigned int instances_count;
+ bool high_entropy;
};
#define MLXSW_AFK_BLOCK(_encoding, _instances) \
@@ -126,6 +129,14 @@ struct mlxsw_afk_block {
.instances_count = ARRAY_SIZE(_instances), \
}
+#define MLXSW_AFK_BLOCK_HIGH_ENTROPY(_encoding, _instances) \
+ { \
+ .encoding = _encoding, \
+ .instances = _instances, \
+ .instances_count = ARRAY_SIZE(_instances), \
+ .high_entropy = true, \
+ }
+
struct mlxsw_afk_element_usage {
DECLARE_BITMAP(usage, MLXSW_AFK_ELEMENT_MAX);
};
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
index d637c0348f..53b150b7ae 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
@@ -34,7 +34,7 @@ struct mlxsw_env {
u8 num_of_slots; /* Including the main board. */
u8 max_eeprom_len; /* Maximum module EEPROM transaction length. */
struct mutex line_cards_lock; /* Protects line cards. */
- struct mlxsw_env_line_card *line_cards[];
+ struct mlxsw_env_line_card *line_cards[] __counted_by(num_of_slots);
};
static bool __mlxsw_env_linecard_is_active(struct mlxsw_env *mlxsw_env,
@@ -775,7 +775,7 @@ static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core,
int err;
mlxsw_reg_mtbr_pack(mtbr_pl, slot_index,
- MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1);
+ MLXSW_REG_MTBR_BASE_MODULE_INDEX + module);
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtbr), mtbr_pl);
if (err)
return err;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
index 0fd290d776..9c12e1feb6 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
@@ -293,7 +293,7 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count;
mlxsw_reg_mtbr_pack(mtbr_pl, mlxsw_hwmon_dev->slot_index,
- MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1);
+ MLXSW_REG_MTBR_BASE_MODULE_INDEX + module);
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
if (err) {
dev_err(dev, "Failed to query module temperature sensor\n");
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c b/drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c
index af37e650a8..e8d6fe35bf 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c
@@ -132,6 +132,7 @@ static int mlxsw_linecard_bdev_probe(struct auxiliary_device *adev,
struct mlxsw_linecard *linecard = linecard_bdev->linecard;
struct mlxsw_linecard_dev *linecard_dev;
struct devlink *devlink;
+ int err;
devlink = devlink_alloc(&mlxsw_linecard_dev_devlink_ops,
sizeof(*linecard_dev), &adev->dev);
@@ -141,8 +142,12 @@ static int mlxsw_linecard_bdev_probe(struct auxiliary_device *adev,
linecard_dev->linecard = linecard_bdev->linecard;
linecard_bdev->linecard_dev = linecard_dev;
+ err = devlink_linecard_nested_dl_set(linecard->devlink_linecard, devlink);
+ if (err) {
+ devlink_free(devlink);
+ return err;
+ }
devlink_register(devlink);
- devlink_linecard_nested_dl_set(linecard->devlink_linecard, devlink);
return 0;
}
@@ -151,9 +156,7 @@ static void mlxsw_linecard_bdev_remove(struct auxiliary_device *adev)
struct mlxsw_linecard_bdev *linecard_bdev =
container_of(adev, struct mlxsw_linecard_bdev, adev);
struct devlink *devlink = priv_to_devlink(linecard_bdev->linecard_dev);
- struct mlxsw_linecard *linecard = linecard_bdev->linecard;
- devlink_linecard_nested_dl_set(linecard->devlink_linecard, NULL);
devlink_unregister(devlink);
devlink_free(devlink);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index 70d7fff24f..f1b48d6615 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -31,6 +31,7 @@
/* External cooling devices, allowed for binding to mlxsw thermal zones. */
static char * const mlxsw_thermal_external_allowed_cdev[] = {
"mlxreg_fan",
+ "emc2305",
};
struct mlxsw_cooling_states {
@@ -535,7 +536,7 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
static int
mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
{
- char tz_name[THERMAL_NAME_LENGTH];
+ char tz_name[40];
int ret;
if (gearbox_tz->slot_index)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
index d23f293e28..1e150ce1c7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -424,9 +424,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size,
if (in_mbox) {
reg_size = mlxsw_i2c_get_reg_size(in_mbox);
- num = reg_size / mlxsw_i2c->block_size;
- if (reg_size % mlxsw_i2c->block_size)
- num++;
+ num = DIV_ROUND_UP(reg_size, mlxsw_i2c->block_size);
if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
dev_err(&client->dev, "Could not acquire lock");
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index 51eea1f052..e4b25e1874 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -105,6 +105,8 @@ struct mlxsw_pci {
u64 free_running_clock_offset;
u64 utc_sec_offset;
u64 utc_nsec_offset;
+ bool lag_mode_support;
+ enum mlxsw_cmd_mbox_config_profile_lag_mode lag_mode;
struct mlxsw_pci_queue_type_group queues[MLXSW_PCI_QUEUE_TYPE_COUNT];
u32 doorbell_offset;
struct mlxsw_core *core;
@@ -352,14 +354,15 @@ static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe,
}
static int mlxsw_pci_rdq_skb_alloc(struct mlxsw_pci *mlxsw_pci,
- struct mlxsw_pci_queue_elem_info *elem_info)
+ struct mlxsw_pci_queue_elem_info *elem_info,
+ gfp_t gfp)
{
size_t buf_len = MLXSW_PORT_MAX_MTU;
char *wqe = elem_info->elem;
struct sk_buff *skb;
int err;
- skb = netdev_alloc_skb_ip_align(NULL, buf_len);
+ skb = __netdev_alloc_skb_ip_align(NULL, buf_len, gfp);
if (!skb)
return -ENOMEM;
@@ -420,7 +423,7 @@ static int mlxsw_pci_rdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox,
for (i = 0; i < q->count; i++) {
elem_info = mlxsw_pci_queue_elem_info_producer_get(q);
BUG_ON(!elem_info);
- err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info);
+ err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info, GFP_KERNEL);
if (err)
goto rollback;
/* Everything is set up, ring doorbell to pass elem to HW */
@@ -640,7 +643,7 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
if (q->consumer_counter++ != consumer_counter_limit)
dev_dbg_ratelimited(&pdev->dev, "Consumer counter does not match limit in RDQ\n");
- err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info);
+ err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info, GFP_ATOMIC);
if (err) {
dev_err_ratelimited(&pdev->dev, "Failed to alloc skb for RDQ\n");
goto out;
@@ -1311,6 +1314,16 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
profile->cqe_time_stamp_type);
}
+ if (profile->lag_mode_prefer_sw && mlxsw_pci->lag_mode_support) {
+ enum mlxsw_cmd_mbox_config_profile_lag_mode lag_mode =
+ MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW;
+
+ mlxsw_cmd_mbox_config_profile_set_lag_mode_set(mbox, 1);
+ mlxsw_cmd_mbox_config_profile_lag_mode_set(mbox, lag_mode);
+ mlxsw_pci->lag_mode = lag_mode;
+ } else {
+ mlxsw_pci->lag_mode = MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_FW;
+ }
return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox);
}
@@ -1586,6 +1599,8 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
mlxsw_pci->utc_nsec_offset =
mlxsw_cmd_mbox_query_fw_utc_nsec_offset_get(mbox);
+ mlxsw_pci->lag_mode_support =
+ mlxsw_cmd_mbox_query_fw_lag_mode_support_get(mbox);
num_pages = mlxsw_cmd_mbox_query_fw_fw_pages_get(mbox);
err = mlxsw_pci_fw_area_init(mlxsw_pci, mbox, num_pages);
if (err)
@@ -1618,9 +1633,8 @@ 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.
+ /* Some resources depend on details of config_profile, such as unified
+ * bridge model. Query the resources again to get correct values.
*/
err = mlxsw_core_resources_query(mlxsw_core, mbox, res);
if (err)
@@ -1895,6 +1909,14 @@ static u32 mlxsw_pci_read_utc_nsec(void *bus_priv)
return mlxsw_pci_read32_off(mlxsw_pci, mlxsw_pci->utc_nsec_offset);
}
+static enum mlxsw_cmd_mbox_config_profile_lag_mode
+mlxsw_pci_lag_mode(void *bus_priv)
+{
+ struct mlxsw_pci *mlxsw_pci = bus_priv;
+
+ return mlxsw_pci->lag_mode;
+}
+
static const struct mlxsw_bus mlxsw_pci_bus = {
.kind = "pci",
.init = mlxsw_pci_init,
@@ -1906,6 +1928,7 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
.read_frc_l = mlxsw_pci_read_frc_l,
.read_utc_sec = mlxsw_pci_read_utc_sec,
.read_utc_nsec = mlxsw_pci_read_utc_nsec,
+ .lag_mode = mlxsw_pci_lag_mode,
.features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET,
};
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index ae556ddd76..25b294fdeb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -38,18 +38,18 @@ static const struct mlxsw_reg_info mlxsw_reg_##_name = { \
MLXSW_REG_DEFINE(sgcr, MLXSW_REG_SGCR_ID, MLXSW_REG_SGCR_LEN);
-/* reg_sgcr_llb
- * Link Local Broadcast (Default=0)
- * When set, all Link Local packets (224.0.0.X) will be treated as broadcast
- * packets and ignore the IGMP snooping entries.
+/* reg_sgcr_lag_lookup_pgt_base
+ * Base address used for lookup in PGT table
+ * Supported when CONFIG_PROFILE.lag_mode = 1
+ * Note: when IGCR.ddd_lag_mode=0, the address shall be aligned to 8 entries.
* Access: RW
*/
-MLXSW_ITEM32(reg, sgcr, llb, 0x04, 0, 1);
+MLXSW_ITEM32(reg, sgcr, lag_lookup_pgt_base, 0x0C, 0, 16);
-static inline void mlxsw_reg_sgcr_pack(char *payload, bool llb)
+static inline void mlxsw_reg_sgcr_pack(char *payload, u16 lag_lookup_pgt_base)
{
MLXSW_REG_ZERO(sgcr, payload);
- mlxsw_reg_sgcr_llb_set(payload, !!llb);
+ mlxsw_reg_sgcr_lag_lookup_pgt_base_set(payload, lag_lookup_pgt_base);
}
/* SPAD - Switch Physical Address Register
@@ -9551,7 +9551,7 @@ MLXSW_ITEM_BIT_ARRAY(reg, mtwe, sensor_warning, 0x0, 0x10, 1);
#define MLXSW_REG_MTBR_ID 0x900F
#define MLXSW_REG_MTBR_BASE_LEN 0x10 /* base length, without records */
#define MLXSW_REG_MTBR_REC_LEN 0x04 /* record length */
-#define MLXSW_REG_MTBR_REC_MAX_COUNT 47 /* firmware limitation */
+#define MLXSW_REG_MTBR_REC_MAX_COUNT 1
#define MLXSW_REG_MTBR_LEN (MLXSW_REG_MTBR_BASE_LEN + \
MLXSW_REG_MTBR_REC_LEN * \
MLXSW_REG_MTBR_REC_MAX_COUNT)
@@ -9597,12 +9597,12 @@ MLXSW_ITEM32_INDEXED(reg, mtbr, rec_temp, MLXSW_REG_MTBR_BASE_LEN, 0, 16,
MLXSW_REG_MTBR_REC_LEN, 0x00, false);
static inline void mlxsw_reg_mtbr_pack(char *payload, u8 slot_index,
- u16 base_sensor_index, u8 num_rec)
+ u16 base_sensor_index)
{
MLXSW_REG_ZERO(mtbr, payload);
mlxsw_reg_mtbr_slot_index_set(payload, slot_index);
mlxsw_reg_mtbr_base_sensor_index_set(payload, base_sensor_index);
- mlxsw_reg_mtbr_num_rec_set(payload, num_rec);
+ mlxsw_reg_mtbr_num_rec_set(payload, 1);
}
/* Error codes from temperatute reading */
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 9dbd5edff0..cec72d99d9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2692,6 +2692,63 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
kfree(mlxsw_sp->trap);
}
+static int mlxsw_sp_lag_pgt_init(struct mlxsw_sp *mlxsw_sp)
+{
+ char sgcr_pl[MLXSW_REG_SGCR_LEN];
+ u16 max_lag;
+ int err;
+
+ if (mlxsw_core_lag_mode(mlxsw_sp->core) !=
+ MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW)
+ return 0;
+
+ err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag);
+ if (err)
+ return err;
+
+ /* In DDD mode, which we by default use, each LAG entry is 8 PGT
+ * entries. The LAG table address needs to be 8-aligned, but that ought
+ * to be the case, since the LAG table is allocated first.
+ */
+ err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &mlxsw_sp->lag_pgt_base,
+ max_lag * 8);
+ if (err)
+ return err;
+ if (WARN_ON_ONCE(mlxsw_sp->lag_pgt_base % 8)) {
+ err = -EINVAL;
+ goto err_mid_alloc_range;
+ }
+
+ mlxsw_reg_sgcr_pack(sgcr_pl, mlxsw_sp->lag_pgt_base);
+ err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sgcr), sgcr_pl);
+ if (err)
+ goto err_mid_alloc_range;
+
+ return 0;
+
+err_mid_alloc_range:
+ mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mlxsw_sp->lag_pgt_base,
+ max_lag * 8);
+ return err;
+}
+
+static void mlxsw_sp_lag_pgt_fini(struct mlxsw_sp *mlxsw_sp)
+{
+ u16 max_lag;
+ int err;
+
+ if (mlxsw_core_lag_mode(mlxsw_sp->core) !=
+ MLXSW_CMD_MBOX_CONFIG_PROFILE_LAG_MODE_SW)
+ return;
+
+ err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag);
+ if (err)
+ return;
+
+ mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mlxsw_sp->lag_pgt_base,
+ max_lag * 8);
+}
+
#define MLXSW_SP_LAG_SEED_INIT 0xcafecafe
static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
@@ -2723,16 +2780,27 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
return -EIO;
+ err = mlxsw_sp_lag_pgt_init(mlxsw_sp);
+ if (err)
+ return err;
+
mlxsw_sp->lags = kcalloc(max_lag, sizeof(struct mlxsw_sp_upper),
GFP_KERNEL);
- if (!mlxsw_sp->lags)
- return -ENOMEM;
+ if (!mlxsw_sp->lags) {
+ err = -ENOMEM;
+ goto err_kcalloc;
+ }
return 0;
+
+err_kcalloc:
+ mlxsw_sp_lag_pgt_fini(mlxsw_sp);
+ return err;
}
static void mlxsw_sp_lag_fini(struct mlxsw_sp *mlxsw_sp)
{
+ mlxsw_sp_lag_pgt_fini(mlxsw_sp);
kfree(mlxsw_sp->lags);
}
@@ -3113,6 +3181,15 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_pgt_init;
}
+ /* Initialize before FIDs so that the LAG table is at the start of PGT
+ * and 8-aligned without overallocation.
+ */
+ err = mlxsw_sp_lag_init(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize LAG\n");
+ goto err_lag_init;
+ }
+
err = mlxsw_sp_fids_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize FIDs\n");
@@ -3143,12 +3220,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_buffers_init;
}
- err = mlxsw_sp_lag_init(mlxsw_sp);
- if (err) {
- dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize LAG\n");
- goto err_lag_init;
- }
-
/* Initialize SPAN before router and switchdev, so that those components
* can call mlxsw_sp_span_respin().
*/
@@ -3300,8 +3371,6 @@ err_counter_pool_init:
err_switchdev_init:
mlxsw_sp_span_fini(mlxsw_sp);
err_span_init:
- mlxsw_sp_lag_fini(mlxsw_sp);
-err_lag_init:
mlxsw_sp_buffers_fini(mlxsw_sp);
err_buffers_init:
mlxsw_sp_devlink_traps_fini(mlxsw_sp);
@@ -3312,6 +3381,8 @@ err_traps_init:
err_policers_init:
mlxsw_sp_fids_fini(mlxsw_sp);
err_fids_init:
+ mlxsw_sp_lag_fini(mlxsw_sp);
+err_lag_init:
mlxsw_sp_pgt_fini(mlxsw_sp);
err_pgt_init:
mlxsw_sp_kvdl_fini(mlxsw_sp);
@@ -3477,12 +3548,12 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_counter_pool_fini(mlxsw_sp);
mlxsw_sp_switchdev_fini(mlxsw_sp);
mlxsw_sp_span_fini(mlxsw_sp);
- mlxsw_sp_lag_fini(mlxsw_sp);
mlxsw_sp_buffers_fini(mlxsw_sp);
mlxsw_sp_devlink_traps_fini(mlxsw_sp);
mlxsw_sp_traps_fini(mlxsw_sp);
mlxsw_sp_policers_fini(mlxsw_sp);
mlxsw_sp_fids_fini(mlxsw_sp);
+ mlxsw_sp_lag_fini(mlxsw_sp);
mlxsw_sp_pgt_fini(mlxsw_sp);
mlxsw_sp_kvdl_fini(mlxsw_sp);
mlxsw_sp_parsing_fini(mlxsw_sp);
@@ -3526,6 +3597,7 @@ static const struct mlxsw_config_profile mlxsw_sp2_config_profile = {
},
.used_cqe_time_stamp_type = 1,
.cqe_time_stamp_type = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC,
+ .lag_mode_prefer_sw = true,
};
/* Reduce number of LAGs from full capacity (256) to the maximum supported LAGs
@@ -3553,6 +3625,7 @@ static const struct mlxsw_config_profile mlxsw_sp4_config_profile = {
},
.used_cqe_time_stamp_type = 1,
.cqe_time_stamp_type = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC,
+ .lag_mode_prefer_sw = true,
};
static void
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 02ca2871b6..c70333b460 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -212,6 +212,7 @@ struct mlxsw_sp {
struct mutex ipv6_addr_ht_lock; /* Protects ipv6_addr_ht */
struct mlxsw_sp_pgt *pgt;
bool pgt_smpe_index_valid;
+ u16 lag_pgt_base;
};
struct mlxsw_sp_ptp_ops {
@@ -1480,7 +1481,7 @@ int mlxsw_sp_policer_resources_register(struct mlxsw_core *mlxsw_core);
/* spectrum_pgt.c */
int mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid);
void mlxsw_sp_pgt_mid_free(struct mlxsw_sp *mlxsw_sp, u16 mid_base);
-int mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
+int mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 *mid_base,
u16 count);
void mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
u16 count);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
index b1178b7a7f..99eeafdc8d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum2_mr_tcam.c
@@ -45,8 +45,7 @@ static int mlxsw_sp2_mr_tcam_bind_group(struct mlxsw_sp *mlxsw_sp,
}
static const enum mlxsw_afk_element mlxsw_sp2_mr_tcam_usage_ipv4[] = {
- MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
- MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER,
MLXSW_AFK_ELEMENT_SRC_IP_0_31,
MLXSW_AFK_ELEMENT_DST_IP_0_31,
};
@@ -89,8 +88,9 @@ static void mlxsw_sp2_mr_tcam_ipv4_fini(struct mlxsw_sp2_mr_tcam *mr_tcam)
}
static const enum mlxsw_afk_element mlxsw_sp2_mr_tcam_usage_ipv6[] = {
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_3,
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_4_7,
MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
- MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
MLXSW_AFK_ELEMENT_SRC_IP_96_127,
MLXSW_AFK_ELEMENT_SRC_IP_64_95,
MLXSW_AFK_ELEMENT_SRC_IP_32_63,
@@ -142,6 +142,8 @@ static void
mlxsw_sp2_mr_tcam_rule_parse4(struct mlxsw_sp_acl_rule_info *rulei,
struct mlxsw_sp_mr_route_key *key)
{
+ mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VIRT_ROUTER,
+ key->vrid, GENMASK(11, 0));
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31,
(char *) &key->source.addr4,
(char *) &key->source_mask.addr4, 4);
@@ -154,6 +156,13 @@ static void
mlxsw_sp2_mr_tcam_rule_parse6(struct mlxsw_sp_acl_rule_info *rulei,
struct mlxsw_sp_mr_route_key *key)
{
+ mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_3,
+ key->vrid, GENMASK(3, 0));
+ mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VIRT_ROUTER_4_7,
+ key->vrid >> 4, GENMASK(3, 0));
+ mlxsw_sp_acl_rulei_keymask_u32(rulei,
+ MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
+ key->vrid >> 8, GENMASK(3, 0));
mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_96_127,
&key->source.addr6.s6_addr[0x0],
&key->source_mask.addr6.s6_addr[0x0], 4);
@@ -189,11 +198,6 @@ mlxsw_sp2_mr_tcam_rule_parse(struct mlxsw_sp_acl_rule *rule,
rulei = mlxsw_sp_acl_rule_rulei(rule);
rulei->priority = priority;
- mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
- key->vrid, GENMASK(7, 0));
- mlxsw_sp_acl_rulei_keymask_u32(rulei,
- MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
- key->vrid >> 8, GENMASK(3, 0));
switch (key->proto) {
case MLXSW_SP_L3_PROTO_IPV4:
return mlxsw_sp2_mr_tcam_rule_parse4(rulei, key);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
index cb746a43b2..eaad786056 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
@@ -171,20 +171,22 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4[] = {
- MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_LSB, 0x04, 24, 8),
- MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x00, 0, 3, 0, true),
+static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5[] = {
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER, 0x04, 20, 11, 0, true),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_0_3, 0x00, 0, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_4_7, 0x00, 0, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
+ MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x00, 0, 3, 0, true),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
};
@@ -220,7 +222,7 @@ static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = {
MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0),
MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1),
MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
- MLXSW_AFK_BLOCK(0x3C, mlxsw_sp_afk_element_info_ipv4_4),
+ MLXSW_AFK_BLOCK(0x3D, mlxsw_sp_afk_element_info_ipv4_5),
MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
MLXSW_AFK_BLOCK(0x42, mlxsw_sp_afk_element_info_ipv6_2),
@@ -322,33 +324,33 @@ static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 9, -1, true), /* RX_ACL_SYSTEM_PORT */
};
-static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_4b[] = {
- MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_LSB, 0x04, 13, 8),
- MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x04, 21, 4),
+static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER, 0x04, 20, 12),
};
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
+ MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x00, 0, 4),
MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
};
static const struct mlxsw_afk_block mlxsw_sp4_afk_blocks[] = {
- MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_mac_0),
- MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_mac_1),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x10, mlxsw_sp_afk_element_info_mac_0),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x11, mlxsw_sp_afk_element_info_mac_1),
MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2),
MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3),
MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
- MLXSW_AFK_BLOCK(0x1A, mlxsw_sp_afk_element_info_mac_5b),
- MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0),
- MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x1A, mlxsw_sp_afk_element_info_mac_5b),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x38, mlxsw_sp_afk_element_info_ipv4_0),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x39, mlxsw_sp_afk_element_info_ipv4_1),
MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
- MLXSW_AFK_BLOCK(0x35, mlxsw_sp_afk_element_info_ipv4_4b),
+ MLXSW_AFK_BLOCK(0x36, mlxsw_sp_afk_element_info_ipv4_5b),
MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
MLXSW_AFK_BLOCK(0x47, mlxsw_sp_afk_element_info_ipv6_2b),
MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3),
MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4),
MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5),
- MLXSW_AFK_BLOCK(0x90, mlxsw_sp_afk_element_info_l4_0),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x90, mlxsw_sp_afk_element_info_l4_0),
MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2),
};
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
index ee59c79156..50e591420b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c
@@ -24,7 +24,7 @@ struct mlxsw_sp_counter_pool {
spinlock_t counter_pool_lock; /* Protects counter pool allocations */
atomic_t active_entries_count;
unsigned int sub_pools_count;
- struct mlxsw_sp_counter_sub_pool sub_pools[];
+ struct mlxsw_sp_counter_sub_pool sub_pools[] __counted_by(sub_pools_count);
};
static const struct mlxsw_sp_counter_sub_pool mlxsw_sp_counter_sub_pools[] = {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
index 472830d07a..0f29e9c194 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
@@ -619,7 +619,7 @@ static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc)
int i;
for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) {
- snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
+ snprintf(*p, ETH_GSTRING_LEN, "%.28s_%d",
mlxsw_sp_port_hw_tc_stats[i].str, tc);
*p += ETH_GSTRING_LEN;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index 9df0984747..e954b8cd2e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -321,6 +321,14 @@ mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
}
static u16
+mlxsw_sp_fid_family_pgt_size(const struct mlxsw_sp_fid_family *fid_family)
+{
+ u16 num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
+
+ return num_fids * fid_family->nr_flood_tables;
+}
+
+static u16
mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
const struct mlxsw_sp_flood_table *flood_table,
u16 fid_offset)
@@ -1068,8 +1076,6 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
#define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
#define MLXSW_SP_FID_RFID_MAX (11 * 1024)
-#define MLXSW_SP_FID_8021Q_PGT_BASE 0
-#define MLXSW_SP_FID_8021D_PGT_BASE (3 * MLXSW_SP_FID_8021Q_MAX)
static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
{
@@ -1434,7 +1440,6 @@ static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021q_family = {
.ops = &mlxsw_sp_fid_8021q_ops,
.flood_rsp = false,
.bridge_type = MLXSW_REG_BRIDGE_TYPE_0,
- .pgt_base = MLXSW_SP_FID_8021Q_PGT_BASE,
.smpe_index_valid = false,
};
@@ -1448,7 +1453,6 @@ static const struct mlxsw_sp_fid_family mlxsw_sp1_fid_8021d_family = {
.rif_type = MLXSW_SP_RIF_TYPE_FID,
.ops = &mlxsw_sp_fid_8021d_ops,
.bridge_type = MLXSW_REG_BRIDGE_TYPE_1,
- .pgt_base = MLXSW_SP_FID_8021D_PGT_BASE,
.smpe_index_valid = false,
};
@@ -1490,7 +1494,6 @@ static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021q_family = {
.ops = &mlxsw_sp_fid_8021q_ops,
.flood_rsp = false,
.bridge_type = MLXSW_REG_BRIDGE_TYPE_0,
- .pgt_base = MLXSW_SP_FID_8021Q_PGT_BASE,
.smpe_index_valid = true,
};
@@ -1504,7 +1507,6 @@ static const struct mlxsw_sp_fid_family mlxsw_sp2_fid_8021d_family = {
.rif_type = MLXSW_SP_RIF_TYPE_FID,
.ops = &mlxsw_sp_fid_8021d_ops,
.bridge_type = MLXSW_REG_BRIDGE_TYPE_1,
- .pgt_base = MLXSW_SP_FID_8021D_PGT_BASE,
.smpe_index_valid = true,
};
@@ -1654,14 +1656,10 @@ mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
const int *sfgc_packet_types;
- u16 num_fids, mid_base;
+ u16 mid_base;
int err, i;
mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
- num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
- err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, mid_base, num_fids);
- if (err)
- return err;
sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
@@ -1675,57 +1673,56 @@ mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
if (err)
- goto err_reg_write;
+ return err;
}
return 0;
-
-err_reg_write:
- mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
- return err;
-}
-
-static void
-mlxsw_sp_fid_flood_table_fini(struct mlxsw_sp_fid_family *fid_family,
- const struct mlxsw_sp_flood_table *flood_table)
-{
- struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
- u16 num_fids, mid_base;
-
- mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
- num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
- mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
}
static int
mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
{
+ struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
+ u16 pgt_size;
+ int err;
int i;
+ if (!fid_family->nr_flood_tables)
+ return 0;
+
+ pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family);
+ err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, &fid_family->pgt_base,
+ pgt_size);
+ if (err)
+ return err;
+
for (i = 0; i < fid_family->nr_flood_tables; i++) {
const struct mlxsw_sp_flood_table *flood_table;
- int err;
flood_table = &fid_family->flood_tables[i];
err = mlxsw_sp_fid_flood_table_init(fid_family, flood_table);
if (err)
- return err;
+ goto err_flood_table_init;
}
return 0;
+
+err_flood_table_init:
+ mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
+ return err;
}
static void
mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
{
- int i;
+ struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
+ u16 pgt_size;
- for (i = 0; i < fid_family->nr_flood_tables; i++) {
- const struct mlxsw_sp_flood_table *flood_table;
+ if (!fid_family->nr_flood_tables)
+ return;
- flood_table = &fid_family->flood_tables[i];
- mlxsw_sp_fid_flood_table_fini(fid_family, flood_table);
- }
+ pgt_size = mlxsw_sp_fid_family_pgt_size(fid_family);
+ mlxsw_sp_pgt_mid_free_range(mlxsw_sp, fid_family->pgt_base, pgt_size);
}
static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
index 7dd3dba0fa..4ef81bac17 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
@@ -54,25 +54,15 @@ void mlxsw_sp_pgt_mid_free(struct mlxsw_sp *mlxsw_sp, u16 mid_base)
mutex_unlock(&mlxsw_sp->pgt->lock);
}
-int
-mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
+int mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 *p_mid_base,
+ u16 count)
{
- unsigned int idr_cursor;
+ unsigned int mid_base;
int i, err;
mutex_lock(&mlxsw_sp->pgt->lock);
- /* This function is supposed to be called several times as part of
- * driver init, in specific order. Verify that the mid_index is the
- * first free index in the idr, to be able to free the indexes in case
- * of error.
- */
- idr_cursor = idr_get_cursor(&mlxsw_sp->pgt->pgt_idr);
- if (WARN_ON(idr_cursor != mid_base)) {
- err = -EINVAL;
- goto err_idr_cursor;
- }
-
+ mid_base = idr_get_cursor(&mlxsw_sp->pgt->pgt_idr);
for (i = 0; i < count; i++) {
err = idr_alloc_cyclic(&mlxsw_sp->pgt->pgt_idr, NULL,
mid_base, mid_base + count, GFP_KERNEL);
@@ -81,12 +71,12 @@ mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
}
mutex_unlock(&mlxsw_sp->pgt->lock);
+ *p_mid_base = mid_base;
return 0;
err_idr_alloc_cyclic:
for (i--; i >= 0; i--)
idr_remove(&mlxsw_sp->pgt->pgt_idr, mid_base + i);
-err_idr_cursor:
mutex_unlock(&mlxsw_sp->pgt->lock);
return err;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index ae2fb9efbc..39e6d941fd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -3107,7 +3107,7 @@ struct mlxsw_sp_nexthop_group_info {
gateway:1, /* routes using the group use a gateway */
is_resilient:1;
struct list_head list; /* member in nh_res_grp_list */
- struct mlxsw_sp_nexthop nexthops[];
+ struct mlxsw_sp_nexthop nexthops[] __counted_by(count);
};
static struct mlxsw_sp_rif *
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index b3472fb946..af50ff9e5f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -31,7 +31,7 @@ struct mlxsw_sp_span {
refcount_t policer_id_base_ref_count;
atomic_t active_entries_count;
int entries_count;
- struct mlxsw_sp_span_entry entries[];
+ struct mlxsw_sp_span_entry entries[] __counted_by(entries_count);
};
struct mlxsw_sp_span_analyzed_port {