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
11 static struct dentry *fbnic_dbg_root;
12
fbnic_dbg_desc_break(struct seq_file * s,int i)13 static void fbnic_dbg_desc_break(struct seq_file *s, int i)
14 {
15 while (i--)
16 seq_putc(s, '-');
17
18 seq_putc(s, '\n');
19 }
20
fbnic_dbg_mac_addr_show(struct seq_file * s,void * v)21 static int fbnic_dbg_mac_addr_show(struct seq_file *s, void *v)
22 {
23 struct fbnic_dev *fbd = s->private;
24 char hdr[80];
25 int i;
26
27 /* Generate Header */
28 snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s\n",
29 "Idx", "S", "TCAM Bitmap", "Addr/Mask");
30 seq_puts(s, hdr);
31 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
32
33 for (i = 0; i < FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES; i++) {
34 struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i];
35
36 seq_printf(s, "%02d %d %64pb %pm\n",
37 i, mac_addr->state, mac_addr->act_tcam,
38 mac_addr->value.addr8);
39 seq_printf(s, " %pm\n",
40 mac_addr->mask.addr8);
41 }
42
43 return 0;
44 }
45 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_mac_addr);
46
fbnic_dbg_tce_tcam_show(struct seq_file * s,void * v)47 static int fbnic_dbg_tce_tcam_show(struct seq_file *s, void *v)
48 {
49 struct fbnic_dev *fbd = s->private;
50 int i, tcam_idx = 0;
51 char hdr[80];
52
53 /* Generate Header */
54 snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s\n",
55 "Idx", "S", "TCAM Bitmap", "Addr/Mask");
56 seq_puts(s, hdr);
57 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
58
59 for (i = 0; i < ARRAY_SIZE(fbd->mac_addr); i++) {
60 struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i];
61
62 /* Verify BMC bit is set */
63 if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam))
64 continue;
65
66 if (tcam_idx == FBNIC_TCE_TCAM_NUM_ENTRIES)
67 break;
68
69 seq_printf(s, "%02d %d %64pb %pm\n",
70 tcam_idx, mac_addr->state, mac_addr->act_tcam,
71 mac_addr->value.addr8);
72 seq_printf(s, " %pm\n",
73 mac_addr->mask.addr8);
74 tcam_idx++;
75 }
76
77 return 0;
78 }
79 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_tce_tcam);
80
fbnic_dbg_act_tcam_show(struct seq_file * s,void * v)81 static int fbnic_dbg_act_tcam_show(struct seq_file *s, void *v)
82 {
83 struct fbnic_dev *fbd = s->private;
84 char hdr[80];
85 int i;
86
87 /* Generate Header */
88 snprintf(hdr, sizeof(hdr), "%3s %s %-55s %-4s %s\n",
89 "Idx", "S", "Value/Mask", "RSS", "Dest");
90 seq_puts(s, hdr);
91 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
92
93 for (i = 0; i < FBNIC_RPC_TCAM_ACT_NUM_ENTRIES; i++) {
94 struct fbnic_act_tcam *act_tcam = &fbd->act_tcam[i];
95
96 seq_printf(s, "%02d %d %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %08x\n",
97 i, act_tcam->state,
98 act_tcam->value.tcam[10], act_tcam->value.tcam[9],
99 act_tcam->value.tcam[8], act_tcam->value.tcam[7],
100 act_tcam->value.tcam[6], act_tcam->value.tcam[5],
101 act_tcam->value.tcam[4], act_tcam->value.tcam[3],
102 act_tcam->value.tcam[2], act_tcam->value.tcam[1],
103 act_tcam->value.tcam[0], act_tcam->rss_en_mask,
104 act_tcam->dest);
105 seq_printf(s, " %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
106 act_tcam->mask.tcam[10], act_tcam->mask.tcam[9],
107 act_tcam->mask.tcam[8], act_tcam->mask.tcam[7],
108 act_tcam->mask.tcam[6], act_tcam->mask.tcam[5],
109 act_tcam->mask.tcam[4], act_tcam->mask.tcam[3],
110 act_tcam->mask.tcam[2], act_tcam->mask.tcam[1],
111 act_tcam->mask.tcam[0]);
112 }
113
114 return 0;
115 }
116 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_act_tcam);
117
fbnic_dbg_ip_addr_show(struct seq_file * s,struct fbnic_ip_addr * ip_addr)118 static int fbnic_dbg_ip_addr_show(struct seq_file *s,
119 struct fbnic_ip_addr *ip_addr)
120 {
121 char hdr[80];
122 int i;
123
124 /* Generate Header */
125 snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s %s\n",
126 "Idx", "S", "TCAM Bitmap", "V", "Addr/Mask");
127 seq_puts(s, hdr);
128 fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
129
130 for (i = 0; i < FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES; i++, ip_addr++) {
131 seq_printf(s, "%02d %d %64pb %d %pi6\n",
132 i, ip_addr->state, ip_addr->act_tcam,
133 ip_addr->version, &ip_addr->value);
134 seq_printf(s, " %pi6\n",
135 &ip_addr->mask);
136 }
137
138 return 0;
139 }
140
fbnic_dbg_ip_src_show(struct seq_file * s,void * v)141 static int fbnic_dbg_ip_src_show(struct seq_file *s, void *v)
142 {
143 struct fbnic_dev *fbd = s->private;
144
145 return fbnic_dbg_ip_addr_show(s, fbd->ip_src);
146 }
147 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ip_src);
148
fbnic_dbg_ip_dst_show(struct seq_file * s,void * v)149 static int fbnic_dbg_ip_dst_show(struct seq_file *s, void *v)
150 {
151 struct fbnic_dev *fbd = s->private;
152
153 return fbnic_dbg_ip_addr_show(s, fbd->ip_dst);
154 }
155 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ip_dst);
156
fbnic_dbg_ipo_src_show(struct seq_file * s,void * v)157 static int fbnic_dbg_ipo_src_show(struct seq_file *s, void *v)
158 {
159 struct fbnic_dev *fbd = s->private;
160
161 return fbnic_dbg_ip_addr_show(s, fbd->ipo_src);
162 }
163 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ipo_src);
164
fbnic_dbg_ipo_dst_show(struct seq_file * s,void * v)165 static int fbnic_dbg_ipo_dst_show(struct seq_file *s, void *v)
166 {
167 struct fbnic_dev *fbd = s->private;
168
169 return fbnic_dbg_ip_addr_show(s, fbd->ipo_dst);
170 }
171 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ipo_dst);
172
fbnic_dbg_fw_log_show(struct seq_file * s,void * v)173 static int fbnic_dbg_fw_log_show(struct seq_file *s, void *v)
174 {
175 struct fbnic_dev *fbd = s->private;
176 struct fbnic_fw_log_entry *entry;
177 unsigned long flags;
178
179 if (!fbnic_fw_log_ready(fbd))
180 return -ENXIO;
181
182 spin_lock_irqsave(&fbd->fw_log.lock, flags);
183
184 list_for_each_entry_reverse(entry, &fbd->fw_log.entries, list) {
185 seq_printf(s, FBNIC_FW_LOG_FMT, entry->index,
186 (entry->timestamp / (MSEC_PER_SEC * 60 * 60 * 24)),
187 (entry->timestamp / (MSEC_PER_SEC * 60 * 60)) % 24,
188 ((entry->timestamp / (MSEC_PER_SEC * 60) % 60)),
189 ((entry->timestamp / MSEC_PER_SEC) % 60),
190 (entry->timestamp % MSEC_PER_SEC),
191 entry->msg);
192 }
193
194 spin_unlock_irqrestore(&fbd->fw_log.lock, flags);
195
196 return 0;
197 }
198 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_fw_log);
199
fbnic_dbg_pcie_stats_show(struct seq_file * s,void * v)200 static int fbnic_dbg_pcie_stats_show(struct seq_file *s, void *v)
201 {
202 struct fbnic_dev *fbd = s->private;
203
204 rtnl_lock();
205 fbnic_get_hw_stats(fbd);
206
207 seq_printf(s, "ob_rd_tlp: %llu\n", fbd->hw_stats.pcie.ob_rd_tlp.value);
208 seq_printf(s, "ob_rd_dword: %llu\n",
209 fbd->hw_stats.pcie.ob_rd_dword.value);
210 seq_printf(s, "ob_wr_tlp: %llu\n", fbd->hw_stats.pcie.ob_wr_tlp.value);
211 seq_printf(s, "ob_wr_dword: %llu\n",
212 fbd->hw_stats.pcie.ob_wr_dword.value);
213 seq_printf(s, "ob_cpl_tlp: %llu\n",
214 fbd->hw_stats.pcie.ob_cpl_tlp.value);
215 seq_printf(s, "ob_cpl_dword: %llu\n",
216 fbd->hw_stats.pcie.ob_cpl_dword.value);
217 seq_printf(s, "ob_rd_no_tag: %llu\n",
218 fbd->hw_stats.pcie.ob_rd_no_tag.value);
219 seq_printf(s, "ob_rd_no_cpl_cred: %llu\n",
220 fbd->hw_stats.pcie.ob_rd_no_cpl_cred.value);
221 seq_printf(s, "ob_rd_no_np_cred: %llu\n",
222 fbd->hw_stats.pcie.ob_rd_no_np_cred.value);
223 rtnl_unlock();
224
225 return 0;
226 }
227
228 DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_pcie_stats);
229
fbnic_dbg_fbd_init(struct fbnic_dev * fbd)230 void fbnic_dbg_fbd_init(struct fbnic_dev *fbd)
231 {
232 struct pci_dev *pdev = to_pci_dev(fbd->dev);
233 const char *name = pci_name(pdev);
234
235 fbd->dbg_fbd = debugfs_create_dir(name, fbnic_dbg_root);
236 debugfs_create_file("pcie_stats", 0400, fbd->dbg_fbd, fbd,
237 &fbnic_dbg_pcie_stats_fops);
238 debugfs_create_file("mac_addr", 0400, fbd->dbg_fbd, fbd,
239 &fbnic_dbg_mac_addr_fops);
240 debugfs_create_file("tce_tcam", 0400, fbd->dbg_fbd, fbd,
241 &fbnic_dbg_tce_tcam_fops);
242 debugfs_create_file("act_tcam", 0400, fbd->dbg_fbd, fbd,
243 &fbnic_dbg_act_tcam_fops);
244 debugfs_create_file("ip_src", 0400, fbd->dbg_fbd, fbd,
245 &fbnic_dbg_ip_src_fops);
246 debugfs_create_file("ip_dst", 0400, fbd->dbg_fbd, fbd,
247 &fbnic_dbg_ip_dst_fops);
248 debugfs_create_file("ipo_src", 0400, fbd->dbg_fbd, fbd,
249 &fbnic_dbg_ipo_src_fops);
250 debugfs_create_file("ipo_dst", 0400, fbd->dbg_fbd, fbd,
251 &fbnic_dbg_ipo_dst_fops);
252 debugfs_create_file("fw_log", 0400, fbd->dbg_fbd, fbd,
253 &fbnic_dbg_fw_log_fops);
254 }
255
fbnic_dbg_fbd_exit(struct fbnic_dev * fbd)256 void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd)
257 {
258 debugfs_remove_recursive(fbd->dbg_fbd);
259 fbd->dbg_fbd = NULL;
260 }
261
fbnic_dbg_init(void)262 void fbnic_dbg_init(void)
263 {
264 fbnic_dbg_root = debugfs_create_dir(fbnic_driver_name, NULL);
265 }
266
fbnic_dbg_exit(void)267 void fbnic_dbg_exit(void)
268 {
269 debugfs_remove_recursive(fbnic_dbg_root);
270 fbnic_dbg_root = NULL;
271 }
272