xref: /linux/drivers/infiniband/hw/bnxt_re/debugfs.c (revision 68a052239fc4b351e961f698b824f7654a346091)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
2 /*
3  * Copyright (c) 2024, Broadcom. All rights reserved.  The term
4  * Broadcom refers to Broadcom Limited and/or its subsidiaries.
5  *
6  * Description: Debugfs component of the bnxt_re driver
7  */
8 
9 #include <linux/debugfs.h>
10 #include <linux/pci.h>
11 #include <linux/seq_file.h>
12 #include <rdma/ib_addr.h>
13 
14 #include "bnxt_ulp.h"
15 #include "roce_hsi.h"
16 #include "qplib_res.h"
17 #include "qplib_sp.h"
18 #include "qplib_fp.h"
19 #include "qplib_rcfw.h"
20 #include "bnxt_re.h"
21 #include "ib_verbs.h"
22 #include "debugfs.h"
23 
24 static struct dentry *bnxt_re_debugfs_root;
25 
26 static const char * const bnxt_re_cc_gen0_name[] = {
27 	"enable_cc",
28 	"run_avg_weight_g",
29 	"num_phase_per_state",
30 	"init_cr",
31 	"init_tr",
32 	"tos_ecn",
33 	"tos_dscp",
34 	"alt_vlan_pcp",
35 	"alt_vlan_dscp",
36 	"rtt",
37 	"cc_mode",
38 	"tcp_cp",
39 	"tx_queue",
40 	"inactivity_cp",
41 };
42 
43 static inline const char *bnxt_re_qp_state_str(u8 state)
44 {
45 	switch (state) {
46 	case CMDQ_MODIFY_QP_NEW_STATE_RESET:
47 		return "RST";
48 	case CMDQ_MODIFY_QP_NEW_STATE_INIT:
49 		return "INIT";
50 	case CMDQ_MODIFY_QP_NEW_STATE_RTR:
51 		return "RTR";
52 	case CMDQ_MODIFY_QP_NEW_STATE_RTS:
53 		return "RTS";
54 	case CMDQ_MODIFY_QP_NEW_STATE_SQE:
55 		return "SQER";
56 	case CMDQ_MODIFY_QP_NEW_STATE_SQD:
57 		return "SQD";
58 	case CMDQ_MODIFY_QP_NEW_STATE_ERR:
59 		return "ERR";
60 	default:
61 		return "Invalid QP state";
62 	}
63 }
64 
65 static inline const char *bnxt_re_qp_type_str(u8 type)
66 {
67 	switch (type) {
68 	case CMDQ_CREATE_QP1_TYPE_GSI: return "QP1";
69 	case CMDQ_CREATE_QP_TYPE_GSI: return "QP1";
70 	case CMDQ_CREATE_QP_TYPE_RC: return "RC";
71 	case CMDQ_CREATE_QP_TYPE_UD: return "UD";
72 	case CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE: return "RAW_ETHERTYPE";
73 	default: return "Invalid transport type";
74 	}
75 }
76 
77 static ssize_t qp_info_read(struct file *filep,
78 			    char __user *buffer,
79 			    size_t count, loff_t *ppos)
80 {
81 	struct bnxt_re_qp *qp = filep->private_data;
82 	char *buf;
83 	int len;
84 
85 	if (*ppos)
86 		return 0;
87 
88 	buf = kasprintf(GFP_KERNEL,
89 			"QPN\t\t: %d\n"
90 			"transport\t: %s\n"
91 			"state\t\t: %s\n"
92 			"mtu\t\t: %d\n"
93 			"timeout\t\t: %d\n"
94 			"remote QPN\t: %d\n",
95 			qp->qplib_qp.id,
96 			bnxt_re_qp_type_str(qp->qplib_qp.type),
97 			bnxt_re_qp_state_str(qp->qplib_qp.state),
98 			qp->qplib_qp.mtu,
99 			qp->qplib_qp.timeout,
100 			qp->qplib_qp.dest_qpn);
101 	if (!buf)
102 		return -ENOMEM;
103 	if (count < strlen(buf)) {
104 		kfree(buf);
105 		return -ENOSPC;
106 	}
107 	len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
108 	kfree(buf);
109 	return len;
110 }
111 
112 static const struct file_operations debugfs_qp_fops = {
113 	.owner = THIS_MODULE,
114 	.open = simple_open,
115 	.read = qp_info_read,
116 };
117 
118 void bnxt_re_debug_add_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
119 {
120 	char resn[32];
121 
122 	sprintf(resn, "0x%x", qp->qplib_qp.id);
123 	qp->dentry = debugfs_create_file(resn, 0400, rdev->qp_debugfs, qp, &debugfs_qp_fops);
124 }
125 
126 void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
127 {
128 	debugfs_remove(qp->dentry);
129 }
130 
131 static int map_cc_config_offset_gen0_ext0(u32 offset, struct bnxt_qplib_cc_param *ccparam, u32 *val)
132 {
133 	u64 map_offset;
134 
135 	map_offset = BIT(offset);
136 
137 	switch (map_offset) {
138 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
139 		*val = ccparam->enable;
140 		break;
141 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
142 		*val = ccparam->g;
143 		break;
144 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
145 		*val = ccparam->nph_per_state;
146 		break;
147 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
148 		*val = ccparam->init_cr;
149 		break;
150 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
151 		*val = ccparam->init_tr;
152 		break;
153 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
154 		*val = ccparam->tos_ecn;
155 		break;
156 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
157 		*val =  ccparam->tos_dscp;
158 		break;
159 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
160 		*val = ccparam->alt_vlan_pcp;
161 		break;
162 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
163 		*val = ccparam->alt_tos_dscp;
164 		break;
165 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
166 	       *val = ccparam->rtt;
167 		break;
168 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
169 		*val = ccparam->cc_mode;
170 		break;
171 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
172 		*val =  ccparam->tcp_cp;
173 		break;
174 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
175 		*val = ccparam->inact_th;
176 		break;
177 	default:
178 		return -EINVAL;
179 	}
180 
181 	return 0;
182 }
183 
184 static ssize_t bnxt_re_cc_config_get(struct file *filp, char __user *buffer,
185 				     size_t usr_buf_len, loff_t *ppos)
186 {
187 	struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
188 	struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
189 	struct bnxt_qplib_cc_param ccparam = {};
190 	u32 offset = dbg_cc_param->offset;
191 	char buf[16];
192 	u32 val;
193 	int rc;
194 
195 	rc = bnxt_qplib_query_cc_param(&rdev->qplib_res, &ccparam);
196 	if (rc)
197 		return rc;
198 
199 	rc = map_cc_config_offset_gen0_ext0(offset, &ccparam, &val);
200 	if (rc)
201 		return rc;
202 
203 	rc = snprintf(buf, sizeof(buf), "%d\n", val);
204 	if (rc < 0)
205 		return rc;
206 
207 	return simple_read_from_buffer(buffer, usr_buf_len, ppos, (u8 *)(buf), rc);
208 }
209 
210 static int bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
211 {
212 	u32 modify_mask;
213 
214 	modify_mask = BIT(offset);
215 
216 	switch (modify_mask) {
217 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
218 		ccparam->enable = val;
219 		break;
220 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
221 		ccparam->g = val;
222 		break;
223 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
224 		ccparam->nph_per_state = val;
225 		break;
226 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
227 		ccparam->init_cr = val;
228 		break;
229 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
230 		ccparam->init_tr = val;
231 		break;
232 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
233 		ccparam->tos_ecn = val;
234 		break;
235 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
236 		ccparam->tos_dscp = val;
237 		break;
238 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
239 		ccparam->alt_vlan_pcp = val;
240 		break;
241 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
242 		ccparam->alt_tos_dscp = val;
243 		break;
244 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
245 		ccparam->rtt = val;
246 		break;
247 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
248 		ccparam->cc_mode = val;
249 		break;
250 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
251 		ccparam->tcp_cp = val;
252 		break;
253 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE:
254 		return -EOPNOTSUPP;
255 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
256 		ccparam->inact_th = val;
257 		break;
258 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TIME_PER_PHASE:
259 		ccparam->time_pph = val;
260 		break;
261 	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_PKTS_PER_PHASE:
262 		ccparam->pkts_pph = val;
263 		break;
264 	}
265 
266 	ccparam->mask = modify_mask;
267 	return 0;
268 }
269 
270 static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offset, u32 val)
271 {
272 	struct bnxt_qplib_cc_param ccparam = { };
273 	int rc;
274 
275 	if (gen_ext != CC_CONFIG_GEN0_EXT0)
276 		return -EOPNOTSUPP;
277 
278 	rc = bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
279 	if (rc)
280 		return rc;
281 
282 	bnxt_qplib_modify_cc(&rdev->qplib_res, &ccparam);
283 	return 0;
284 }
285 
286 static ssize_t bnxt_re_cc_config_set(struct file *filp, const char __user *buffer,
287 				     size_t count, loff_t *ppos)
288 {
289 	struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
290 	struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
291 	u32 offset = dbg_cc_param->offset;
292 	u8 cc_gen = dbg_cc_param->cc_gen;
293 	char buf[16];
294 	u32 val;
295 	int rc;
296 
297 	if (count >= sizeof(buf))
298 		return -EINVAL;
299 
300 	if (copy_from_user(buf, buffer, count))
301 		return -EFAULT;
302 
303 	buf[count] = '\0';
304 	if (kstrtou32(buf, 0, &val))
305 		return -EINVAL;
306 
307 	rc = bnxt_re_configure_cc(rdev, cc_gen, offset, val);
308 	return rc ? rc : count;
309 }
310 
311 static const struct file_operations bnxt_re_cc_config_ops = {
312 	.owner = THIS_MODULE,
313 	.open = simple_open,
314 	.read = bnxt_re_cc_config_get,
315 	.write = bnxt_re_cc_config_set,
316 };
317 
318 static int info_show(struct seq_file *m, void *unused)
319 {
320 	struct bnxt_re_dev *rdev = m->private;
321 	struct bnxt_re_res_cntrs *res_s = &rdev->stats.res;
322 
323 	seq_puts(m, "Info:\n");
324 	seq_printf(m, "Device Name\t\t: %s\n", dev_name(&rdev->ibdev.dev));
325 	seq_printf(m, "PD Watermark\t\t: %llu\n", res_s->pd_watermark);
326 	seq_printf(m, "AH Watermark\t\t: %llu\n", res_s->ah_watermark);
327 	seq_printf(m, "QP Watermark\t\t: %llu\n", res_s->qp_watermark);
328 	seq_printf(m, "RC QP Watermark\t\t: %llu\n", res_s->rc_qp_watermark);
329 	seq_printf(m, "UD QP Watermark\t\t: %llu\n", res_s->ud_qp_watermark);
330 	seq_printf(m, "SRQ Watermark\t\t: %llu\n", res_s->srq_watermark);
331 	seq_printf(m, "CQ Watermark\t\t: %llu\n", res_s->cq_watermark);
332 	seq_printf(m, "MR Watermark\t\t: %llu\n", res_s->mr_watermark);
333 	seq_printf(m, "MW Watermark\t\t: %llu\n", res_s->mw_watermark);
334 	seq_printf(m, "CQ Resize Count\t\t: %d\n", atomic_read(&res_s->resize_count));
335 	if (rdev->pacing.dbr_pacing) {
336 		seq_printf(m, "DB Pacing Reschedule\t: %llu\n", rdev->stats.pacing.resched);
337 		seq_printf(m, "DB Pacing Complete\t: %llu\n", rdev->stats.pacing.complete);
338 		seq_printf(m, "DB Pacing Alerts\t: %llu\n", rdev->stats.pacing.alerts);
339 		seq_printf(m, "DB FIFO Register\t: 0x%x\n",
340 			   readl(rdev->en_dev->bar0 + rdev->pacing.dbr_db_fifo_reg_off));
341 	}
342 
343 	return 0;
344 }
345 DEFINE_SHOW_ATTRIBUTE(info);
346 
347 static void bnxt_re_debugfs_add_info(struct bnxt_re_dev *rdev)
348 {
349 	debugfs_create_file("info", 0400, rdev->dbg_root, rdev, &info_fops);
350 }
351 
352 void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev)
353 {
354 	struct pci_dev *pdev = rdev->en_dev->pdev;
355 	struct bnxt_re_dbg_cc_config_params *cc_params;
356 	int i;
357 
358 	rdev->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), bnxt_re_debugfs_root);
359 
360 	rdev->qp_debugfs = debugfs_create_dir("QPs", rdev->dbg_root);
361 	rdev->cc_config = debugfs_create_dir("cc_config", rdev->dbg_root);
362 
363 	bnxt_re_debugfs_add_info(rdev);
364 
365 	rdev->cc_config_params = kzalloc(sizeof(*cc_params), GFP_KERNEL);
366 
367 	for (i = 0; i < BNXT_RE_CC_PARAM_GEN0; i++) {
368 		struct bnxt_re_cc_param *tmp_params = &rdev->cc_config_params->gen0_parms[i];
369 
370 		tmp_params->rdev = rdev;
371 		tmp_params->offset = i;
372 		tmp_params->cc_gen = CC_CONFIG_GEN0_EXT0;
373 		tmp_params->dentry = debugfs_create_file(bnxt_re_cc_gen0_name[i], 0400,
374 							 rdev->cc_config, tmp_params,
375 							 &bnxt_re_cc_config_ops);
376 	}
377 }
378 
379 void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev)
380 {
381 	debugfs_remove_recursive(rdev->qp_debugfs);
382 	debugfs_remove_recursive(rdev->cc_config);
383 	kfree(rdev->cc_config_params);
384 	debugfs_remove_recursive(rdev->dbg_root);
385 	rdev->dbg_root = NULL;
386 }
387 
388 void bnxt_re_register_debugfs(void)
389 {
390 	bnxt_re_debugfs_root = debugfs_create_dir("bnxt_re", NULL);
391 }
392 
393 void bnxt_re_unregister_debugfs(void)
394 {
395 	debugfs_remove(bnxt_re_debugfs_root);
396 }
397