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