xref: /openbmc/linux/drivers/infiniband/hw/mlx5/cong.c (revision 4a2da0b8c0782816f3ae6846ae7942fcbb0f8172)
1*4a2da0b8SParav Pandit /*
2*4a2da0b8SParav Pandit  * Copyright (c) 2013-2017, Mellanox Technologies. All rights reserved.
3*4a2da0b8SParav Pandit  *
4*4a2da0b8SParav Pandit  * This software is available to you under a choice of one of two
5*4a2da0b8SParav Pandit  * licenses.  You may choose to be licensed under the terms of the GNU
6*4a2da0b8SParav Pandit  * General Public License (GPL) Version 2, available from the file
7*4a2da0b8SParav Pandit  * COPYING in the main directory of this source tree, or the
8*4a2da0b8SParav Pandit  * OpenIB.org BSD license below:
9*4a2da0b8SParav Pandit  *
10*4a2da0b8SParav Pandit  *     Redistribution and use in source and binary forms, with or
11*4a2da0b8SParav Pandit  *     without modification, are permitted provided that the following
12*4a2da0b8SParav Pandit  *     conditions are met:
13*4a2da0b8SParav Pandit  *
14*4a2da0b8SParav Pandit  *      - Redistributions of source code must retain the above
15*4a2da0b8SParav Pandit  *        copyright notice, this list of conditions and the following
16*4a2da0b8SParav Pandit  *        disclaimer.
17*4a2da0b8SParav Pandit  *
18*4a2da0b8SParav Pandit  *      - Redistributions in binary form must reproduce the above
19*4a2da0b8SParav Pandit  *        copyright notice, this list of conditions and the following
20*4a2da0b8SParav Pandit  *        disclaimer in the documentation and/or other materials
21*4a2da0b8SParav Pandit  *        provided with the distribution.
22*4a2da0b8SParav Pandit  *
23*4a2da0b8SParav Pandit  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24*4a2da0b8SParav Pandit  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25*4a2da0b8SParav Pandit  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26*4a2da0b8SParav Pandit  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27*4a2da0b8SParav Pandit  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28*4a2da0b8SParav Pandit  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29*4a2da0b8SParav Pandit  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30*4a2da0b8SParav Pandit  * SOFTWARE.
31*4a2da0b8SParav Pandit  */
32*4a2da0b8SParav Pandit 
33*4a2da0b8SParav Pandit #include <linux/debugfs.h>
34*4a2da0b8SParav Pandit 
35*4a2da0b8SParav Pandit #include "mlx5_ib.h"
36*4a2da0b8SParav Pandit #include "cmd.h"
37*4a2da0b8SParav Pandit 
38*4a2da0b8SParav Pandit enum mlx5_ib_cong_node_type {
39*4a2da0b8SParav Pandit 	MLX5_IB_RROCE_ECN_RP = 1,
40*4a2da0b8SParav Pandit 	MLX5_IB_RROCE_ECN_NP = 2,
41*4a2da0b8SParav Pandit };
42*4a2da0b8SParav Pandit 
43*4a2da0b8SParav Pandit static const char * const mlx5_ib_dbg_cc_name[] = {
44*4a2da0b8SParav Pandit 	"rp_clamp_tgt_rate",
45*4a2da0b8SParav Pandit 	"rp_clamp_tgt_rate_ati",
46*4a2da0b8SParav Pandit 	"rp_time_reset",
47*4a2da0b8SParav Pandit 	"rp_byte_reset",
48*4a2da0b8SParav Pandit 	"rp_threshold",
49*4a2da0b8SParav Pandit 	"rp_ai_rate",
50*4a2da0b8SParav Pandit 	"rp_hai_rate",
51*4a2da0b8SParav Pandit 	"rp_min_dec_fac",
52*4a2da0b8SParav Pandit 	"rp_min_rate",
53*4a2da0b8SParav Pandit 	"rp_rate_to_set_on_first_cnp",
54*4a2da0b8SParav Pandit 	"rp_dce_tcp_g",
55*4a2da0b8SParav Pandit 	"rp_dce_tcp_rtt",
56*4a2da0b8SParav Pandit 	"rp_rate_reduce_monitor_period",
57*4a2da0b8SParav Pandit 	"rp_initial_alpha_value",
58*4a2da0b8SParav Pandit 	"rp_gd",
59*4a2da0b8SParav Pandit 	"np_cnp_dscp",
60*4a2da0b8SParav Pandit 	"np_cnp_prio_mode",
61*4a2da0b8SParav Pandit 	"np_cnp_prio",
62*4a2da0b8SParav Pandit };
63*4a2da0b8SParav Pandit 
64*4a2da0b8SParav Pandit #define MLX5_IB_RP_CLAMP_TGT_RATE_ATTR			BIT(1)
65*4a2da0b8SParav Pandit #define MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR		BIT(2)
66*4a2da0b8SParav Pandit #define MLX5_IB_RP_TIME_RESET_ATTR			BIT(3)
67*4a2da0b8SParav Pandit #define MLX5_IB_RP_BYTE_RESET_ATTR			BIT(4)
68*4a2da0b8SParav Pandit #define MLX5_IB_RP_THRESHOLD_ATTR			BIT(5)
69*4a2da0b8SParav Pandit #define MLX5_IB_RP_AI_RATE_ATTR				BIT(7)
70*4a2da0b8SParav Pandit #define MLX5_IB_RP_HAI_RATE_ATTR			BIT(8)
71*4a2da0b8SParav Pandit #define MLX5_IB_RP_MIN_DEC_FAC_ATTR			BIT(9)
72*4a2da0b8SParav Pandit #define MLX5_IB_RP_MIN_RATE_ATTR			BIT(10)
73*4a2da0b8SParav Pandit #define MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR	BIT(11)
74*4a2da0b8SParav Pandit #define MLX5_IB_RP_DCE_TCP_G_ATTR			BIT(12)
75*4a2da0b8SParav Pandit #define MLX5_IB_RP_DCE_TCP_RTT_ATTR			BIT(13)
76*4a2da0b8SParav Pandit #define MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR	BIT(14)
77*4a2da0b8SParav Pandit #define MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR		BIT(15)
78*4a2da0b8SParav Pandit #define MLX5_IB_RP_GD_ATTR				BIT(16)
79*4a2da0b8SParav Pandit 
80*4a2da0b8SParav Pandit #define MLX5_IB_NP_CNP_DSCP_ATTR			BIT(3)
81*4a2da0b8SParav Pandit #define MLX5_IB_NP_CNP_PRIO_MODE_ATTR			BIT(4)
82*4a2da0b8SParav Pandit 
83*4a2da0b8SParav Pandit static enum mlx5_ib_cong_node_type
84*4a2da0b8SParav Pandit mlx5_ib_param_to_node(enum mlx5_ib_dbg_cc_types param_offset)
85*4a2da0b8SParav Pandit {
86*4a2da0b8SParav Pandit 	if (param_offset >= MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE &&
87*4a2da0b8SParav Pandit 	    param_offset <= MLX5_IB_DBG_CC_RP_GD)
88*4a2da0b8SParav Pandit 		return MLX5_IB_RROCE_ECN_RP;
89*4a2da0b8SParav Pandit 	else
90*4a2da0b8SParav Pandit 		return MLX5_IB_RROCE_ECN_NP;
91*4a2da0b8SParav Pandit }
92*4a2da0b8SParav Pandit 
93*4a2da0b8SParav Pandit static u32 mlx5_get_cc_param_val(void *field, int offset)
94*4a2da0b8SParav Pandit {
95*4a2da0b8SParav Pandit 	switch (offset) {
96*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE:
97*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
98*4a2da0b8SParav Pandit 				clamp_tgt_rate);
99*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI:
100*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
101*4a2da0b8SParav Pandit 				clamp_tgt_rate_after_time_inc);
102*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_TIME_RESET:
103*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
104*4a2da0b8SParav Pandit 				rpg_time_reset);
105*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_BYTE_RESET:
106*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
107*4a2da0b8SParav Pandit 				rpg_byte_reset);
108*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_THRESHOLD:
109*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
110*4a2da0b8SParav Pandit 				rpg_threshold);
111*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_AI_RATE:
112*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
113*4a2da0b8SParav Pandit 				rpg_ai_rate);
114*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_HAI_RATE:
115*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
116*4a2da0b8SParav Pandit 				rpg_hai_rate);
117*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC:
118*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
119*4a2da0b8SParav Pandit 				rpg_min_dec_fac);
120*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_MIN_RATE:
121*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
122*4a2da0b8SParav Pandit 				rpg_min_rate);
123*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP:
124*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
125*4a2da0b8SParav Pandit 				rate_to_set_on_first_cnp);
126*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_DCE_TCP_G:
127*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
128*4a2da0b8SParav Pandit 				dce_tcp_g);
129*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT:
130*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
131*4a2da0b8SParav Pandit 				dce_tcp_rtt);
132*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD:
133*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
134*4a2da0b8SParav Pandit 				rate_reduce_monitor_period);
135*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE:
136*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
137*4a2da0b8SParav Pandit 				initial_alpha_value);
138*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_GD:
139*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_rp, field,
140*4a2da0b8SParav Pandit 				rpg_gd);
141*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_NP_CNP_DSCP:
142*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_np, field,
143*4a2da0b8SParav Pandit 				cnp_dscp);
144*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE:
145*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_np, field,
146*4a2da0b8SParav Pandit 				cnp_prio_mode);
147*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_NP_CNP_PRIO:
148*4a2da0b8SParav Pandit 		return MLX5_GET(cong_control_r_roce_ecn_np, field,
149*4a2da0b8SParav Pandit 				cnp_802p_prio);
150*4a2da0b8SParav Pandit 	default:
151*4a2da0b8SParav Pandit 		return 0;
152*4a2da0b8SParav Pandit 	}
153*4a2da0b8SParav Pandit }
154*4a2da0b8SParav Pandit 
155*4a2da0b8SParav Pandit static void mlx5_ib_set_cc_param_mask_val(void *field, int offset,
156*4a2da0b8SParav Pandit 					  u32 var, u32 *attr_mask)
157*4a2da0b8SParav Pandit {
158*4a2da0b8SParav Pandit 	switch (offset) {
159*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE:
160*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATTR;
161*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
162*4a2da0b8SParav Pandit 			 clamp_tgt_rate, var);
163*4a2da0b8SParav Pandit 		break;
164*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_CLAMP_TGT_RATE_ATI:
165*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_CLAMP_TGT_RATE_ATI_ATTR;
166*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
167*4a2da0b8SParav Pandit 			 clamp_tgt_rate_after_time_inc, var);
168*4a2da0b8SParav Pandit 		break;
169*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_TIME_RESET:
170*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_TIME_RESET_ATTR;
171*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
172*4a2da0b8SParav Pandit 			 rpg_time_reset, var);
173*4a2da0b8SParav Pandit 		break;
174*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_BYTE_RESET:
175*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_BYTE_RESET_ATTR;
176*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
177*4a2da0b8SParav Pandit 			 rpg_byte_reset, var);
178*4a2da0b8SParav Pandit 		break;
179*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_THRESHOLD:
180*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_THRESHOLD_ATTR;
181*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
182*4a2da0b8SParav Pandit 			 rpg_threshold, var);
183*4a2da0b8SParav Pandit 		break;
184*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_AI_RATE:
185*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_AI_RATE_ATTR;
186*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
187*4a2da0b8SParav Pandit 			 rpg_ai_rate, var);
188*4a2da0b8SParav Pandit 		break;
189*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_HAI_RATE:
190*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_HAI_RATE_ATTR;
191*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
192*4a2da0b8SParav Pandit 			 rpg_hai_rate, var);
193*4a2da0b8SParav Pandit 		break;
194*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_MIN_DEC_FAC:
195*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_MIN_DEC_FAC_ATTR;
196*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
197*4a2da0b8SParav Pandit 			 rpg_min_dec_fac, var);
198*4a2da0b8SParav Pandit 		break;
199*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_MIN_RATE:
200*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_MIN_RATE_ATTR;
201*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
202*4a2da0b8SParav Pandit 			 rpg_min_rate, var);
203*4a2da0b8SParav Pandit 		break;
204*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_RATE_TO_SET_ON_FIRST_CNP:
205*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_RATE_TO_SET_ON_FIRST_CNP_ATTR;
206*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
207*4a2da0b8SParav Pandit 			 rate_to_set_on_first_cnp, var);
208*4a2da0b8SParav Pandit 		break;
209*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_DCE_TCP_G:
210*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_DCE_TCP_G_ATTR;
211*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
212*4a2da0b8SParav Pandit 			 dce_tcp_g, var);
213*4a2da0b8SParav Pandit 		break;
214*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_DCE_TCP_RTT:
215*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_DCE_TCP_RTT_ATTR;
216*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
217*4a2da0b8SParav Pandit 			 dce_tcp_rtt, var);
218*4a2da0b8SParav Pandit 		break;
219*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_RATE_REDUCE_MONITOR_PERIOD:
220*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_RATE_REDUCE_MONITOR_PERIOD_ATTR;
221*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
222*4a2da0b8SParav Pandit 			 rate_reduce_monitor_period, var);
223*4a2da0b8SParav Pandit 		break;
224*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_INITIAL_ALPHA_VALUE:
225*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_INITIAL_ALPHA_VALUE_ATTR;
226*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
227*4a2da0b8SParav Pandit 			 initial_alpha_value, var);
228*4a2da0b8SParav Pandit 		break;
229*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_RP_GD:
230*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_RP_GD_ATTR;
231*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_rp, field,
232*4a2da0b8SParav Pandit 			 rpg_gd, var);
233*4a2da0b8SParav Pandit 		break;
234*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_NP_CNP_DSCP:
235*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_NP_CNP_DSCP_ATTR;
236*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_dscp, var);
237*4a2da0b8SParav Pandit 		break;
238*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_NP_CNP_PRIO_MODE:
239*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR;
240*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_prio_mode, var);
241*4a2da0b8SParav Pandit 		break;
242*4a2da0b8SParav Pandit 	case MLX5_IB_DBG_CC_NP_CNP_PRIO:
243*4a2da0b8SParav Pandit 		*attr_mask |= MLX5_IB_NP_CNP_PRIO_MODE_ATTR;
244*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_prio_mode, 0);
245*4a2da0b8SParav Pandit 		MLX5_SET(cong_control_r_roce_ecn_np, field, cnp_802p_prio, var);
246*4a2da0b8SParav Pandit 		break;
247*4a2da0b8SParav Pandit 	}
248*4a2da0b8SParav Pandit }
249*4a2da0b8SParav Pandit 
250*4a2da0b8SParav Pandit static int mlx5_ib_get_cc_params(struct mlx5_ib_dev *dev, int offset, u32 *var)
251*4a2da0b8SParav Pandit {
252*4a2da0b8SParav Pandit 	int outlen = MLX5_ST_SZ_BYTES(query_cong_params_out);
253*4a2da0b8SParav Pandit 	void *out;
254*4a2da0b8SParav Pandit 	void *field;
255*4a2da0b8SParav Pandit 	int err;
256*4a2da0b8SParav Pandit 	enum mlx5_ib_cong_node_type node;
257*4a2da0b8SParav Pandit 
258*4a2da0b8SParav Pandit 	out = kvzalloc(outlen, GFP_KERNEL);
259*4a2da0b8SParav Pandit 	if (!out)
260*4a2da0b8SParav Pandit 		return -ENOMEM;
261*4a2da0b8SParav Pandit 
262*4a2da0b8SParav Pandit 	node = mlx5_ib_param_to_node(offset);
263*4a2da0b8SParav Pandit 
264*4a2da0b8SParav Pandit 	err = mlx5_cmd_query_cong_params(dev->mdev, node, out, outlen);
265*4a2da0b8SParav Pandit 	if (err)
266*4a2da0b8SParav Pandit 		goto free;
267*4a2da0b8SParav Pandit 
268*4a2da0b8SParav Pandit 	field = MLX5_ADDR_OF(query_cong_params_out, out, congestion_parameters);
269*4a2da0b8SParav Pandit 	*var = mlx5_get_cc_param_val(field, offset);
270*4a2da0b8SParav Pandit 
271*4a2da0b8SParav Pandit free:
272*4a2da0b8SParav Pandit 	kvfree(out);
273*4a2da0b8SParav Pandit 	return err;
274*4a2da0b8SParav Pandit }
275*4a2da0b8SParav Pandit 
276*4a2da0b8SParav Pandit static int mlx5_ib_set_cc_params(struct mlx5_ib_dev *dev, int offset, u32 var)
277*4a2da0b8SParav Pandit {
278*4a2da0b8SParav Pandit 	int inlen = MLX5_ST_SZ_BYTES(modify_cong_params_in);
279*4a2da0b8SParav Pandit 	void *in;
280*4a2da0b8SParav Pandit 	void *field;
281*4a2da0b8SParav Pandit 	enum mlx5_ib_cong_node_type node;
282*4a2da0b8SParav Pandit 	u32 attr_mask = 0;
283*4a2da0b8SParav Pandit 	int err;
284*4a2da0b8SParav Pandit 
285*4a2da0b8SParav Pandit 	in = kvzalloc(inlen, GFP_KERNEL);
286*4a2da0b8SParav Pandit 	if (!in)
287*4a2da0b8SParav Pandit 		return -ENOMEM;
288*4a2da0b8SParav Pandit 
289*4a2da0b8SParav Pandit 	MLX5_SET(modify_cong_params_in, in, opcode,
290*4a2da0b8SParav Pandit 		 MLX5_CMD_OP_MODIFY_CONG_PARAMS);
291*4a2da0b8SParav Pandit 
292*4a2da0b8SParav Pandit 	node = mlx5_ib_param_to_node(offset);
293*4a2da0b8SParav Pandit 	MLX5_SET(modify_cong_params_in, in, cong_protocol, node);
294*4a2da0b8SParav Pandit 
295*4a2da0b8SParav Pandit 	field = MLX5_ADDR_OF(modify_cong_params_in, in, congestion_parameters);
296*4a2da0b8SParav Pandit 	mlx5_ib_set_cc_param_mask_val(field, offset, var, &attr_mask);
297*4a2da0b8SParav Pandit 
298*4a2da0b8SParav Pandit 	field = MLX5_ADDR_OF(modify_cong_params_in, in, field_select);
299*4a2da0b8SParav Pandit 	MLX5_SET(field_select_r_roce_rp, field, field_select_r_roce_rp,
300*4a2da0b8SParav Pandit 		 attr_mask);
301*4a2da0b8SParav Pandit 
302*4a2da0b8SParav Pandit 	err = mlx5_cmd_modify_cong_params(dev->mdev, in, inlen);
303*4a2da0b8SParav Pandit 	kvfree(in);
304*4a2da0b8SParav Pandit 	return err;
305*4a2da0b8SParav Pandit }
306*4a2da0b8SParav Pandit 
307*4a2da0b8SParav Pandit static ssize_t set_param(struct file *filp, const char __user *buf,
308*4a2da0b8SParav Pandit 			 size_t count, loff_t *pos)
309*4a2da0b8SParav Pandit {
310*4a2da0b8SParav Pandit 	struct mlx5_ib_dbg_param *param = filp->private_data;
311*4a2da0b8SParav Pandit 	int offset = param->offset;
312*4a2da0b8SParav Pandit 	char lbuf[11] = { };
313*4a2da0b8SParav Pandit 	u32 var;
314*4a2da0b8SParav Pandit 	int ret;
315*4a2da0b8SParav Pandit 
316*4a2da0b8SParav Pandit 	if (count > sizeof(lbuf))
317*4a2da0b8SParav Pandit 		return -EINVAL;
318*4a2da0b8SParav Pandit 
319*4a2da0b8SParav Pandit 	if (copy_from_user(lbuf, buf, count))
320*4a2da0b8SParav Pandit 		return -EFAULT;
321*4a2da0b8SParav Pandit 
322*4a2da0b8SParav Pandit 	lbuf[sizeof(lbuf) - 1] = '\0';
323*4a2da0b8SParav Pandit 
324*4a2da0b8SParav Pandit 	if (kstrtou32(lbuf, 0, &var))
325*4a2da0b8SParav Pandit 		return -EINVAL;
326*4a2da0b8SParav Pandit 
327*4a2da0b8SParav Pandit 	ret = mlx5_ib_set_cc_params(param->dev, offset, var);
328*4a2da0b8SParav Pandit 	return ret ? ret : count;
329*4a2da0b8SParav Pandit }
330*4a2da0b8SParav Pandit 
331*4a2da0b8SParav Pandit static ssize_t get_param(struct file *filp, char __user *buf, size_t count,
332*4a2da0b8SParav Pandit 			 loff_t *pos)
333*4a2da0b8SParav Pandit {
334*4a2da0b8SParav Pandit 	struct mlx5_ib_dbg_param *param = filp->private_data;
335*4a2da0b8SParav Pandit 	int offset = param->offset;
336*4a2da0b8SParav Pandit 	u32 var = 0;
337*4a2da0b8SParav Pandit 	int ret;
338*4a2da0b8SParav Pandit 	char lbuf[11];
339*4a2da0b8SParav Pandit 
340*4a2da0b8SParav Pandit 	if (*pos)
341*4a2da0b8SParav Pandit 		return 0;
342*4a2da0b8SParav Pandit 
343*4a2da0b8SParav Pandit 	ret = mlx5_ib_get_cc_params(param->dev, offset, &var);
344*4a2da0b8SParav Pandit 	if (ret)
345*4a2da0b8SParav Pandit 		return ret;
346*4a2da0b8SParav Pandit 
347*4a2da0b8SParav Pandit 	ret = snprintf(lbuf, sizeof(lbuf), "%d\n", var);
348*4a2da0b8SParav Pandit 	if (ret < 0)
349*4a2da0b8SParav Pandit 		return ret;
350*4a2da0b8SParav Pandit 
351*4a2da0b8SParav Pandit 	if (copy_to_user(buf, lbuf, ret))
352*4a2da0b8SParav Pandit 		return -EFAULT;
353*4a2da0b8SParav Pandit 
354*4a2da0b8SParav Pandit 	*pos += ret;
355*4a2da0b8SParav Pandit 	return ret;
356*4a2da0b8SParav Pandit }
357*4a2da0b8SParav Pandit 
358*4a2da0b8SParav Pandit static const struct file_operations dbg_cc_fops = {
359*4a2da0b8SParav Pandit 	.owner	= THIS_MODULE,
360*4a2da0b8SParav Pandit 	.open	= simple_open,
361*4a2da0b8SParav Pandit 	.write	= set_param,
362*4a2da0b8SParav Pandit 	.read	= get_param,
363*4a2da0b8SParav Pandit };
364*4a2da0b8SParav Pandit 
365*4a2da0b8SParav Pandit void mlx5_ib_cleanup_cong_debugfs(struct mlx5_ib_dev *dev)
366*4a2da0b8SParav Pandit {
367*4a2da0b8SParav Pandit 	if (!mlx5_debugfs_root ||
368*4a2da0b8SParav Pandit 	    !dev->dbg_cc_params ||
369*4a2da0b8SParav Pandit 	    !dev->dbg_cc_params->root)
370*4a2da0b8SParav Pandit 		return;
371*4a2da0b8SParav Pandit 
372*4a2da0b8SParav Pandit 	debugfs_remove_recursive(dev->dbg_cc_params->root);
373*4a2da0b8SParav Pandit 	kfree(dev->dbg_cc_params);
374*4a2da0b8SParav Pandit 	dev->dbg_cc_params = NULL;
375*4a2da0b8SParav Pandit }
376*4a2da0b8SParav Pandit 
377*4a2da0b8SParav Pandit int mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev *dev)
378*4a2da0b8SParav Pandit {
379*4a2da0b8SParav Pandit 	struct mlx5_ib_dbg_cc_params *dbg_cc_params;
380*4a2da0b8SParav Pandit 	int i;
381*4a2da0b8SParav Pandit 
382*4a2da0b8SParav Pandit 	if (!mlx5_debugfs_root)
383*4a2da0b8SParav Pandit 		goto out;
384*4a2da0b8SParav Pandit 
385*4a2da0b8SParav Pandit 	if (!MLX5_CAP_GEN(dev->mdev, cc_query_allowed) ||
386*4a2da0b8SParav Pandit 	    !MLX5_CAP_GEN(dev->mdev, cc_modify_allowed))
387*4a2da0b8SParav Pandit 		goto out;
388*4a2da0b8SParav Pandit 
389*4a2da0b8SParav Pandit 	dbg_cc_params = kzalloc(sizeof(*dbg_cc_params), GFP_KERNEL);
390*4a2da0b8SParav Pandit 	if (!dbg_cc_params)
391*4a2da0b8SParav Pandit 		goto out;
392*4a2da0b8SParav Pandit 
393*4a2da0b8SParav Pandit 	dev->dbg_cc_params = dbg_cc_params;
394*4a2da0b8SParav Pandit 
395*4a2da0b8SParav Pandit 	dbg_cc_params->root = debugfs_create_dir("cc_params",
396*4a2da0b8SParav Pandit 						 dev->mdev->priv.dbg_root);
397*4a2da0b8SParav Pandit 	if (!dbg_cc_params->root)
398*4a2da0b8SParav Pandit 		goto err;
399*4a2da0b8SParav Pandit 
400*4a2da0b8SParav Pandit 	for (i = 0; i < MLX5_IB_DBG_CC_MAX; i++) {
401*4a2da0b8SParav Pandit 		dbg_cc_params->params[i].offset = i;
402*4a2da0b8SParav Pandit 		dbg_cc_params->params[i].dev = dev;
403*4a2da0b8SParav Pandit 		dbg_cc_params->params[i].dentry =
404*4a2da0b8SParav Pandit 			debugfs_create_file(mlx5_ib_dbg_cc_name[i],
405*4a2da0b8SParav Pandit 					    0600, dbg_cc_params->root,
406*4a2da0b8SParav Pandit 					    &dbg_cc_params->params[i],
407*4a2da0b8SParav Pandit 					    &dbg_cc_fops);
408*4a2da0b8SParav Pandit 		if (!dbg_cc_params->params[i].dentry)
409*4a2da0b8SParav Pandit 			goto err;
410*4a2da0b8SParav Pandit 	}
411*4a2da0b8SParav Pandit out:	return 0;
412*4a2da0b8SParav Pandit 
413*4a2da0b8SParav Pandit err:
414*4a2da0b8SParav Pandit 	mlx5_ib_warn(dev, "cong debugfs failure\n");
415*4a2da0b8SParav Pandit 	mlx5_ib_cleanup_cong_debugfs(dev);
416*4a2da0b8SParav Pandit 	/*
417*4a2da0b8SParav Pandit 	 * We don't want to fail driver if debugfs failed to initialize,
418*4a2da0b8SParav Pandit 	 * so we are not forwarding error to the user.
419*4a2da0b8SParav Pandit 	 */
420*4a2da0b8SParav Pandit 	return 0;
421*4a2da0b8SParav Pandit }
422