File Index
Files and directories
Sign in
FILE

debugfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/infiniband/hw/bnxt_re/debugfs.c C
  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
 24static struct dentry *bnxt_re_debugfs_root;
 25
 26static const char * const bnxt_re_cq_coal_str[] = {
 27	"buf_maxtime",
 28	"normal_maxbuf",
 29	"during_maxbuf",
 30	"en_ring_idle_mode",
 31	"enable",
 32};
 33
 34static const char * const bnxt_re_cc_gen0_name[] = {
 35	"enable_cc",
 36	"run_avg_weight_g",
 37	"num_phase_per_state",
 38	"init_cr",
 39	"init_tr",
 40	"tos_ecn",
 41	"tos_dscp",
 42	"alt_vlan_pcp",
 43	"alt_vlan_dscp",
 44	"rtt",
 45	"cc_mode",
 46	"tcp_cp",
 47	"tx_queue",
 48	"inactivity_cp",
 49};
 50
 51static inline const char *bnxt_re_qp_state_str(u8 state)
 52{
 53	switch (state) {
 54	case CMDQ_MODIFY_QP_NEW_STATE_RESET:
 55		return "RST";
 56	case CMDQ_MODIFY_QP_NEW_STATE_INIT:
 57		return "INIT";
 58	case CMDQ_MODIFY_QP_NEW_STATE_RTR:
 59		return "RTR";
 60	case CMDQ_MODIFY_QP_NEW_STATE_RTS:
 61		return "RTS";
 62	case CMDQ_MODIFY_QP_NEW_STATE_SQE:
 63		return "SQER";
 64	case CMDQ_MODIFY_QP_NEW_STATE_SQD:
 65		return "SQD";
 66	case CMDQ_MODIFY_QP_NEW_STATE_ERR:
 67		return "ERR";
 68	default:
 69		return "Invalid QP state";
 70	}
 71}
 72
 73static inline const char *bnxt_re_qp_type_str(u8 type)
 74{
 75	switch (type) {
 76	case CMDQ_CREATE_QP1_TYPE_GSI: return "QP1";
 77	case CMDQ_CREATE_QP_TYPE_GSI: return "QP1";
 78	case CMDQ_CREATE_QP_TYPE_RC: return "RC";
 79	case CMDQ_CREATE_QP_TYPE_UD: return "UD";
 80	case CMDQ_CREATE_QP_TYPE_RAW_ETHERTYPE: return "RAW_ETHERTYPE";
 81	default: return "Invalid transport type";
 82	}
 83}
 84
 85static ssize_t qp_info_read(struct file *filep,
 86			    char __user *buffer,
 87			    size_t count, loff_t *ppos)
 88{
 89	struct bnxt_re_qp *qp = filep->private_data;
 90	char *buf;
 91	int len;
 92
 93	if (*ppos)
 94		return 0;
 95
 96	buf = kasprintf(GFP_KERNEL,
 97			"QPN\t\t: %d\n"
 98			"transport\t: %s\n"
 99			"state\t\t: %s\n"
100			"mtu\t\t: %d\n"
101			"timeout\t\t: %d\n"
102			"remote QPN\t: %d\n",
103			qp->qplib_qp.id,
104			bnxt_re_qp_type_str(qp->qplib_qp.type),
105			bnxt_re_qp_state_str(qp->qplib_qp.state),
106			qp->qplib_qp.mtu,
107			qp->qplib_qp.timeout,
108			qp->qplib_qp.dest_qpn);
109	if (!buf)
110		return -ENOMEM;
111	if (count < strlen(buf)) {
112		kfree(buf);
113		return -ENOSPC;
114	}
115	len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
116	kfree(buf);
117	return len;
118}
119
120static const struct file_operations debugfs_qp_fops = {
121	.owner = THIS_MODULE,
122	.open = simple_open,
123	.read = qp_info_read,
124};
125
126void bnxt_re_debug_add_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
127{
128	char resn[32];
129
130	sprintf(resn, "0x%x", qp->qplib_qp.id);
131	qp->dentry = debugfs_create_file(resn, 0400, rdev->qp_debugfs, qp, &debugfs_qp_fops);
132}
133
134void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
135{
136	debugfs_remove(qp->dentry);
137}
138
139static int map_cc_config_offset_gen0_ext0(u32 offset, struct bnxt_qplib_cc_param *ccparam, u32 *val)
140{
141	u64 map_offset;
142
143	map_offset = BIT(offset);
144
145	switch (map_offset) {
146	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
147		*val = ccparam->enable;
148		break;
149	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
150		*val = ccparam->g;
151		break;
152	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
153		*val = ccparam->nph_per_state;
154		break;
155	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
156		*val = ccparam->init_cr;
157		break;
158	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
159		*val = ccparam->init_tr;
160		break;
161	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
162		*val = ccparam->tos_ecn;
163		break;
164	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
165		*val =  ccparam->tos_dscp;
166		break;
167	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
168		*val = ccparam->alt_vlan_pcp;
169		break;
170	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
171		*val = ccparam->alt_tos_dscp;
172		break;
173	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
174	       *val = ccparam->rtt;
175		break;
176	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
177		*val = ccparam->cc_mode;
178		break;
179	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
180		*val =  ccparam->tcp_cp;
181		break;
182	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
183		*val = ccparam->inact_th;
184		break;
185	default:
186		return -EINVAL;
187	}
188
189	return 0;
190}
191
192static ssize_t bnxt_re_cc_config_get(struct file *filp, char __user *buffer,
193				     size_t usr_buf_len, loff_t *ppos)
194{
195	struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
196	struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
197	struct bnxt_qplib_cc_param ccparam = {};
198	u32 offset = dbg_cc_param->offset;
199	char buf[16];
200	u32 val;
201	int rc;
202
203	rc = bnxt_qplib_query_cc_param(&rdev->qplib_res, &ccparam);
204	if (rc)
205		return rc;
206
207	rc = map_cc_config_offset_gen0_ext0(offset, &ccparam, &val);
208	if (rc)
209		return rc;
210
211	rc = snprintf(buf, sizeof(buf), "%d\n", val);
212	if (rc < 0)
213		return rc;
214
215	return simple_read_from_buffer(buffer, usr_buf_len, ppos, (u8 *)(buf), rc);
216}
217
218static int bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param *ccparam, u32 offset, u32 val)
219{
220	u32 modify_mask;
221
222	modify_mask = BIT(offset);
223
224	switch (modify_mask) {
225	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ENABLE_CC:
226		ccparam->enable = val;
227		break;
228	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_G:
229		ccparam->g = val;
230		break;
231	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_NUMPHASEPERSTATE:
232		ccparam->nph_per_state = val;
233		break;
234	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_CR:
235		ccparam->init_cr = val;
236		break;
237	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INIT_TR:
238		ccparam->init_tr = val;
239		break;
240	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_ECN:
241		ccparam->tos_ecn = val;
242		break;
243	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TOS_DSCP:
244		ccparam->tos_dscp = val;
245		break;
246	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_VLAN_PCP:
247		ccparam->alt_vlan_pcp = val;
248		break;
249	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_ALT_TOS_DSCP:
250		ccparam->alt_tos_dscp = val;
251		break;
252	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_RTT:
253		ccparam->rtt = val;
254		break;
255	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_CC_MODE:
256		ccparam->cc_mode = val;
257		break;
258	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TCP_CP:
259		ccparam->tcp_cp = val;
260		break;
261	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TX_QUEUE:
262		return -EOPNOTSUPP;
263	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_INACTIVITY_CP:
264		ccparam->inact_th = val;
265		break;
266	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_TIME_PER_PHASE:
267		ccparam->time_pph = val;
268		break;
269	case CMDQ_MODIFY_ROCE_CC_MODIFY_MASK_PKTS_PER_PHASE:
270		ccparam->pkts_pph = val;
271		break;
272	}
273
274	ccparam->mask = modify_mask;
275	return 0;
276}
277
278static int bnxt_re_configure_cc(struct bnxt_re_dev *rdev, u32 gen_ext, u32 offset, u32 val)
279{
280	struct bnxt_qplib_cc_param ccparam = { };
281	int rc;
282
283	if (gen_ext != CC_CONFIG_GEN0_EXT0)
284		return -EOPNOTSUPP;
285
286	rc = bnxt_re_fill_gen0_ext0(&ccparam, offset, val);
287	if (rc)
288		return rc;
289
290	bnxt_qplib_modify_cc(&rdev->qplib_res, &ccparam);
291	return 0;
292}
293
294static ssize_t bnxt_re_cc_config_set(struct file *filp, const char __user *buffer,
295				     size_t count, loff_t *ppos)
296{
297	struct bnxt_re_cc_param *dbg_cc_param = filp->private_data;
298	struct bnxt_re_dev *rdev = dbg_cc_param->rdev;
299	u32 offset = dbg_cc_param->offset;
300	u8 cc_gen = dbg_cc_param->cc_gen;
301	char buf[16];
302	u32 val;
303	int rc;
304
305	if (count >= sizeof(buf))
306		return -EINVAL;
307
308	if (copy_from_user(buf, buffer, count))
309		return -EFAULT;
310
311	buf[count] = '\0';
312	if (kstrtou32(buf, 0, &val))
313		return -EINVAL;
314
315	rc = bnxt_re_configure_cc(rdev, cc_gen, offset, val);
316	return rc ? rc : count;
317}
318
319static const struct file_operations bnxt_re_cc_config_ops = {
320	.owner = THIS_MODULE,
321	.open = simple_open,
322	.read = bnxt_re_cc_config_get,
323	.write = bnxt_re_cc_config_set,
324};
325
326static int info_show(struct seq_file *m, void *unused)
327{
328	struct bnxt_re_dev *rdev = m->private;
329	struct bnxt_re_res_cntrs *res_s = &rdev->stats.res;
330
331	seq_puts(m, "Info:\n");
332	seq_printf(m, "Device Name\t\t: %s\n", dev_name(&rdev->ibdev.dev));
333	seq_printf(m, "PD Watermark\t\t: %llu\n", res_s->pd_watermark);
334	seq_printf(m, "AH Watermark\t\t: %llu\n", res_s->ah_watermark);
335	seq_printf(m, "QP Watermark\t\t: %llu\n", res_s->qp_watermark);
336	seq_printf(m, "RC QP Watermark\t\t: %llu\n", res_s->rc_qp_watermark);
337	seq_printf(m, "UD QP Watermark\t\t: %llu\n", res_s->ud_qp_watermark);
338	seq_printf(m, "SRQ Watermark\t\t: %llu\n", res_s->srq_watermark);
339	seq_printf(m, "CQ Watermark\t\t: %llu\n", res_s->cq_watermark);
340	seq_printf(m, "MR Watermark\t\t: %llu\n", res_s->mr_watermark);
341	seq_printf(m, "MW Watermark\t\t: %llu\n", res_s->mw_watermark);
342	seq_printf(m, "CQ Resize Count\t\t: %d\n", atomic_read(&res_s->resize_count));
343	if (rdev->pacing.dbr_pacing) {
344		seq_printf(m, "DB Pacing Reschedule\t: %llu\n", rdev->stats.pacing.resched);
345		seq_printf(m, "DB Pacing Complete\t: %llu\n", rdev->stats.pacing.complete);
346		seq_printf(m, "DB Pacing Alerts\t: %llu\n", rdev->stats.pacing.alerts);
347		seq_printf(m, "DB FIFO Register\t: 0x%x\n",
348			   readl(rdev->en_dev->bar0 + rdev->pacing.dbr_db_fifo_reg_off));
349	}
350
351	return 0;
352}
353DEFINE_SHOW_ATTRIBUTE(info);
354
355static void bnxt_re_debugfs_add_info(struct bnxt_re_dev *rdev)
356{
357	debugfs_create_file("info", 0400, rdev->dbg_root, rdev, &info_fops);
358}
359
360static ssize_t cq_coal_cfg_write(struct file *file,
361				 const char __user *buf,
362				 size_t count, loff_t *pos)
363{
364	struct seq_file *s = file->private_data;
365	struct bnxt_re_cq_coal_param *param = s->private;
366	struct bnxt_re_dev *rdev = param->rdev;
367	int offset = param->offset;
368	char lbuf[16] = { };
369	u32 val;
370
371	if (count > sizeof(lbuf))
372		return -EINVAL;
373
374	if (copy_from_user(lbuf, buf, count))
375		return -EFAULT;
376
377	lbuf[sizeof(lbuf) - 1] = '\0';
378
379	if (kstrtou32(lbuf, 0, &val))
380		return -EINVAL;
381
382	switch (offset) {
383	case BNXT_RE_COAL_CQ_BUF_MAXTIME:
384		if (val < 1 || val > BNXT_QPLIB_CQ_COAL_MAX_BUF_MAXTIME)
385			return -EINVAL;
386		rdev->cq_coalescing.buf_maxtime = val;
387		break;
388	case BNXT_RE_COAL_CQ_NORMAL_MAXBUF:
389		if (val < 1 || val > BNXT_QPLIB_CQ_COAL_MAX_NORMAL_MAXBUF)
390			return -EINVAL;
391		rdev->cq_coalescing.normal_maxbuf = val;
392		break;
393	case BNXT_RE_COAL_CQ_DURING_MAXBUF:
394		if (val < 1 || val > BNXT_QPLIB_CQ_COAL_MAX_DURING_MAXBUF)
395			return -EINVAL;
396		rdev->cq_coalescing.during_maxbuf = val;
397		break;
398	case BNXT_RE_COAL_CQ_EN_RING_IDLE_MODE:
399		if (val > BNXT_QPLIB_CQ_COAL_MAX_EN_RING_IDLE_MODE)
400			return -EINVAL;
401		rdev->cq_coalescing.en_ring_idle_mode = val;
402		break;
403	case BNXT_RE_COAL_CQ_ENABLE:
404		if (val > 1)
405			return -EINVAL;
406		rdev->cq_coalescing.enable = val;
407		break;
408	default:
409		return -EINVAL;
410	}
411	return  count;
412}
413
414static int cq_coal_cfg_show(struct seq_file *s, void *unused)
415{
416	struct bnxt_re_cq_coal_param *param = s->private;
417	struct bnxt_re_dev *rdev = param->rdev;
418	int offset = param->offset;
419	u32 val = 0;
420
421	switch (offset) {
422	case BNXT_RE_COAL_CQ_BUF_MAXTIME:
423		val = rdev->cq_coalescing.buf_maxtime;
424		break;
425	case BNXT_RE_COAL_CQ_NORMAL_MAXBUF:
426		val = rdev->cq_coalescing.normal_maxbuf;
427		break;
428	case BNXT_RE_COAL_CQ_DURING_MAXBUF:
429		val = rdev->cq_coalescing.during_maxbuf;
430		break;
431	case BNXT_RE_COAL_CQ_EN_RING_IDLE_MODE:
432		val = rdev->cq_coalescing.en_ring_idle_mode;
433		break;
434	case BNXT_RE_COAL_CQ_ENABLE:
435		val = rdev->cq_coalescing.enable;
436		break;
437	default:
438		return -EINVAL;
439	}
440
441	seq_printf(s, "%u\n", val);
442	return 0;
443}
444DEFINE_SHOW_STORE_ATTRIBUTE(cq_coal_cfg);
445
446static void bnxt_re_cleanup_cq_coal_debugfs(struct bnxt_re_dev *rdev)
447{
448	debugfs_remove_recursive(rdev->cq_coal_cfg);
449	kfree(rdev->cq_coal_cfg_params);
450}
451
452static void bnxt_re_init_cq_coal_debugfs(struct bnxt_re_dev *rdev)
453{
454	struct bnxt_re_dbg_cq_coal_params *dbg_cq_coal_params;
455	int i;
456
457	if (!_is_cq_coalescing_supported(rdev->dev_attr->dev_cap_flags2))
458		return;
459
460	dbg_cq_coal_params = kzalloc(sizeof(*dbg_cq_coal_params), GFP_KERNEL);
461	if (!dbg_cq_coal_params)
462		return;
463
464	rdev->cq_coal_cfg = debugfs_create_dir("cq_coal_cfg", rdev->dbg_root);
465	rdev->cq_coal_cfg_params = dbg_cq_coal_params;
466
467	for (i = 0; i < BNXT_RE_COAL_CQ_MAX; i++) {
468		dbg_cq_coal_params->params[i].offset = i;
469		dbg_cq_coal_params->params[i].rdev = rdev;
470		debugfs_create_file(bnxt_re_cq_coal_str[i],
471				    0600, rdev->cq_coal_cfg,
472				    &dbg_cq_coal_params->params[i],
473				    &cq_coal_cfg_fops);
474	}
475}
476
477void bnxt_re_debugfs_add_pdev(struct bnxt_re_dev *rdev)
478{
479	struct pci_dev *pdev = rdev->en_dev->pdev;
480	struct bnxt_re_dbg_cc_config_params *cc_params;
481	int i;
482
483	rdev->dbg_root = debugfs_create_dir(dev_name(&pdev->dev), bnxt_re_debugfs_root);
484
485	rdev->qp_debugfs = debugfs_create_dir("QPs", rdev->dbg_root);
486	rdev->cc_config = debugfs_create_dir("cc_config", rdev->dbg_root);
487
488	bnxt_re_debugfs_add_info(rdev);
489
490	rdev->cc_config_params = kzalloc(sizeof(*cc_params), GFP_KERNEL);
491
492	for (i = 0; i < BNXT_RE_CC_PARAM_GEN0; i++) {
493		struct bnxt_re_cc_param *tmp_params = &rdev->cc_config_params->gen0_parms[i];
494
495		tmp_params->rdev = rdev;
496		tmp_params->offset = i;
497		tmp_params->cc_gen = CC_CONFIG_GEN0_EXT0;
498		tmp_params->dentry = debugfs_create_file(bnxt_re_cc_gen0_name[i], 0400,
499							 rdev->cc_config, tmp_params,
500							 &bnxt_re_cc_config_ops);
501	}
502
503	bnxt_re_init_cq_coal_debugfs(rdev);
504}
505
506void bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev *rdev)
507{
508	bnxt_re_cleanup_cq_coal_debugfs(rdev);
509	debugfs_remove_recursive(rdev->qp_debugfs);
510	debugfs_remove_recursive(rdev->cc_config);
511	kfree(rdev->cc_config_params);
512	debugfs_remove_recursive(rdev->dbg_root);
513	rdev->dbg_root = NULL;
514}
515
516void bnxt_re_register_debugfs(void)
517{
518	bnxt_re_debugfs_root = debugfs_create_dir("bnxt_re", NULL);
519}
520
521void bnxt_re_unregister_debugfs(void)
522{
523	debugfs_remove(bnxt_re_debugfs_root);
524}
~/ Read-only file preview.