Commit | Line | Data |
---|---|---|
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" | |
5e69ea7e | 8 | #include "hns3_debugfs.h" |
b2292360 | 9 | #include "hns3_enet.h" |
10 | ||
b2292360 | 11 | static struct dentry *hns3_dbgfs_root; |
12 | ||
5e69ea7e YM |
13 | static struct hns3_dbg_dentry_info hns3_dbg_dentry[] = { |
14 | { | |
15 | .name = "tm" | |
16 | }, | |
77e91848 HT |
17 | { |
18 | .name = "tx_bd_info" | |
19 | }, | |
20 | { | |
21 | .name = "rx_bd_info" | |
22 | }, | |
1556ea91 HT |
23 | { |
24 | .name = "mac_list" | |
25 | }, | |
5e69ea7e YM |
26 | /* keep common at the bottom and add new directory above */ |
27 | { | |
28 | .name = "common" | |
29 | }, | |
30 | }; | |
31 | ||
77e91848 | 32 | static int hns3_dbg_bd_file_init(struct hnae3_handle *handle, unsigned int cmd); |
5e69ea7e YM |
33 | static int hns3_dbg_common_file_init(struct hnae3_handle *handle, |
34 | unsigned int cmd); | |
35 | ||
36 | static struct hns3_dbg_cmd_info hns3_dbg_cmd[] = { | |
37 | { | |
38 | .name = "tm_nodes", | |
39 | .cmd = HNAE3_DBG_CMD_TM_NODES, | |
40 | .dentry = HNS3_DBG_DENTRY_TM, | |
41 | .buf_len = HNS3_DBG_READ_LEN, | |
42 | .init = hns3_dbg_common_file_init, | |
43 | }, | |
44 | { | |
45 | .name = "tm_priority", | |
46 | .cmd = HNAE3_DBG_CMD_TM_PRI, | |
47 | .dentry = HNS3_DBG_DENTRY_TM, | |
48 | .buf_len = HNS3_DBG_READ_LEN, | |
49 | .init = hns3_dbg_common_file_init, | |
50 | }, | |
51 | { | |
52 | .name = "tm_qset", | |
53 | .cmd = HNAE3_DBG_CMD_TM_QSET, | |
54 | .dentry = HNS3_DBG_DENTRY_TM, | |
55 | .buf_len = HNS3_DBG_READ_LEN, | |
56 | .init = hns3_dbg_common_file_init, | |
57 | }, | |
c929bc2a JZ |
58 | { |
59 | .name = "dev_info", | |
60 | .cmd = HNAE3_DBG_CMD_DEV_INFO, | |
61 | .dentry = HNS3_DBG_DENTRY_COMMON, | |
62 | .buf_len = HNS3_DBG_READ_LEN, | |
63 | .init = hns3_dbg_common_file_init, | |
64 | }, | |
77e91848 HT |
65 | { |
66 | .name = "tx_bd_queue", | |
67 | .cmd = HNAE3_DBG_CMD_TX_BD, | |
68 | .dentry = HNS3_DBG_DENTRY_TX_BD, | |
69 | .buf_len = HNS3_DBG_READ_LEN_4MB, | |
70 | .init = hns3_dbg_bd_file_init, | |
71 | }, | |
72 | { | |
73 | .name = "rx_bd_queue", | |
74 | .cmd = HNAE3_DBG_CMD_RX_BD, | |
75 | .dentry = HNS3_DBG_DENTRY_RX_BD, | |
76 | .buf_len = HNS3_DBG_READ_LEN_4MB, | |
77 | .init = hns3_dbg_bd_file_init, | |
78 | }, | |
1556ea91 HT |
79 | { |
80 | .name = "uc", | |
81 | .cmd = HNAE3_DBG_CMD_MAC_UC, | |
82 | .dentry = HNS3_DBG_DENTRY_MAC, | |
83 | .buf_len = HNS3_DBG_READ_LEN, | |
84 | .init = hns3_dbg_common_file_init, | |
85 | }, | |
86 | { | |
87 | .name = "mc", | |
88 | .cmd = HNAE3_DBG_CMD_MAC_MC, | |
89 | .dentry = HNS3_DBG_DENTRY_MAC, | |
90 | .buf_len = HNS3_DBG_READ_LEN, | |
91 | .init = hns3_dbg_common_file_init, | |
92 | }, | |
8ddfd9c4 YM |
93 | { |
94 | .name = "mng_tbl", | |
95 | .cmd = HNAE3_DBG_CMD_MNG_TBL, | |
96 | .dentry = HNS3_DBG_DENTRY_COMMON, | |
97 | .buf_len = HNS3_DBG_READ_LEN, | |
98 | .init = hns3_dbg_common_file_init, | |
99 | }, | |
d658ff34 YM |
100 | { |
101 | .name = "loopback", | |
102 | .cmd = HNAE3_DBG_CMD_LOOPBACK, | |
103 | .dentry = HNS3_DBG_DENTRY_COMMON, | |
104 | .buf_len = HNS3_DBG_READ_LEN, | |
105 | .init = hns3_dbg_common_file_init, | |
106 | }, | |
9149ca0f JZ |
107 | { |
108 | .name = "interrupt_info", | |
109 | .cmd = HNAE3_DBG_CMD_INTERRUPT_INFO, | |
110 | .dentry = HNS3_DBG_DENTRY_COMMON, | |
111 | .buf_len = HNS3_DBG_READ_LEN, | |
112 | .init = hns3_dbg_common_file_init, | |
113 | }, | |
1a7ff828 JZ |
114 | { |
115 | .name = "reset_info", | |
116 | .cmd = HNAE3_DBG_CMD_RESET_INFO, | |
117 | .dentry = HNS3_DBG_DENTRY_COMMON, | |
118 | .buf_len = HNS3_DBG_READ_LEN, | |
119 | .init = hns3_dbg_common_file_init, | |
120 | }, | |
0b198b0d JZ |
121 | { |
122 | .name = "imp_info", | |
123 | .cmd = HNAE3_DBG_CMD_IMP_INFO, | |
124 | .dentry = HNS3_DBG_DENTRY_COMMON, | |
125 | .buf_len = HNS3_DBG_READ_LEN, | |
126 | .init = hns3_dbg_common_file_init, | |
127 | }, | |
c929bc2a JZ |
128 | }; |
129 | ||
130 | static struct hns3_dbg_cap_info hns3_dbg_cap[] = { | |
131 | { | |
132 | .name = "support FD", | |
133 | .cap_bit = HNAE3_DEV_SUPPORT_FD_B, | |
134 | }, { | |
135 | .name = "support GRO", | |
136 | .cap_bit = HNAE3_DEV_SUPPORT_GRO_B, | |
137 | }, { | |
138 | .name = "support FEC", | |
139 | .cap_bit = HNAE3_DEV_SUPPORT_FEC_B, | |
140 | }, { | |
141 | .name = "support UDP GSO", | |
142 | .cap_bit = HNAE3_DEV_SUPPORT_UDP_GSO_B, | |
143 | }, { | |
144 | .name = "support PTP", | |
145 | .cap_bit = HNAE3_DEV_SUPPORT_PTP_B, | |
146 | }, { | |
147 | .name = "support INT QL", | |
148 | .cap_bit = HNAE3_DEV_SUPPORT_INT_QL_B, | |
149 | }, { | |
150 | .name = "support HW TX csum", | |
151 | .cap_bit = HNAE3_DEV_SUPPORT_HW_TX_CSUM_B, | |
152 | }, { | |
153 | .name = "support UDP tunnel csum", | |
154 | .cap_bit = HNAE3_DEV_SUPPORT_UDP_TUNNEL_CSUM_B, | |
155 | }, { | |
156 | .name = "support TX push", | |
157 | .cap_bit = HNAE3_DEV_SUPPORT_TX_PUSH_B, | |
158 | }, { | |
159 | .name = "support imp-controlled PHY", | |
160 | .cap_bit = HNAE3_DEV_SUPPORT_PHY_IMP_B, | |
161 | }, { | |
162 | .name = "support rxd advanced layout", | |
163 | .cap_bit = HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, | |
164 | }, | |
5e69ea7e YM |
165 | }; |
166 | ||
77e91848 HT |
167 | static void hns3_dbg_fill_content(char *content, u16 len, |
168 | const struct hns3_dbg_item *items, | |
169 | const char **result, u16 size) | |
170 | { | |
171 | char *pos = content; | |
172 | u16 i; | |
173 | ||
174 | memset(content, ' ', len); | |
175 | for (i = 0; i < size; i++) { | |
176 | if (result) | |
177 | strncpy(pos, result[i], strlen(result[i])); | |
178 | else | |
179 | strncpy(pos, items[i].name, strlen(items[i].name)); | |
180 | ||
181 | pos += strlen(items[i].name) + items[i].interval; | |
182 | } | |
183 | ||
184 | *pos++ = '\n'; | |
185 | *pos++ = '\0'; | |
186 | } | |
187 | ||
ebaf1908 WL |
188 | static int hns3_dbg_queue_info(struct hnae3_handle *h, |
189 | const char *cmd_buf) | |
57ceee2c | 190 | { |
dbaae5bb | 191 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); |
57ceee2c | 192 | struct hns3_nic_priv *priv = h->priv; |
57ceee2c | 193 | struct hns3_enet_ring *ring; |
194 | u32 base_add_l, base_add_h; | |
195 | u32 queue_num, queue_max; | |
9d8d5a36 | 196 | u32 value, i; |
57ceee2c | 197 | int cnt; |
198 | ||
5f06b903 YL |
199 | if (!priv->ring) { |
200 | dev_err(&h->pdev->dev, "priv->ring is NULL\n"); | |
57ceee2c | 201 | return -EFAULT; |
202 | } | |
203 | ||
204 | queue_max = h->kinfo.num_tqps; | |
205 | cnt = kstrtouint(&cmd_buf[11], 0, &queue_num); | |
206 | if (cnt) | |
207 | queue_num = 0; | |
208 | else | |
209 | queue_max = queue_num + 1; | |
210 | ||
211 | dev_info(&h->pdev->dev, "queue info\n"); | |
212 | ||
213 | if (queue_num >= h->kinfo.num_tqps) { | |
214 | dev_err(&h->pdev->dev, | |
ed5b255b | 215 | "Queue number(%u) is out of range(0-%u)\n", queue_num, |
57ceee2c | 216 | h->kinfo.num_tqps - 1); |
217 | return -EINVAL; | |
218 | } | |
219 | ||
57ceee2c | 220 | for (i = queue_num; i < queue_max; i++) { |
221 | /* Each cycle needs to determine whether the instance is reset, | |
222 | * to prevent reference to invalid memory. And need to ensure | |
223 | * that the following code is executed within 100ms. | |
224 | */ | |
7737f1fb | 225 | if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || |
57ceee2c | 226 | test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) |
227 | return -EPERM; | |
228 | ||
5f06b903 | 229 | ring = &priv->ring[(u32)(i + h->kinfo.num_tqps)]; |
57ceee2c | 230 | base_add_h = readl_relaxed(ring->tqp->io_base + |
231 | HNS3_RING_RX_RING_BASEADDR_H_REG); | |
232 | base_add_l = readl_relaxed(ring->tqp->io_base + | |
233 | HNS3_RING_RX_RING_BASEADDR_L_REG); | |
adcf738b | 234 | dev_info(&h->pdev->dev, "RX(%u) BASE ADD: 0x%08x%08x\n", i, |
57ceee2c | 235 | base_add_h, base_add_l); |
236 | ||
237 | value = readl_relaxed(ring->tqp->io_base + | |
238 | HNS3_RING_RX_RING_BD_NUM_REG); | |
adcf738b | 239 | dev_info(&h->pdev->dev, "RX(%u) RING BD NUM: %u\n", i, value); |
57ceee2c | 240 | |
241 | value = readl_relaxed(ring->tqp->io_base + | |
242 | HNS3_RING_RX_RING_BD_LEN_REG); | |
adcf738b | 243 | dev_info(&h->pdev->dev, "RX(%u) RING BD LEN: %u\n", i, value); |
57ceee2c | 244 | |
245 | value = readl_relaxed(ring->tqp->io_base + | |
246 | HNS3_RING_RX_RING_TAIL_REG); | |
adcf738b | 247 | dev_info(&h->pdev->dev, "RX(%u) RING TAIL: %u\n", i, value); |
57ceee2c | 248 | |
249 | value = readl_relaxed(ring->tqp->io_base + | |
250 | HNS3_RING_RX_RING_HEAD_REG); | |
adcf738b | 251 | dev_info(&h->pdev->dev, "RX(%u) RING HEAD: %u\n", i, value); |
57ceee2c | 252 | |
253 | value = readl_relaxed(ring->tqp->io_base + | |
254 | HNS3_RING_RX_RING_FBDNUM_REG); | |
adcf738b | 255 | dev_info(&h->pdev->dev, "RX(%u) RING FBDNUM: %u\n", i, value); |
57ceee2c | 256 | |
257 | value = readl_relaxed(ring->tqp->io_base + | |
258 | HNS3_RING_RX_RING_PKTNUM_RECORD_REG); | |
adcf738b | 259 | dev_info(&h->pdev->dev, "RX(%u) RING PKTNUM: %u\n", i, value); |
57ceee2c | 260 | |
5f06b903 | 261 | ring = &priv->ring[i]; |
57ceee2c | 262 | base_add_h = readl_relaxed(ring->tqp->io_base + |
263 | HNS3_RING_TX_RING_BASEADDR_H_REG); | |
264 | base_add_l = readl_relaxed(ring->tqp->io_base + | |
265 | HNS3_RING_TX_RING_BASEADDR_L_REG); | |
adcf738b | 266 | dev_info(&h->pdev->dev, "TX(%u) BASE ADD: 0x%08x%08x\n", i, |
57ceee2c | 267 | base_add_h, base_add_l); |
268 | ||
269 | value = readl_relaxed(ring->tqp->io_base + | |
270 | HNS3_RING_TX_RING_BD_NUM_REG); | |
adcf738b | 271 | dev_info(&h->pdev->dev, "TX(%u) RING BD NUM: %u\n", i, value); |
57ceee2c | 272 | |
273 | value = readl_relaxed(ring->tqp->io_base + | |
274 | HNS3_RING_TX_RING_TC_REG); | |
adcf738b | 275 | dev_info(&h->pdev->dev, "TX(%u) RING TC: %u\n", i, value); |
57ceee2c | 276 | |
277 | value = readl_relaxed(ring->tqp->io_base + | |
278 | HNS3_RING_TX_RING_TAIL_REG); | |
adcf738b | 279 | dev_info(&h->pdev->dev, "TX(%u) RING TAIL: %u\n", i, value); |
57ceee2c | 280 | |
281 | value = readl_relaxed(ring->tqp->io_base + | |
282 | HNS3_RING_TX_RING_HEAD_REG); | |
adcf738b | 283 | dev_info(&h->pdev->dev, "TX(%u) RING HEAD: %u\n", i, value); |
57ceee2c | 284 | |
285 | value = readl_relaxed(ring->tqp->io_base + | |
286 | HNS3_RING_TX_RING_FBDNUM_REG); | |
adcf738b | 287 | dev_info(&h->pdev->dev, "TX(%u) RING FBDNUM: %u\n", i, value); |
57ceee2c | 288 | |
289 | value = readl_relaxed(ring->tqp->io_base + | |
290 | HNS3_RING_TX_RING_OFFSET_REG); | |
adcf738b | 291 | dev_info(&h->pdev->dev, "TX(%u) RING OFFSET: %u\n", i, value); |
57ceee2c | 292 | |
293 | value = readl_relaxed(ring->tqp->io_base + | |
294 | HNS3_RING_TX_RING_PKTNUM_RECORD_REG); | |
dbaae5bb GH |
295 | dev_info(&h->pdev->dev, "TX(%u) RING PKTNUM: %u\n", i, value); |
296 | ||
297 | value = readl_relaxed(ring->tqp->io_base + HNS3_RING_EN_REG); | |
298 | dev_info(&h->pdev->dev, "TX/RX(%u) RING EN: %s\n", i, | |
299 | value ? "enable" : "disable"); | |
300 | ||
301 | if (hnae3_ae_dev_tqp_txrx_indep_supported(ae_dev)) { | |
302 | value = readl_relaxed(ring->tqp->io_base + | |
303 | HNS3_RING_TX_EN_REG); | |
304 | dev_info(&h->pdev->dev, "TX(%u) RING EN: %s\n", i, | |
305 | value ? "enable" : "disable"); | |
306 | ||
307 | value = readl_relaxed(ring->tqp->io_base + | |
308 | HNS3_RING_RX_EN_REG); | |
309 | dev_info(&h->pdev->dev, "RX(%u) RING EN: %s\n", i, | |
310 | value ? "enable" : "disable"); | |
311 | } | |
312 | ||
313 | dev_info(&h->pdev->dev, "\n"); | |
57ceee2c | 314 | } |
315 | ||
316 | return 0; | |
317 | } | |
318 | ||
0c29d191 | 319 | static int hns3_dbg_queue_map(struct hnae3_handle *h) |
320 | { | |
321 | struct hns3_nic_priv *priv = h->priv; | |
0c29d191 | 322 | int i; |
323 | ||
324 | if (!h->ae_algo->ops->get_global_queue_id) | |
325 | return -EOPNOTSUPP; | |
326 | ||
327 | dev_info(&h->pdev->dev, "map info for queue id and vector id\n"); | |
328 | dev_info(&h->pdev->dev, | |
329 | "local queue id | global queue id | vector id\n"); | |
330 | for (i = 0; i < h->kinfo.num_tqps; i++) { | |
331 | u16 global_qid; | |
332 | ||
333 | global_qid = h->ae_algo->ops->get_global_queue_id(h, i); | |
5f06b903 | 334 | if (!priv->ring || !priv->ring[i].tqp_vector) |
0c29d191 | 335 | continue; |
336 | ||
337 | dev_info(&h->pdev->dev, | |
c5aaf176 | 338 | " %4d %4u %4d\n", |
5f06b903 | 339 | i, global_qid, priv->ring[i].tqp_vector->vector_irq); |
0c29d191 | 340 | } |
341 | ||
342 | return 0; | |
343 | } | |
344 | ||
77e91848 HT |
345 | static const struct hns3_dbg_item rx_bd_info_items[] = { |
346 | { "BD_IDX", 3 }, | |
347 | { "L234_INFO", 2 }, | |
348 | { "PKT_LEN", 3 }, | |
349 | { "SIZE", 4 }, | |
350 | { "RSS_HASH", 4 }, | |
351 | { "FD_ID", 2 }, | |
352 | { "VLAN_TAG", 2 }, | |
353 | { "O_DM_VLAN_ID_FB", 2 }, | |
354 | { "OT_VLAN_TAG", 2 }, | |
355 | { "BD_BASE_INFO", 2 }, | |
356 | { "PTYPE", 2 }, | |
357 | { "HW_CSUM", 2 }, | |
358 | }; | |
359 | ||
360 | static void hns3_dump_rx_bd_info(struct hns3_nic_priv *priv, | |
361 | struct hns3_desc *desc, char **result, int idx) | |
122bedc5 | 362 | { |
77e91848 HT |
363 | unsigned int j = 0; |
364 | ||
365 | sprintf(result[j++], "%5d", idx); | |
366 | sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.l234_info)); | |
367 | sprintf(result[j++], "%7u", le16_to_cpu(desc->rx.pkt_len)); | |
368 | sprintf(result[j++], "%4u", le16_to_cpu(desc->rx.size)); | |
369 | sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.rss_hash)); | |
370 | sprintf(result[j++], "%5u", le16_to_cpu(desc->rx.fd_id)); | |
371 | sprintf(result[j++], "%8u", le16_to_cpu(desc->rx.vlan_tag)); | |
372 | sprintf(result[j++], "%15u", le16_to_cpu(desc->rx.o_dm_vlan_id_fb)); | |
373 | sprintf(result[j++], "%11u", le16_to_cpu(desc->rx.ot_vlan_tag)); | |
374 | sprintf(result[j++], "%#x", le32_to_cpu(desc->rx.bd_base_info)); | |
375 | if (test_bit(HNS3_NIC_STATE_RXD_ADV_LAYOUT_ENABLE, &priv->state)) { | |
376 | u32 ol_info = le32_to_cpu(desc->rx.ol_info); | |
377 | ||
378 | sprintf(result[j++], "%5lu", hnae3_get_field(ol_info, | |
379 | HNS3_RXD_PTYPE_M, | |
380 | HNS3_RXD_PTYPE_S)); | |
381 | sprintf(result[j++], "%7u", le16_to_cpu(desc->csum)); | |
382 | } else { | |
383 | sprintf(result[j++], "NA"); | |
384 | sprintf(result[j++], "NA"); | |
385 | } | |
386 | } | |
387 | ||
388 | static int hns3_dbg_rx_bd_info(struct hns3_dbg_data *d, char *buf, int len) | |
389 | { | |
390 | char data_str[ARRAY_SIZE(rx_bd_info_items)][HNS3_DBG_DATA_STR_LEN]; | |
391 | struct hns3_nic_priv *priv = d->handle->priv; | |
392 | char *result[ARRAY_SIZE(rx_bd_info_items)]; | |
393 | char content[HNS3_DBG_INFO_LEN]; | |
122bedc5 | 394 | struct hns3_enet_ring *ring; |
77e91848 HT |
395 | struct hns3_desc *desc; |
396 | unsigned int i; | |
397 | int pos = 0; | |
122bedc5 | 398 | |
77e91848 HT |
399 | if (d->qid >= d->handle->kinfo.num_tqps) { |
400 | dev_err(&d->handle->pdev->dev, | |
401 | "queue%u is not in use\n", d->qid); | |
122bedc5 | 402 | return -EINVAL; |
403 | } | |
404 | ||
77e91848 HT |
405 | for (i = 0; i < ARRAY_SIZE(rx_bd_info_items); i++) |
406 | result[i] = &data_str[i][0]; | |
407 | ||
408 | pos += scnprintf(buf + pos, len - pos, | |
409 | "Queue %u rx bd info:\n", d->qid); | |
410 | hns3_dbg_fill_content(content, sizeof(content), rx_bd_info_items, | |
411 | NULL, ARRAY_SIZE(rx_bd_info_items)); | |
412 | pos += scnprintf(buf + pos, len - pos, "%s", content); | |
413 | ||
414 | ring = &priv->ring[d->qid + d->handle->kinfo.num_tqps]; | |
415 | for (i = 0; i < ring->desc_num; i++) { | |
416 | desc = &ring->desc[i]; | |
417 | ||
418 | hns3_dump_rx_bd_info(priv, desc, result, i); | |
419 | hns3_dbg_fill_content(content, sizeof(content), | |
420 | rx_bd_info_items, (const char **)result, | |
421 | ARRAY_SIZE(rx_bd_info_items)); | |
422 | pos += scnprintf(buf + pos, len - pos, "%s", content); | |
122bedc5 | 423 | } |
424 | ||
77e91848 HT |
425 | return 0; |
426 | } | |
427 | ||
428 | static const struct hns3_dbg_item tx_bd_info_items[] = { | |
429 | { "BD_IDX", 5 }, | |
430 | { "ADDRESS", 2 }, | |
431 | { "VLAN_TAG", 2 }, | |
432 | { "SIZE", 2 }, | |
433 | { "T_CS_VLAN_TSO", 2 }, | |
434 | { "OT_VLAN_TAG", 3 }, | |
435 | { "TV", 2 }, | |
436 | { "OLT_VLAN_LEN", 2}, | |
437 | { "PAYLEN_OL4CS", 2}, | |
438 | { "BD_FE_SC_VLD", 2}, | |
439 | { "MSS_HW_CSUM", 0}, | |
440 | }; | |
122bedc5 | 441 | |
77e91848 HT |
442 | static void hns3_dump_tx_bd_info(struct hns3_nic_priv *priv, |
443 | struct hns3_desc *desc, char **result, int idx) | |
444 | { | |
445 | unsigned int j = 0; | |
446 | ||
447 | sprintf(result[j++], "%6d", idx); | |
448 | sprintf(result[j++], "%#llx", le64_to_cpu(desc->addr)); | |
449 | sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.vlan_tag)); | |
450 | sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.send_size)); | |
451 | sprintf(result[j++], "%#x", | |
452 | le32_to_cpu(desc->tx.type_cs_vlan_tso_len)); | |
453 | sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.outer_vlan_tag)); | |
454 | sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.tv)); | |
455 | sprintf(result[j++], "%10u", | |
456 | le32_to_cpu(desc->tx.ol_type_vlan_len_msec)); | |
457 | sprintf(result[j++], "%#x", le32_to_cpu(desc->tx.paylen_ol4cs)); | |
458 | sprintf(result[j++], "%#x", le16_to_cpu(desc->tx.bdtp_fe_sc_vld_ra_ri)); | |
459 | sprintf(result[j++], "%5u", le16_to_cpu(desc->tx.mss_hw_csum)); | |
460 | } | |
461 | ||
462 | static int hns3_dbg_tx_bd_info(struct hns3_dbg_data *d, char *buf, int len) | |
463 | { | |
464 | char data_str[ARRAY_SIZE(tx_bd_info_items)][HNS3_DBG_DATA_STR_LEN]; | |
465 | struct hns3_nic_priv *priv = d->handle->priv; | |
466 | char *result[ARRAY_SIZE(tx_bd_info_items)]; | |
467 | char content[HNS3_DBG_INFO_LEN]; | |
468 | struct hns3_enet_ring *ring; | |
469 | struct hns3_desc *desc; | |
470 | unsigned int i; | |
471 | int pos = 0; | |
472 | ||
473 | if (d->qid >= d->handle->kinfo.num_tqps) { | |
474 | dev_err(&d->handle->pdev->dev, | |
475 | "queue%u is not in use\n", d->qid); | |
122bedc5 | 476 | return -EINVAL; |
477 | } | |
478 | ||
77e91848 HT |
479 | for (i = 0; i < ARRAY_SIZE(tx_bd_info_items); i++) |
480 | result[i] = &data_str[i][0]; | |
481 | ||
482 | pos += scnprintf(buf + pos, len - pos, | |
483 | "Queue %u tx bd info:\n", d->qid); | |
484 | hns3_dbg_fill_content(content, sizeof(content), tx_bd_info_items, | |
485 | NULL, ARRAY_SIZE(tx_bd_info_items)); | |
486 | pos += scnprintf(buf + pos, len - pos, "%s", content); | |
b1533ada | 487 | |
77e91848 HT |
488 | ring = &priv->ring[d->qid]; |
489 | for (i = 0; i < ring->desc_num; i++) { | |
490 | desc = &ring->desc[i]; | |
491 | ||
492 | hns3_dump_tx_bd_info(priv, desc, result, i); | |
493 | hns3_dbg_fill_content(content, sizeof(content), | |
494 | tx_bd_info_items, (const char **)result, | |
495 | ARRAY_SIZE(tx_bd_info_items)); | |
496 | pos += scnprintf(buf + pos, len - pos, "%s", content); | |
497 | } | |
122bedc5 | 498 | |
499 | return 0; | |
500 | } | |
501 | ||
b2292360 | 502 | static void hns3_dbg_help(struct hnae3_handle *h) |
503 | { | |
27cf979a | 504 | #define HNS3_DBG_BUF_LEN 256 |
505 | ||
506 | char printf_buf[HNS3_DBG_BUF_LEN]; | |
507 | ||
b2292360 | 508 | dev_info(&h->pdev->dev, "available commands\n"); |
ed5b255b | 509 | dev_info(&h->pdev->dev, "queue info <number>\n"); |
0c29d191 | 510 | dev_info(&h->pdev->dev, "queue map\n"); |
97afd47b YM |
511 | |
512 | if (!hns3_is_phys_func(h->pdev)) | |
513 | return; | |
514 | ||
b2292360 | 515 | dev_info(&h->pdev->dev, "dump fd tcam\n"); |
2849d4e7 | 516 | dev_info(&h->pdev->dev, "dump tc\n"); |
ed5b255b | 517 | dev_info(&h->pdev->dev, "dump tm map <q_num>\n"); |
96227f4c | 518 | dev_info(&h->pdev->dev, "dump tm\n"); |
d958919d | 519 | dev_info(&h->pdev->dev, "dump qos pause cfg\n"); |
6fc22440 | 520 | dev_info(&h->pdev->dev, "dump qos pri map\n"); |
7d9d7f88 | 521 | dev_info(&h->pdev->dev, "dump qos buf cfg\n"); |
ffd140e2 | 522 | dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n"); |
a6345787 | 523 | dev_info(&h->pdev->dev, "dump mac tnl status\n"); |
89ec9485 | 524 | dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n"); |
27cf979a | 525 | |
526 | memset(printf_buf, 0, HNS3_DBG_BUF_LEN); | |
ed5b255b | 527 | strncat(printf_buf, "dump reg [[bios common] [ssu <port_id>]", |
27cf979a | 528 | HNS3_DBG_BUF_LEN - 1); |
529 | strncat(printf_buf + strlen(printf_buf), | |
ed5b255b | 530 | " [igu egu <port_id>] [rpu <tc_queue_num>]", |
27cf979a | 531 | HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); |
532 | strncat(printf_buf + strlen(printf_buf), | |
5cb51cfe | 533 | " [rtc] [ppp] [rcb] [tqp <queue_num>] [mac]]\n", |
27cf979a | 534 | HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); |
535 | dev_info(&h->pdev->dev, "%s", printf_buf); | |
c0ebebb9 | 536 | |
537 | memset(printf_buf, 0, HNS3_DBG_BUF_LEN); | |
ed5b255b | 538 | strncat(printf_buf, "dump reg dcb <port_id> <pri_id> <pg_id>", |
c0ebebb9 | 539 | HNS3_DBG_BUF_LEN - 1); |
ed5b255b | 540 | strncat(printf_buf + strlen(printf_buf), " <rq_id> <nq_id> <qset_id>\n", |
c0ebebb9 | 541 | HNS3_DBG_BUF_LEN - strlen(printf_buf) - 1); |
542 | dev_info(&h->pdev->dev, "%s", printf_buf); | |
b2292360 | 543 | } |
544 | ||
c929bc2a JZ |
545 | static void |
546 | hns3_dbg_dev_caps(struct hnae3_handle *h, char *buf, int len, int *pos) | |
9484e337 GH |
547 | { |
548 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); | |
c929bc2a JZ |
549 | static const char * const str[] = {"no", "yes"}; |
550 | unsigned long *caps = ae_dev->caps; | |
551 | u32 i, state; | |
552 | ||
553 | *pos += scnprintf(buf + *pos, len - *pos, "dev capability:\n"); | |
554 | ||
555 | for (i = 0; i < ARRAY_SIZE(hns3_dbg_cap); i++) { | |
556 | state = test_bit(hns3_dbg_cap[i].cap_bit, caps); | |
557 | *pos += scnprintf(buf + *pos, len - *pos, "%s: %s\n", | |
558 | hns3_dbg_cap[i].name, str[state]); | |
559 | } | |
560 | ||
561 | *pos += scnprintf(buf + *pos, len - *pos, "\n"); | |
9484e337 GH |
562 | } |
563 | ||
c929bc2a JZ |
564 | static void |
565 | hns3_dbg_dev_specs(struct hnae3_handle *h, char *buf, int len, int *pos) | |
b4442ec5 GH |
566 | { |
567 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev); | |
568 | struct hnae3_dev_specs *dev_specs = &ae_dev->dev_specs; | |
569 | struct hnae3_knic_private_info *kinfo = &h->kinfo; | |
c929bc2a JZ |
570 | |
571 | *pos += scnprintf(buf + *pos, len - *pos, "dev_spec:\n"); | |
572 | *pos += scnprintf(buf + *pos, len - *pos, "MAC entry num: %u\n", | |
573 | dev_specs->mac_entry_num); | |
574 | *pos += scnprintf(buf + *pos, len - *pos, "MNG entry num: %u\n", | |
575 | dev_specs->mng_entry_num); | |
576 | *pos += scnprintf(buf + *pos, len - *pos, "MAX non tso bd num: %u\n", | |
577 | dev_specs->max_non_tso_bd_num); | |
578 | *pos += scnprintf(buf + *pos, len - *pos, "RSS ind tbl size: %u\n", | |
579 | dev_specs->rss_ind_tbl_size); | |
580 | *pos += scnprintf(buf + *pos, len - *pos, "RSS key size: %u\n", | |
581 | dev_specs->rss_key_size); | |
582 | *pos += scnprintf(buf + *pos, len - *pos, "RSS size: %u\n", | |
583 | kinfo->rss_size); | |
584 | *pos += scnprintf(buf + *pos, len - *pos, "Allocated RSS size: %u\n", | |
585 | kinfo->req_rss_size); | |
586 | *pos += scnprintf(buf + *pos, len - *pos, | |
587 | "Task queue pairs numbers: %u\n", | |
588 | kinfo->num_tqps); | |
589 | *pos += scnprintf(buf + *pos, len - *pos, "RX buffer length: %u\n", | |
590 | kinfo->rx_buf_len); | |
591 | *pos += scnprintf(buf + *pos, len - *pos, "Desc num per TX queue: %u\n", | |
592 | kinfo->num_tx_desc); | |
593 | *pos += scnprintf(buf + *pos, len - *pos, "Desc num per RX queue: %u\n", | |
594 | kinfo->num_rx_desc); | |
595 | *pos += scnprintf(buf + *pos, len - *pos, | |
596 | "Total number of enabled TCs: %u\n", | |
597 | kinfo->tc_info.num_tc); | |
598 | *pos += scnprintf(buf + *pos, len - *pos, "MAX INT QL: %u\n", | |
599 | dev_specs->int_ql_max); | |
600 | *pos += scnprintf(buf + *pos, len - *pos, "MAX INT GL: %u\n", | |
601 | dev_specs->max_int_gl); | |
602 | *pos += scnprintf(buf + *pos, len - *pos, "MAX TM RATE: %u\n", | |
603 | dev_specs->max_tm_rate); | |
604 | *pos += scnprintf(buf + *pos, len - *pos, "MAX QSET number: %u\n", | |
605 | dev_specs->max_qset_num); | |
606 | } | |
607 | ||
608 | static int hns3_dbg_dev_info(struct hnae3_handle *h, char *buf, int len) | |
609 | { | |
610 | int pos = 0; | |
611 | ||
612 | hns3_dbg_dev_caps(h, buf, len, &pos); | |
613 | ||
614 | hns3_dbg_dev_specs(h, buf, len, &pos); | |
615 | ||
616 | return 0; | |
b4442ec5 GH |
617 | } |
618 | ||
b2292360 | 619 | static ssize_t hns3_dbg_cmd_read(struct file *filp, char __user *buffer, |
620 | size_t count, loff_t *ppos) | |
621 | { | |
622 | int uncopy_bytes; | |
623 | char *buf; | |
624 | int len; | |
625 | ||
626 | if (*ppos != 0) | |
627 | return 0; | |
628 | ||
629 | if (count < HNS3_DBG_READ_LEN) | |
630 | return -ENOSPC; | |
631 | ||
632 | buf = kzalloc(HNS3_DBG_READ_LEN, GFP_KERNEL); | |
633 | if (!buf) | |
634 | return -ENOMEM; | |
635 | ||
49e211c0 CZ |
636 | len = scnprintf(buf, HNS3_DBG_READ_LEN, "%s\n", |
637 | "Please echo help to cmd to get help information"); | |
b2292360 | 638 | uncopy_bytes = copy_to_user(buffer, buf, len); |
639 | ||
640 | kfree(buf); | |
641 | ||
642 | if (uncopy_bytes) | |
643 | return -EFAULT; | |
644 | ||
645 | return (*ppos = len); | |
646 | } | |
647 | ||
c318af3f PL |
648 | static int hns3_dbg_check_cmd(struct hnae3_handle *handle, char *cmd_buf) |
649 | { | |
650 | int ret = 0; | |
651 | ||
652 | if (strncmp(cmd_buf, "help", 4) == 0) | |
653 | hns3_dbg_help(handle); | |
654 | else if (strncmp(cmd_buf, "queue info", 10) == 0) | |
655 | ret = hns3_dbg_queue_info(handle, cmd_buf); | |
656 | else if (strncmp(cmd_buf, "queue map", 9) == 0) | |
657 | ret = hns3_dbg_queue_map(handle); | |
c318af3f PL |
658 | else if (handle->ae_algo->ops->dbg_run_cmd) |
659 | ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf); | |
660 | else | |
661 | ret = -EOPNOTSUPP; | |
662 | ||
663 | return ret; | |
664 | } | |
665 | ||
b2292360 | 666 | static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer, |
667 | size_t count, loff_t *ppos) | |
668 | { | |
669 | struct hnae3_handle *handle = filp->private_data; | |
57ceee2c | 670 | struct hns3_nic_priv *priv = handle->priv; |
b2292360 | 671 | char *cmd_buf, *cmd_buf_tmp; |
672 | int uncopied_bytes; | |
c318af3f | 673 | int ret; |
b2292360 | 674 | |
675 | if (*ppos != 0) | |
676 | return 0; | |
677 | ||
57ceee2c | 678 | /* Judge if the instance is being reset. */ |
7737f1fb | 679 | if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || |
57ceee2c | 680 | test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) |
681 | return 0; | |
682 | ||
7ac243f9 YM |
683 | if (count > HNS3_DBG_WRITE_LEN) |
684 | return -ENOSPC; | |
685 | ||
b2292360 | 686 | cmd_buf = kzalloc(count + 1, GFP_KERNEL); |
687 | if (!cmd_buf) | |
688 | return count; | |
689 | ||
690 | uncopied_bytes = copy_from_user(cmd_buf, buffer, count); | |
691 | if (uncopied_bytes) { | |
692 | kfree(cmd_buf); | |
693 | return -EFAULT; | |
694 | } | |
695 | ||
696 | cmd_buf[count] = '\0'; | |
697 | ||
698 | cmd_buf_tmp = strchr(cmd_buf, '\n'); | |
699 | if (cmd_buf_tmp) { | |
700 | *cmd_buf_tmp = '\0'; | |
701 | count = cmd_buf_tmp - cmd_buf + 1; | |
702 | } | |
703 | ||
c318af3f | 704 | ret = hns3_dbg_check_cmd(handle, cmd_buf); |
b2292360 | 705 | if (ret) |
706 | hns3_dbg_help(handle); | |
707 | ||
708 | kfree(cmd_buf); | |
709 | cmd_buf = NULL; | |
710 | ||
711 | return count; | |
712 | } | |
713 | ||
5e69ea7e YM |
714 | static int hns3_dbg_get_cmd_index(struct hnae3_handle *handle, |
715 | const unsigned char *name, u32 *index) | |
716 | { | |
717 | u32 i; | |
718 | ||
719 | for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) { | |
720 | if (!strncmp(name, hns3_dbg_cmd[i].name, | |
721 | strlen(hns3_dbg_cmd[i].name))) { | |
722 | *index = i; | |
723 | return 0; | |
724 | } | |
725 | } | |
726 | ||
727 | dev_err(&handle->pdev->dev, "unknown command(%s)\n", name); | |
728 | return -EINVAL; | |
729 | } | |
730 | ||
c929bc2a JZ |
731 | static const struct hns3_dbg_func hns3_dbg_cmd_func[] = { |
732 | { | |
733 | .cmd = HNAE3_DBG_CMD_DEV_INFO, | |
734 | .dbg_dump = hns3_dbg_dev_info, | |
735 | }, | |
77e91848 HT |
736 | { |
737 | .cmd = HNAE3_DBG_CMD_TX_BD, | |
738 | .dbg_dump_bd = hns3_dbg_tx_bd_info, | |
739 | }, | |
740 | { | |
741 | .cmd = HNAE3_DBG_CMD_RX_BD, | |
742 | .dbg_dump_bd = hns3_dbg_rx_bd_info, | |
743 | }, | |
c929bc2a JZ |
744 | }; |
745 | ||
77e91848 | 746 | static int hns3_dbg_read_cmd(struct hns3_dbg_data *dbg_data, |
5e69ea7e YM |
747 | enum hnae3_dbg_cmd cmd, char *buf, int len) |
748 | { | |
77e91848 HT |
749 | const struct hnae3_ae_ops *ops = dbg_data->handle->ae_algo->ops; |
750 | const struct hns3_dbg_func *cmd_func; | |
c929bc2a JZ |
751 | u32 i; |
752 | ||
753 | for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd_func); i++) { | |
77e91848 HT |
754 | if (cmd == hns3_dbg_cmd_func[i].cmd) { |
755 | cmd_func = &hns3_dbg_cmd_func[i]; | |
756 | if (cmd_func->dbg_dump) | |
757 | return cmd_func->dbg_dump(dbg_data->handle, buf, | |
758 | len); | |
759 | else | |
760 | return cmd_func->dbg_dump_bd(dbg_data, buf, | |
761 | len); | |
762 | } | |
c929bc2a | 763 | } |
5e69ea7e YM |
764 | |
765 | if (!ops->dbg_read_cmd) | |
766 | return -EOPNOTSUPP; | |
767 | ||
77e91848 | 768 | return ops->dbg_read_cmd(dbg_data->handle, cmd, buf, len); |
5e69ea7e YM |
769 | } |
770 | ||
04987ca1 GH |
771 | static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer, |
772 | size_t count, loff_t *ppos) | |
773 | { | |
77e91848 HT |
774 | struct hns3_dbg_data *dbg_data = filp->private_data; |
775 | struct hnae3_handle *handle = dbg_data->handle; | |
04987ca1 | 776 | struct hns3_nic_priv *priv = handle->priv; |
04987ca1 | 777 | ssize_t size = 0; |
5e69ea7e YM |
778 | char **save_buf; |
779 | char *read_buf; | |
780 | u32 index; | |
781 | int ret; | |
04987ca1 | 782 | |
5e69ea7e YM |
783 | ret = hns3_dbg_get_cmd_index(handle, filp->f_path.dentry->d_iname, |
784 | &index); | |
785 | if (ret) | |
786 | return ret; | |
04987ca1 | 787 | |
5e69ea7e | 788 | save_buf = &hns3_dbg_cmd[index].buf; |
04987ca1 | 789 | |
5e69ea7e YM |
790 | if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) || |
791 | test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) { | |
792 | ret = -EBUSY; | |
04987ca1 GH |
793 | goto out; |
794 | } | |
795 | ||
5e69ea7e YM |
796 | if (*save_buf) { |
797 | read_buf = *save_buf; | |
798 | } else { | |
799 | read_buf = kvzalloc(hns3_dbg_cmd[index].buf_len, GFP_KERNEL); | |
800 | if (!read_buf) | |
801 | return -ENOMEM; | |
802 | ||
803 | /* save the buffer addr until the last read operation */ | |
804 | *save_buf = read_buf; | |
805 | } | |
806 | ||
807 | /* get data ready for the first time to read */ | |
808 | if (!*ppos) { | |
77e91848 | 809 | ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd, |
5e69ea7e YM |
810 | read_buf, hns3_dbg_cmd[index].buf_len); |
811 | if (ret) | |
812 | goto out; | |
813 | } | |
814 | ||
04987ca1 GH |
815 | size = simple_read_from_buffer(buffer, count, ppos, read_buf, |
816 | strlen(read_buf)); | |
5e69ea7e YM |
817 | if (size > 0) |
818 | return size; | |
04987ca1 GH |
819 | |
820 | out: | |
5e69ea7e YM |
821 | /* free the buffer for the last read operation */ |
822 | if (*save_buf) { | |
823 | kvfree(*save_buf); | |
824 | *save_buf = NULL; | |
825 | } | |
826 | ||
827 | return ret; | |
04987ca1 GH |
828 | } |
829 | ||
b2292360 | 830 | static const struct file_operations hns3_dbg_cmd_fops = { |
831 | .owner = THIS_MODULE, | |
832 | .open = simple_open, | |
833 | .read = hns3_dbg_cmd_read, | |
834 | .write = hns3_dbg_cmd_write, | |
835 | }; | |
836 | ||
04987ca1 GH |
837 | static const struct file_operations hns3_dbg_fops = { |
838 | .owner = THIS_MODULE, | |
839 | .open = simple_open, | |
840 | .read = hns3_dbg_read, | |
841 | }; | |
842 | ||
77e91848 HT |
843 | static int hns3_dbg_bd_file_init(struct hnae3_handle *handle, u32 cmd) |
844 | { | |
845 | struct dentry *entry_dir; | |
846 | struct hns3_dbg_data *data; | |
847 | u16 max_queue_num; | |
848 | unsigned int i; | |
849 | ||
850 | entry_dir = hns3_dbg_dentry[hns3_dbg_cmd[cmd].dentry].dentry; | |
851 | max_queue_num = hns3_get_max_available_channels(handle); | |
852 | data = devm_kzalloc(&handle->pdev->dev, max_queue_num * sizeof(*data), | |
853 | GFP_KERNEL); | |
854 | if (!data) | |
855 | return -ENOMEM; | |
856 | ||
857 | for (i = 0; i < max_queue_num; i++) { | |
858 | char name[HNS3_DBG_FILE_NAME_LEN]; | |
859 | ||
860 | data[i].handle = handle; | |
861 | data[i].qid = i; | |
862 | sprintf(name, "%s%u", hns3_dbg_cmd[cmd].name, i); | |
863 | debugfs_create_file(name, 0400, entry_dir, &data[i], | |
864 | &hns3_dbg_fops); | |
865 | } | |
866 | ||
867 | return 0; | |
868 | } | |
869 | ||
5e69ea7e YM |
870 | static int |
871 | hns3_dbg_common_file_init(struct hnae3_handle *handle, u32 cmd) | |
872 | { | |
77e91848 | 873 | struct hns3_dbg_data *data; |
5e69ea7e YM |
874 | struct dentry *entry_dir; |
875 | ||
77e91848 HT |
876 | data = devm_kzalloc(&handle->pdev->dev, sizeof(*data), GFP_KERNEL); |
877 | if (!data) | |
878 | return -ENOMEM; | |
879 | ||
880 | data->handle = handle; | |
5e69ea7e YM |
881 | entry_dir = hns3_dbg_dentry[hns3_dbg_cmd[cmd].dentry].dentry; |
882 | debugfs_create_file(hns3_dbg_cmd[cmd].name, 0400, entry_dir, | |
77e91848 | 883 | data, &hns3_dbg_fops); |
5e69ea7e YM |
884 | |
885 | return 0; | |
886 | } | |
887 | ||
888 | int hns3_dbg_init(struct hnae3_handle *handle) | |
b2292360 | 889 | { |
04987ca1 | 890 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev); |
b2292360 | 891 | const char *name = pci_name(handle->pdev); |
5e69ea7e YM |
892 | int ret; |
893 | u32 i; | |
b2292360 | 894 | |
5e69ea7e YM |
895 | hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry = |
896 | debugfs_create_dir(name, hns3_dbgfs_root); | |
897 | handle->hnae3_dbgfs = hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry; | |
b2292360 | 898 | |
11ab11e6 GKH |
899 | debugfs_create_file("cmd", 0600, handle->hnae3_dbgfs, handle, |
900 | &hns3_dbg_cmd_fops); | |
04987ca1 | 901 | |
5e69ea7e YM |
902 | for (i = 0; i < HNS3_DBG_DENTRY_COMMON; i++) |
903 | hns3_dbg_dentry[i].dentry = | |
904 | debugfs_create_dir(hns3_dbg_dentry[i].name, | |
905 | handle->hnae3_dbgfs); | |
906 | ||
907 | for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) { | |
908 | if (hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES && | |
909 | ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) | |
910 | continue; | |
911 | ||
912 | if (!hns3_dbg_cmd[i].init) { | |
913 | dev_err(&handle->pdev->dev, | |
914 | "cmd %s lack of init func\n", | |
915 | hns3_dbg_cmd[i].name); | |
916 | ret = -EINVAL; | |
917 | goto out; | |
918 | } | |
919 | ||
920 | ret = hns3_dbg_cmd[i].init(handle, i); | |
921 | if (ret) { | |
922 | dev_err(&handle->pdev->dev, "failed to init cmd %s\n", | |
923 | hns3_dbg_cmd[i].name); | |
924 | goto out; | |
925 | } | |
926 | } | |
927 | ||
928 | return 0; | |
929 | ||
930 | out: | |
931 | debugfs_remove_recursive(handle->hnae3_dbgfs); | |
932 | handle->hnae3_dbgfs = NULL; | |
933 | return ret; | |
b2292360 | 934 | } |
935 | ||
936 | void hns3_dbg_uninit(struct hnae3_handle *handle) | |
937 | { | |
5e69ea7e YM |
938 | u32 i; |
939 | ||
940 | for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) | |
941 | if (hns3_dbg_cmd[i].buf) { | |
942 | kvfree(hns3_dbg_cmd[i].buf); | |
943 | hns3_dbg_cmd[i].buf = NULL; | |
944 | } | |
945 | ||
b2292360 | 946 | debugfs_remove_recursive(handle->hnae3_dbgfs); |
947 | handle->hnae3_dbgfs = NULL; | |
948 | } | |
949 | ||
950 | void hns3_dbg_register_debugfs(const char *debugfs_dir_name) | |
951 | { | |
952 | hns3_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL); | |
b2292360 | 953 | } |
954 | ||
955 | void hns3_dbg_unregister_debugfs(void) | |
956 | { | |
957 | debugfs_remove_recursive(hns3_dbgfs_root); | |
958 | hns3_dbgfs_root = NULL; | |
959 | } |