]>
Commit | Line | Data |
---|---|---|
a9556d8c | 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 | ||
09dac155 | 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 | */ | |
6e87b62b | 51 | if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || |
09dac155 | 52 | test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) |
53 | return -EPERM; | |
54 | ||
e2a3560b | 55 | ring = ring_data[(u32)(i + h->kinfo.num_tqps)].ring; |
09dac155 | 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 | ||
89d6386f | 128 | static int hns3_dbg_queue_map(struct hnae3_handle *h) |
129 | { | |
130 | struct hns3_nic_priv *priv = h->priv; | |
131 | struct hns3_nic_ring_data *ring_data; | |
132 | int i; | |
133 | ||
134 | if (!h->ae_algo->ops->get_global_queue_id) | |
135 | return -EOPNOTSUPP; | |
136 | ||
137 | dev_info(&h->pdev->dev, "map info for queue id and vector id\n"); | |
138 | dev_info(&h->pdev->dev, | |
139 | "local queue id | global queue id | vector id\n"); | |
140 | for (i = 0; i < h->kinfo.num_tqps; i++) { | |
141 | u16 global_qid; | |
142 | ||
143 | global_qid = h->ae_algo->ops->get_global_queue_id(h, i); | |
144 | ring_data = &priv->ring_data[i]; | |
145 | if (!ring_data || !ring_data->ring || | |
146 | !ring_data->ring->tqp_vector) | |
147 | continue; | |
148 | ||
149 | dev_info(&h->pdev->dev, | |
150 | " %4d %4d %4d\n", | |
151 | i, global_qid, | |
152 | ring_data->ring->tqp_vector->vector_irq); | |
153 | } | |
154 | ||
155 | return 0; | |
156 | } | |
157 | ||
e2a3560b | 158 | static int hns3_dbg_bd_info(struct hnae3_handle *h, char *cmd_buf) |
159 | { | |
160 | struct hns3_nic_priv *priv = h->priv; | |
161 | struct hns3_nic_ring_data *ring_data; | |
162 | struct hns3_desc *rx_desc, *tx_desc; | |
163 | struct device *dev = &h->pdev->dev; | |
164 | struct hns3_enet_ring *ring; | |
165 | u32 tx_index, rx_index; | |
166 | u32 q_num, value; | |
167 | int cnt; | |
168 | ||
169 | cnt = sscanf(&cmd_buf[8], "%u %u", &q_num, &tx_index); | |
170 | if (cnt == 2) { | |
171 | rx_index = tx_index; | |
172 | } else if (cnt != 1) { | |
173 | dev_err(dev, "bd info: bad command string, cnt=%d\n", cnt); | |
174 | return -EINVAL; | |
175 | } | |
176 | ||
177 | if (q_num >= h->kinfo.num_tqps) { | |
178 | dev_err(dev, "Queue number(%u) is out of range(%u)\n", q_num, | |
179 | h->kinfo.num_tqps - 1); | |
180 | return -EINVAL; | |
181 | } | |
182 | ||
183 | ring_data = priv->ring_data; | |
184 | ring = ring_data[q_num].ring; | |
185 | value = readl_relaxed(ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG); | |
186 | tx_index = (cnt == 1) ? value : tx_index; | |
187 | ||
188 | if (tx_index >= ring->desc_num) { | |
189 | dev_err(dev, "bd index (%u) is out of range(%u)\n", tx_index, | |
190 | ring->desc_num - 1); | |
191 | return -EINVAL; | |
192 | } | |
193 | ||
194 | tx_desc = &ring->desc[tx_index]; | |
195 | dev_info(dev, "TX Queue Num: %u, BD Index: %u\n", q_num, tx_index); | |
196 | dev_info(dev, "(TX) addr: 0x%llx\n", tx_desc->addr); | |
197 | dev_info(dev, "(TX)vlan_tag: %u\n", tx_desc->tx.vlan_tag); | |
198 | dev_info(dev, "(TX)send_size: %u\n", tx_desc->tx.send_size); | |
199 | dev_info(dev, "(TX)vlan_tso: %u\n", tx_desc->tx.type_cs_vlan_tso); | |
200 | dev_info(dev, "(TX)l2_len: %u\n", tx_desc->tx.l2_len); | |
201 | dev_info(dev, "(TX)l3_len: %u\n", tx_desc->tx.l3_len); | |
202 | dev_info(dev, "(TX)l4_len: %u\n", tx_desc->tx.l4_len); | |
203 | dev_info(dev, "(TX)vlan_tag: %u\n", tx_desc->tx.outer_vlan_tag); | |
204 | dev_info(dev, "(TX)tv: %u\n", tx_desc->tx.tv); | |
205 | dev_info(dev, "(TX)vlan_msec: %u\n", tx_desc->tx.ol_type_vlan_msec); | |
206 | dev_info(dev, "(TX)ol2_len: %u\n", tx_desc->tx.ol2_len); | |
207 | dev_info(dev, "(TX)ol3_len: %u\n", tx_desc->tx.ol3_len); | |
208 | dev_info(dev, "(TX)ol4_len: %u\n", tx_desc->tx.ol4_len); | |
209 | dev_info(dev, "(TX)paylen: %u\n", tx_desc->tx.paylen); | |
210 | dev_info(dev, "(TX)vld_ra_ri: %u\n", tx_desc->tx.bdtp_fe_sc_vld_ra_ri); | |
211 | dev_info(dev, "(TX)mss: %u\n", tx_desc->tx.mss); | |
212 | ||
213 | ring = ring_data[q_num + h->kinfo.num_tqps].ring; | |
214 | value = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_TAIL_REG); | |
215 | rx_index = (cnt == 1) ? value : tx_index; | |
216 | rx_desc = &ring->desc[rx_index]; | |
217 | ||
218 | dev_info(dev, "RX Queue Num: %u, BD Index: %u\n", q_num, rx_index); | |
219 | dev_info(dev, "(RX)addr: 0x%llx\n", rx_desc->addr); | |
220 | dev_info(dev, "(RX)pkt_len: %u\n", rx_desc->rx.pkt_len); | |
221 | dev_info(dev, "(RX)size: %u\n", rx_desc->rx.size); | |
222 | dev_info(dev, "(RX)rss_hash: %u\n", rx_desc->rx.rss_hash); | |
223 | dev_info(dev, "(RX)fd_id: %u\n", rx_desc->rx.fd_id); | |
224 | dev_info(dev, "(RX)vlan_tag: %u\n", rx_desc->rx.vlan_tag); | |
225 | dev_info(dev, "(RX)o_dm_vlan_id_fb: %u\n", rx_desc->rx.o_dm_vlan_id_fb); | |
226 | dev_info(dev, "(RX)ot_vlan_tag: %u\n", rx_desc->rx.ot_vlan_tag); | |
227 | dev_info(dev, "(RX)bd_base_info: %u\n", rx_desc->rx.bd_base_info); | |
228 | ||
229 | return 0; | |
230 | } | |
231 | ||
a9556d8c | 232 | static void hns3_dbg_help(struct hnae3_handle *h) |
233 | { | |
fe84b06d | 234 | #define HNS3_DBG_BUF_LEN 256 |
235 | ||
236 | char printf_buf[HNS3_DBG_BUF_LEN]; | |
237 | ||
a9556d8c | 238 | dev_info(&h->pdev->dev, "available commands\n"); |
239 | dev_info(&h->pdev->dev, "queue info [number]\n"); | |
89d6386f | 240 | dev_info(&h->pdev->dev, "queue map\n"); |
e2a3560b | 241 | dev_info(&h->pdev->dev, "bd info [q_num] <bd index>\n"); |
a9556d8c | 242 | dev_info(&h->pdev->dev, "dump fd tcam\n"); |
960a99e9 | 243 | dev_info(&h->pdev->dev, "dump tc\n"); |
949902aa | 244 | dev_info(&h->pdev->dev, "dump tm map [q_num]\n"); |
ff48513b | 245 | dev_info(&h->pdev->dev, "dump tm\n"); |
e95f9d79 | 246 | dev_info(&h->pdev->dev, "dump qos pause cfg\n"); |
c07b8f83 | 247 | dev_info(&h->pdev->dev, "dump qos pri map\n"); |
9acc5342 | 248 | dev_info(&h->pdev->dev, "dump qos buf cfg\n"); |
6e87b62b | 249 | dev_info(&h->pdev->dev, "dump mng tbl\n"); |
fe84b06d | 250 | |
251 | memset(printf_buf, 0, HNS3_DBG_BUF_LEN); | |
252 | strncat(printf_buf, "dump reg [[bios common] [ssu <prt_id>]", | |
253 | HNS3_DBG_BUF_LEN - 1); | |
254 | strncat(printf_buf + strlen(printf_buf), | |
255 | " [igu egu <prt_id>] [rpu <tc_queue_num>]", | |
256 | HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); | |
257 | strncat(printf_buf + strlen(printf_buf), | |
258 | " [rtc] [ppp] [rcb] [tqp <q_num>]]\n", | |
259 | HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); | |
260 | dev_info(&h->pdev->dev, "%s", printf_buf); | |
12ef3c6b | 261 | |
262 | memset(printf_buf, 0, HNS3_DBG_BUF_LEN); | |
263 | strncat(printf_buf, "dump reg dcb [port_id] [pri_id] [pg_id]", | |
264 | HNS3_DBG_BUF_LEN - 1); | |
265 | strncat(printf_buf + strlen(printf_buf), " [rq_id] [nq_id] [qset_id]\n", | |
266 | HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); | |
267 | dev_info(&h->pdev->dev, "%s", printf_buf); | |
a9556d8c | 268 | } |
269 | ||
270 | static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, | |
271 | size_t count, loff_t *ppos) | |
272 | { | |
273 | int uncopy_bytes; | |
274 | char *buf; | |
275 | int len; | |
276 | ||
277 | if (*ppos != 0) | |
278 | return 0; | |
279 | ||
280 | if (count < HNS3_DBG_READ_LEN) | |
281 | return -ENOSPC; | |
282 | ||
283 | buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL); | |
284 | if (!buf) | |
285 | return -ENOMEM; | |
286 | ||
287 | len = snprintf(buf, HNS3_DBG_READ_LEN, "%s\n", | |
288 | "Please echo help to cmd to get help information"); | |
289 | uncopy_bytes = copy_to_user(buffer, buf, len); | |
290 | ||
291 | kfree(buf); | |
292 | ||
293 | if (uncopy_bytes) | |
294 | return -EFAULT; | |
295 | ||
296 | return (*ppos = len); | |
297 | } | |
298 | ||
299 | static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, | |
300 | size_t count, loff_t *ppos) | |
301 | { | |
302 | struct hnae3_handle *handle = filp->private_data; | |
09dac155 | 303 | struct hns3_nic_priv *priv = handle->priv; |
a9556d8c | 304 | char *cmd_buf, *cmd_buf_tmp; |
305 | int uncopied_bytes; | |
306 | int ret = 0; | |
307 | ||
308 | if (*ppos != 0) | |
309 | return 0; | |
310 | ||
09dac155 | 311 | /* Judge if the instance is being reset. */ |
6e87b62b | 312 | if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || |
09dac155 | 313 | test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) |
314 | return 0; | |
315 | ||
a9556d8c | 316 | cmd_buf = kzalloc(count + 1, GFP_KERNEL); |
317 | if (!cmd_buf) | |
318 | return count; | |
319 | ||
320 | uncopied_bytes = copy_from_user(cmd_buf, buffer, count); | |
321 | if (uncopied_bytes) { | |
322 | kfree(cmd_buf); | |
323 | return -EFAULT; | |
324 | } | |
325 | ||
326 | cmd_buf[count] = '\0'; | |
327 | ||
328 | cmd_buf_tmp = strchr(cmd_buf, '\n'); | |
329 | if (cmd_buf_tmp) { | |
330 | *cmd_buf_tmp = '\0'; | |
331 | count = cmd_buf_tmp - cmd_buf + 1; | |
332 | } | |
333 | ||
334 | if (strncmp(cmd_buf, "help", 4) == 0) | |
335 | hns3_dbg_help(handle); | |
09dac155 | 336 | else if (strncmp(cmd_buf, "queue info", 10) == 0) |
337 | ret = hns3_dbg_queue_info(handle, cmd_buf); | |
89d6386f | 338 | else if (strncmp(cmd_buf, "queue map", 9) == 0) |
339 | ret = hns3_dbg_queue_map(handle); | |
e2a3560b | 340 | else if (strncmp(cmd_buf, "bd info", 7) == 0) |
341 | ret = hns3_dbg_bd_info(handle, cmd_buf); | |
bf4fd28d | 342 | else if (handle->ae_algo->ops->dbg_run_cmd) |
343 | ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); | |
a9556d8c | 344 | |
345 | if (ret) | |
346 | hns3_dbg_help(handle); | |
347 | ||
348 | kfree(cmd_buf); | |
349 | cmd_buf = NULL; | |
350 | ||
351 | return count; | |
352 | } | |
353 | ||
354 | static const struct file_operations hns3_dbg_cmd_fops = { | |
355 | .owner = THIS_MODULE, | |
356 | .open = simple_open, | |
357 | .read = hns3_dbg_cmd_read, | |
358 | .write = hns3_dbg_cmd_write, | |
359 | }; | |
360 | ||
361 | void hns3_dbg_init(struct hnae3_handle *handle) | |
362 | { | |
363 | const char *name = pci_name(handle->pdev); | |
364 | struct dentry *pfile; | |
365 | ||
366 | handle->hnae3_dbgfs = debugfs_create_dir(name, hns3_dbgfs_root); | |
367 | if (!handle->hnae3_dbgfs) | |
368 | return; | |
369 | ||
370 | pfile = debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, | |
371 | &hns3_dbg_cmd_fops); | |
372 | if (!pfile) { | |
373 | debugfs_remove_recursive(handle->hnae3_dbgfs); | |
374 | handle->hnae3_dbgfs = NULL; | |
375 | dev_warn(&handle->pdev->dev, "create file for %s fail\n", | |
376 | name); | |
377 | } | |
378 | } | |
379 | ||
380 | void hns3_dbg_uninit(struct hnae3_handle *handle) | |
381 | { | |
382 | debugfs_remove_recursive(handle->hnae3_dbgfs); | |
383 | handle->hnae3_dbgfs = NULL; | |
384 | } | |
385 | ||
386 | void hns3_dbg_register_debugfs(const char *debugfs_dir_name) | |
387 | { | |
388 | hns3_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL); | |
389 | if (!hns3_dbgfs_root) { | |
390 | pr_warn("Register debugfs for %s fail\n", debugfs_dir_name); | |
391 | return; | |
392 | } | |
393 | } | |
394 | ||
395 | void hns3_dbg_unregister_debugfs(void) | |
396 | { | |
397 | debugfs_remove_recursive(hns3_dbgfs_root); | |
398 | hns3_dbgfs_root = NULL; | |
399 | } |