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_cq_coal_str[] = {
27 "buf_maxtime",
28 "normal_maxbuf",
29 "during_maxbuf",
30 "en_ring_idle_mode",
31 "enable",
32 };
33
34 static 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
bnxt_re_qp_state_str(u8 state)51 static 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
bnxt_re_qp_type_str(u8 type)73 static 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
qp_info_read(struct file * filep,char __user * buffer,size_t count,loff_t * ppos)85 static 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
120 static const struct file_operations debugfs_qp_fops = {
121 .owner = THIS_MODULE,
122 .open = simple_open,
123 .read = qp_info_read,
124 };
125
bnxt_re_debug_add_qpinfo(struct bnxt_re_dev * rdev,struct bnxt_re_qp * qp)126 void 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
bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev * rdev,struct bnxt_re_qp * qp)134 void bnxt_re_debug_rem_qpinfo(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
135 {
136 debugfs_remove(qp->dentry);
137 }
138
map_cc_config_offset_gen0_ext0(u32 offset,struct bnxt_qplib_cc_param * ccparam,u32 * val)139 static 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
bnxt_re_cc_config_get(struct file * filp,char __user * buffer,size_t usr_buf_len,loff_t * ppos)192 static 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
bnxt_re_fill_gen0_ext0(struct bnxt_qplib_cc_param * ccparam,u32 offset,u32 val)218 static 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
bnxt_re_configure_cc(struct bnxt_re_dev * rdev,u32 gen_ext,u32 offset,u32 val)278 static 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
bnxt_re_cc_config_set(struct file * filp,const char __user * buffer,size_t count,loff_t * ppos)294 static 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
319 static 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
info_show(struct seq_file * m,void * unused)326 static 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 }
353 DEFINE_SHOW_ATTRIBUTE(info);
354
bnxt_re_debugfs_add_info(struct bnxt_re_dev * rdev)355 static 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
cq_coal_cfg_write(struct file * file,const char __user * buf,size_t count,loff_t * pos)360 static 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
cq_coal_cfg_show(struct seq_file * s,void * unused)414 static 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 }
444 DEFINE_SHOW_STORE_ATTRIBUTE(cq_coal_cfg);
445
bnxt_re_cleanup_cq_coal_debugfs(struct bnxt_re_dev * rdev)446 static 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
bnxt_re_init_cq_coal_debugfs(struct bnxt_re_dev * rdev)452 static 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
bnxt_re_debugfs_add_pdev(struct bnxt_re_dev * rdev)477 void 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
bnxt_re_debugfs_rem_pdev(struct bnxt_re_dev * rdev)506 void 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
bnxt_re_register_debugfs(void)516 void bnxt_re_register_debugfs(void)
517 {
518 bnxt_re_debugfs_root = debugfs_create_dir("bnxt_re", NULL);
519 }
520
bnxt_re_unregister_debugfs(void)521 void bnxt_re_unregister_debugfs(void)
522 {
523 debugfs_remove(bnxt_re_debugfs_root);
524 }
525