0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <linux/debugfs.h>
0034
0035 #include "mlx5_ib.h"
0036 #include "cmd.h"
0037
0038 enum mlx5_ib_cong_node_type {
0039 MLX5_IB_RROCE_ECN_RP = 1,
0040 MLX5_IB_RROCE_ECN_NP = 2,
0041 };
0042
0043 static const char * const mlx5_ib_dbg_cc_name[] = {
0044 "rp_clamp_tgt_rate",
0045 "rp_clamp_tgt_rate_ati",
0046 "rp_time_reset",
0047 "rp_byte_reset",
0048 "rp_threshold",
0049 "rp_ai_rate",
0050 "rp_max_rate",
0051 "rp_hai_rate",
0052 "rp_min_dec_fac",
0053 "rp_min_rate",
0054 "rp_rate_to_set_on_first_cnp",
0055 "rp_dce_tcp_g",
0056 "rp_dce_tcp_rtt",
0057 "rp_rate_reduce_monitor_period",
0058 "rp_initial_alpha_value",
0059 "rp_gd",
0060 "np_min_time_between_cnps",
0061 "np_cnp_dscp",
0062 "np_cnp_prio_mode",
0063 "np_cnp_prio",
0064 };
0065
0066 #define MLX5_IB_RP_CLAMP_TGT_RATE_ATTR BIT(1)
0067 #define MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR BIT(2)
0068 #define MLX5_IB_RP_TIME_RESET_ATTR BIT(3)
0069 #define MLX5_IB_RP_BYTE_RESET_ATTR BIT(4)
0070 #define MLX5_IB_RP_THRESHOLD_ATTR BIT(5)
0071 #define MLX5_IB_RP_MAX_RATE_ATTR BIT(6)
0072 #define MLX5_IB_RP_AI_RATE_ATTR BIT(7)
0073 #define MLX5_IB_RP_HAI_RATE_ATTR BIT(8)
0074 #define MLX5_IB_RP_MIN_DEC_FAC_ATTR BIT(9)
0075 #define MLX5_IB_RP_MIN_RATE_ATTR BIT(10)
0076 #define MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR BIT(11)
0077 #define MLX5_IB_RP_DCE_TCP_G_ATTR BIT(12)
0078 #define MLX5_IB_RP_DCE_TCP_RTT_ATTR BIT(13)
0079 #define MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR BIT(14)
0080 #define MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR BIT(15)
0081 #define MLX5_IB_RP_GD_ATTR BIT(16)
0082
0083 #define MLX5_IB_NP_MIN_TIME_BETWEEN_CNPS_ATTR BIT(2)
0084 #define MLX5_IB_NP_CNP_DSCP_ATTR BIT(3)
0085 #define MLX5_IB_NP_CNP_PRIO_MODE_ATTR BIT(4)
0086
0087 static enum mlx5_ib_cong_node_type
0088 mlx5_ib_param_to_node(enum mlx5_ib_dbg_cc_types param_offset)
0089 {
0090 if (param_offset >= MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE &&
0091 param_offset <= MLX5_IB_DBG_CC_RP_GD)
0092 return MLX5_IB_RROCE_ECN_RP;
0093 else
0094 return MLX5_IB_RROCE_ECN_NP;
0095 }
0096
0097 static u32 mlx5_get_cc_param_val(void *field, int offset)
0098 {
0099 switch (offset) {
0100 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE:
0101 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0102 clamp_tgt_rate);
0103 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI:
0104 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0105 clamp_tgt_rate_after_time_inc);
0106 case MLX5_IB_DBG_CC_RP_TIME_RESET:
0107 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0108 rpg_time_reset);
0109 case MLX5_IB_DBG_CC_RP_BYTE_RESET:
0110 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0111 rpg_byte_reset);
0112 case MLX5_IB_DBG_CC_RP_THRESHOLD:
0113 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0114 rpg_threshold);
0115 case MLX5_IB_DBG_CC_RP_AI_RATE:
0116 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0117 rpg_ai_rate);
0118 case MLX5_IB_DBG_CC_RP_MAX_RATE:
0119 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0120 rpg_max_rate);
0121 case MLX5_IB_DBG_CC_RP_HAI_RATE:
0122 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0123 rpg_hai_rate);
0124 case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC:
0125 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0126 rpg_min_dec_fac);
0127 case MLX5_IB_DBG_CC_RP_MIN_RATE:
0128 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0129 rpg_min_rate);
0130 case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP:
0131 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0132 rate_to_set_on_first_cnp);
0133 case MLX5_IB_DBG_CC_RP_DCE_TCP_G:
0134 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0135 dce_tcp_g);
0136 case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT:
0137 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0138 dce_tcp_rtt);
0139 case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD:
0140 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0141 rate_reduce_monitor_period);
0142 case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE:
0143 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0144 initial_alpha_value);
0145 case MLX5_IB_DBG_CC_RP_GD:
0146 return MLX5_GET(cong_control_r_roce_ecn_rp, field,
0147 rpg_gd);
0148 case MLX5_IB_DBG_CC_NP_MIN_TIME_BETWEEN_CNPS:
0149 return MLX5_GET(cong_control_r_roce_ecn_np, field,
0150 min_time_between_cnps);
0151 case MLX5_IB_DBG_CC_NP_CNP_DSCP:
0152 return MLX5_GET(cong_control_r_roce_ecn_np, field,
0153 cnp_dscp);
0154 case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE:
0155 return MLX5_GET(cong_control_r_roce_ecn_np, field,
0156 cnp_prio_mode);
0157 case MLX5_IB_DBG_CC_NP_CNP_PRIO:
0158 return MLX5_GET(cong_control_r_roce_ecn_np, field,
0159 cnp_802p_prio);
0160 default:
0161 return 0;
0162 }
0163 }
0164
0165 static void mlx5_ib_set_cc_param_mask_val(void *field, int offset,
0166 u32 var, u32 *attr_mask)
0167 {
0168 switch (offset) {
0169 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE:
0170 *attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATTR;
0171 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0172 clamp_tgt_rate, var);
0173 break;
0174 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI:
0175 *attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR;
0176 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0177 clamp_tgt_rate_after_time_inc, var);
0178 break;
0179 case MLX5_IB_DBG_CC_RP_TIME_RESET:
0180 *attr_mask |= MLX5_IB_RP_TIME_RESET_ATTR;
0181 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0182 rpg_time_reset, var);
0183 break;
0184 case MLX5_IB_DBG_CC_RP_BYTE_RESET:
0185 *attr_mask |= MLX5_IB_RP_BYTE_RESET_ATTR;
0186 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0187 rpg_byte_reset, var);
0188 break;
0189 case MLX5_IB_DBG_CC_RP_THRESHOLD:
0190 *attr_mask |= MLX5_IB_RP_THRESHOLD_ATTR;
0191 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0192 rpg_threshold, var);
0193 break;
0194 case MLX5_IB_DBG_CC_RP_AI_RATE:
0195 *attr_mask |= MLX5_IB_RP_AI_RATE_ATTR;
0196 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0197 rpg_ai_rate, var);
0198 break;
0199 case MLX5_IB_DBG_CC_RP_MAX_RATE:
0200 *attr_mask |= MLX5_IB_RP_MAX_RATE_ATTR;
0201 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0202 rpg_max_rate, var);
0203 break;
0204 case MLX5_IB_DBG_CC_RP_HAI_RATE:
0205 *attr_mask |= MLX5_IB_RP_HAI_RATE_ATTR;
0206 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0207 rpg_hai_rate, var);
0208 break;
0209 case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC:
0210 *attr_mask |= MLX5_IB_RP_MIN_DEC_FAC_ATTR;
0211 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0212 rpg_min_dec_fac, var);
0213 break;
0214 case MLX5_IB_DBG_CC_RP_MIN_RATE:
0215 *attr_mask |= MLX5_IB_RP_MIN_RATE_ATTR;
0216 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0217 rpg_min_rate, var);
0218 break;
0219 case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP:
0220 *attr_mask |= MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR;
0221 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0222 rate_to_set_on_first_cnp, var);
0223 break;
0224 case MLX5_IB_DBG_CC_RP_DCE_TCP_G:
0225 *attr_mask |= MLX5_IB_RP_DCE_TCP_G_ATTR;
0226 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0227 dce_tcp_g, var);
0228 break;
0229 case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT:
0230 *attr_mask |= MLX5_IB_RP_DCE_TCP_RTT_ATTR;
0231 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0232 dce_tcp_rtt, var);
0233 break;
0234 case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD:
0235 *attr_mask |= MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR;
0236 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0237 rate_reduce_monitor_period, var);
0238 break;
0239 case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE:
0240 *attr_mask |= MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR;
0241 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0242 initial_alpha_value, var);
0243 break;
0244 case MLX5_IB_DBG_CC_RP_GD:
0245 *attr_mask |= MLX5_IB_RP_GD_ATTR;
0246 MLX5_SET(cong_control_r_roce_ecn_rp, field,
0247 rpg_gd, var);
0248 break;
0249 case MLX5_IB_DBG_CC_NP_MIN_TIME_BETWEEN_CNPS:
0250 *attr_mask |= MLX5_IB_NP_MIN_TIME_BETWEEN_CNPS_ATTR;
0251 MLX5_SET(cong_control_r_roce_ecn_np, field,
0252 min_time_between_cnps, var);
0253 break;
0254 case MLX5_IB_DBG_CC_NP_CNP_DSCP:
0255 *attr_mask |= MLX5_IB_NP_CNP_DSCP_ATTR;
0256 MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_dscp, var);
0257 break;
0258 case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE:
0259 *attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR;
0260 MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_prio_mode, var);
0261 break;
0262 case MLX5_IB_DBG_CC_NP_CNP_PRIO:
0263 *attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR;
0264 MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_prio_mode, 0);
0265 MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_802p_prio, var);
0266 break;
0267 }
0268 }
0269
0270 static int mlx5_ib_get_cc_params(struct mlx5_ib_dev *dev, u32 port_num,
0271 int offset, u32 *var)
0272 {
0273 int outlen = MLX5_ST_SZ_BYTES(query_cong_params_out);
0274 void *out;
0275 void *field;
0276 int err;
0277 enum mlx5_ib_cong_node_type node;
0278 struct mlx5_core_dev *mdev;
0279
0280
0281 mdev = mlx5_ib_get_native_port_mdev(dev, port_num + 1, NULL);
0282 if (!mdev)
0283 return -ENODEV;
0284
0285 out = kvzalloc(outlen, GFP_KERNEL);
0286 if (!out) {
0287 err = -ENOMEM;
0288 goto alloc_err;
0289 }
0290
0291 node = mlx5_ib_param_to_node(offset);
0292
0293 err = mlx5_cmd_query_cong_params(mdev, node, out);
0294 if (err)
0295 goto free;
0296
0297 field = MLX5_ADDR_OF(query_cong_params_out, out, congestion_parameters);
0298 *var = mlx5_get_cc_param_val(field, offset);
0299
0300 free:
0301 kvfree(out);
0302 alloc_err:
0303 mlx5_ib_put_native_port_mdev(dev, port_num + 1);
0304 return err;
0305 }
0306
0307 static int mlx5_ib_set_cc_params(struct mlx5_ib_dev *dev, u32 port_num,
0308 int offset, u32 var)
0309 {
0310 int inlen = MLX5_ST_SZ_BYTES(modify_cong_params_in);
0311 void *in;
0312 void *field;
0313 enum mlx5_ib_cong_node_type node;
0314 struct mlx5_core_dev *mdev;
0315 u32 attr_mask = 0;
0316 int err;
0317
0318
0319 mdev = mlx5_ib_get_native_port_mdev(dev, port_num + 1, NULL);
0320 if (!mdev)
0321 return -ENODEV;
0322
0323 in = kvzalloc(inlen, GFP_KERNEL);
0324 if (!in) {
0325 err = -ENOMEM;
0326 goto alloc_err;
0327 }
0328
0329 MLX5_SET(modify_cong_params_in, in, opcode,
0330 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
0331
0332 node = mlx5_ib_param_to_node(offset);
0333 MLX5_SET(modify_cong_params_in, in, cong_protocol, node);
0334
0335 field = MLX5_ADDR_OF(modify_cong_params_in, in, congestion_parameters);
0336 mlx5_ib_set_cc_param_mask_val(field, offset, var, &attr_mask);
0337
0338 field = MLX5_ADDR_OF(modify_cong_params_in, in, field_select);
0339 MLX5_SET(field_select_r_roce_rp, field, field_select_r_roce_rp,
0340 attr_mask);
0341
0342 err = mlx5_cmd_exec_in(dev->mdev, modify_cong_params, in);
0343 kvfree(in);
0344 alloc_err:
0345 mlx5_ib_put_native_port_mdev(dev, port_num + 1);
0346 return err;
0347 }
0348
0349 static ssize_t set_param(struct file *filp, const char __user *buf,
0350 size_t count, loff_t *pos)
0351 {
0352 struct mlx5_ib_dbg_param *param = filp->private_data;
0353 int offset = param->offset;
0354 char lbuf[11] = { };
0355 u32 var;
0356 int ret;
0357
0358 if (count > sizeof(lbuf))
0359 return -EINVAL;
0360
0361 if (copy_from_user(lbuf, buf, count))
0362 return -EFAULT;
0363
0364 lbuf[sizeof(lbuf) - 1] = '\0';
0365
0366 if (kstrtou32(lbuf, 0, &var))
0367 return -EINVAL;
0368
0369 ret = mlx5_ib_set_cc_params(param->dev, param->port_num, offset, var);
0370 return ret ? ret : count;
0371 }
0372
0373 static ssize_t get_param(struct file *filp, char __user *buf, size_t count,
0374 loff_t *pos)
0375 {
0376 struct mlx5_ib_dbg_param *param = filp->private_data;
0377 int offset = param->offset;
0378 u32 var = 0;
0379 int ret;
0380 char lbuf[11];
0381
0382 ret = mlx5_ib_get_cc_params(param->dev, param->port_num, offset, &var);
0383 if (ret)
0384 return ret;
0385
0386 ret = snprintf(lbuf, sizeof(lbuf), "%d\n", var);
0387 if (ret < 0)
0388 return ret;
0389
0390 return simple_read_from_buffer(buf, count, pos, lbuf, ret);
0391 }
0392
0393 static const struct file_operations dbg_cc_fops = {
0394 .owner = THIS_MODULE,
0395 .open = simple_open,
0396 .write = set_param,
0397 .read = get_param,
0398 };
0399
0400 void mlx5_ib_cleanup_cong_debugfs(struct mlx5_ib_dev *dev, u32 port_num)
0401 {
0402 if (!mlx5_debugfs_root ||
0403 !dev->port[port_num].dbg_cc_params ||
0404 !dev->port[port_num].dbg_cc_params->root)
0405 return;
0406
0407 debugfs_remove_recursive(dev->port[port_num].dbg_cc_params->root);
0408 kfree(dev->port[port_num].dbg_cc_params);
0409 dev->port[port_num].dbg_cc_params = NULL;
0410 }
0411
0412 void mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev *dev, u32 port_num)
0413 {
0414 struct mlx5_ib_dbg_cc_params *dbg_cc_params;
0415 struct mlx5_core_dev *mdev;
0416 int i;
0417
0418 if (!mlx5_debugfs_root)
0419 return;
0420
0421
0422 mdev = mlx5_ib_get_native_port_mdev(dev, port_num + 1, NULL);
0423 if (!mdev)
0424 return;
0425
0426 if (!MLX5_CAP_GEN(mdev, cc_query_allowed) ||
0427 !MLX5_CAP_GEN(mdev, cc_modify_allowed))
0428 goto put_mdev;
0429
0430 dbg_cc_params = kzalloc(sizeof(*dbg_cc_params), GFP_KERNEL);
0431 if (!dbg_cc_params)
0432 goto err;
0433
0434 dev->port[port_num].dbg_cc_params = dbg_cc_params;
0435
0436 dbg_cc_params->root = debugfs_create_dir("cc_params", mlx5_debugfs_get_dev_root(mdev));
0437
0438 for (i = 0; i < MLX5_IB_DBG_CC_MAX; i++) {
0439 dbg_cc_params->params[i].offset = i;
0440 dbg_cc_params->params[i].dev = dev;
0441 dbg_cc_params->params[i].port_num = port_num;
0442 dbg_cc_params->params[i].dentry =
0443 debugfs_create_file(mlx5_ib_dbg_cc_name[i],
0444 0600, dbg_cc_params->root,
0445 &dbg_cc_params->params[i],
0446 &dbg_cc_fops);
0447 }
0448
0449 put_mdev:
0450 mlx5_ib_put_native_port_mdev(dev, port_num + 1);
0451 return;
0452
0453 err:
0454 mlx5_ib_warn(dev, "cong debugfs failure\n");
0455 mlx5_ib_cleanup_cong_debugfs(dev, port_num);
0456 mlx5_ib_put_native_port_mdev(dev, port_num + 1);
0457
0458
0459
0460
0461
0462 return;
0463 }