| .. | .. |
|---|
| 35 | 35 | #include "en/port.h" |
|---|
| 36 | 36 | #include "en/port_buffer.h" |
|---|
| 37 | 37 | |
|---|
| 38 | +#define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */ |
|---|
| 39 | + |
|---|
| 38 | 40 | #define MLX5E_100MB (100000) |
|---|
| 39 | 41 | #define MLX5E_1GB (1000000) |
|---|
| 40 | 42 | |
|---|
| .. | .. |
|---|
| 47 | 49 | enum { |
|---|
| 48 | 50 | MLX5E_VENDOR_TC_GROUP_NUM = 7, |
|---|
| 49 | 51 | MLX5E_LOWEST_PRIO_GROUP = 0, |
|---|
| 52 | +}; |
|---|
| 53 | + |
|---|
| 54 | +enum { |
|---|
| 55 | + MLX5_DCB_CHG_RESET, |
|---|
| 56 | + MLX5_DCB_NO_CHG, |
|---|
| 57 | + MLX5_DCB_CHG_NO_RESET, |
|---|
| 50 | 58 | }; |
|---|
| 51 | 59 | |
|---|
| 52 | 60 | #define MLX5_DSCP_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, qcam_reg) && \ |
|---|
| .. | .. |
|---|
| 109 | 117 | if (!MLX5_CAP_GEN(priv->mdev, ets)) |
|---|
| 110 | 118 | return -EOPNOTSUPP; |
|---|
| 111 | 119 | |
|---|
| 112 | | - ets->ets_cap = mlx5_max_tc(priv->mdev) + 1; |
|---|
| 113 | | - for (i = 0; i < ets->ets_cap; i++) { |
|---|
| 120 | + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { |
|---|
| 114 | 121 | err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]); |
|---|
| 115 | 122 | if (err) |
|---|
| 116 | 123 | return err; |
|---|
| 124 | + } |
|---|
| 117 | 125 | |
|---|
| 126 | + ets->ets_cap = mlx5_max_tc(priv->mdev) + 1; |
|---|
| 127 | + for (i = 0; i < ets->ets_cap; i++) { |
|---|
| 118 | 128 | err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]); |
|---|
| 119 | 129 | if (err) |
|---|
| 120 | 130 | return err; |
|---|
| .. | .. |
|---|
| 238 | 248 | * Report both group #0 and #1 as ETS type. |
|---|
| 239 | 249 | * All the tcs in group #0 will be reported with 0% BW. |
|---|
| 240 | 250 | */ |
|---|
| 241 | | -int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets) |
|---|
| 251 | +static int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets) |
|---|
| 242 | 252 | { |
|---|
| 243 | 253 | struct mlx5_core_dev *mdev = priv->mdev; |
|---|
| 244 | 254 | u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS]; |
|---|
| .. | .. |
|---|
| 680 | 690 | |
|---|
| 681 | 691 | memset(perm_addr, 0xff, MAX_ADDR_LEN); |
|---|
| 682 | 692 | |
|---|
| 683 | | - mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr); |
|---|
| 693 | + mlx5_query_mac_address(priv->mdev, perm_addr); |
|---|
| 684 | 694 | } |
|---|
| 685 | 695 | |
|---|
| 686 | 696 | static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev, |
|---|
| .. | .. |
|---|
| 977 | 987 | return err; |
|---|
| 978 | 988 | } |
|---|
| 979 | 989 | |
|---|
| 980 | | -const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = { |
|---|
| 990 | +static const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = { |
|---|
| 981 | 991 | .ieee_getets = mlx5e_dcbnl_ieee_getets, |
|---|
| 982 | 992 | .ieee_setets = mlx5e_dcbnl_ieee_setets, |
|---|
| 983 | 993 | .ieee_getmaxrate = mlx5e_dcbnl_ieee_getmaxrate, |
|---|
| .. | .. |
|---|
| 1008 | 1018 | .getpfcstate = mlx5e_dcbnl_getpfcstate, |
|---|
| 1009 | 1019 | .setpfcstate = mlx5e_dcbnl_setpfcstate, |
|---|
| 1010 | 1020 | }; |
|---|
| 1021 | + |
|---|
| 1022 | +void mlx5e_dcbnl_build_netdev(struct net_device *netdev) |
|---|
| 1023 | +{ |
|---|
| 1024 | + struct mlx5e_priv *priv = netdev_priv(netdev); |
|---|
| 1025 | + struct mlx5_core_dev *mdev = priv->mdev; |
|---|
| 1026 | + |
|---|
| 1027 | + if (MLX5_CAP_GEN(mdev, vport_group_manager) && MLX5_CAP_GEN(mdev, qos)) |
|---|
| 1028 | + netdev->dcbnl_ops = &mlx5e_dcbnl_ops; |
|---|
| 1029 | +} |
|---|
| 1030 | + |
|---|
| 1031 | +void mlx5e_dcbnl_build_rep_netdev(struct net_device *netdev) |
|---|
| 1032 | +{ |
|---|
| 1033 | + struct mlx5e_priv *priv = netdev_priv(netdev); |
|---|
| 1034 | + struct mlx5_core_dev *mdev = priv->mdev; |
|---|
| 1035 | + |
|---|
| 1036 | + if (MLX5_CAP_GEN(mdev, qos)) |
|---|
| 1037 | + netdev->dcbnl_ops = &mlx5e_dcbnl_ops; |
|---|
| 1038 | +} |
|---|
| 1011 | 1039 | |
|---|
| 1012 | 1040 | static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv, |
|---|
| 1013 | 1041 | enum mlx5_dcbx_oper_mode *mode) |
|---|
| .. | .. |
|---|
| 1098 | 1126 | mlx5e_dcbnl_dscp_app(priv, DELETE); |
|---|
| 1099 | 1127 | } |
|---|
| 1100 | 1128 | |
|---|
| 1101 | | -static void mlx5e_trust_update_tx_min_inline_mode(struct mlx5e_priv *priv, |
|---|
| 1102 | | - struct mlx5e_params *params) |
|---|
| 1129 | +static void mlx5e_params_calc_trust_tx_min_inline_mode(struct mlx5_core_dev *mdev, |
|---|
| 1130 | + struct mlx5e_params *params, |
|---|
| 1131 | + u8 trust_state) |
|---|
| 1103 | 1132 | { |
|---|
| 1104 | | - params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(priv->mdev); |
|---|
| 1105 | | - if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP && |
|---|
| 1133 | + mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode); |
|---|
| 1134 | + if (trust_state == MLX5_QPTS_TRUST_DSCP && |
|---|
| 1106 | 1135 | params->tx_min_inline_mode == MLX5_INLINE_MODE_L2) |
|---|
| 1107 | 1136 | params->tx_min_inline_mode = MLX5_INLINE_MODE_IP; |
|---|
| 1108 | 1137 | } |
|---|
| 1109 | 1138 | |
|---|
| 1110 | | -static void mlx5e_trust_update_sq_inline_mode(struct mlx5e_priv *priv) |
|---|
| 1139 | +static int mlx5e_update_trust_state_hw(struct mlx5e_priv *priv, void *context) |
|---|
| 1111 | 1140 | { |
|---|
| 1112 | | - struct mlx5e_channels new_channels = {}; |
|---|
| 1141 | + u8 *trust_state = context; |
|---|
| 1142 | + int err; |
|---|
| 1113 | 1143 | |
|---|
| 1114 | | - mutex_lock(&priv->state_lock); |
|---|
| 1144 | + err = mlx5_set_trust_state(priv->mdev, *trust_state); |
|---|
| 1145 | + if (err) |
|---|
| 1146 | + return err; |
|---|
| 1147 | + priv->dcbx_dp.trust_state = *trust_state; |
|---|
| 1115 | 1148 | |
|---|
| 1116 | | - new_channels.params = priv->channels.params; |
|---|
| 1117 | | - mlx5e_trust_update_tx_min_inline_mode(priv, &new_channels.params); |
|---|
| 1118 | | - |
|---|
| 1119 | | - if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { |
|---|
| 1120 | | - priv->channels.params = new_channels.params; |
|---|
| 1121 | | - goto out; |
|---|
| 1122 | | - } |
|---|
| 1123 | | - |
|---|
| 1124 | | - /* Skip if tx_min_inline is the same */ |
|---|
| 1125 | | - if (new_channels.params.tx_min_inline_mode == |
|---|
| 1126 | | - priv->channels.params.tx_min_inline_mode) |
|---|
| 1127 | | - goto out; |
|---|
| 1128 | | - |
|---|
| 1129 | | - if (mlx5e_open_channels(priv, &new_channels)) |
|---|
| 1130 | | - goto out; |
|---|
| 1131 | | - mlx5e_switch_priv_channels(priv, &new_channels, NULL); |
|---|
| 1132 | | - |
|---|
| 1133 | | -out: |
|---|
| 1134 | | - mutex_unlock(&priv->state_lock); |
|---|
| 1149 | + return 0; |
|---|
| 1135 | 1150 | } |
|---|
| 1136 | 1151 | |
|---|
| 1137 | 1152 | static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state) |
|---|
| 1138 | 1153 | { |
|---|
| 1139 | | - int err; |
|---|
| 1154 | + struct mlx5e_channels new_channels = {}; |
|---|
| 1155 | + bool reset_channels = true; |
|---|
| 1156 | + bool opened; |
|---|
| 1157 | + int err = 0; |
|---|
| 1140 | 1158 | |
|---|
| 1141 | | - err = mlx5_set_trust_state(priv->mdev, trust_state); |
|---|
| 1142 | | - if (err) |
|---|
| 1143 | | - return err; |
|---|
| 1144 | | - priv->dcbx_dp.trust_state = trust_state; |
|---|
| 1145 | | - mlx5e_trust_update_sq_inline_mode(priv); |
|---|
| 1159 | + mutex_lock(&priv->state_lock); |
|---|
| 1160 | + |
|---|
| 1161 | + new_channels.params = priv->channels.params; |
|---|
| 1162 | + mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &new_channels.params, |
|---|
| 1163 | + trust_state); |
|---|
| 1164 | + |
|---|
| 1165 | + opened = test_bit(MLX5E_STATE_OPENED, &priv->state); |
|---|
| 1166 | + if (!opened) |
|---|
| 1167 | + reset_channels = false; |
|---|
| 1168 | + |
|---|
| 1169 | + /* Skip if tx_min_inline is the same */ |
|---|
| 1170 | + if (new_channels.params.tx_min_inline_mode == |
|---|
| 1171 | + priv->channels.params.tx_min_inline_mode) |
|---|
| 1172 | + reset_channels = false; |
|---|
| 1173 | + |
|---|
| 1174 | + if (reset_channels) { |
|---|
| 1175 | + err = mlx5e_safe_switch_channels(priv, &new_channels, |
|---|
| 1176 | + mlx5e_update_trust_state_hw, |
|---|
| 1177 | + &trust_state); |
|---|
| 1178 | + } else { |
|---|
| 1179 | + err = mlx5e_update_trust_state_hw(priv, &trust_state); |
|---|
| 1180 | + if (!err && !opened) |
|---|
| 1181 | + priv->channels.params = new_channels.params; |
|---|
| 1182 | + } |
|---|
| 1183 | + |
|---|
| 1184 | + mutex_unlock(&priv->state_lock); |
|---|
| 1146 | 1185 | |
|---|
| 1147 | 1186 | return err; |
|---|
| 1148 | 1187 | } |
|---|
| .. | .. |
|---|
| 1173 | 1212 | if (err) |
|---|
| 1174 | 1213 | return err; |
|---|
| 1175 | 1214 | |
|---|
| 1176 | | - mlx5e_trust_update_tx_min_inline_mode(priv, &priv->channels.params); |
|---|
| 1215 | + if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_PCP && priv->dcbx.dscp_app_cnt) { |
|---|
| 1216 | + /* |
|---|
| 1217 | + * Align the driver state with the register state. |
|---|
| 1218 | + * Temporary state change is required to enable the app list reset. |
|---|
| 1219 | + */ |
|---|
| 1220 | + priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_DSCP; |
|---|
| 1221 | + mlx5e_dcbnl_delete_app(priv); |
|---|
| 1222 | + priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_PCP; |
|---|
| 1223 | + } |
|---|
| 1224 | + |
|---|
| 1225 | + mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &priv->channels.params, |
|---|
| 1226 | + priv->dcbx_dp.trust_state); |
|---|
| 1177 | 1227 | |
|---|
| 1178 | 1228 | err = mlx5_query_dscp2prio(priv->mdev, priv->dcbx_dp.dscp2prio); |
|---|
| 1179 | 1229 | if (err) |
|---|
| 1180 | 1230 | return err; |
|---|
| 1181 | 1231 | |
|---|
| 1182 | 1232 | return 0; |
|---|
| 1233 | +} |
|---|
| 1234 | + |
|---|
| 1235 | +#define MLX5E_BUFFER_CELL_SHIFT 7 |
|---|
| 1236 | + |
|---|
| 1237 | +static u16 mlx5e_query_port_buffers_cell_size(struct mlx5e_priv *priv) |
|---|
| 1238 | +{ |
|---|
| 1239 | + struct mlx5_core_dev *mdev = priv->mdev; |
|---|
| 1240 | + u32 out[MLX5_ST_SZ_DW(sbcam_reg)] = {}; |
|---|
| 1241 | + u32 in[MLX5_ST_SZ_DW(sbcam_reg)] = {}; |
|---|
| 1242 | + |
|---|
| 1243 | + if (!MLX5_CAP_GEN(mdev, sbcam_reg)) |
|---|
| 1244 | + return (1 << MLX5E_BUFFER_CELL_SHIFT); |
|---|
| 1245 | + |
|---|
| 1246 | + if (mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), |
|---|
| 1247 | + MLX5_REG_SBCAM, 0, 0)) |
|---|
| 1248 | + return (1 << MLX5E_BUFFER_CELL_SHIFT); |
|---|
| 1249 | + |
|---|
| 1250 | + return MLX5_GET(sbcam_reg, out, cap_cell_size); |
|---|
| 1183 | 1251 | } |
|---|
| 1184 | 1252 | |
|---|
| 1185 | 1253 | void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv) |
|---|
| .. | .. |
|---|
| 1199 | 1267 | if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST) |
|---|
| 1200 | 1268 | priv->dcbx.cap |= DCB_CAP_DCBX_HOST; |
|---|
| 1201 | 1269 | |
|---|
| 1270 | + priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv); |
|---|
| 1202 | 1271 | priv->dcbx.manual_buffer = false; |
|---|
| 1203 | 1272 | priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN; |
|---|
| 1204 | 1273 | |
|---|