186331b51SJijie Shao // SPDX-License-Identifier: GPL-2.0+ 286331b51SJijie Shao // Copyright (c) 2024 Hisilicon Limited. 386331b51SJijie Shao 486331b51SJijie Shao #include <linux/debugfs.h> 586331b51SJijie Shao #include <linux/device.h> 686331b51SJijie Shao #include <linux/etherdevice.h> 786331b51SJijie Shao #include <linux/seq_file.h> 886331b51SJijie Shao #include <linux/string_choices.h> 986331b51SJijie Shao #include "hbg_common.h" 1086331b51SJijie Shao #include "hbg_debugfs.h" 1186331b51SJijie Shao #include "hbg_hw.h" 1286331b51SJijie Shao #include "hbg_irq.h" 1386331b51SJijie Shao #include "hbg_txrx.h" 1486331b51SJijie Shao 1586331b51SJijie Shao static struct dentry *hbg_dbgfs_root; 1686331b51SJijie Shao 1786331b51SJijie Shao struct hbg_dbg_info { 1886331b51SJijie Shao const char *name; 1986331b51SJijie Shao int (*read)(struct seq_file *seq, void *data); 2086331b51SJijie Shao }; 2186331b51SJijie Shao 22*3f5a61f6SJijie Shao #define state_str_true_false(p, s) str_true_false(test_bit(s, &(p)->state)) 23*3f5a61f6SJijie Shao 2486331b51SJijie Shao static void hbg_dbg_ring(struct hbg_priv *priv, struct hbg_ring *ring, 2586331b51SJijie Shao struct seq_file *s) 2686331b51SJijie Shao { 2786331b51SJijie Shao u32 irq_mask = ring->dir == HBG_DIR_TX ? HBG_INT_MSK_TX_B : 2886331b51SJijie Shao HBG_INT_MSK_RX_B; 2986331b51SJijie Shao 3086331b51SJijie Shao seq_printf(s, "ring used num: %u\n", 3186331b51SJijie Shao hbg_get_queue_used_num(ring)); 3286331b51SJijie Shao seq_printf(s, "ring max num: %u\n", ring->len); 3386331b51SJijie Shao seq_printf(s, "ring head: %u, tail: %u\n", ring->head, ring->tail); 3486331b51SJijie Shao seq_printf(s, "fifo used num: %u\n", 3586331b51SJijie Shao hbg_hw_get_fifo_used_num(priv, ring->dir)); 3686331b51SJijie Shao seq_printf(s, "fifo max num: %u\n", 3786331b51SJijie Shao hbg_get_spec_fifo_max_num(priv, ring->dir)); 3886331b51SJijie Shao seq_printf(s, "irq enabled: %s\n", 3986331b51SJijie Shao str_true_false(hbg_hw_irq_is_enabled(priv, irq_mask))); 4086331b51SJijie Shao } 4186331b51SJijie Shao 4286331b51SJijie Shao static int hbg_dbg_tx_ring(struct seq_file *s, void *unused) 4386331b51SJijie Shao { 4486331b51SJijie Shao struct net_device *netdev = dev_get_drvdata(s->private); 4586331b51SJijie Shao struct hbg_priv *priv = netdev_priv(netdev); 4686331b51SJijie Shao 4786331b51SJijie Shao hbg_dbg_ring(priv, &priv->tx_ring, s); 4886331b51SJijie Shao return 0; 4986331b51SJijie Shao } 5086331b51SJijie Shao 5186331b51SJijie Shao static int hbg_dbg_rx_ring(struct seq_file *s, void *unused) 5286331b51SJijie Shao { 5386331b51SJijie Shao struct net_device *netdev = dev_get_drvdata(s->private); 5486331b51SJijie Shao struct hbg_priv *priv = netdev_priv(netdev); 5586331b51SJijie Shao 5686331b51SJijie Shao hbg_dbg_ring(priv, &priv->rx_ring, s); 5786331b51SJijie Shao return 0; 5886331b51SJijie Shao } 5986331b51SJijie Shao 60df491c41SJijie Shao static int hbg_dbg_irq_info(struct seq_file *s, void *unused) 61df491c41SJijie Shao { 62df491c41SJijie Shao struct net_device *netdev = dev_get_drvdata(s->private); 63df491c41SJijie Shao struct hbg_priv *priv = netdev_priv(netdev); 64df491c41SJijie Shao struct hbg_irq_info *info; 65df491c41SJijie Shao u32 i; 66df491c41SJijie Shao 67df491c41SJijie Shao for (i = 0; i < priv->vectors.info_array_len; i++) { 68df491c41SJijie Shao info = &priv->vectors.info_array[i]; 69df491c41SJijie Shao seq_printf(s, 70df491c41SJijie Shao "%-20s: enabled: %-5s, logged: %-5s, count: %llu\n", 71df491c41SJijie Shao info->name, 72df491c41SJijie Shao str_true_false(hbg_hw_irq_is_enabled(priv, 73df491c41SJijie Shao info->mask)), 74df491c41SJijie Shao str_true_false(info->need_print), 75df491c41SJijie Shao info->count); 76df491c41SJijie Shao } 77df491c41SJijie Shao 78df491c41SJijie Shao return 0; 79df491c41SJijie Shao } 80df491c41SJijie Shao 8137b367d6SJijie Shao static int hbg_dbg_mac_table(struct seq_file *s, void *unused) 8237b367d6SJijie Shao { 8337b367d6SJijie Shao struct net_device *netdev = dev_get_drvdata(s->private); 8437b367d6SJijie Shao struct hbg_priv *priv = netdev_priv(netdev); 8537b367d6SJijie Shao struct hbg_mac_filter *filter; 8637b367d6SJijie Shao u32 i; 8737b367d6SJijie Shao 8837b367d6SJijie Shao filter = &priv->filter; 8937b367d6SJijie Shao seq_printf(s, "mac addr max count: %u\n", filter->table_max_len); 9037b367d6SJijie Shao seq_printf(s, "filter enabled: %s\n", str_true_false(filter->enabled)); 9137b367d6SJijie Shao 9237b367d6SJijie Shao for (i = 0; i < filter->table_max_len; i++) { 9337b367d6SJijie Shao if (is_zero_ether_addr(filter->mac_table[i].addr)) 9437b367d6SJijie Shao continue; 9537b367d6SJijie Shao 9637b367d6SJijie Shao seq_printf(s, "[%u] %pM\n", i, filter->mac_table[i].addr); 9737b367d6SJijie Shao } 9837b367d6SJijie Shao 9937b367d6SJijie Shao return 0; 10037b367d6SJijie Shao } 10137b367d6SJijie Shao 102*3f5a61f6SJijie Shao static const char * const reset_type_str[] = {"None", "FLR", "Function"}; 103*3f5a61f6SJijie Shao 104*3f5a61f6SJijie Shao static int hbg_dbg_nic_state(struct seq_file *s, void *unused) 105*3f5a61f6SJijie Shao { 106*3f5a61f6SJijie Shao struct net_device *netdev = dev_get_drvdata(s->private); 107*3f5a61f6SJijie Shao struct hbg_priv *priv = netdev_priv(netdev); 108*3f5a61f6SJijie Shao 109*3f5a61f6SJijie Shao seq_printf(s, "event handling state: %s\n", 110*3f5a61f6SJijie Shao state_str_true_false(priv, HBG_NIC_STATE_EVENT_HANDLING)); 111*3f5a61f6SJijie Shao seq_printf(s, "resetting state: %s\n", 112*3f5a61f6SJijie Shao state_str_true_false(priv, HBG_NIC_STATE_RESETTING)); 113*3f5a61f6SJijie Shao seq_printf(s, "reset fail state: %s\n", 114*3f5a61f6SJijie Shao state_str_true_false(priv, HBG_NIC_STATE_RESET_FAIL)); 115*3f5a61f6SJijie Shao seq_printf(s, "last reset type: %s\n", 116*3f5a61f6SJijie Shao reset_type_str[priv->reset_type]); 117*3f5a61f6SJijie Shao 118*3f5a61f6SJijie Shao return 0; 119*3f5a61f6SJijie Shao } 120*3f5a61f6SJijie Shao 12186331b51SJijie Shao static const struct hbg_dbg_info hbg_dbg_infos[] = { 12286331b51SJijie Shao { "tx_ring", hbg_dbg_tx_ring }, 12386331b51SJijie Shao { "rx_ring", hbg_dbg_rx_ring }, 124df491c41SJijie Shao { "irq_info", hbg_dbg_irq_info }, 12537b367d6SJijie Shao { "mac_table", hbg_dbg_mac_table }, 126*3f5a61f6SJijie Shao { "nic_state", hbg_dbg_nic_state }, 12786331b51SJijie Shao }; 12886331b51SJijie Shao 12986331b51SJijie Shao static void hbg_debugfs_uninit(void *data) 13086331b51SJijie Shao { 13186331b51SJijie Shao debugfs_remove_recursive((struct dentry *)data); 13286331b51SJijie Shao } 13386331b51SJijie Shao 13486331b51SJijie Shao void hbg_debugfs_init(struct hbg_priv *priv) 13586331b51SJijie Shao { 13686331b51SJijie Shao const char *name = pci_name(priv->pdev); 13786331b51SJijie Shao struct device *dev = &priv->pdev->dev; 13886331b51SJijie Shao struct dentry *root; 13986331b51SJijie Shao u32 i; 14086331b51SJijie Shao 14186331b51SJijie Shao root = debugfs_create_dir(name, hbg_dbgfs_root); 14286331b51SJijie Shao 14386331b51SJijie Shao for (i = 0; i < ARRAY_SIZE(hbg_dbg_infos); i++) 14486331b51SJijie Shao debugfs_create_devm_seqfile(dev, hbg_dbg_infos[i].name, 14586331b51SJijie Shao root, hbg_dbg_infos[i].read); 14686331b51SJijie Shao 14786331b51SJijie Shao /* Ignore the failure because debugfs is not a key feature. */ 14886331b51SJijie Shao devm_add_action_or_reset(dev, hbg_debugfs_uninit, root); 14986331b51SJijie Shao } 15086331b51SJijie Shao 15186331b51SJijie Shao void hbg_debugfs_register(void) 15286331b51SJijie Shao { 15386331b51SJijie Shao hbg_dbgfs_root = debugfs_create_dir("hibmcge", NULL); 15486331b51SJijie Shao } 15586331b51SJijie Shao 15686331b51SJijie Shao void hbg_debugfs_unregister(void) 15786331b51SJijie Shao { 15886331b51SJijie Shao debugfs_remove_recursive(hbg_dbgfs_root); 15986331b51SJijie Shao hbg_dbgfs_root = NULL; 16086331b51SJijie Shao } 161