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