1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */ 3 4 #include <linux/debugfs.h> 5 #include <linux/pci.h> 6 #include <linux/rtnetlink.h> 7 #include <linux/seq_file.h> 8 9 #include "fbnic.h" 10 #include "fbnic_txrx.h" 11 12 static struct dentry *fbnic_dbg_root; 13 14 /* Descriptor Seq Functions */ 15 16 static void fbnic_dbg_desc_break(struct seq_file *s, int i) 17 { 18 while (i--) 19 seq_putc(s, '-'); 20 21 seq_putc(s, '\n'); 22 } 23 24 static void fbnic_dbg_ring_show(struct seq_file *s) 25 { 26 struct fbnic_ring *ring = s->private; 27 unsigned long doorbell_offset; 28 u32 head = 0, tail = 0; 29 u32 __iomem *csr_base; 30 31 csr_base = fbnic_ring_csr_base(ring); 32 doorbell_offset = ring->doorbell - csr_base; 33 34 seq_printf(s, "doorbell CSR: %#05lx q_idx: %d\n", 35 doorbell_offset, ring->q_idx); 36 seq_printf(s, "size_mask: %#06x size: %zu flags: 0x%02x\n", 37 ring->size_mask, ring->size, ring->flags); 38 seq_printf(s, "SW: head: %#06x tail: %#06x\n", 39 ring->head, ring->tail); 40 41 switch (doorbell_offset) { 42 case FBNIC_QUEUE_TWQ0_TAIL: 43 tail = readl(csr_base + FBNIC_QUEUE_TWQ0_PTRS); 44 head = FIELD_GET(FBNIC_QUEUE_TWQ_PTRS_HEAD_MASK, tail); 45 break; 46 case FBNIC_QUEUE_TWQ1_TAIL: 47 tail = readl(csr_base + FBNIC_QUEUE_TWQ1_PTRS); 48 head = FIELD_GET(FBNIC_QUEUE_TWQ_PTRS_HEAD_MASK, tail); 49 break; 50 case FBNIC_QUEUE_TCQ_HEAD: 51 head = readl(csr_base + FBNIC_QUEUE_TCQ_PTRS); 52 tail = FIELD_GET(FBNIC_QUEUE_TCQ_PTRS_TAIL_MASK, head); 53 break; 54 case FBNIC_QUEUE_BDQ_HPQ_TAIL: 55 tail = readl(csr_base + FBNIC_QUEUE_BDQ_HPQ_PTRS); 56 head = FIELD_GET(FBNIC_QUEUE_BDQ_PTRS_HEAD_MASK, tail); 57 break; 58 case FBNIC_QUEUE_BDQ_PPQ_TAIL: 59 tail = readl(csr_base + FBNIC_QUEUE_BDQ_PPQ_PTRS); 60 head = FIELD_GET(FBNIC_QUEUE_BDQ_PTRS_HEAD_MASK, tail); 61 break; 62 case FBNIC_QUEUE_RCQ_HEAD: 63 head = readl(csr_base + FBNIC_QUEUE_RCQ_PTRS); 64 tail = FIELD_GET(FBNIC_QUEUE_RCQ_PTRS_TAIL_MASK, head); 65 break; 66 } 67 68 tail &= FBNIC_QUEUE_BDQ_PTRS_TAIL_MASK; 69 head &= FBNIC_QUEUE_RCQ_PTRS_HEAD_MASK; 70 71 seq_printf(s, "HW: head: %#06x tail: %#06x\n", head, tail); 72 73 seq_puts(s, "\n"); 74 } 75 76 static void fbnic_dbg_twd_desc_seq_show(struct seq_file *s, int i) 77 { 78 struct fbnic_ring *ring = s->private; 79 u64 twd = le64_to_cpu(ring->desc[i]); 80 81 switch (FIELD_GET(FBNIC_TWD_TYPE_MASK, twd)) { 82 case FBNIC_TWD_TYPE_META: 83 seq_printf(s, "%04x %#06llx %llx %llx %llx %llx %llx %#llx %#llx %llx %#04llx %#04llx %llx %#04llx\n", 84 i, FIELD_GET(FBNIC_TWD_LEN_MASK, twd), 85 FIELD_GET(FBNIC_TWD_TYPE_MASK, twd), 86 FIELD_GET(FBNIC_TWD_FLAG_REQ_COMPLETION, twd), 87 FIELD_GET(FBNIC_TWD_FLAG_REQ_CSO, twd), 88 FIELD_GET(FBNIC_TWD_FLAG_REQ_LSO, twd), 89 FIELD_GET(FBNIC_TWD_FLAG_REQ_TS, twd), 90 FIELD_GET(FBNIC_TWD_L4_HLEN_MASK, twd), 91 FIELD_GET(FBNIC_TWD_CSUM_OFFSET_MASK, twd), 92 FIELD_GET(FBNIC_TWD_L4_TYPE_MASK, twd), 93 FIELD_GET(FBNIC_TWD_L3_IHLEN_MASK, twd), 94 FIELD_GET(FBNIC_TWD_L3_OHLEN_MASK, twd), 95 FIELD_GET(FBNIC_TWD_L3_TYPE_MASK, twd), 96 FIELD_GET(FBNIC_TWD_L2_HLEN_MASK, twd)); 97 break; 98 default: 99 seq_printf(s, "%04x %#06llx %llx %#014llx\n", i, 100 FIELD_GET(FBNIC_TWD_LEN_MASK, twd), 101 FIELD_GET(FBNIC_TWD_TYPE_MASK, twd), 102 FIELD_GET(FBNIC_TWD_ADDR_MASK, twd)); 103 break; 104 } 105 } 106 107 static int fbnic_dbg_twq_desc_seq_show(struct seq_file *s, void *v) 108 { 109 struct fbnic_ring *ring = s->private; 110 char hdr[80]; 111 int i; 112 113 /* Generate header on first entry */ 114 fbnic_dbg_ring_show(s); 115 snprintf(hdr, sizeof(hdr), "%4s %5s %s %s\n", 116 "DESC", "LEN/MSS", "T", "METADATA/TIMESTAMP/BUFFER_ADDR"); 117 seq_puts(s, hdr); 118 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 119 120 /* Display descriptor */ 121 if (!ring->desc) { 122 seq_puts(s, "Descriptor ring not allocated.\n"); 123 return 0; 124 } 125 126 for (i = 0; i <= ring->size_mask; i++) 127 fbnic_dbg_twd_desc_seq_show(s, i); 128 129 return 0; 130 } 131 132 static int fbnic_dbg_tcq_desc_seq_show(struct seq_file *s, void *v) 133 { 134 struct fbnic_ring *ring = s->private; 135 char hdr[80]; 136 int i; 137 138 /* Generate header on first entry */ 139 fbnic_dbg_ring_show(s); 140 snprintf(hdr, sizeof(hdr), "%4s %s %s %s %5s %-16s %-6s %-6s\n", 141 "DESC", "D", "T", "Q", "STATUS", "TIMESTAMP", "HEAD1", "HEAD0"); 142 seq_puts(s, hdr); 143 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 144 145 /* Display descriptor */ 146 if (!ring->desc) { 147 seq_puts(s, "Descriptor ring not allocated.\n"); 148 return 0; 149 } 150 151 for (i = 0; i <= ring->size_mask; i++) { 152 u64 tcd = le64_to_cpu(ring->desc[i]); 153 154 switch (FIELD_GET(FBNIC_TCD_TYPE_MASK, tcd)) { 155 case FBNIC_TCD_TYPE_0: 156 seq_printf(s, "%04x %llx %llx %llx %#05llx %-17s %#06llx %#06llx\n", 157 i, FIELD_GET(FBNIC_TCD_DONE, tcd), 158 FIELD_GET(FBNIC_TCD_TYPE_MASK, tcd), 159 FIELD_GET(FBNIC_TCD_TWQ1, tcd), 160 FIELD_GET(FBNIC_TCD_STATUS_MASK, tcd), 161 "", 162 FIELD_GET(FBNIC_TCD_TYPE0_HEAD1_MASK, tcd), 163 FIELD_GET(FBNIC_TCD_TYPE0_HEAD0_MASK, tcd)); 164 break; 165 case FBNIC_TCD_TYPE_1: 166 seq_printf(s, "%04x %llx %llx %llx %#05llx %#012llx\n", 167 i, FIELD_GET(FBNIC_TCD_DONE, tcd), 168 FIELD_GET(FBNIC_TCD_TYPE_MASK, tcd), 169 FIELD_GET(FBNIC_TCD_TWQ1, tcd), 170 FIELD_GET(FBNIC_TCD_STATUS_MASK, tcd), 171 FIELD_GET(FBNIC_TCD_TYPE1_TS_MASK, tcd)); 172 break; 173 default: 174 break; 175 } 176 } 177 178 return 0; 179 } 180 181 static int fbnic_dbg_bdq_desc_seq_show(struct seq_file *s, void *v) 182 { 183 struct fbnic_ring *ring = s->private; 184 char hdr[80]; 185 int i; 186 187 /* Generate header on first entry */ 188 fbnic_dbg_ring_show(s); 189 snprintf(hdr, sizeof(hdr), "%4s %-4s %s\n", 190 "DESC", "ID", "BUFFER_ADDR"); 191 seq_puts(s, hdr); 192 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 193 194 /* Display descriptor */ 195 if (!ring->desc) { 196 seq_puts(s, "Descriptor ring not allocated.\n"); 197 return 0; 198 } 199 200 for (i = 0; i <= ring->size_mask; i++) { 201 u64 bd = le64_to_cpu(ring->desc[i]); 202 203 seq_printf(s, "%04x %#04llx %#014llx\n", i, 204 FIELD_GET(FBNIC_BD_DESC_ID_MASK, bd), 205 FIELD_GET(FBNIC_BD_DESC_ADDR_MASK, bd)); 206 } 207 208 return 0; 209 } 210 211 static void fbnic_dbg_rcd_desc_seq_show(struct seq_file *s, int i) 212 { 213 struct fbnic_ring *ring = s->private; 214 u64 rcd = le64_to_cpu(ring->desc[i]); 215 216 switch (FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd)) { 217 case FBNIC_RCD_TYPE_HDR_AL: 218 case FBNIC_RCD_TYPE_PAY_AL: 219 seq_printf(s, "%04x %llx %llx %llx %#06llx %#06llx %#06llx\n", 220 i, FIELD_GET(FBNIC_RCD_DONE, rcd), 221 FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd), 222 FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd), 223 FIELD_GET(FBNIC_RCD_AL_BUFF_OFF_MASK, rcd), 224 FIELD_GET(FBNIC_RCD_AL_BUFF_LEN_MASK, rcd), 225 FIELD_GET(FBNIC_RCD_AL_BUFF_ID_MASK, rcd)); 226 break; 227 case FBNIC_RCD_TYPE_OPT_META: 228 seq_printf(s, "%04x %llx %llx %llx %llx %llx %#06llx %#012llx\n", 229 i, FIELD_GET(FBNIC_RCD_DONE, rcd), 230 FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd), 231 FIELD_GET(FBNIC_RCD_OPT_META_TYPE_MASK, rcd), 232 FIELD_GET(FBNIC_RCD_OPT_META_TS, rcd), 233 FIELD_GET(FBNIC_RCD_OPT_META_ACTION, rcd), 234 FIELD_GET(FBNIC_RCD_OPT_META_ACTION_MASK, rcd), 235 FIELD_GET(FBNIC_RCD_OPT_META_TS_MASK, rcd)); 236 break; 237 case FBNIC_RCD_TYPE_META: 238 seq_printf(s, "%04x %llx %llx %llx %llx %llx %llx %llx %llx %llx %#06llx %#010llx\n", 239 i, FIELD_GET(FBNIC_RCD_DONE, rcd), 240 FIELD_GET(FBNIC_RCD_TYPE_MASK, rcd), 241 FIELD_GET(FBNIC_RCD_META_ECN, rcd), 242 FIELD_GET(FBNIC_RCD_META_L4_CSUM_UNNECESSARY, rcd), 243 FIELD_GET(FBNIC_RCD_META_ERR_MAC_EOP, rcd), 244 FIELD_GET(FBNIC_RCD_META_ERR_TRUNCATED_FRAME, rcd), 245 FIELD_GET(FBNIC_RCD_META_ERR_PARSER, rcd), 246 FIELD_GET(FBNIC_RCD_META_L4_TYPE_MASK, rcd), 247 FIELD_GET(FBNIC_RCD_META_L3_TYPE_MASK, rcd), 248 FIELD_GET(FBNIC_RCD_META_L2_CSUM_MASK, rcd), 249 FIELD_GET(FBNIC_RCD_META_RSS_HASH_MASK, rcd)); 250 break; 251 } 252 } 253 254 static int fbnic_dbg_rcq_desc_seq_show(struct seq_file *s, void *v) 255 { 256 struct fbnic_ring *ring = s->private; 257 char hdr[80]; 258 int i; 259 260 /* Generate header on first entry */ 261 fbnic_dbg_ring_show(s); 262 snprintf(hdr, sizeof(hdr), 263 "%18s %s %s\n", "OFFSET/", "L", "L"); 264 seq_puts(s, hdr); 265 snprintf(hdr, sizeof(hdr), 266 "%4s %s %s %s %s %s %s %s %s %s %-8s %s\n", 267 "DESC", "D", "T", "F", "C", "M", "T", "P", "4", "3", "LEN/CSUM", "ID/TS/RSS"); 268 seq_puts(s, hdr); 269 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 270 271 /* Display descriptor */ 272 if (!ring->desc) { 273 seq_puts(s, "Descriptor ring not allocated.\n"); 274 return 0; 275 } 276 277 for (i = 0; i <= ring->size_mask; i++) 278 fbnic_dbg_rcd_desc_seq_show(s, i); 279 280 return 0; 281 } 282 283 static int fbnic_dbg_desc_open(struct inode *inode, struct file *file) 284 { 285 struct fbnic_ring *ring = inode->i_private; 286 int (*show)(struct seq_file *s, void *v); 287 288 switch (ring->doorbell - fbnic_ring_csr_base(ring)) { 289 case FBNIC_QUEUE_TWQ0_TAIL: 290 case FBNIC_QUEUE_TWQ1_TAIL: 291 show = fbnic_dbg_twq_desc_seq_show; 292 break; 293 case FBNIC_QUEUE_TCQ_HEAD: 294 show = fbnic_dbg_tcq_desc_seq_show; 295 break; 296 case FBNIC_QUEUE_BDQ_HPQ_TAIL: 297 case FBNIC_QUEUE_BDQ_PPQ_TAIL: 298 show = fbnic_dbg_bdq_desc_seq_show; 299 break; 300 case FBNIC_QUEUE_RCQ_HEAD: 301 show = fbnic_dbg_rcq_desc_seq_show; 302 break; 303 default: 304 return -EINVAL; 305 } 306 307 return single_open(file, show, ring); 308 } 309 310 static const struct file_operations fbnic_dbg_desc_fops = { 311 .owner = THIS_MODULE, 312 .open = fbnic_dbg_desc_open, 313 .read = seq_read, 314 .llseek = seq_lseek, 315 .release = single_release, 316 }; 317 318 void fbnic_dbg_nv_init(struct fbnic_napi_vector *nv) 319 { 320 struct fbnic_dev *fbd = nv->fbd; 321 char name[16]; 322 int i, j; 323 324 /* Generate a folder for each napi vector */ 325 snprintf(name, sizeof(name), "nv.%03d", nv->v_idx); 326 327 nv->dbg_nv = debugfs_create_dir(name, fbd->dbg_fbd); 328 329 /* Generate a file for each Tx ring in the napi vector */ 330 for (i = 0; i < nv->txt_count; i++) { 331 struct fbnic_q_triad *qt = &nv->qt[i]; 332 unsigned int hw_idx; 333 334 hw_idx = fbnic_ring_csr_base(&qt->cmpl) - 335 &fbd->uc_addr0[FBNIC_QUEUE(0)]; 336 hw_idx /= FBNIC_QUEUE_STRIDE; 337 338 snprintf(name, sizeof(name), "twq0.%03d", hw_idx); 339 debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub0, 340 &fbnic_dbg_desc_fops); 341 342 snprintf(name, sizeof(name), "twq1.%03d", hw_idx); 343 debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub1, 344 &fbnic_dbg_desc_fops); 345 346 snprintf(name, sizeof(name), "tcq.%03d", hw_idx); 347 debugfs_create_file(name, 0400, nv->dbg_nv, &qt->cmpl, 348 &fbnic_dbg_desc_fops); 349 } 350 351 /* Generate a file for each Rx ring in the napi vector */ 352 for (j = 0; j < nv->rxt_count; j++, i++) { 353 struct fbnic_q_triad *qt = &nv->qt[i]; 354 unsigned int hw_idx; 355 356 hw_idx = fbnic_ring_csr_base(&qt->cmpl) - 357 &fbd->uc_addr0[FBNIC_QUEUE(0)]; 358 hw_idx /= FBNIC_QUEUE_STRIDE; 359 360 snprintf(name, sizeof(name), "hpq.%03d", hw_idx); 361 debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub0, 362 &fbnic_dbg_desc_fops); 363 364 snprintf(name, sizeof(name), "ppq.%03d", hw_idx); 365 debugfs_create_file(name, 0400, nv->dbg_nv, &qt->sub1, 366 &fbnic_dbg_desc_fops); 367 368 snprintf(name, sizeof(name), "rcq.%03d", hw_idx); 369 debugfs_create_file(name, 0400, nv->dbg_nv, &qt->cmpl, 370 &fbnic_dbg_desc_fops); 371 } 372 } 373 374 void fbnic_dbg_nv_exit(struct fbnic_napi_vector *nv) 375 { 376 debugfs_remove_recursive(nv->dbg_nv); 377 nv->dbg_nv = NULL; 378 } 379 380 static int fbnic_dbg_mac_addr_show(struct seq_file *s, void *v) 381 { 382 struct fbnic_dev *fbd = s->private; 383 char hdr[80]; 384 int i; 385 386 /* Generate Header */ 387 snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s\n", 388 "Idx", "S", "TCAM Bitmap", "Addr/Mask"); 389 seq_puts(s, hdr); 390 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 391 392 for (i = 0; i < FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES; i++) { 393 struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i]; 394 395 seq_printf(s, "%02d %d %64pb %pm\n", 396 i, mac_addr->state, mac_addr->act_tcam, 397 mac_addr->value.addr8); 398 seq_printf(s, " %pm\n", 399 mac_addr->mask.addr8); 400 } 401 402 return 0; 403 } 404 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_mac_addr); 405 406 static int fbnic_dbg_tce_tcam_show(struct seq_file *s, void *v) 407 { 408 struct fbnic_dev *fbd = s->private; 409 int i, tcam_idx = 0; 410 char hdr[80]; 411 412 /* Generate Header */ 413 snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s\n", 414 "Idx", "S", "TCAM Bitmap", "Addr/Mask"); 415 seq_puts(s, hdr); 416 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 417 418 for (i = 0; i < ARRAY_SIZE(fbd->mac_addr); i++) { 419 struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i]; 420 421 /* Verify BMC bit is set */ 422 if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam)) 423 continue; 424 425 if (tcam_idx == FBNIC_TCE_TCAM_NUM_ENTRIES) 426 break; 427 428 seq_printf(s, "%02d %d %64pb %pm\n", 429 tcam_idx, mac_addr->state, mac_addr->act_tcam, 430 mac_addr->value.addr8); 431 seq_printf(s, " %pm\n", 432 mac_addr->mask.addr8); 433 tcam_idx++; 434 } 435 436 return 0; 437 } 438 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_tce_tcam); 439 440 static int fbnic_dbg_act_tcam_show(struct seq_file *s, void *v) 441 { 442 struct fbnic_dev *fbd = s->private; 443 char hdr[80]; 444 int i; 445 446 /* Generate Header */ 447 snprintf(hdr, sizeof(hdr), "%3s %s %-55s %-4s %s\n", 448 "Idx", "S", "Value/Mask", "RSS", "Dest"); 449 seq_puts(s, hdr); 450 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 451 452 for (i = 0; i < FBNIC_RPC_TCAM_ACT_NUM_ENTRIES; i++) { 453 struct fbnic_act_tcam *act_tcam = &fbd->act_tcam[i]; 454 455 seq_printf(s, "%02d %d %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %08x\n", 456 i, act_tcam->state, 457 act_tcam->value.tcam[10], act_tcam->value.tcam[9], 458 act_tcam->value.tcam[8], act_tcam->value.tcam[7], 459 act_tcam->value.tcam[6], act_tcam->value.tcam[5], 460 act_tcam->value.tcam[4], act_tcam->value.tcam[3], 461 act_tcam->value.tcam[2], act_tcam->value.tcam[1], 462 act_tcam->value.tcam[0], act_tcam->rss_en_mask, 463 act_tcam->dest); 464 seq_printf(s, " %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", 465 act_tcam->mask.tcam[10], act_tcam->mask.tcam[9], 466 act_tcam->mask.tcam[8], act_tcam->mask.tcam[7], 467 act_tcam->mask.tcam[6], act_tcam->mask.tcam[5], 468 act_tcam->mask.tcam[4], act_tcam->mask.tcam[3], 469 act_tcam->mask.tcam[2], act_tcam->mask.tcam[1], 470 act_tcam->mask.tcam[0]); 471 } 472 473 return 0; 474 } 475 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_act_tcam); 476 477 static int fbnic_dbg_ip_addr_show(struct seq_file *s, 478 struct fbnic_ip_addr *ip_addr) 479 { 480 char hdr[80]; 481 int i; 482 483 /* Generate Header */ 484 snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s %s\n", 485 "Idx", "S", "TCAM Bitmap", "V", "Addr/Mask"); 486 seq_puts(s, hdr); 487 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 488 489 for (i = 0; i < FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES; i++, ip_addr++) { 490 seq_printf(s, "%02d %d %64pb %d %pi6\n", 491 i, ip_addr->state, ip_addr->act_tcam, 492 ip_addr->version, &ip_addr->value); 493 seq_printf(s, " %pi6\n", 494 &ip_addr->mask); 495 } 496 497 return 0; 498 } 499 500 static int fbnic_dbg_ip_src_show(struct seq_file *s, void *v) 501 { 502 struct fbnic_dev *fbd = s->private; 503 504 return fbnic_dbg_ip_addr_show(s, fbd->ip_src); 505 } 506 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ip_src); 507 508 static int fbnic_dbg_ip_dst_show(struct seq_file *s, void *v) 509 { 510 struct fbnic_dev *fbd = s->private; 511 512 return fbnic_dbg_ip_addr_show(s, fbd->ip_dst); 513 } 514 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ip_dst); 515 516 static int fbnic_dbg_ipo_src_show(struct seq_file *s, void *v) 517 { 518 struct fbnic_dev *fbd = s->private; 519 520 return fbnic_dbg_ip_addr_show(s, fbd->ipo_src); 521 } 522 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ipo_src); 523 524 static int fbnic_dbg_ipo_dst_show(struct seq_file *s, void *v) 525 { 526 struct fbnic_dev *fbd = s->private; 527 528 return fbnic_dbg_ip_addr_show(s, fbd->ipo_dst); 529 } 530 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ipo_dst); 531 532 static void fbnic_dbg_fw_mbx_display(struct seq_file *s, 533 struct fbnic_dev *fbd, int mbx_idx) 534 { 535 struct fbnic_fw_mbx *mbx = &fbd->mbx[mbx_idx]; 536 char hdr[80]; 537 int i; 538 539 /* Generate header */ 540 seq_puts(s, mbx_idx == FBNIC_IPC_MBX_RX_IDX ? "Rx\n" : "Tx\n"); 541 542 seq_printf(s, "Rdy: %d Head: %d Tail: %d\n", 543 mbx->ready, mbx->head, mbx->tail); 544 545 snprintf(hdr, sizeof(hdr), "%3s %-4s %s %-12s %s %-3s %-16s\n", 546 "Idx", "Len", "E", "Addr", "F", "H", "Raw"); 547 seq_puts(s, hdr); 548 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr))); 549 550 for (i = 0; i < FBNIC_IPC_MBX_DESC_LEN; i++) { 551 u64 desc = __fbnic_mbx_rd_desc(fbd, mbx_idx, i); 552 553 seq_printf(s, "%-3.2d %04lld %d %012llx %d %-3d %016llx\n", 554 i, FIELD_GET(FBNIC_IPC_MBX_DESC_LEN_MASK, desc), 555 !!(desc & FBNIC_IPC_MBX_DESC_EOM), 556 desc & FBNIC_IPC_MBX_DESC_ADDR_MASK, 557 !!(desc & FBNIC_IPC_MBX_DESC_FW_CMPL), 558 !!(desc & FBNIC_IPC_MBX_DESC_HOST_CMPL), 559 desc); 560 } 561 } 562 563 static int fbnic_dbg_fw_mbx_show(struct seq_file *s, void *v) 564 { 565 struct fbnic_dev *fbd = s->private; 566 567 fbnic_dbg_fw_mbx_display(s, fbd, FBNIC_IPC_MBX_RX_IDX); 568 569 /* Add blank line between Rx and Tx */ 570 seq_puts(s, "\n"); 571 572 fbnic_dbg_fw_mbx_display(s, fbd, FBNIC_IPC_MBX_TX_IDX); 573 574 return 0; 575 } 576 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_fw_mbx); 577 578 static int fbnic_dbg_fw_log_show(struct seq_file *s, void *v) 579 { 580 struct fbnic_dev *fbd = s->private; 581 struct fbnic_fw_log_entry *entry; 582 unsigned long flags; 583 584 if (!fbnic_fw_log_ready(fbd)) 585 return -ENXIO; 586 587 spin_lock_irqsave(&fbd->fw_log.lock, flags); 588 589 list_for_each_entry_reverse(entry, &fbd->fw_log.entries, list) { 590 seq_printf(s, FBNIC_FW_LOG_FMT, entry->index, 591 (entry->timestamp / (MSEC_PER_SEC * 60 * 60 * 24)), 592 (entry->timestamp / (MSEC_PER_SEC * 60 * 60)) % 24, 593 ((entry->timestamp / (MSEC_PER_SEC * 60) % 60)), 594 ((entry->timestamp / MSEC_PER_SEC) % 60), 595 (entry->timestamp % MSEC_PER_SEC), 596 entry->msg); 597 } 598 599 spin_unlock_irqrestore(&fbd->fw_log.lock, flags); 600 601 return 0; 602 } 603 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_fw_log); 604 605 static int fbnic_dbg_pcie_stats_show(struct seq_file *s, void *v) 606 { 607 struct fbnic_dev *fbd = s->private; 608 609 rtnl_lock(); 610 fbnic_get_hw_stats(fbd); 611 612 seq_printf(s, "ob_rd_tlp: %llu\n", fbd->hw_stats.pcie.ob_rd_tlp.value); 613 seq_printf(s, "ob_rd_dword: %llu\n", 614 fbd->hw_stats.pcie.ob_rd_dword.value); 615 seq_printf(s, "ob_wr_tlp: %llu\n", fbd->hw_stats.pcie.ob_wr_tlp.value); 616 seq_printf(s, "ob_wr_dword: %llu\n", 617 fbd->hw_stats.pcie.ob_wr_dword.value); 618 seq_printf(s, "ob_cpl_tlp: %llu\n", 619 fbd->hw_stats.pcie.ob_cpl_tlp.value); 620 seq_printf(s, "ob_cpl_dword: %llu\n", 621 fbd->hw_stats.pcie.ob_cpl_dword.value); 622 seq_printf(s, "ob_rd_no_tag: %llu\n", 623 fbd->hw_stats.pcie.ob_rd_no_tag.value); 624 seq_printf(s, "ob_rd_no_cpl_cred: %llu\n", 625 fbd->hw_stats.pcie.ob_rd_no_cpl_cred.value); 626 seq_printf(s, "ob_rd_no_np_cred: %llu\n", 627 fbd->hw_stats.pcie.ob_rd_no_np_cred.value); 628 rtnl_unlock(); 629 630 return 0; 631 } 632 633 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_pcie_stats); 634 635 void fbnic_dbg_fbd_init(struct fbnic_dev *fbd) 636 { 637 struct pci_dev *pdev = to_pci_dev(fbd->dev); 638 const char *name = pci_name(pdev); 639 640 fbd->dbg_fbd = debugfs_create_dir(name, fbnic_dbg_root); 641 debugfs_create_file("pcie_stats", 0400, fbd->dbg_fbd, fbd, 642 &fbnic_dbg_pcie_stats_fops); 643 debugfs_create_file("mac_addr", 0400, fbd->dbg_fbd, fbd, 644 &fbnic_dbg_mac_addr_fops); 645 debugfs_create_file("tce_tcam", 0400, fbd->dbg_fbd, fbd, 646 &fbnic_dbg_tce_tcam_fops); 647 debugfs_create_file("act_tcam", 0400, fbd->dbg_fbd, fbd, 648 &fbnic_dbg_act_tcam_fops); 649 debugfs_create_file("ip_src", 0400, fbd->dbg_fbd, fbd, 650 &fbnic_dbg_ip_src_fops); 651 debugfs_create_file("ip_dst", 0400, fbd->dbg_fbd, fbd, 652 &fbnic_dbg_ip_dst_fops); 653 debugfs_create_file("ipo_src", 0400, fbd->dbg_fbd, fbd, 654 &fbnic_dbg_ipo_src_fops); 655 debugfs_create_file("ipo_dst", 0400, fbd->dbg_fbd, fbd, 656 &fbnic_dbg_ipo_dst_fops); 657 debugfs_create_file("fw_mbx", 0400, fbd->dbg_fbd, fbd, 658 &fbnic_dbg_fw_mbx_fops); 659 debugfs_create_file("fw_log", 0400, fbd->dbg_fbd, fbd, 660 &fbnic_dbg_fw_log_fops); 661 } 662 663 void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd) 664 { 665 debugfs_remove_recursive(fbd->dbg_fbd); 666 fbd->dbg_fbd = NULL; 667 } 668 669 void fbnic_dbg_init(void) 670 { 671 fbnic_dbg_root = debugfs_create_dir(fbnic_driver_name, NULL); 672 } 673 674 void fbnic_dbg_exit(void) 675 { 676 debugfs_remove_recursive(fbnic_dbg_root); 677 fbnic_dbg_root = NULL; 678 } 679