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",
53 "rp_rate_to_set_on_first_cnp",
56 "rp_rate_reduce_monitor_period",
57 "rp_initial_alpha_value",
64 #define MLX5_IB_RP_CLAMP_TGT_RATE_ATTR BIT(1)
65 #define MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR BIT(2)
66 #define MLX5_IB_RP_TIME_RESET_ATTR BIT(3)
67 #define MLX5_IB_RP_BYTE_RESET_ATTR BIT(4)
68 #define MLX5_IB_RP_THRESHOLD_ATTR BIT(5)
69 #define MLX5_IB_RP_AI_RATE_ATTR BIT(7)
70 #define MLX5_IB_RP_HAI_RATE_ATTR BIT(8)
71 #define MLX5_IB_RP_MIN_DEC_FAC_ATTR BIT(9)
72 #define MLX5_IB_RP_MIN_RATE_ATTR BIT(10)
73 #define MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR BIT(11)
74 #define MLX5_IB_RP_DCE_TCP_G_ATTR BIT(12)
75 #define MLX5_IB_RP_DCE_TCP_RTT_ATTR BIT(13)
76 #define MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR BIT(14)
77 #define MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR BIT(15)
78 #define MLX5_IB_RP_GD_ATTR BIT(16)
80 #define MLX5_IB_NP_CNP_DSCP_ATTR BIT(3)
81 #define MLX5_IB_NP_CNP_PRIO_MODE_ATTR BIT(4)
83 static enum mlx5_ib_cong_node_type
84 mlx5_ib_param_to_node(enum mlx5_ib_dbg_cc_types param_offset
)
86 if (param_offset
>= MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE
&&
87 param_offset
<= MLX5_IB_DBG_CC_RP_GD
)
88 return MLX5_IB_RROCE_ECN_RP
;
90 return MLX5_IB_RROCE_ECN_NP
;
93 static u32
mlx5_get_cc_param_val(void *field
, int offset
)
96 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE
:
97 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
99 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI
:
100 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
101 clamp_tgt_rate_after_time_inc
);
102 case MLX5_IB_DBG_CC_RP_TIME_RESET
:
103 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
105 case MLX5_IB_DBG_CC_RP_BYTE_RESET
:
106 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
108 case MLX5_IB_DBG_CC_RP_THRESHOLD
:
109 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
111 case MLX5_IB_DBG_CC_RP_AI_RATE
:
112 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
114 case MLX5_IB_DBG_CC_RP_HAI_RATE
:
115 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
117 case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC
:
118 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
120 case MLX5_IB_DBG_CC_RP_MIN_RATE
:
121 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
123 case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP
:
124 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
125 rate_to_set_on_first_cnp
);
126 case MLX5_IB_DBG_CC_RP_DCE_TCP_G
:
127 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
129 case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT
:
130 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
132 case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD
:
133 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
134 rate_reduce_monitor_period
);
135 case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE
:
136 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
137 initial_alpha_value
);
138 case MLX5_IB_DBG_CC_RP_GD
:
139 return MLX5_GET(cong_control_r_roce_ecn_rp
, field
,
141 case MLX5_IB_DBG_CC_NP_CNP_DSCP
:
142 return MLX5_GET(cong_control_r_roce_ecn_np
, field
,
144 case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE
:
145 return MLX5_GET(cong_control_r_roce_ecn_np
, field
,
147 case MLX5_IB_DBG_CC_NP_CNP_PRIO
:
148 return MLX5_GET(cong_control_r_roce_ecn_np
, field
,
155 static void mlx5_ib_set_cc_param_mask_val(void *field
, int offset
,
156 u32 var
, u32
*attr_mask
)
159 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE
:
160 *attr_mask
|= MLX5_IB_RP_CLAMP_TGT_RATE_ATTR
;
161 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
162 clamp_tgt_rate
, var
);
164 case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI
:
165 *attr_mask
|= MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR
;
166 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
167 clamp_tgt_rate_after_time_inc
, var
);
169 case MLX5_IB_DBG_CC_RP_TIME_RESET
:
170 *attr_mask
|= MLX5_IB_RP_TIME_RESET_ATTR
;
171 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
172 rpg_time_reset
, var
);
174 case MLX5_IB_DBG_CC_RP_BYTE_RESET
:
175 *attr_mask
|= MLX5_IB_RP_BYTE_RESET_ATTR
;
176 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
177 rpg_byte_reset
, var
);
179 case MLX5_IB_DBG_CC_RP_THRESHOLD
:
180 *attr_mask
|= MLX5_IB_RP_THRESHOLD_ATTR
;
181 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
184 case MLX5_IB_DBG_CC_RP_AI_RATE
:
185 *attr_mask
|= MLX5_IB_RP_AI_RATE_ATTR
;
186 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
189 case MLX5_IB_DBG_CC_RP_HAI_RATE
:
190 *attr_mask
|= MLX5_IB_RP_HAI_RATE_ATTR
;
191 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
194 case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC
:
195 *attr_mask
|= MLX5_IB_RP_MIN_DEC_FAC_ATTR
;
196 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
197 rpg_min_dec_fac
, var
);
199 case MLX5_IB_DBG_CC_RP_MIN_RATE
:
200 *attr_mask
|= MLX5_IB_RP_MIN_RATE_ATTR
;
201 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
204 case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP
:
205 *attr_mask
|= MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR
;
206 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
207 rate_to_set_on_first_cnp
, var
);
209 case MLX5_IB_DBG_CC_RP_DCE_TCP_G
:
210 *attr_mask
|= MLX5_IB_RP_DCE_TCP_G_ATTR
;
211 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
214 case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT
:
215 *attr_mask
|= MLX5_IB_RP_DCE_TCP_RTT_ATTR
;
216 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
219 case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD
:
220 *attr_mask
|= MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR
;
221 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
222 rate_reduce_monitor_period
, var
);
224 case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE
:
225 *attr_mask
|= MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR
;
226 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
227 initial_alpha_value
, var
);
229 case MLX5_IB_DBG_CC_RP_GD
:
230 *attr_mask
|= MLX5_IB_RP_GD_ATTR
;
231 MLX5_SET(cong_control_r_roce_ecn_rp
, field
,
234 case MLX5_IB_DBG_CC_NP_CNP_DSCP
:
235 *attr_mask
|= MLX5_IB_NP_CNP_DSCP_ATTR
;
236 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_dscp
, var
);
238 case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE
:
239 *attr_mask
|= MLX5_IB_NP_CNP_PRIO_MODE_ATTR
;
240 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_prio_mode
, var
);
242 case MLX5_IB_DBG_CC_NP_CNP_PRIO
:
243 *attr_mask
|= MLX5_IB_NP_CNP_PRIO_MODE_ATTR
;
244 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_prio_mode
, 0);
245 MLX5_SET(cong_control_r_roce_ecn_np
, field
, cnp_802p_prio
, var
);
250 static int mlx5_ib_get_cc_params(struct mlx5_ib_dev
*dev
, u8 port_num
,
251 int offset
, u32
*var
)
253 int outlen
= MLX5_ST_SZ_BYTES(query_cong_params_out
);
257 enum mlx5_ib_cong_node_type node
;
258 struct mlx5_core_dev
*mdev
;
260 /* Takes a 1-based port number */
261 mdev
= mlx5_ib_get_native_port_mdev(dev
, port_num
+ 1, NULL
);
265 out
= kvzalloc(outlen
, GFP_KERNEL
);
271 node
= mlx5_ib_param_to_node(offset
);
273 err
= mlx5_cmd_query_cong_params(mdev
, node
, out
, outlen
);
277 field
= MLX5_ADDR_OF(query_cong_params_out
, out
, congestion_parameters
);
278 *var
= mlx5_get_cc_param_val(field
, offset
);
283 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
287 static int mlx5_ib_set_cc_params(struct mlx5_ib_dev
*dev
, u8 port_num
,
290 int inlen
= MLX5_ST_SZ_BYTES(modify_cong_params_in
);
293 enum mlx5_ib_cong_node_type node
;
294 struct mlx5_core_dev
*mdev
;
298 /* Takes a 1-based port number */
299 mdev
= mlx5_ib_get_native_port_mdev(dev
, port_num
+ 1, NULL
);
303 in
= kvzalloc(inlen
, GFP_KERNEL
);
309 MLX5_SET(modify_cong_params_in
, in
, opcode
,
310 MLX5_CMD_OP_MODIFY_CONG_PARAMS
);
312 node
= mlx5_ib_param_to_node(offset
);
313 MLX5_SET(modify_cong_params_in
, in
, cong_protocol
, node
);
315 field
= MLX5_ADDR_OF(modify_cong_params_in
, in
, congestion_parameters
);
316 mlx5_ib_set_cc_param_mask_val(field
, offset
, var
, &attr_mask
);
318 field
= MLX5_ADDR_OF(modify_cong_params_in
, in
, field_select
);
319 MLX5_SET(field_select_r_roce_rp
, field
, field_select_r_roce_rp
,
322 err
= mlx5_cmd_modify_cong_params(mdev
, in
, inlen
);
325 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
329 static ssize_t
set_param(struct file
*filp
, const char __user
*buf
,
330 size_t count
, loff_t
*pos
)
332 struct mlx5_ib_dbg_param
*param
= filp
->private_data
;
333 int offset
= param
->offset
;
338 if (count
> sizeof(lbuf
))
341 if (copy_from_user(lbuf
, buf
, count
))
344 lbuf
[sizeof(lbuf
) - 1] = '\0';
346 if (kstrtou32(lbuf
, 0, &var
))
349 ret
= mlx5_ib_set_cc_params(param
->dev
, param
->port_num
, offset
, var
);
350 return ret
? ret
: count
;
353 static ssize_t
get_param(struct file
*filp
, char __user
*buf
, size_t count
,
356 struct mlx5_ib_dbg_param
*param
= filp
->private_data
;
357 int offset
= param
->offset
;
362 ret
= mlx5_ib_get_cc_params(param
->dev
, param
->port_num
, offset
, &var
);
366 ret
= snprintf(lbuf
, sizeof(lbuf
), "%d\n", var
);
370 return simple_read_from_buffer(buf
, count
, pos
, lbuf
, ret
);
373 static const struct file_operations dbg_cc_fops
= {
374 .owner
= THIS_MODULE
,
380 void mlx5_ib_cleanup_cong_debugfs(struct mlx5_ib_dev
*dev
, u8 port_num
)
382 if (!mlx5_debugfs_root
||
383 !dev
->port
[port_num
].dbg_cc_params
||
384 !dev
->port
[port_num
].dbg_cc_params
->root
)
387 debugfs_remove_recursive(dev
->port
[port_num
].dbg_cc_params
->root
);
388 kfree(dev
->port
[port_num
].dbg_cc_params
);
389 dev
->port
[port_num
].dbg_cc_params
= NULL
;
392 void mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev
*dev
, u8 port_num
)
394 struct mlx5_ib_dbg_cc_params
*dbg_cc_params
;
395 struct mlx5_core_dev
*mdev
;
398 if (!mlx5_debugfs_root
)
401 /* Takes a 1-based port number */
402 mdev
= mlx5_ib_get_native_port_mdev(dev
, port_num
+ 1, NULL
);
406 if (!MLX5_CAP_GEN(mdev
, cc_query_allowed
) ||
407 !MLX5_CAP_GEN(mdev
, cc_modify_allowed
))
410 dbg_cc_params
= kzalloc(sizeof(*dbg_cc_params
), GFP_KERNEL
);
414 dev
->port
[port_num
].dbg_cc_params
= dbg_cc_params
;
416 dbg_cc_params
->root
= debugfs_create_dir("cc_params",
417 mdev
->priv
.dbg_root
);
419 for (i
= 0; i
< MLX5_IB_DBG_CC_MAX
; i
++) {
420 dbg_cc_params
->params
[i
].offset
= i
;
421 dbg_cc_params
->params
[i
].dev
= dev
;
422 dbg_cc_params
->params
[i
].port_num
= port_num
;
423 dbg_cc_params
->params
[i
].dentry
=
424 debugfs_create_file(mlx5_ib_dbg_cc_name
[i
],
425 0600, dbg_cc_params
->root
,
426 &dbg_cc_params
->params
[i
],
431 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
435 mlx5_ib_warn(dev
, "cong debugfs failure\n");
436 mlx5_ib_cleanup_cong_debugfs(dev
, port_num
);
437 mlx5_ib_put_native_port_mdev(dev
, port_num
+ 1);
440 * We don't want to fail driver if debugfs failed to initialize,
441 * so we are not forwarding error to the user.