mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-31 22:23:05 +00:00

Allow reading the firmware log in DebugFS by accessing the fw_log file. Buffer is read while a spinlock is acquired. Signed-off-by: Lee Trager <lee@trager.us> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/20250702192207.697368-7-lee@trager.us Signed-off-by: Jakub Kicinski <kuba@kernel.org>
272 lines
7.5 KiB
C
272 lines
7.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
|
|
|
|
#include <linux/debugfs.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/rtnetlink.h>
|
|
#include <linux/seq_file.h>
|
|
|
|
#include "fbnic.h"
|
|
|
|
static struct dentry *fbnic_dbg_root;
|
|
|
|
static void fbnic_dbg_desc_break(struct seq_file *s, int i)
|
|
{
|
|
while (i--)
|
|
seq_putc(s, '-');
|
|
|
|
seq_putc(s, '\n');
|
|
}
|
|
|
|
static int fbnic_dbg_mac_addr_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
char hdr[80];
|
|
int i;
|
|
|
|
/* Generate Header */
|
|
snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s\n",
|
|
"Idx", "S", "TCAM Bitmap", "Addr/Mask");
|
|
seq_puts(s, hdr);
|
|
fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
|
|
|
|
for (i = 0; i < FBNIC_RPC_TCAM_MACDA_NUM_ENTRIES; i++) {
|
|
struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i];
|
|
|
|
seq_printf(s, "%02d %d %64pb %pm\n",
|
|
i, mac_addr->state, mac_addr->act_tcam,
|
|
mac_addr->value.addr8);
|
|
seq_printf(s, " %pm\n",
|
|
mac_addr->mask.addr8);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_mac_addr);
|
|
|
|
static int fbnic_dbg_tce_tcam_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
int i, tcam_idx = 0;
|
|
char hdr[80];
|
|
|
|
/* Generate Header */
|
|
snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s\n",
|
|
"Idx", "S", "TCAM Bitmap", "Addr/Mask");
|
|
seq_puts(s, hdr);
|
|
fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(fbd->mac_addr); i++) {
|
|
struct fbnic_mac_addr *mac_addr = &fbd->mac_addr[i];
|
|
|
|
/* Verify BMC bit is set */
|
|
if (!test_bit(FBNIC_MAC_ADDR_T_BMC, mac_addr->act_tcam))
|
|
continue;
|
|
|
|
if (tcam_idx == FBNIC_TCE_TCAM_NUM_ENTRIES)
|
|
break;
|
|
|
|
seq_printf(s, "%02d %d %64pb %pm\n",
|
|
tcam_idx, mac_addr->state, mac_addr->act_tcam,
|
|
mac_addr->value.addr8);
|
|
seq_printf(s, " %pm\n",
|
|
mac_addr->mask.addr8);
|
|
tcam_idx++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_tce_tcam);
|
|
|
|
static int fbnic_dbg_act_tcam_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
char hdr[80];
|
|
int i;
|
|
|
|
/* Generate Header */
|
|
snprintf(hdr, sizeof(hdr), "%3s %s %-55s %-4s %s\n",
|
|
"Idx", "S", "Value/Mask", "RSS", "Dest");
|
|
seq_puts(s, hdr);
|
|
fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
|
|
|
|
for (i = 0; i < FBNIC_RPC_TCAM_ACT_NUM_ENTRIES; i++) {
|
|
struct fbnic_act_tcam *act_tcam = &fbd->act_tcam[i];
|
|
|
|
seq_printf(s, "%02d %d %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %08x\n",
|
|
i, act_tcam->state,
|
|
act_tcam->value.tcam[10], act_tcam->value.tcam[9],
|
|
act_tcam->value.tcam[8], act_tcam->value.tcam[7],
|
|
act_tcam->value.tcam[6], act_tcam->value.tcam[5],
|
|
act_tcam->value.tcam[4], act_tcam->value.tcam[3],
|
|
act_tcam->value.tcam[2], act_tcam->value.tcam[1],
|
|
act_tcam->value.tcam[0], act_tcam->rss_en_mask,
|
|
act_tcam->dest);
|
|
seq_printf(s, " %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
|
|
act_tcam->mask.tcam[10], act_tcam->mask.tcam[9],
|
|
act_tcam->mask.tcam[8], act_tcam->mask.tcam[7],
|
|
act_tcam->mask.tcam[6], act_tcam->mask.tcam[5],
|
|
act_tcam->mask.tcam[4], act_tcam->mask.tcam[3],
|
|
act_tcam->mask.tcam[2], act_tcam->mask.tcam[1],
|
|
act_tcam->mask.tcam[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_act_tcam);
|
|
|
|
static int fbnic_dbg_ip_addr_show(struct seq_file *s,
|
|
struct fbnic_ip_addr *ip_addr)
|
|
{
|
|
char hdr[80];
|
|
int i;
|
|
|
|
/* Generate Header */
|
|
snprintf(hdr, sizeof(hdr), "%3s %s %-17s %s %s\n",
|
|
"Idx", "S", "TCAM Bitmap", "V", "Addr/Mask");
|
|
seq_puts(s, hdr);
|
|
fbnic_dbg_desc_break(s, strnlen(hdr, sizeof(hdr)));
|
|
|
|
for (i = 0; i < FBNIC_RPC_TCAM_IP_ADDR_NUM_ENTRIES; i++, ip_addr++) {
|
|
seq_printf(s, "%02d %d %64pb %d %pi6\n",
|
|
i, ip_addr->state, ip_addr->act_tcam,
|
|
ip_addr->version, &ip_addr->value);
|
|
seq_printf(s, " %pi6\n",
|
|
&ip_addr->mask);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fbnic_dbg_ip_src_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
|
|
return fbnic_dbg_ip_addr_show(s, fbd->ip_src);
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ip_src);
|
|
|
|
static int fbnic_dbg_ip_dst_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
|
|
return fbnic_dbg_ip_addr_show(s, fbd->ip_dst);
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ip_dst);
|
|
|
|
static int fbnic_dbg_ipo_src_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
|
|
return fbnic_dbg_ip_addr_show(s, fbd->ipo_src);
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ipo_src);
|
|
|
|
static int fbnic_dbg_ipo_dst_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
|
|
return fbnic_dbg_ip_addr_show(s, fbd->ipo_dst);
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_ipo_dst);
|
|
|
|
static int fbnic_dbg_fw_log_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
struct fbnic_fw_log_entry *entry;
|
|
unsigned long flags;
|
|
|
|
if (!fbnic_fw_log_ready(fbd))
|
|
return -ENXIO;
|
|
|
|
spin_lock_irqsave(&fbd->fw_log.lock, flags);
|
|
|
|
list_for_each_entry_reverse(entry, &fbd->fw_log.entries, list) {
|
|
seq_printf(s, FBNIC_FW_LOG_FMT, entry->index,
|
|
(entry->timestamp / (MSEC_PER_SEC * 60 * 60 * 24)),
|
|
(entry->timestamp / (MSEC_PER_SEC * 60 * 60)) % 24,
|
|
((entry->timestamp / (MSEC_PER_SEC * 60) % 60)),
|
|
((entry->timestamp / MSEC_PER_SEC) % 60),
|
|
(entry->timestamp % MSEC_PER_SEC),
|
|
entry->msg);
|
|
}
|
|
|
|
spin_unlock_irqrestore(&fbd->fw_log.lock, flags);
|
|
|
|
return 0;
|
|
}
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_fw_log);
|
|
|
|
static int fbnic_dbg_pcie_stats_show(struct seq_file *s, void *v)
|
|
{
|
|
struct fbnic_dev *fbd = s->private;
|
|
|
|
rtnl_lock();
|
|
fbnic_get_hw_stats(fbd);
|
|
|
|
seq_printf(s, "ob_rd_tlp: %llu\n", fbd->hw_stats.pcie.ob_rd_tlp.value);
|
|
seq_printf(s, "ob_rd_dword: %llu\n",
|
|
fbd->hw_stats.pcie.ob_rd_dword.value);
|
|
seq_printf(s, "ob_wr_tlp: %llu\n", fbd->hw_stats.pcie.ob_wr_tlp.value);
|
|
seq_printf(s, "ob_wr_dword: %llu\n",
|
|
fbd->hw_stats.pcie.ob_wr_dword.value);
|
|
seq_printf(s, "ob_cpl_tlp: %llu\n",
|
|
fbd->hw_stats.pcie.ob_cpl_tlp.value);
|
|
seq_printf(s, "ob_cpl_dword: %llu\n",
|
|
fbd->hw_stats.pcie.ob_cpl_dword.value);
|
|
seq_printf(s, "ob_rd_no_tag: %llu\n",
|
|
fbd->hw_stats.pcie.ob_rd_no_tag.value);
|
|
seq_printf(s, "ob_rd_no_cpl_cred: %llu\n",
|
|
fbd->hw_stats.pcie.ob_rd_no_cpl_cred.value);
|
|
seq_printf(s, "ob_rd_no_np_cred: %llu\n",
|
|
fbd->hw_stats.pcie.ob_rd_no_np_cred.value);
|
|
rtnl_unlock();
|
|
|
|
return 0;
|
|
}
|
|
|
|
DEFINE_SHOW_ATTRIBUTE(fbnic_dbg_pcie_stats);
|
|
|
|
void fbnic_dbg_fbd_init(struct fbnic_dev *fbd)
|
|
{
|
|
struct pci_dev *pdev = to_pci_dev(fbd->dev);
|
|
const char *name = pci_name(pdev);
|
|
|
|
fbd->dbg_fbd = debugfs_create_dir(name, fbnic_dbg_root);
|
|
debugfs_create_file("pcie_stats", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_pcie_stats_fops);
|
|
debugfs_create_file("mac_addr", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_mac_addr_fops);
|
|
debugfs_create_file("tce_tcam", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_tce_tcam_fops);
|
|
debugfs_create_file("act_tcam", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_act_tcam_fops);
|
|
debugfs_create_file("ip_src", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_ip_src_fops);
|
|
debugfs_create_file("ip_dst", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_ip_dst_fops);
|
|
debugfs_create_file("ipo_src", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_ipo_src_fops);
|
|
debugfs_create_file("ipo_dst", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_ipo_dst_fops);
|
|
debugfs_create_file("fw_log", 0400, fbd->dbg_fbd, fbd,
|
|
&fbnic_dbg_fw_log_fops);
|
|
}
|
|
|
|
void fbnic_dbg_fbd_exit(struct fbnic_dev *fbd)
|
|
{
|
|
debugfs_remove_recursive(fbd->dbg_fbd);
|
|
fbd->dbg_fbd = NULL;
|
|
}
|
|
|
|
void fbnic_dbg_init(void)
|
|
{
|
|
fbnic_dbg_root = debugfs_create_dir(fbnic_driver_name, NULL);
|
|
}
|
|
|
|
void fbnic_dbg_exit(void)
|
|
{
|
|
debugfs_remove_recursive(fbnic_dbg_root);
|
|
fbnic_dbg_root = NULL;
|
|
}
|