1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright (c) 2024 Hisilicon Limited.
3
4 #include <linux/debugfs.h>
5 #include <linux/device.h>
6 #include <linux/etherdevice.h>
7 #include <linux/seq_file.h>
8 #include <linux/string_choices.h>
9 #include "hbg_common.h"
10 #include "hbg_debugfs.h"
11 #include "hbg_hw.h"
12 #include "hbg_irq.h"
13 #include "hbg_txrx.h"
14
15 static struct dentry *hbg_dbgfs_root;
16
17 struct hbg_dbg_info {
18 const char *name;
19 int (*read)(struct seq_file *seq, void *data);
20 };
21
22 #define state_str_true_false(p, s) str_true_false(test_bit(s, &(p)->state))
23
hbg_dbg_ring(struct hbg_priv * priv,struct hbg_ring * ring,struct seq_file * s)24 static void hbg_dbg_ring(struct hbg_priv *priv, struct hbg_ring *ring,
25 struct seq_file *s)
26 {
27 u32 irq_mask = ring->dir == HBG_DIR_TX ? HBG_INT_MSK_TX_B :
28 HBG_INT_MSK_RX_B;
29
30 seq_printf(s, "ring used num: %u\n",
31 hbg_get_queue_used_num(ring));
32 seq_printf(s, "ring max num: %u\n", ring->len);
33 seq_printf(s, "ring head: %u, tail: %u\n", ring->head, ring->tail);
34 seq_printf(s, "fifo used num: %u\n",
35 hbg_hw_get_fifo_used_num(priv, ring->dir));
36 seq_printf(s, "fifo max num: %u\n",
37 hbg_get_spec_fifo_max_num(priv, ring->dir));
38 seq_printf(s, "irq enabled: %s\n",
39 str_true_false(hbg_hw_irq_is_enabled(priv, irq_mask)));
40 }
41
hbg_dbg_tx_ring(struct seq_file * s,void * unused)42 static int hbg_dbg_tx_ring(struct seq_file *s, void *unused)
43 {
44 struct net_device *netdev = dev_get_drvdata(s->private);
45 struct hbg_priv *priv = netdev_priv(netdev);
46
47 hbg_dbg_ring(priv, &priv->tx_ring, s);
48 return 0;
49 }
50
hbg_dbg_rx_ring(struct seq_file * s,void * unused)51 static int hbg_dbg_rx_ring(struct seq_file *s, void *unused)
52 {
53 struct net_device *netdev = dev_get_drvdata(s->private);
54 struct hbg_priv *priv = netdev_priv(netdev);
55
56 hbg_dbg_ring(priv, &priv->rx_ring, s);
57 return 0;
58 }
59
hbg_dbg_irq_info(struct seq_file * s,void * unused)60 static int hbg_dbg_irq_info(struct seq_file *s, void *unused)
61 {
62 struct net_device *netdev = dev_get_drvdata(s->private);
63 struct hbg_priv *priv = netdev_priv(netdev);
64 const struct hbg_irq_info *info;
65 u32 i;
66
67 for (i = 0; i < priv->vectors.info_array_len; i++) {
68 info = &priv->vectors.info_array[i];
69 seq_printf(s,
70 "%-20s: enabled: %-5s, reset: %-5s, logged: %-5s, count: %llu\n",
71 info->name,
72 str_true_false(hbg_hw_irq_is_enabled(priv,
73 info->mask)),
74 str_true_false(info->need_reset),
75 str_true_false(info->need_print),
76 priv->vectors.stats_array[i]);
77 }
78
79 return 0;
80 }
81
hbg_dbg_mac_table(struct seq_file * s,void * unused)82 static int hbg_dbg_mac_table(struct seq_file *s, void *unused)
83 {
84 struct net_device *netdev = dev_get_drvdata(s->private);
85 struct hbg_priv *priv = netdev_priv(netdev);
86 struct hbg_mac_filter *filter;
87 u32 i;
88
89 filter = &priv->filter;
90 seq_printf(s, "mac addr max count: %u\n", filter->table_max_len);
91 seq_printf(s, "filter enabled: %s\n", str_true_false(filter->enabled));
92
93 for (i = 0; i < filter->table_max_len; i++) {
94 if (is_zero_ether_addr(filter->mac_table[i].addr))
95 continue;
96
97 seq_printf(s, "[%u] %pM\n", i, filter->mac_table[i].addr);
98 }
99
100 return 0;
101 }
102
103 static const char * const reset_type_str[] = {"None", "FLR", "Function"};
104
hbg_dbg_nic_state(struct seq_file * s,void * unused)105 static int hbg_dbg_nic_state(struct seq_file *s, void *unused)
106 {
107 struct net_device *netdev = dev_get_drvdata(s->private);
108 struct hbg_priv *priv = netdev_priv(netdev);
109 bool np_link_fail;
110
111 seq_printf(s, "event handling state: %s\n",
112 state_str_true_false(priv, HBG_NIC_STATE_EVENT_HANDLING));
113 seq_printf(s, "resetting state: %s\n",
114 state_str_true_false(priv, HBG_NIC_STATE_RESETTING));
115 seq_printf(s, "reset fail state: %s\n",
116 state_str_true_false(priv, HBG_NIC_STATE_RESET_FAIL));
117 seq_printf(s, "last reset type: %s\n",
118 reset_type_str[priv->reset_type]);
119 seq_printf(s, "need reset state: %s\n",
120 state_str_true_false(priv, HBG_NIC_STATE_NEED_RESET));
121
122 np_link_fail = !hbg_reg_read_field(priv, HBG_REG_AN_NEG_STATE_ADDR,
123 HBG_REG_AN_NEG_STATE_NP_LINK_OK_B);
124 seq_printf(s, "np_link fail state: %s\n", str_true_false(np_link_fail));
125
126 return 0;
127 }
128
129 static const struct hbg_dbg_info hbg_dbg_infos[] = {
130 { "tx_ring", hbg_dbg_tx_ring },
131 { "rx_ring", hbg_dbg_rx_ring },
132 { "irq_info", hbg_dbg_irq_info },
133 { "mac_table", hbg_dbg_mac_table },
134 { "nic_state", hbg_dbg_nic_state },
135 };
136
hbg_debugfs_uninit(void * data)137 static void hbg_debugfs_uninit(void *data)
138 {
139 debugfs_remove_recursive((struct dentry *)data);
140 }
141
hbg_debugfs_init(struct hbg_priv * priv)142 void hbg_debugfs_init(struct hbg_priv *priv)
143 {
144 const char *name = pci_name(priv->pdev);
145 struct device *dev = &priv->pdev->dev;
146 struct dentry *root;
147 u32 i;
148
149 root = debugfs_create_dir(name, hbg_dbgfs_root);
150
151 for (i = 0; i < ARRAY_SIZE(hbg_dbg_infos); i++)
152 debugfs_create_devm_seqfile(dev, hbg_dbg_infos[i].name,
153 root, hbg_dbg_infos[i].read);
154
155 /* Ignore the failure because debugfs is not a key feature. */
156 devm_add_action_or_reset(dev, hbg_debugfs_uninit, root);
157 }
158
hbg_debugfs_register(void)159 void hbg_debugfs_register(void)
160 {
161 hbg_dbgfs_root = debugfs_create_dir("hibmcge", NULL);
162 }
163
hbg_debugfs_unregister(void)164 void hbg_debugfs_unregister(void)
165 {
166 debugfs_remove_recursive(hbg_dbgfs_root);
167 hbg_dbgfs_root = NULL;
168 }
169