diff options
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/spectrum.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 618 |
1 files changed, 129 insertions, 489 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 4186e29119c2..16b47fce540b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -42,11 +42,10 @@ #include "spectrum_span.h" #include "spectrum_ptp.h" #include "spectrum_trap.h" -#include "../mlxfw/mlxfw.h" #define MLXSW_SP1_FWREV_MAJOR 13 -#define MLXSW_SP1_FWREV_MINOR 2007 -#define MLXSW_SP1_FWREV_SUBMINOR 1168 +#define MLXSW_SP1_FWREV_MINOR 2008 +#define MLXSW_SP1_FWREV_SUBMINOR 1310 #define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702 static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = { @@ -62,8 +61,8 @@ static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = { "." __stringify(MLXSW_SP1_FWREV_SUBMINOR) ".mfa2" #define MLXSW_SP2_FWREV_MAJOR 29 -#define MLXSW_SP2_FWREV_MINOR 2007 -#define MLXSW_SP2_FWREV_SUBMINOR 1168 +#define MLXSW_SP2_FWREV_MINOR 2008 +#define MLXSW_SP2_FWREV_SUBMINOR 1310 static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = { .major = MLXSW_SP2_FWREV_MAJOR, @@ -77,8 +76,8 @@ static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = { "." __stringify(MLXSW_SP2_FWREV_SUBMINOR) ".mfa2" #define MLXSW_SP3_FWREV_MAJOR 30 -#define MLXSW_SP3_FWREV_MINOR 2007 -#define MLXSW_SP3_FWREV_SUBMINOR 1168 +#define MLXSW_SP3_FWREV_MINOR 2008 +#define MLXSW_SP3_FWREV_SUBMINOR 1310 static const struct mlxsw_fw_rev mlxsw_sp3_fw_rev = { .major = MLXSW_SP3_FWREV_MAJOR, @@ -170,274 +169,6 @@ MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16); */ MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4); -struct mlxsw_sp_mlxfw_dev { - struct mlxfw_dev mlxfw_dev; - struct mlxsw_sp *mlxsw_sp; -}; - -static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev, - u16 component_index, u32 *p_max_size, - u8 *p_align_bits, u16 *p_max_write_size) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcqi_pl[MLXSW_REG_MCQI_LEN]; - int err; - - mlxsw_reg_mcqi_pack(mcqi_pl, component_index); - err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcqi), mcqi_pl); - if (err) - return err; - mlxsw_reg_mcqi_unpack(mcqi_pl, p_max_size, p_align_bits, - p_max_write_size); - - *p_align_bits = max_t(u8, *p_align_bits, 2); - *p_max_write_size = min_t(u16, *p_max_write_size, - MLXSW_REG_MCDA_MAX_DATA_LEN); - return 0; -} - -static int mlxsw_sp_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcc_pl[MLXSW_REG_MCC_LEN]; - u8 control_state; - int err; - - mlxsw_reg_mcc_pack(mcc_pl, 0, 0, 0, 0); - err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); - if (err) - return err; - - mlxsw_reg_mcc_unpack(mcc_pl, fwhandle, NULL, &control_state); - if (control_state != MLXFW_FSM_STATE_IDLE) - return -EBUSY; - - mlxsw_reg_mcc_pack(mcc_pl, - MLXSW_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE, - 0, *fwhandle, 0); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); -} - -static int mlxsw_sp_fsm_component_update(struct mlxfw_dev *mlxfw_dev, - u32 fwhandle, u16 component_index, - u32 component_size) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcc_pl[MLXSW_REG_MCC_LEN]; - - mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_UPDATE_COMPONENT, - component_index, fwhandle, component_size); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); -} - -static int mlxsw_sp_fsm_block_download(struct mlxfw_dev *mlxfw_dev, - u32 fwhandle, u8 *data, u16 size, - u32 offset) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcda_pl[MLXSW_REG_MCDA_LEN]; - - mlxsw_reg_mcda_pack(mcda_pl, fwhandle, offset, size, data); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcda), mcda_pl); -} - -static int mlxsw_sp_fsm_component_verify(struct mlxfw_dev *mlxfw_dev, - u32 fwhandle, u16 component_index) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcc_pl[MLXSW_REG_MCC_LEN]; - - mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_VERIFY_COMPONENT, - component_index, fwhandle, 0); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); -} - -static int mlxsw_sp_fsm_activate(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcc_pl[MLXSW_REG_MCC_LEN]; - - mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_ACTIVATE, 0, - fwhandle, 0); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); -} - -static int mlxsw_sp_fsm_query_state(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, - enum mlxfw_fsm_state *fsm_state, - enum mlxfw_fsm_state_err *fsm_state_err) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcc_pl[MLXSW_REG_MCC_LEN]; - u8 control_state; - u8 error_code; - int err; - - mlxsw_reg_mcc_pack(mcc_pl, 0, 0, fwhandle, 0); - err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); - if (err) - return err; - - mlxsw_reg_mcc_unpack(mcc_pl, NULL, &error_code, &control_state); - *fsm_state = control_state; - *fsm_state_err = min_t(enum mlxfw_fsm_state_err, error_code, - MLXFW_FSM_STATE_ERR_MAX); - return 0; -} - -static void mlxsw_sp_fsm_cancel(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcc_pl[MLXSW_REG_MCC_LEN]; - - mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_CANCEL, 0, - fwhandle, 0); - mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); -} - -static void mlxsw_sp_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) -{ - struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev = - container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp; - char mcc_pl[MLXSW_REG_MCC_LEN]; - - mlxsw_reg_mcc_pack(mcc_pl, - MLXSW_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE, 0, - fwhandle, 0); - mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); -} - -static const struct mlxfw_dev_ops mlxsw_sp_mlxfw_dev_ops = { - .component_query = mlxsw_sp_component_query, - .fsm_lock = mlxsw_sp_fsm_lock, - .fsm_component_update = mlxsw_sp_fsm_component_update, - .fsm_block_download = mlxsw_sp_fsm_block_download, - .fsm_component_verify = mlxsw_sp_fsm_component_verify, - .fsm_activate = mlxsw_sp_fsm_activate, - .fsm_query_state = mlxsw_sp_fsm_query_state, - .fsm_cancel = mlxsw_sp_fsm_cancel, - .fsm_release = mlxsw_sp_fsm_release, -}; - -static int mlxsw_sp_firmware_flash(struct mlxsw_sp *mlxsw_sp, - const struct firmware *firmware, - struct netlink_ext_ack *extack) -{ - struct mlxsw_sp_mlxfw_dev mlxsw_sp_mlxfw_dev = { - .mlxfw_dev = { - .ops = &mlxsw_sp_mlxfw_dev_ops, - .psid = mlxsw_sp->bus_info->psid, - .psid_size = strlen(mlxsw_sp->bus_info->psid), - .devlink = priv_to_devlink(mlxsw_sp->core), - }, - .mlxsw_sp = mlxsw_sp - }; - int err; - - mlxsw_core_fw_flash_start(mlxsw_sp->core); - err = mlxfw_firmware_flash(&mlxsw_sp_mlxfw_dev.mlxfw_dev, - firmware, extack); - mlxsw_core_fw_flash_end(mlxsw_sp->core); - - return err; -} - -static int mlxsw_sp_fw_rev_validate(struct mlxsw_sp *mlxsw_sp) -{ - const struct mlxsw_fw_rev *rev = &mlxsw_sp->bus_info->fw_rev; - const struct mlxsw_fw_rev *req_rev = mlxsw_sp->req_rev; - const char *fw_filename = mlxsw_sp->fw_filename; - union devlink_param_value value; - const struct firmware *firmware; - int err; - - /* Don't check if driver does not require it */ - if (!req_rev || !fw_filename) - return 0; - - /* Don't check if devlink 'fw_load_policy' param is 'flash' */ - err = devlink_param_driverinit_value_get(priv_to_devlink(mlxsw_sp->core), - DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, - &value); - if (err) - return err; - if (value.vu8 == DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH) - return 0; - - /* Validate driver & FW are compatible */ - if (rev->major != req_rev->major) { - WARN(1, "Mismatch in major FW version [%d:%d] is never expected; Please contact support\n", - rev->major, req_rev->major); - return -EINVAL; - } - if (mlxsw_core_fw_rev_minor_subminor_validate(rev, req_rev)) - return 0; - - dev_err(mlxsw_sp->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver (required >= %d.%d.%d)\n", - rev->major, rev->minor, rev->subminor, req_rev->major, - req_rev->minor, req_rev->subminor); - dev_info(mlxsw_sp->bus_info->dev, "Flashing firmware using file %s\n", - fw_filename); - - err = request_firmware_direct(&firmware, fw_filename, - mlxsw_sp->bus_info->dev); - if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Could not request firmware file %s\n", - fw_filename); - return err; - } - - err = mlxsw_sp_firmware_flash(mlxsw_sp, firmware, NULL); - release_firmware(firmware); - if (err) - dev_err(mlxsw_sp->bus_info->dev, "Could not upgrade firmware\n"); - - /* On FW flash success, tell the caller FW reset is needed - * if current FW supports it. - */ - if (rev->minor >= req_rev->can_reset_minor) - return err ? err : -EAGAIN; - else - return 0; -} - -static int mlxsw_sp_flash_update(struct mlxsw_core *mlxsw_core, - const char *file_name, const char *component, - struct netlink_ext_ack *extack) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); - const struct firmware *firmware; - int err; - - if (component) - return -EOPNOTSUPP; - - err = request_firmware_direct(&firmware, file_name, - mlxsw_sp->bus_info->dev); - if (err) - return err; - err = mlxsw_sp_firmware_flash(mlxsw_sp, firmware, extack); - release_firmware(firmware); - - return err; -} - int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp, unsigned int counter_index, u64 *packets, u64 *bytes) @@ -590,21 +321,28 @@ static int mlxsw_sp_port_dev_addr_init(struct mlxsw_sp_port *mlxsw_sp_port) return mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr); } -static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu) +static int mlxsw_sp_port_max_mtu_get(struct mlxsw_sp_port *mlxsw_sp_port, int *p_max_mtu) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; char pmtu_pl[MLXSW_REG_PMTU_LEN]; - int max_mtu; int err; - mtu += MLXSW_TXHDR_LEN + ETH_HLEN; mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, 0); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl); if (err) return err; - max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl); - if (mtu > max_mtu) + *p_max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl); + return 0; +} + +static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char pmtu_pl[MLXSW_REG_PMTU_LEN]; + + mtu += MLXSW_TXHDR_LEN + ETH_HLEN; + if (mtu > mlxsw_sp_port->max_mtu) return -EINVAL; mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, mtu); @@ -872,133 +610,25 @@ static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p) return 0; } -static u16 mlxsw_sp_pg_buf_threshold_get(const struct mlxsw_sp *mlxsw_sp, - int mtu) -{ - return 2 * mlxsw_sp_bytes_cells(mlxsw_sp, mtu); -} - -#define MLXSW_SP_CELL_FACTOR 2 /* 2 * cell_size / (IPG + cell_size + 1) */ - -static u16 mlxsw_sp_pfc_delay_get(const struct mlxsw_sp *mlxsw_sp, int mtu, - u16 delay) -{ - delay = mlxsw_sp_bytes_cells(mlxsw_sp, DIV_ROUND_UP(delay, - BITS_PER_BYTE)); - return MLXSW_SP_CELL_FACTOR * delay + mlxsw_sp_bytes_cells(mlxsw_sp, - mtu); -} - -/* Maximum delay buffer needed in case of PAUSE frames, in bytes. - * Assumes 100m cable and maximum MTU. - */ -#define MLXSW_SP_PAUSE_DELAY 58752 - -static u16 mlxsw_sp_pg_buf_delay_get(const struct mlxsw_sp *mlxsw_sp, int mtu, - u16 delay, bool pfc, bool pause) -{ - if (pfc) - return mlxsw_sp_pfc_delay_get(mlxsw_sp, mtu, delay); - else if (pause) - return mlxsw_sp_bytes_cells(mlxsw_sp, MLXSW_SP_PAUSE_DELAY); - else - return 0; -} - -static void mlxsw_sp_pg_buf_pack(char *pbmc_pl, int index, u16 size, u16 thres, - bool lossy) +static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) { - if (lossy) - mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, index, size); - else - mlxsw_reg_pbmc_lossless_buffer_pack(pbmc_pl, index, size, - thres); -} + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp_hdroom orig_hdroom; + struct mlxsw_sp_hdroom hdroom; + int err; -int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu, - u8 *prio_tc, bool pause_en, - struct ieee_pfc *my_pfc) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u8 pfc_en = !!my_pfc ? my_pfc->pfc_en : 0; - u16 delay = !!my_pfc ? my_pfc->delay : 0; - char pbmc_pl[MLXSW_REG_PBMC_LEN]; - u32 taken_headroom_cells = 0; - u32 max_headroom_cells; - int i, j, err; + orig_hdroom = *mlxsw_sp_port->hdroom; - max_headroom_cells = mlxsw_sp_sb_max_headroom_cells(mlxsw_sp); + hdroom = orig_hdroom; + hdroom.mtu = mtu; + mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom); - mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, 0, 0); - err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); - if (err) + err = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom); + if (err) { + netdev_err(dev, "Failed to configure port's headroom\n"); return err; - - for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { - bool configure = false; - bool pfc = false; - u16 thres_cells; - u16 delay_cells; - u16 total_cells; - bool lossy; - - for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) { - if (prio_tc[j] == i) { - pfc = pfc_en & BIT(j); - configure = true; - break; - } - } - - if (!configure) - continue; - - lossy = !(pfc || pause_en); - thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu); - thres_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, thres_cells); - delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay, - pfc, pause_en); - delay_cells = mlxsw_sp_port_headroom_8x_adjust(mlxsw_sp_port, delay_cells); - total_cells = thres_cells + delay_cells; - - taken_headroom_cells += total_cells; - if (taken_headroom_cells > max_headroom_cells) - return -ENOBUFS; - - mlxsw_sp_pg_buf_pack(pbmc_pl, i, total_cells, - thres_cells, lossy); } - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl); -} - -int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, - int mtu, bool pause_en) -{ - u8 def_prio_tc[IEEE_8021QAZ_MAX_TCS] = {0}; - bool dcb_en = !!mlxsw_sp_port->dcb.ets; - struct ieee_pfc *my_pfc; - u8 *prio_tc; - - prio_tc = dcb_en ? mlxsw_sp_port->dcb.ets->prio_tc : def_prio_tc; - my_pfc = dcb_en ? mlxsw_sp_port->dcb.pfc : NULL; - - return __mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, prio_tc, - pause_en, my_pfc); -} - -static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) -{ - struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); - bool pause_en = mlxsw_sp_port_is_pause_en(mlxsw_sp_port); - int err; - - err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, mtu, pause_en); - if (err) - return err; - err = mlxsw_sp_span_port_mtu_update(mlxsw_sp_port, mtu); - if (err) - goto err_span_port_mtu_update; err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu); if (err) goto err_port_mtu_set; @@ -1006,9 +636,7 @@ static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) return 0; err_port_mtu_set: - mlxsw_sp_span_port_mtu_update(mlxsw_sp_port, dev->mtu); -err_span_port_mtu_update: - mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en); + mlxsw_sp_hdroom_configure(mlxsw_sp_port, &orig_hdroom); return err; } @@ -1737,6 +1365,22 @@ static int mlxsw_sp_port_tc_mc_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qtctm), qtctm_pl); } +static int mlxsw_sp_port_overheat_init_val_set(struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u8 module = mlxsw_sp_port->mapping.module; + u64 overheat_counter; + int err; + + err = mlxsw_env_module_overheat_counter_get(mlxsw_sp->core, module, + &overheat_counter); + if (err) + return err; + + mlxsw_sp_port->module_overheat_initial_val = overheat_counter; + return 0; +} + static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, u8 split_base_local_port, struct mlxsw_sp_port_mapping *port_mapping) @@ -1842,6 +1486,21 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_port_speed_by_width_set; } + err = mlxsw_sp->port_type_speed_ops->ptys_max_speed(mlxsw_sp_port, + &mlxsw_sp_port->max_speed); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to get maximum speed\n", + mlxsw_sp_port->local_port); + goto err_max_speed_get; + } + + err = mlxsw_sp_port_max_mtu_get(mlxsw_sp_port, &mlxsw_sp_port->max_mtu); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to get maximum MTU\n", + mlxsw_sp_port->local_port); + goto err_port_max_mtu_get; + } + err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, ETH_DATA_LEN); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set MTU\n", @@ -1930,10 +1589,16 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, INIT_DELAYED_WORK(&mlxsw_sp_port->ptp.shaper_dw, mlxsw_sp->ptp_ops->shaper_work); - INIT_DELAYED_WORK(&mlxsw_sp_port->span.speed_update_dw, - mlxsw_sp_span_speed_update_work); mlxsw_sp->ports[local_port] = mlxsw_sp_port; + + err = mlxsw_sp_port_overheat_init_val_set(mlxsw_sp_port); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set overheat initial value\n", + mlxsw_sp_port->local_port); + goto err_port_overheat_init_val_set; + } + err = register_netdev(dev); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register netdev\n", @@ -1947,6 +1612,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, return 0; err_register_netdev: +err_port_overheat_init_val_set: mlxsw_sp->ports[local_port] = NULL; mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan); err_port_vlan_create: @@ -1963,9 +1629,12 @@ err_port_dcb_init: mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false); err_port_tc_mc_mode: err_port_ets_init: + mlxsw_sp_port_buffers_fini(mlxsw_sp_port); err_port_buffers_init: err_port_admin_status_set: err_port_mtu_set: +err_port_max_mtu_get: +err_max_speed_get: err_port_speed_by_width_set: err_port_system_port_mapping_set: err_dev_addr_init: @@ -1986,7 +1655,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; cancel_delayed_work_sync(&mlxsw_sp_port->periodic_hw_stats.update_dw); - cancel_delayed_work_sync(&mlxsw_sp_port->span.speed_update_dw); cancel_delayed_work_sync(&mlxsw_sp_port->ptp.shaper_dw); mlxsw_sp_port_ptp_clear(mlxsw_sp_port); mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp); @@ -1998,6 +1666,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_sp_port_fids_fini(mlxsw_sp_port); mlxsw_sp_port_dcb_fini(mlxsw_sp_port); mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false); + mlxsw_sp_port_buffers_fini(mlxsw_sp_port); mlxsw_sp_port_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT); mlxsw_sp_port_module_unmap(mlxsw_sp_port); free_percpu(mlxsw_sp_port->pcpu_stats); @@ -2390,7 +2059,6 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, netdev_info(mlxsw_sp_port->dev, "link up\n"); netif_carrier_on(mlxsw_sp_port->dev); mlxsw_core_schedule_dw(&mlxsw_sp_port->ptp.shaper_dw, 0); - mlxsw_core_schedule_dw(&mlxsw_sp_port->span.speed_update_dw, 0); } else { netdev_info(mlxsw_sp_port->dev, "link down\n"); netif_carrier_off(mlxsw_sp_port->dev); @@ -2783,11 +2451,36 @@ static void mlxsw_sp_lag_fini(struct mlxsw_sp *mlxsw_sp) static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core) { char htgt_pl[MLXSW_REG_HTGT_LEN]; + int err; mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, MLXSW_REG_HTGT_INVALID_POLICER, MLXSW_REG_HTGT_DEFAULT_PRIORITY, MLXSW_REG_HTGT_DEFAULT_TC); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); + if (err) + return err; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_MFDE, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); + if (err) + return err; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_MTWE, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); + err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); + if (err) + return err; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_PMPE, + MLXSW_REG_HTGT_INVALID_POLICER, + MLXSW_REG_HTGT_DEFAULT_PRIORITY, + MLXSW_REG_HTGT_DEFAULT_TC); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl); } @@ -2836,10 +2529,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->core = mlxsw_core; mlxsw_sp->bus_info = mlxsw_bus_info; - err = mlxsw_sp_fw_rev_validate(mlxsw_sp); - if (err) - return err; - mlxsw_core_emad_string_tlv_enable(mlxsw_core); err = mlxsw_sp_base_mac_get(mlxsw_sp); @@ -3039,8 +2728,6 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); - mlxsw_sp->req_rev = &mlxsw_sp1_fw_rev; - mlxsw_sp->fw_filename = MLXSW_SP1_FW_FILENAME; mlxsw_sp->kvdl_ops = &mlxsw_sp1_kvdl_ops; mlxsw_sp->afa_ops = &mlxsw_sp1_act_afa_ops; mlxsw_sp->afk_ops = &mlxsw_sp1_afk_ops; @@ -3051,6 +2738,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp1_rif_ops_arr; mlxsw_sp->sb_vals = &mlxsw_sp1_sb_vals; + mlxsw_sp->sb_ops = &mlxsw_sp1_sb_ops; mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops; mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops; mlxsw_sp->span_ops = &mlxsw_sp1_span_ops; @@ -3069,8 +2757,6 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); - mlxsw_sp->req_rev = &mlxsw_sp2_fw_rev; - mlxsw_sp->fw_filename = MLXSW_SP2_FW_FILENAME; mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops; mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops; mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops; @@ -3081,6 +2767,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr; mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; + mlxsw_sp->sb_ops = &mlxsw_sp2_sb_ops; mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops; mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops; mlxsw_sp->span_ops = &mlxsw_sp2_span_ops; @@ -3097,8 +2784,6 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core, { struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core); - mlxsw_sp->req_rev = &mlxsw_sp3_fw_rev; - mlxsw_sp->fw_filename = MLXSW_SP3_FW_FILENAME; mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops; mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops; mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops; @@ -3109,6 +2794,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core, mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask; mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr; mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; + mlxsw_sp->sb_ops = &mlxsw_sp3_sb_ops; mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops; mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops; mlxsw_sp->span_ops = &mlxsw_sp3_span_ops; @@ -3451,52 +3137,6 @@ static int mlxsw_sp_kvd_sizes_get(struct mlxsw_core *mlxsw_core, } static int -mlxsw_sp_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id, - union devlink_param_value val, - struct netlink_ext_ack *extack) -{ - if ((val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER) && - (val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH)) { - NL_SET_ERR_MSG_MOD(extack, "'fw_load_policy' must be 'driver' or 'flash'"); - return -EINVAL; - } - - return 0; -} - -static const struct devlink_param mlxsw_sp_devlink_params[] = { - DEVLINK_PARAM_GENERIC(FW_LOAD_POLICY, - BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), - NULL, NULL, - mlxsw_sp_devlink_param_fw_load_policy_validate), -}; - -static int mlxsw_sp_params_register(struct mlxsw_core *mlxsw_core) -{ - struct devlink *devlink = priv_to_devlink(mlxsw_core); - union devlink_param_value value; - int err; - - err = devlink_params_register(devlink, mlxsw_sp_devlink_params, - ARRAY_SIZE(mlxsw_sp_devlink_params)); - if (err) - return err; - - value.vu8 = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER; - devlink_param_driverinit_value_set(devlink, - DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, - value); - return 0; -} - -static void mlxsw_sp_params_unregister(struct mlxsw_core *mlxsw_core) -{ - devlink_params_unregister(priv_to_devlink(mlxsw_core), - mlxsw_sp_devlink_params, - ARRAY_SIZE(mlxsw_sp_devlink_params)); -} - -static int mlxsw_sp_params_acl_region_rehash_intrvl_get(struct devlink *devlink, u32 id, struct devlink_param_gset_ctx *ctx) { @@ -3533,24 +3173,16 @@ static int mlxsw_sp2_params_register(struct mlxsw_core *mlxsw_core) union devlink_param_value value; int err; - err = mlxsw_sp_params_register(mlxsw_core); - if (err) - return err; - err = devlink_params_register(devlink, mlxsw_sp2_devlink_params, ARRAY_SIZE(mlxsw_sp2_devlink_params)); if (err) - goto err_devlink_params_register; + return err; value.vu32 = 0; devlink_param_driverinit_value_set(devlink, MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL, value); return 0; - -err_devlink_params_register: - mlxsw_sp_params_unregister(mlxsw_core); - return err; } static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core) @@ -3558,7 +3190,6 @@ static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core) devlink_params_unregister(priv_to_devlink(mlxsw_core), mlxsw_sp2_devlink_params, ARRAY_SIZE(mlxsw_sp2_devlink_params)); - mlxsw_sp_params_unregister(mlxsw_core); } static void mlxsw_sp_ptp_transmitted(struct mlxsw_core *mlxsw_core, @@ -3573,6 +3204,8 @@ static void mlxsw_sp_ptp_transmitted(struct mlxsw_core *mlxsw_core, static struct mlxsw_driver mlxsw_sp1_driver = { .kind = mlxsw_sp1_driver_name, .priv_size = sizeof(struct mlxsw_sp), + .fw_req_rev = &mlxsw_sp1_fw_rev, + .fw_filename = MLXSW_SP1_FW_FILENAME, .init = mlxsw_sp1_init, .fini = mlxsw_sp_fini, .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set, @@ -3588,7 +3221,6 @@ static struct mlxsw_driver mlxsw_sp1_driver = { .sb_occ_max_clear = mlxsw_sp_sb_occ_max_clear, .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, - .flash_update = mlxsw_sp_flash_update, .trap_init = mlxsw_sp_trap_init, .trap_fini = mlxsw_sp_trap_fini, .trap_action_set = mlxsw_sp_trap_action_set, @@ -3601,17 +3233,19 @@ static struct mlxsw_driver mlxsw_sp1_driver = { .txhdr_construct = mlxsw_sp_txhdr_construct, .resources_register = mlxsw_sp1_resources_register, .kvd_sizes_get = mlxsw_sp_kvd_sizes_get, - .params_register = mlxsw_sp_params_register, - .params_unregister = mlxsw_sp_params_unregister, .ptp_transmitted = mlxsw_sp_ptp_transmitted, .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sp1_config_profile, .res_query_enabled = true, + .fw_fatal_enabled = true, + .temp_warn_enabled = true, }; static struct mlxsw_driver mlxsw_sp2_driver = { .kind = mlxsw_sp2_driver_name, .priv_size = sizeof(struct mlxsw_sp), + .fw_req_rev = &mlxsw_sp2_fw_rev, + .fw_filename = MLXSW_SP2_FW_FILENAME, .init = mlxsw_sp2_init, .fini = mlxsw_sp_fini, .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set, @@ -3627,7 +3261,6 @@ static struct mlxsw_driver mlxsw_sp2_driver = { .sb_occ_max_clear = mlxsw_sp_sb_occ_max_clear, .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, - .flash_update = mlxsw_sp_flash_update, .trap_init = mlxsw_sp_trap_init, .trap_fini = mlxsw_sp_trap_fini, .trap_action_set = mlxsw_sp_trap_action_set, @@ -3645,11 +3278,15 @@ static struct mlxsw_driver mlxsw_sp2_driver = { .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sp2_config_profile, .res_query_enabled = true, + .fw_fatal_enabled = true, + .temp_warn_enabled = true, }; static struct mlxsw_driver mlxsw_sp3_driver = { .kind = mlxsw_sp3_driver_name, .priv_size = sizeof(struct mlxsw_sp), + .fw_req_rev = &mlxsw_sp3_fw_rev, + .fw_filename = MLXSW_SP3_FW_FILENAME, .init = mlxsw_sp3_init, .fini = mlxsw_sp_fini, .basic_trap_groups_set = mlxsw_sp_basic_trap_groups_set, @@ -3665,7 +3302,6 @@ static struct mlxsw_driver mlxsw_sp3_driver = { .sb_occ_max_clear = mlxsw_sp_sb_occ_max_clear, .sb_occ_port_pool_get = mlxsw_sp_sb_occ_port_pool_get, .sb_occ_tc_port_bind_get = mlxsw_sp_sb_occ_tc_port_bind_get, - .flash_update = mlxsw_sp_flash_update, .trap_init = mlxsw_sp_trap_init, .trap_fini = mlxsw_sp_trap_fini, .trap_action_set = mlxsw_sp_trap_action_set, @@ -3683,6 +3319,8 @@ static struct mlxsw_driver mlxsw_sp3_driver = { .txhdr_len = MLXSW_TXHDR_LEN, .profile = &mlxsw_sp2_config_profile, .res_query_enabled = true, + .fw_fatal_enabled = true, + .temp_warn_enabled = true, }; bool mlxsw_sp_port_dev_check(const struct net_device *dev) @@ -3690,13 +3328,13 @@ bool mlxsw_sp_port_dev_check(const struct net_device *dev) return dev->netdev_ops == &mlxsw_sp_port_netdev_ops; } -static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev, void *data) +static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev, + struct netdev_nested_priv *priv) { - struct mlxsw_sp_port **p_mlxsw_sp_port = data; int ret = 0; if (mlxsw_sp_port_dev_check(lower_dev)) { - *p_mlxsw_sp_port = netdev_priv(lower_dev); + priv->data = (void *)netdev_priv(lower_dev); ret = 1; } @@ -3705,15 +3343,16 @@ static int mlxsw_sp_lower_dev_walk(struct net_device *lower_dev, void *data) struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev) { - struct mlxsw_sp_port *mlxsw_sp_port; + struct netdev_nested_priv priv = { + .data = NULL, + }; if (mlxsw_sp_port_dev_check(dev)) return netdev_priv(dev); - mlxsw_sp_port = NULL; - netdev_walk_all_lower_dev(dev, mlxsw_sp_lower_dev_walk, &mlxsw_sp_port); + netdev_walk_all_lower_dev(dev, mlxsw_sp_lower_dev_walk, &priv); - return mlxsw_sp_port; + return (struct mlxsw_sp_port *)priv.data; } struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev) @@ -3726,16 +3365,17 @@ struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev) struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev) { - struct mlxsw_sp_port *mlxsw_sp_port; + struct netdev_nested_priv priv = { + .data = NULL, + }; if (mlxsw_sp_port_dev_check(dev)) return netdev_priv(dev); - mlxsw_sp_port = NULL; netdev_walk_all_lower_dev_rcu(dev, mlxsw_sp_lower_dev_walk, - &mlxsw_sp_port); + &priv); - return mlxsw_sp_port; + return (struct mlxsw_sp_port *)priv.data; } struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev) |