b2292360 |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* Copyright (c) 2018-2019 Hisilicon Limited. */ |
3 | |
4 | #include <linux/debugfs.h> |
5 | #include <linux/device.h> |
6 | |
7 | #include "hnae3.h" |
8 | #include "hns3_enet.h" |
9 | |
10 | #define HNS3_DBG_READ_LEN 256 |
11 | |
12 | static struct dentry *hns3_dbgfs_root; |
13 | |
57ceee2c |
14 | static int hns3_dbg_queue_info(struct hnae3_handle *h, char *cmd_buf) |
15 | { |
16 | struct hns3_nic_priv *priv = h->priv; |
17 | struct hns3_nic_ring_data *ring_data; |
18 | struct hns3_enet_ring *ring; |
19 | u32 base_add_l, base_add_h; |
20 | u32 queue_num, queue_max; |
21 | u32 value, i = 0; |
22 | int cnt; |
23 | |
24 | if (!priv->ring_data) { |
25 | dev_err(&h->pdev->dev, "ring_data is NULL\n"); |
26 | return -EFAULT; |
27 | } |
28 | |
29 | queue_max = h->kinfo.num_tqps; |
30 | cnt = kstrtouint(&cmd_buf[11], 0, &queue_num); |
31 | if (cnt) |
32 | queue_num = 0; |
33 | else |
34 | queue_max = queue_num + 1; |
35 | |
36 | dev_info(&h->pdev->dev, "queue info\n"); |
37 | |
38 | if (queue_num >= h->kinfo.num_tqps) { |
39 | dev_err(&h->pdev->dev, |
40 | "Queue number(%u) is out of range(%u)\n", queue_num, |
41 | h->kinfo.num_tqps - 1); |
42 | return -EINVAL; |
43 | } |
44 | |
45 | ring_data = priv->ring_data; |
46 | for (i = queue_num; i < queue_max; i++) { |
47 | /* Each cycle needs to determine whether the instance is reset, |
48 | * to prevent reference to invalid memory. And need to ensure |
49 | * that the following code is executed within 100ms. |
50 | */ |
51 | if (test_bit(HNS3_NIC_STATE_INITED, &priv->state) || |
52 | test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) |
53 | return -EPERM; |
54 | |
55 | ring = ring_data[i + h->kinfo.num_tqps].ring; |
56 | base_add_h = readl_relaxed(ring->tqp->io_base + |
57 | HNS3_RING_RX_RING_BASEADDR_H_REG); |
58 | base_add_l = readl_relaxed(ring->tqp->io_base + |
59 | HNS3_RING_RX_RING_BASEADDR_L_REG); |
60 | dev_info(&h->pdev->dev, "RX(%d) BASE ADD: 0x%08x%08x\n", i, |
61 | base_add_h, base_add_l); |
62 | |
63 | value = readl_relaxed(ring->tqp->io_base + |
64 | HNS3_RING_RX_RING_BD_NUM_REG); |
65 | dev_info(&h->pdev->dev, "RX(%d) RING BD NUM: %u\n", i, value); |
66 | |
67 | value = readl_relaxed(ring->tqp->io_base + |
68 | HNS3_RING_RX_RING_BD_LEN_REG); |
69 | dev_info(&h->pdev->dev, "RX(%d) RING BD LEN: %u\n", i, value); |
70 | |
71 | value = readl_relaxed(ring->tqp->io_base + |
72 | HNS3_RING_RX_RING_TAIL_REG); |
73 | dev_info(&h->pdev->dev, "RX(%d) RING TAIL: %u\n", i, value); |
74 | |
75 | value = readl_relaxed(ring->tqp->io_base + |
76 | HNS3_RING_RX_RING_HEAD_REG); |
77 | dev_info(&h->pdev->dev, "RX(%d) RING HEAD: %u\n", i, value); |
78 | |
79 | value = readl_relaxed(ring->tqp->io_base + |
80 | HNS3_RING_RX_RING_FBDNUM_REG); |
81 | dev_info(&h->pdev->dev, "RX(%d) RING FBDNUM: %u\n", i, value); |
82 | |
83 | value = readl_relaxed(ring->tqp->io_base + |
84 | HNS3_RING_RX_RING_PKTNUM_RECORD_REG); |
85 | dev_info(&h->pdev->dev, "RX(%d) RING PKTNUM: %u\n", i, value); |
86 | |
87 | ring = ring_data[i].ring; |
88 | base_add_h = readl_relaxed(ring->tqp->io_base + |
89 | HNS3_RING_TX_RING_BASEADDR_H_REG); |
90 | base_add_l = readl_relaxed(ring->tqp->io_base + |
91 | HNS3_RING_TX_RING_BASEADDR_L_REG); |
92 | dev_info(&h->pdev->dev, "TX(%d) BASE ADD: 0x%08x%08x\n", i, |
93 | base_add_h, base_add_l); |
94 | |
95 | value = readl_relaxed(ring->tqp->io_base + |
96 | HNS3_RING_TX_RING_BD_NUM_REG); |
97 | dev_info(&h->pdev->dev, "TX(%d) RING BD NUM: %u\n", i, value); |
98 | |
99 | value = readl_relaxed(ring->tqp->io_base + |
100 | HNS3_RING_TX_RING_TC_REG); |
101 | dev_info(&h->pdev->dev, "TX(%d) RING TC: %u\n", i, value); |
102 | |
103 | value = readl_relaxed(ring->tqp->io_base + |
104 | HNS3_RING_TX_RING_TAIL_REG); |
105 | dev_info(&h->pdev->dev, "TX(%d) RING TAIL: %u\n", i, value); |
106 | |
107 | value = readl_relaxed(ring->tqp->io_base + |
108 | HNS3_RING_TX_RING_HEAD_REG); |
109 | dev_info(&h->pdev->dev, "TX(%d) RING HEAD: %u\n", i, value); |
110 | |
111 | value = readl_relaxed(ring->tqp->io_base + |
112 | HNS3_RING_TX_RING_FBDNUM_REG); |
113 | dev_info(&h->pdev->dev, "TX(%d) RING FBDNUM: %u\n", i, value); |
114 | |
115 | value = readl_relaxed(ring->tqp->io_base + |
116 | HNS3_RING_TX_RING_OFFSET_REG); |
117 | dev_info(&h->pdev->dev, "TX(%d) RING OFFSET: %u\n", i, value); |
118 | |
119 | value = readl_relaxed(ring->tqp->io_base + |
120 | HNS3_RING_TX_RING_PKTNUM_RECORD_REG); |
121 | dev_info(&h->pdev->dev, "TX(%d) RING PKTNUM: %u\n\n", i, |
122 | value); |
123 | } |
124 | |
125 | return 0; |
126 | } |
127 | |
b2292360 |
128 | static void hns3_dbg_help(struct hnae3_handle *h) |
129 | { |
130 | dev_info(&h->pdev->dev, "available commands\n"); |
131 | dev_info(&h->pdev->dev, "queue info [number]\n"); |
132 | dev_info(&h->pdev->dev, "dump fd tcam\n"); |
2849d4e7 |
133 | dev_info(&h->pdev->dev, "dump tc\n"); |
b2292360 |
134 | } |
135 | |
136 | static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, |
137 | size_t count, loff_t *ppos) |
138 | { |
139 | int uncopy_bytes; |
140 | char *buf; |
141 | int len; |
142 | |
143 | if (*ppos != 0) |
144 | return 0; |
145 | |
146 | if (count < HNS3_DBG_READ_LEN) |
147 | return -ENOSPC; |
148 | |
149 | buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL); |
150 | if (!buf) |
151 | return -ENOMEM; |
152 | |
153 | len = snprintf(buf, HNS3_DBG_READ_LEN, "%s\n", |
154 | "Please echo help to cmd to get help information"); |
155 | uncopy_bytes = copy_to_user(buffer, buf, len); |
156 | |
157 | kfree(buf); |
158 | |
159 | if (uncopy_bytes) |
160 | return -EFAULT; |
161 | |
162 | return (*ppos = len); |
163 | } |
164 | |
165 | static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, |
166 | size_t count, loff_t *ppos) |
167 | { |
168 | struct hnae3_handle *handle = filp->private_data; |
57ceee2c |
169 | struct hns3_nic_priv *priv = handle->priv; |
b2292360 |
170 | char *cmd_buf, *cmd_buf_tmp; |
171 | int uncopied_bytes; |
172 | int ret = 0; |
173 | |
174 | if (*ppos != 0) |
175 | return 0; |
176 | |
57ceee2c |
177 | /* Judge if the instance is being reset. */ |
178 | if (test_bit(HNS3_NIC_STATE_INITED, &priv->state) || |
179 | test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) |
180 | return 0; |
181 | |
b2292360 |
182 | cmd_buf = kzalloc(count + 1, GFP_KERNEL); |
183 | if (!cmd_buf) |
184 | return count; |
185 | |
186 | uncopied_bytes = copy_from_user(cmd_buf, buffer, count); |
187 | if (uncopied_bytes) { |
188 | kfree(cmd_buf); |
189 | return -EFAULT; |
190 | } |
191 | |
192 | cmd_buf[count] = '\0'; |
193 | |
194 | cmd_buf_tmp = strchr(cmd_buf, '\n'); |
195 | if (cmd_buf_tmp) { |
196 | *cmd_buf_tmp = '\0'; |
197 | count = cmd_buf_tmp - cmd_buf + 1; |
198 | } |
199 | |
200 | if (strncmp(cmd_buf, "help", 4) == 0) |
201 | hns3_dbg_help(handle); |
57ceee2c |
202 | else if (strncmp(cmd_buf, "queue info", 10) == 0) |
203 | ret = hns3_dbg_queue_info(handle, cmd_buf); |
3c666b58 |
204 | else if (handle->ae_algo->ops->dbg_run_cmd) |
205 | ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); |
b2292360 |
206 | |
207 | if (ret) |
208 | hns3_dbg_help(handle); |
209 | |
210 | kfree(cmd_buf); |
211 | cmd_buf = NULL; |
212 | |
213 | return count; |
214 | } |
215 | |
216 | static const struct file_operations hns3_dbg_cmd_fops = { |
217 | .owner = THIS_MODULE, |
218 | .open = simple_open, |
219 | .read = hns3_dbg_cmd_read, |
220 | .write = hns3_dbg_cmd_write, |
221 | }; |
222 | |
223 | void hns3_dbg_init(struct hnae3_handle *handle) |
224 | { |
225 | const char *name = pci_name(handle->pdev); |
226 | struct dentry *pfile; |
227 | |
228 | handle->hnae3_dbgfs = debugfs_create_dir(name, hns3_dbgfs_root); |
229 | if (!handle->hnae3_dbgfs) |
230 | return; |
231 | |
232 | pfile = debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, |
233 | &hns3_dbg_cmd_fops); |
234 | if (!pfile) { |
235 | debugfs_remove_recursive(handle->hnae3_dbgfs); |
236 | handle->hnae3_dbgfs = NULL; |
237 | dev_warn(&handle->pdev->dev, "create file for %s fail\n", |
238 | name); |
239 | } |
240 | } |
241 | |
242 | void hns3_dbg_uninit(struct hnae3_handle *handle) |
243 | { |
244 | debugfs_remove_recursive(handle->hnae3_dbgfs); |
245 | handle->hnae3_dbgfs = NULL; |
246 | } |
247 | |
248 | void hns3_dbg_register_debugfs(const char *debugfs_dir_name) |
249 | { |
250 | hns3_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL); |
251 | if (!hns3_dbgfs_root) { |
252 | pr_warn("Register debugfs for %s fail\n", debugfs_dir_name); |
253 | return; |
254 | } |
255 | } |
256 | |
257 | void hns3_dbg_unregister_debugfs(void) |
258 | { |
259 | debugfs_remove_recursive(hns3_dbgfs_root); |
260 | hns3_dbgfs_root = NULL; |
261 | } |