diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index e52841627966396a2a027c761fcd8087a2085d0e..9f344914c4a57c080ef4e3bf512e3ca624047988 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -3544,6 +3544,42 @@ mlxsw_reg_qpdpm_dscp_pack(char *payload, unsigned short dscp, u8 prio) mlxsw_reg_qpdpm_dscp_entry_prio_set(payload, dscp, prio); } +/* QTCTM - QoS Switch Traffic Class Table is Multicast-Aware Register + * ------------------------------------------------------------------ + * This register configures if the Switch Priority to Traffic Class mapping is + * based on Multicast packet indication. If so, then multicast packets will get + * a Traffic Class that is plus (cap_max_tclass_data/2) the value configured by + * QTCT. + * By default, Switch Priority to Traffic Class mapping is not based on + * Multicast packet indication. + */ +#define MLXSW_REG_QTCTM_ID 0x401A +#define MLXSW_REG_QTCTM_LEN 0x08 + +MLXSW_REG_DEFINE(qtctm, MLXSW_REG_QTCTM_ID, MLXSW_REG_QTCTM_LEN); + +/* reg_qtctm_local_port + * Local port number. + * No support for CPU port. + * Access: Index + */ +MLXSW_ITEM32(reg, qtctm, local_port, 0x00, 16, 8); + +/* reg_qtctm_mc + * Multicast Mode + * Whether Switch Priority to Traffic Class mapping is based on Multicast packet + * indication (default is 0, not based on Multicast packet indication). + */ +MLXSW_ITEM32(reg, qtctm, mc, 0x04, 0, 1); + +static inline void +mlxsw_reg_qtctm_pack(char *payload, u8 local_port, bool mc) +{ + MLXSW_REG_ZERO(qtctm, payload); + mlxsw_reg_qtctm_local_port_set(payload, local_port); + mlxsw_reg_qtctm_mc_set(payload, mc); +} + /* PMLP - Ports Module to Local Port Register * ------------------------------------------ * Configures the assignment of modules to local ports. @@ -8761,6 +8797,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(qrwe), MLXSW_REG(qpdsm), MLXSW_REG(qpdpm), + MLXSW_REG(qtctm), MLXSW_REG(pmlp), MLXSW_REG(pmtu), MLXSW_REG(ptys), diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 039228525fb10bdf57a6354af02ad33c6961fe7c..028ecc9aa5f1106de19e351b94ced5e9aafe6ed7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2793,9 +2793,16 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port) false, 0); if (err) return err; + + err = mlxsw_sp_port_ets_set(mlxsw_sp_port, + MLXSW_REG_QEEC_HIERARCY_TC, + i + 8, i, + false, 0); + if (err) + return err; } - /* Make sure the max shaper is disabled in all hierarcies that + /* Make sure the max shaper is disabled in all hierarchies that * support it. */ err = mlxsw_sp_port_ets_maxrate_set(mlxsw_sp_port, @@ -2830,6 +2837,16 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port) return 0; } +static int mlxsw_sp_port_tc_mc_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, + bool enable) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char qtctm_pl[MLXSW_REG_QTCTM_LEN]; + + mlxsw_reg_qtctm_pack(qtctm_pl, mlxsw_sp_port->local_port, enable); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qtctm), qtctm_pl); +} + static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, bool split, u8 module, u8 width, u8 lane) { @@ -2958,6 +2975,13 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, goto err_port_ets_init; } + err = mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, true); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize TC MC mode\n", + mlxsw_sp_port->local_port); + goto err_port_tc_mc_mode; + } + /* ETS and buffers must be initialized before DCB. */ err = mlxsw_sp_port_dcb_init(mlxsw_sp_port); if (err) { @@ -3014,6 +3038,8 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err_port_fids_init: mlxsw_sp_port_dcb_fini(mlxsw_sp_port); err_port_dcb_init: + mlxsw_sp_port_tc_mc_mode_set(mlxsw_sp_port, false); +err_port_tc_mc_mode: err_port_ets_init: err_port_buffers_init: err_port_admin_status_set: @@ -3048,6 +3074,7 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_sp_tc_qdisc_fini(mlxsw_sp_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_swid_set(mlxsw_sp_port, MLXSW_PORT_SWID_DISABLED_PORT); mlxsw_sp_port_module_unmap(mlxsw_sp_port); kfree(mlxsw_sp_port->sample);