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
fbnic_dbg_desc_break(struct seq_file * s,int i)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
fbnic_dbg_ring_show(struct seq_file * s)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
fbnic_dbg_twd_desc_seq_show(struct seq_file * s,int i)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
fbnic_dbg_twq_desc_seq_show(struct seq_file * s,void * v)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
fbnic_dbg_tcq_desc_seq_show(struct seq_file * s,void * v)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
fbnic_dbg_bdq_desc_seq_show(struct seq_file * s,void * v)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 + 1) * FBNIC_BD_FRAG_COUNT; 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
fbnic_dbg_rcd_desc_seq_show(struct seq_file * s,int i)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
fbnic_dbg_rcq_desc_seq_show(struct seq_file * s,void * v)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
fbnic_dbg_desc_open(struct inode * inode,struct file * file)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
fbnic_dbg_nv_init(struct fbnic_napi_vector * nv)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
fbnic_dbg_nv_exit(struct fbnic_napi_vector * nv)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
fbnic_dbg_mac_addr_show(struct seq_file * s,void * v)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
fbnic_dbg_tce_tcam_show(struct seq_file * s,void * v)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
fbnic_dbg_act_tcam_show(struct seq_file * s,void * v)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
fbnic_dbg_ip_addr_show(struct seq_file * s,struct fbnic_ip_addr * ip_addr)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
fbnic_dbg_ip_src_show(struct seq_file * s,void * v)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
fbnic_dbg_ip_dst_show(struct seq_file * s,void * v)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
fbnic_dbg_ipo_src_show(struct seq_file * s,void * v)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
fbnic_dbg_ipo_dst_show(struct seq_file * s,void * v)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
fbnic_dbg_fw_mbx_display(struct seq_file * s,struct fbnic_dev * fbd,int mbx_idx)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
fbnic_dbg_fw_mbx_show(struct seq_file * s,void * v)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
fbnic_dbg_fw_log_show(struct seq_file * s,void * v)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
fbnic_dbg_pcie_stats_show(struct seq_file * s,void * v)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
fbnic_dbg_fbd_init(struct fbnic_dev * fbd)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
fbnic_dbg_fbd_exit(struct fbnic_dev * fbd)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
fbnic_dbg_init(void)669 void fbnic_dbg_init(void)
670 {
671 fbnic_dbg_root = debugfs_create_dir(fbnic_driver_name, NULL);
672 }
673
fbnic_dbg_exit(void)674 void fbnic_dbg_exit(void)
675 {
676 debugfs_remove_recursive(fbnic_dbg_root);
677 fbnic_dbg_root = NULL;
678 }
679