2 * Copyright (c) 2013-2017, Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <linux/debugfs.h>
38 enum mlx5_ib_cong_node_type
{
39 MLX5_IB_RROCE_ECN_RP
= 1,
40 MLX5_IB_RROCE_ECN_NP
= 2,
43 static const char * const mlx5_ib_dbg_cc_name
[] = {
45 "rp_clamp_tgt_rate_ati",
54 "rp_rate_to_set_on_first_cnp",
57 "rp_rate_reduce_monitor_period",
58 "rp_initial_alpha_value",
60 "np_min_time_between_cnps",
66 #define MLX5_IB_RP_CLAMP_TGT_RATE_ATTR BIT(1)
67 #define MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR BIT(2)
68 #define MLX5_IB_RP_TIME_RESET_ATTR BIT(3)
69 #define MLX5_IB_RP_BYTE_RESET_ATTR BIT(4)
70 #define MLX5_IB_RP_THRESHOLD_ATTR BIT(5)
71 #define MLX5_IB_RP_MAX_RATE_ATTR BIT(6)
72 #define MLX5_IB_RP_AI_RATE_ATTR BIT(7)
73 #define MLX5_IB_RP_HAI_RATE_ATTR BIT(8)
74 #define MLX5_IB_RP_MIN_DEC_FAC_ATTR BIT(9)
75 #define MLX5_IB_RP_MIN_RATE_ATTR BIT(10)
76 #define MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR BIT(11)
77 #define MLX5_IB_RP_DCE_TCP_G_ATTR BIT(12)
78 #define MLX5_IB_RP_DCE_TCP_RTT_ATTR BIT(13)
79 #define MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR BIT(14)
80 #define MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR BIT(15)
81 #define MLX5_IB_RP_GD_ATTR BIT(16)
83 #define MLX5_IB_NP_MIN_TIME_BETWEEN_CNPS_ATTR BIT(2)
84 #define MLX5_IB_NP_CNP_DSCP_ATTR BIT(3)
85 #define MLX5_IB_NP_CNP_PRIO_MODE_ATTR BIT(4)
87 static enum mlx5_ib_cong_node_type
88 mlx5_ib_param_to_node(enum mlx5_ib_dbg_cc_types param_offset
)
90 if (param_offset
>= MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE
&&
91 param_offset
<= MLX5_IB_DBG_CC_RP_GD
)
92 return MLX5_IB_RROCE_ECN_RP
;
94 return MLX5_IB_RROCE_ECN_NP
;
97 static u32
mlx5_get_cc_param_val(void *field
, int offset
)
100 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE
:
101 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
103 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI
:
104 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
105 clamp_tgt_rate_after_time_inc
);
106 case MLX5_IB_DBG_CC_RP_TIME_RESET
:
107 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
109 case MLX5_IB_DBG_CC_RP_BYTE_RESET
:
110 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
112 case MLX5_IB_DBG_CC_RP_THRESHOLD
:
113 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
115 case MLX5_IB_DBG_CC_RP_AI_RATE
:
116 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
118 case MLX5_IB_DBG_CC_RP_MAX_RATE
:
119 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
121 case MLX5_IB_DBG_CC_RP_HAI_RATE
:
122 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
124 case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC
:
125 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
127 case MLX5_IB_DBG_CC_RP_MIN_RATE
:
128 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
130 case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP
:
131 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
132 rate_to_set_on_first_cnp
);
133 case MLX5_IB_DBG_CC_RP_DCE_TCP_G
:
134 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
136 case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT
:
137 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
139 case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD
:
140 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
141 rate_reduce_monitor_period
);
142 case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE
:
143 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
144 initial_alpha_value
);
145 case MLX5_IB_DBG_CC_RP_GD
:
146 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
148 case MLX5_IB_DBG_CC_NP_MIN_TIME_BETWEEN_CNPS
:
149 return MLX5_GET(cong_control_r_roce_ecn_np
, field
,
150 min_time_between_cnps
);
151 case MLX5_IB_DBG_CC_NP_CNP_DSCP
:
152 return MLX5_GET(cong_control_r_roce_ecn_np
, field
,
154 case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE
:
155 return MLX5_GET(cong_control_r_roce_ecn_np
, field
,
157 case MLX5_IB_DBG_CC_NP_CNP_PRIO
:
158 return MLX5_GET(cong_control_r_roce_ecn_np
, field
,
165 static void mlx5_ib_set_cc_param_mask_val(void *field
, int offset
,
166 u32 var
, u32
*attr_mask
)
169 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE
:
170 *attr_mask
|= MLX5_IB_RP_CLAMP_TGT_RATE_ATTR
;
171 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
172 clamp_tgt_rate
, var
);
174 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI
:
175 *attr_mask
|= MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR
;
176 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
177 clamp_tgt_rate_after_time_inc
, var
);
179 case MLX5_IB_DBG_CC_RP_TIME_RESET
:
180 *attr_mask
|= MLX5_IB_RP_TIME_RESET_ATTR
;
181 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
182 rpg_time_reset
, var
);
184 case MLX5_IB_DBG_CC_RP_BYTE_RESET
:
185 *attr_mask
|= MLX5_IB_RP_BYTE_RESET_ATTR
;
186 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
187 rpg_byte_reset
, var
);
189 case MLX5_IB_DBG_CC_RP_THRESHOLD
:
190 *attr_mask
|= MLX5_IB_RP_THRESHOLD_ATTR
;
191 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
194 case MLX5_IB_DBG_CC_RP_AI_RATE
:
195 *attr_mask
|= MLX5_IB_RP_AI_RATE_ATTR
;
196 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
199 case MLX5_IB_DBG_CC_RP_MAX_RATE
:
200 *attr_mask
|= MLX5_IB_RP_MAX_RATE_ATTR
;
201 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
204 case MLX5_IB_DBG_CC_RP_HAI_RATE
:
205 *attr_mask
|= MLX5_IB_RP_HAI_RATE_ATTR
;
206 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
209 case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC
:
210 *attr_mask
|= MLX5_IB_RP_MIN_DEC_FAC_ATTR
;
211 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
212 rpg_min_dec_fac
, var
);
214 case MLX5_IB_DBG_CC_RP_MIN_RATE
:
215 *attr_mask
|= MLX5_IB_RP_MIN_RATE_ATTR
;
216 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
219 case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP
:
220 *attr_mask
|= MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR
;
221 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
222 rate_to_set_on_first_cnp
, var
);
224 case MLX5_IB_DBG_CC_RP_DCE_TCP_G
:
225 *attr_mask
|= MLX5_IB_RP_DCE_TCP_G_ATTR
;
226 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
229 case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT
:
230 *attr_mask
|= MLX5_IB_RP_DCE_TCP_RTT_ATTR
;
231 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
234 case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD
:
235 *attr_mask
|= MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR
;
236 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
237 rate_reduce_monitor_period
, var
);
239 case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE
:
240 *attr_mask
|= MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR
;
241 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
242 initial_alpha_value
, var
);
244 case MLX5_IB_DBG_CC_RP_GD
:
245 *attr_mask
|= MLX5_IB_RP_GD_ATTR
;
246 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
249 case MLX5_IB_DBG_CC_NP_MIN_TIME_BETWEEN_CNPS
:
250 *attr_mask
|= MLX5_IB_NP_MIN_TIME_BETWEEN_CNPS_ATTR
;
251 MLX5_SET(cong_control_r_roce_ecn_np
, field
,
252 min_time_between_cnps
, var
);
254 case MLX5_IB_DBG_CC_NP_CNP_DSCP
:
255 *attr_mask
|= MLX5_IB_NP_CNP_DSCP_ATTR
;
256 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_dscp
, var
);
258 case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE
:
259 *attr_mask
|= MLX5_IB_NP_CNP_PRIO_MODE_ATTR
;
260 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_prio_mode
, var
);
262 case MLX5_IB_DBG_CC_NP_CNP_PRIO
:
263 *attr_mask
|= MLX5_IB_NP_CNP_PRIO_MODE_ATTR
;
264 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_prio_mode
, 0);
265 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_802p_prio
, var
);
270 static int mlx5_ib_get_cc_params(struct mlx5_ib_dev
*dev
, u8 port_num
,
271 int offset
, u32
*var
)
273 int outlen
= MLX5_ST_SZ_BYTES(query_cong_params_out
);
277 enum mlx5_ib_cong_node_type node
;
278 struct mlx5_core_dev
*mdev
;
280 /* Takes a 1-based port number */
281 mdev
= mlx5_ib_get_native_port_mdev(dev
, port_num
+ 1, NULL
);
285 out
= kvzalloc(outlen
, GFP_KERNEL
);
291 node
= mlx5_ib_param_to_node(offset
);
293 err
= mlx5_cmd_query_cong_params(mdev
, node
, out
);
297 field
= MLX5_ADDR_OF(query_cong_params_out
, out
, congestion_parameters
);
298 *var
= mlx5_get_cc_param_val(field
, offset
);
303 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
307 static int mlx5_ib_set_cc_params(struct mlx5_ib_dev
*dev
, u8 port_num
,
310 int inlen
= MLX5_ST_SZ_BYTES(modify_cong_params_in
);
313 enum mlx5_ib_cong_node_type node
;
314 struct mlx5_core_dev
*mdev
;
318 /* Takes a 1-based port number */
319 mdev
= mlx5_ib_get_native_port_mdev(dev
, port_num
+ 1, NULL
);
323 in
= kvzalloc(inlen
, GFP_KERNEL
);
329 MLX5_SET(modify_cong_params_in
, in
, opcode
,
330 MLX5_CMD_OP_MODIFY_CONG_PARAMS
);
332 node
= mlx5_ib_param_to_node(offset
);
333 MLX5_SET(modify_cong_params_in
, in
, cong_protocol
, node
);
335 field
= MLX5_ADDR_OF(modify_cong_params_in
, in
, congestion_parameters
);
336 mlx5_ib_set_cc_param_mask_val(field
, offset
, var
, &attr_mask
);
338 field
= MLX5_ADDR_OF(modify_cong_params_in
, in
, field_select
);
339 MLX5_SET(field_select_r_roce_rp
, field
, field_select_r_roce_rp
,
342 err
= mlx5_cmd_exec_in(dev
->mdev
, modify_cong_params
, in
);
345 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
349 static ssize_t
set_param(struct file
*filp
, const char __user
*buf
,
350 size_t count
, loff_t
*pos
)
352 struct mlx5_ib_dbg_param
*param
= filp
->private_data
;
353 int offset
= param
->offset
;
358 if (count
> sizeof(lbuf
))
361 if (copy_from_user(lbuf
, buf
, count
))
364 lbuf
[sizeof(lbuf
) - 1] = '\0';
366 if (kstrtou32(lbuf
, 0, &var
))
369 ret
= mlx5_ib_set_cc_params(param
->dev
, param
->port_num
, offset
, var
);
370 return ret
? ret
: count
;
373 static ssize_t
get_param(struct file
*filp
, char __user
*buf
, size_t count
,
376 struct mlx5_ib_dbg_param
*param
= filp
->private_data
;
377 int offset
= param
->offset
;
382 ret
= mlx5_ib_get_cc_params(param
->dev
, param
->port_num
, offset
, &var
);
386 ret
= snprintf(lbuf
, sizeof(lbuf
), "%d\n", var
);
390 return simple_read_from_buffer(buf
, count
, pos
, lbuf
, ret
);
393 static const struct file_operations dbg_cc_fops
= {
394 .owner
= THIS_MODULE
,
400 void mlx5_ib_cleanup_cong_debugfs(struct mlx5_ib_dev
*dev
, u8 port_num
)
402 if (!mlx5_debugfs_root
||
403 !dev
->port
[port_num
].dbg_cc_params
||
404 !dev
->port
[port_num
].dbg_cc_params
->root
)
407 debugfs_remove_recursive(dev
->port
[port_num
].dbg_cc_params
->root
);
408 kfree(dev
->port
[port_num
].dbg_cc_params
);
409 dev
->port
[port_num
].dbg_cc_params
= NULL
;
412 void mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev
*dev
, u8 port_num
)
414 struct mlx5_ib_dbg_cc_params
*dbg_cc_params
;
415 struct mlx5_core_dev
*mdev
;
418 if (!mlx5_debugfs_root
)
421 /* Takes a 1-based port number */
422 mdev
= mlx5_ib_get_native_port_mdev(dev
, port_num
+ 1, NULL
);
426 if (!MLX5_CAP_GEN(mdev
, cc_query_allowed
) ||
427 !MLX5_CAP_GEN(mdev
, cc_modify_allowed
))
430 dbg_cc_params
= kzalloc(sizeof(*dbg_cc_params
), GFP_KERNEL
);
434 dev
->port
[port_num
].dbg_cc_params
= dbg_cc_params
;
436 dbg_cc_params
->root
= debugfs_create_dir("cc_params",
437 mdev
->priv
.dbg_root
);
439 for (i
= 0; i
< MLX5_IB_DBG_CC_MAX
; i
++) {
440 dbg_cc_params
->params
[i
].offset
= i
;
441 dbg_cc_params
->params
[i
].dev
= dev
;
442 dbg_cc_params
->params
[i
].port_num
= port_num
;
443 dbg_cc_params
->params
[i
].dentry
=
444 debugfs_create_file(mlx5_ib_dbg_cc_name
[i
],
445 0600, dbg_cc_params
->root
,
446 &dbg_cc_params
->params
[i
],
451 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
455 mlx5_ib_warn(dev
, "cong debugfs failure\n");
456 mlx5_ib_cleanup_cong_debugfs(dev
, port_num
);
457 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
460 * We don't want to fail driver if debugfs failed to initialize,
461 * so we are not forwarding error to the user.