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 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 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 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 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 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 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 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 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 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 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 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 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 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 262 void fbnic_dbg_init(void) 263 { 264 fbnic_dbg_root = debugfs_create_dir(fbnic_driver_name, NULL); 265 } 266 267 void fbnic_dbg_exit(void) 268 { 269 debugfs_remove_recursive(fbnic_dbg_root); 270 fbnic_dbg_root = NULL; 271 } 272