xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_debugfs.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
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