1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // Copyright (c) 2016-2017 Hisilicon Limited. |
3 | |
4 | #include <linux/etherdevice.h> |
5 | #include <linux/string.h> |
6 | #include <linux/phy.h> |
7 | #include <linux/sfp.h> |
8 | |
9 | #include "hns3_enet.h" |
10 | #include "hns3_ethtool.h" |
11 | |
12 | /* tqp related stats */ |
13 | #define HNS3_TQP_STAT(_string, _member) { \ |
14 | .stats_string = _string, \ |
15 | .stats_offset = offsetof(struct hns3_enet_ring, stats) +\ |
16 | offsetof(struct ring_stats, _member), \ |
17 | } |
18 | |
19 | static const struct hns3_stats hns3_txq_stats[] = { |
20 | /* Tx per-queue statistics */ |
21 | HNS3_TQP_STAT("dropped" , sw_err_cnt), |
22 | HNS3_TQP_STAT("seg_pkt_cnt" , seg_pkt_cnt), |
23 | HNS3_TQP_STAT("packets" , tx_pkts), |
24 | HNS3_TQP_STAT("bytes" , tx_bytes), |
25 | HNS3_TQP_STAT("more" , tx_more), |
26 | HNS3_TQP_STAT("push" , tx_push), |
27 | HNS3_TQP_STAT("mem_doorbell" , tx_mem_doorbell), |
28 | HNS3_TQP_STAT("wake" , restart_queue), |
29 | HNS3_TQP_STAT("busy" , tx_busy), |
30 | HNS3_TQP_STAT("copy" , tx_copy), |
31 | HNS3_TQP_STAT("vlan_err" , tx_vlan_err), |
32 | HNS3_TQP_STAT("l4_proto_err" , tx_l4_proto_err), |
33 | HNS3_TQP_STAT("l2l3l4_err" , tx_l2l3l4_err), |
34 | HNS3_TQP_STAT("tso_err" , tx_tso_err), |
35 | HNS3_TQP_STAT("over_max_recursion" , over_max_recursion), |
36 | HNS3_TQP_STAT("hw_limitation" , hw_limitation), |
37 | HNS3_TQP_STAT("bounce" , tx_bounce), |
38 | HNS3_TQP_STAT("spare_full" , tx_spare_full), |
39 | HNS3_TQP_STAT("copy_bits_err" , copy_bits_err), |
40 | HNS3_TQP_STAT("sgl" , tx_sgl), |
41 | HNS3_TQP_STAT("skb2sgl_err" , skb2sgl_err), |
42 | HNS3_TQP_STAT("map_sg_err" , map_sg_err), |
43 | }; |
44 | |
45 | #define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats) |
46 | |
47 | static const struct hns3_stats hns3_rxq_stats[] = { |
48 | /* Rx per-queue statistics */ |
49 | HNS3_TQP_STAT("dropped" , sw_err_cnt), |
50 | HNS3_TQP_STAT("seg_pkt_cnt" , seg_pkt_cnt), |
51 | HNS3_TQP_STAT("packets" , rx_pkts), |
52 | HNS3_TQP_STAT("bytes" , rx_bytes), |
53 | HNS3_TQP_STAT("errors" , rx_err_cnt), |
54 | HNS3_TQP_STAT("reuse_pg_cnt" , reuse_pg_cnt), |
55 | HNS3_TQP_STAT("err_pkt_len" , err_pkt_len), |
56 | HNS3_TQP_STAT("err_bd_num" , err_bd_num), |
57 | HNS3_TQP_STAT("l2_err" , l2_err), |
58 | HNS3_TQP_STAT("l3l4_csum_err" , l3l4_csum_err), |
59 | HNS3_TQP_STAT("csum_complete" , csum_complete), |
60 | HNS3_TQP_STAT("multicast" , rx_multicast), |
61 | HNS3_TQP_STAT("non_reuse_pg" , non_reuse_pg), |
62 | HNS3_TQP_STAT("frag_alloc_err" , frag_alloc_err), |
63 | HNS3_TQP_STAT("frag_alloc" , frag_alloc), |
64 | }; |
65 | |
66 | #define HNS3_PRIV_FLAGS_LEN ARRAY_SIZE(hns3_priv_flags) |
67 | |
68 | #define HNS3_RXQ_STATS_COUNT ARRAY_SIZE(hns3_rxq_stats) |
69 | |
70 | #define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT) |
71 | |
72 | #define HNS3_NIC_LB_TEST_PKT_NUM 1 |
73 | #define HNS3_NIC_LB_TEST_RING_ID 0 |
74 | #define HNS3_NIC_LB_TEST_PACKET_SIZE 128 |
75 | #define HNS3_NIC_LB_SETUP_USEC 10000 |
76 | |
77 | /* Nic loopback test err */ |
78 | #define HNS3_NIC_LB_TEST_NO_MEM_ERR 1 |
79 | #define HNS3_NIC_LB_TEST_TX_CNT_ERR 2 |
80 | #define HNS3_NIC_LB_TEST_RX_CNT_ERR 3 |
81 | #define HNS3_NIC_LB_TEST_UNEXECUTED 4 |
82 | |
83 | static int hns3_get_sset_count(struct net_device *netdev, int stringset); |
84 | |
85 | static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) |
86 | { |
87 | struct hnae3_handle *h = hns3_get_handle(ndev); |
88 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
89 | int ret; |
90 | |
91 | if (!h->ae_algo->ops->set_loopback || |
92 | !h->ae_algo->ops->set_promisc_mode) |
93 | return -EOPNOTSUPP; |
94 | |
95 | switch (loop) { |
96 | case HNAE3_LOOP_SERIAL_SERDES: |
97 | case HNAE3_LOOP_PARALLEL_SERDES: |
98 | case HNAE3_LOOP_APP: |
99 | case HNAE3_LOOP_PHY: |
100 | case HNAE3_LOOP_EXTERNAL: |
101 | ret = h->ae_algo->ops->set_loopback(h, loop, en); |
102 | break; |
103 | default: |
104 | ret = -ENOTSUPP; |
105 | break; |
106 | } |
107 | |
108 | if (ret || ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) |
109 | return ret; |
110 | |
111 | if (en) |
112 | h->ae_algo->ops->set_promisc_mode(h, true, true); |
113 | else |
114 | /* recover promisc mode before loopback test */ |
115 | hns3_request_update_promisc_mode(handle: h); |
116 | |
117 | return ret; |
118 | } |
119 | |
120 | static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode) |
121 | { |
122 | struct hnae3_handle *h = hns3_get_handle(ndev); |
123 | int ret; |
124 | |
125 | ret = hns3_nic_reset_all_ring(h); |
126 | if (ret) |
127 | return ret; |
128 | |
129 | ret = hns3_lp_setup(ndev, loop: loop_mode, en: true); |
130 | usleep_range(HNS3_NIC_LB_SETUP_USEC, HNS3_NIC_LB_SETUP_USEC * 2); |
131 | |
132 | return ret; |
133 | } |
134 | |
135 | static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode) |
136 | { |
137 | int ret; |
138 | |
139 | ret = hns3_lp_setup(ndev, loop: loop_mode, en: false); |
140 | if (ret) { |
141 | netdev_err(dev: ndev, format: "lb_setup return error: %d\n" , ret); |
142 | return ret; |
143 | } |
144 | |
145 | usleep_range(HNS3_NIC_LB_SETUP_USEC, HNS3_NIC_LB_SETUP_USEC * 2); |
146 | |
147 | return 0; |
148 | } |
149 | |
150 | static void hns3_lp_setup_skb(struct sk_buff *skb) |
151 | { |
152 | #define HNS3_NIC_LB_DST_MAC_ADDR 0x1f |
153 | |
154 | struct net_device *ndev = skb->dev; |
155 | struct hnae3_handle *handle; |
156 | struct hnae3_ae_dev *ae_dev; |
157 | unsigned char *packet; |
158 | struct ethhdr *ethh; |
159 | unsigned int i; |
160 | |
161 | skb_reserve(skb, NET_IP_ALIGN); |
162 | ethh = skb_put(skb, len: sizeof(struct ethhdr)); |
163 | packet = skb_put(skb, HNS3_NIC_LB_TEST_PACKET_SIZE); |
164 | |
165 | memcpy(ethh->h_dest, ndev->dev_addr, ETH_ALEN); |
166 | |
167 | /* The dst mac addr of loopback packet is the same as the host' |
168 | * mac addr, the SSU component may loop back the packet to host |
169 | * before the packet reaches mac or serdes, which will defect |
170 | * the purpose of mac or serdes selftest. |
171 | */ |
172 | handle = hns3_get_handle(ndev); |
173 | ae_dev = pci_get_drvdata(pdev: handle->pdev); |
174 | if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) |
175 | ethh->h_dest[5] += HNS3_NIC_LB_DST_MAC_ADDR; |
176 | eth_zero_addr(addr: ethh->h_source); |
177 | ethh->h_proto = htons(ETH_P_ARP); |
178 | skb_reset_mac_header(skb); |
179 | |
180 | for (i = 0; i < HNS3_NIC_LB_TEST_PACKET_SIZE; i++) |
181 | packet[i] = (unsigned char)(i & 0xff); |
182 | } |
183 | |
184 | static void hns3_lb_check_skb_data(struct hns3_enet_ring *ring, |
185 | struct sk_buff *skb) |
186 | { |
187 | struct hns3_enet_tqp_vector *tqp_vector = ring->tqp_vector; |
188 | unsigned char *packet = skb->data; |
189 | u32 len = skb_headlen(skb); |
190 | u32 i; |
191 | |
192 | len = min_t(u32, len, HNS3_NIC_LB_TEST_PACKET_SIZE); |
193 | |
194 | for (i = 0; i < len; i++) |
195 | if (packet[i] != (unsigned char)(i & 0xff)) |
196 | break; |
197 | |
198 | /* The packet is correctly received */ |
199 | if (i == HNS3_NIC_LB_TEST_PACKET_SIZE) |
200 | tqp_vector->rx_group.total_packets++; |
201 | else |
202 | print_hex_dump(KERN_ERR, prefix_str: "selftest:" , prefix_type: DUMP_PREFIX_OFFSET, rowsize: 16, groupsize: 1, |
203 | buf: skb->data, len, ascii: true); |
204 | |
205 | dev_kfree_skb_any(skb); |
206 | } |
207 | |
208 | static u32 hns3_lb_check_rx_ring(struct hns3_nic_priv *priv, u32 budget) |
209 | { |
210 | struct hnae3_handle *h = priv->ae_handle; |
211 | struct hnae3_knic_private_info *kinfo; |
212 | u32 i, rcv_good_pkt_total = 0; |
213 | |
214 | kinfo = &h->kinfo; |
215 | for (i = kinfo->num_tqps; i < kinfo->num_tqps * 2; i++) { |
216 | struct hns3_enet_ring *ring = &priv->ring[i]; |
217 | struct hns3_enet_ring_group *rx_group; |
218 | u64 pre_rx_pkt; |
219 | |
220 | rx_group = &ring->tqp_vector->rx_group; |
221 | pre_rx_pkt = rx_group->total_packets; |
222 | |
223 | preempt_disable(); |
224 | hns3_clean_rx_ring(ring, budget, rx_fn: hns3_lb_check_skb_data); |
225 | preempt_enable(); |
226 | |
227 | rcv_good_pkt_total += (rx_group->total_packets - pre_rx_pkt); |
228 | rx_group->total_packets = pre_rx_pkt; |
229 | } |
230 | return rcv_good_pkt_total; |
231 | } |
232 | |
233 | static void hns3_lb_clear_tx_ring(struct hns3_nic_priv *priv, u32 start_ringid, |
234 | u32 end_ringid) |
235 | { |
236 | u32 i; |
237 | |
238 | for (i = start_ringid; i <= end_ringid; i++) { |
239 | struct hns3_enet_ring *ring = &priv->ring[i]; |
240 | |
241 | hns3_clean_tx_ring(ring, budget: 0); |
242 | } |
243 | } |
244 | |
245 | /** |
246 | * hns3_lp_run_test - run loopback test |
247 | * @ndev: net device |
248 | * @mode: loopback type |
249 | * |
250 | * Return: %0 for success or a NIC loopback test error code on failure |
251 | */ |
252 | static int hns3_lp_run_test(struct net_device *ndev, enum hnae3_loop mode) |
253 | { |
254 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
255 | struct sk_buff *skb; |
256 | u32 i, good_cnt; |
257 | int ret_val = 0; |
258 | |
259 | skb = alloc_skb(HNS3_NIC_LB_TEST_PACKET_SIZE + ETH_HLEN + NET_IP_ALIGN, |
260 | GFP_KERNEL); |
261 | if (!skb) |
262 | return HNS3_NIC_LB_TEST_NO_MEM_ERR; |
263 | |
264 | skb->dev = ndev; |
265 | hns3_lp_setup_skb(skb); |
266 | skb->queue_mapping = HNS3_NIC_LB_TEST_RING_ID; |
267 | |
268 | good_cnt = 0; |
269 | for (i = 0; i < HNS3_NIC_LB_TEST_PKT_NUM; i++) { |
270 | netdev_tx_t tx_ret; |
271 | |
272 | skb_get(skb); |
273 | tx_ret = hns3_nic_net_xmit(skb, netdev: ndev); |
274 | if (tx_ret == NETDEV_TX_OK) { |
275 | good_cnt++; |
276 | } else { |
277 | kfree_skb(skb); |
278 | netdev_err(dev: ndev, format: "hns3_lb_run_test xmit failed: %d\n" , |
279 | tx_ret); |
280 | } |
281 | } |
282 | if (good_cnt != HNS3_NIC_LB_TEST_PKT_NUM) { |
283 | ret_val = HNS3_NIC_LB_TEST_TX_CNT_ERR; |
284 | netdev_err(dev: ndev, format: "mode %d sent fail, cnt=0x%x, budget=0x%x\n" , |
285 | mode, good_cnt, HNS3_NIC_LB_TEST_PKT_NUM); |
286 | goto out; |
287 | } |
288 | |
289 | /* Allow 200 milliseconds for packets to go from Tx to Rx */ |
290 | msleep(msecs: 200); |
291 | |
292 | good_cnt = hns3_lb_check_rx_ring(priv, HNS3_NIC_LB_TEST_PKT_NUM); |
293 | if (good_cnt != HNS3_NIC_LB_TEST_PKT_NUM) { |
294 | ret_val = HNS3_NIC_LB_TEST_RX_CNT_ERR; |
295 | netdev_err(dev: ndev, format: "mode %d recv fail, cnt=0x%x, budget=0x%x\n" , |
296 | mode, good_cnt, HNS3_NIC_LB_TEST_PKT_NUM); |
297 | } |
298 | |
299 | out: |
300 | hns3_lb_clear_tx_ring(priv, HNS3_NIC_LB_TEST_RING_ID, |
301 | HNS3_NIC_LB_TEST_RING_ID); |
302 | |
303 | kfree_skb(skb); |
304 | return ret_val; |
305 | } |
306 | |
307 | static void hns3_set_selftest_param(struct hnae3_handle *h, int (*st_param)[2]) |
308 | { |
309 | st_param[HNAE3_LOOP_EXTERNAL][0] = HNAE3_LOOP_EXTERNAL; |
310 | st_param[HNAE3_LOOP_EXTERNAL][1] = |
311 | h->flags & HNAE3_SUPPORT_EXTERNAL_LOOPBACK; |
312 | |
313 | st_param[HNAE3_LOOP_APP][0] = HNAE3_LOOP_APP; |
314 | st_param[HNAE3_LOOP_APP][1] = |
315 | h->flags & HNAE3_SUPPORT_APP_LOOPBACK; |
316 | |
317 | st_param[HNAE3_LOOP_SERIAL_SERDES][0] = HNAE3_LOOP_SERIAL_SERDES; |
318 | st_param[HNAE3_LOOP_SERIAL_SERDES][1] = |
319 | h->flags & HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK; |
320 | |
321 | st_param[HNAE3_LOOP_PARALLEL_SERDES][0] = |
322 | HNAE3_LOOP_PARALLEL_SERDES; |
323 | st_param[HNAE3_LOOP_PARALLEL_SERDES][1] = |
324 | h->flags & HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK; |
325 | |
326 | st_param[HNAE3_LOOP_PHY][0] = HNAE3_LOOP_PHY; |
327 | st_param[HNAE3_LOOP_PHY][1] = |
328 | h->flags & HNAE3_SUPPORT_PHY_LOOPBACK; |
329 | } |
330 | |
331 | static void hns3_selftest_prepare(struct net_device *ndev, bool if_running) |
332 | { |
333 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
334 | struct hnae3_handle *h = priv->ae_handle; |
335 | |
336 | if (if_running) |
337 | ndev->netdev_ops->ndo_stop(ndev); |
338 | |
339 | #if IS_ENABLED(CONFIG_VLAN_8021Q) |
340 | /* Disable the vlan filter for selftest does not support it */ |
341 | if (h->ae_algo->ops->enable_vlan_filter && |
342 | ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) |
343 | h->ae_algo->ops->enable_vlan_filter(h, false); |
344 | #endif |
345 | |
346 | /* Tell firmware to stop mac autoneg before loopback test start, |
347 | * otherwise loopback test may be failed when the port is still |
348 | * negotiating. |
349 | */ |
350 | if (h->ae_algo->ops->halt_autoneg) |
351 | h->ae_algo->ops->halt_autoneg(h, true); |
352 | |
353 | set_bit(nr: HNS3_NIC_STATE_TESTING, addr: &priv->state); |
354 | } |
355 | |
356 | static void hns3_selftest_restore(struct net_device *ndev, bool if_running) |
357 | { |
358 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
359 | struct hnae3_handle *h = priv->ae_handle; |
360 | |
361 | clear_bit(nr: HNS3_NIC_STATE_TESTING, addr: &priv->state); |
362 | |
363 | if (h->ae_algo->ops->halt_autoneg) |
364 | h->ae_algo->ops->halt_autoneg(h, false); |
365 | |
366 | #if IS_ENABLED(CONFIG_VLAN_8021Q) |
367 | if (h->ae_algo->ops->enable_vlan_filter && |
368 | ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) |
369 | h->ae_algo->ops->enable_vlan_filter(h, true); |
370 | #endif |
371 | |
372 | if (if_running) |
373 | ndev->netdev_ops->ndo_open(ndev); |
374 | } |
375 | |
376 | static void hns3_do_selftest(struct net_device *ndev, int (*st_param)[2], |
377 | struct ethtool_test *eth_test, u64 *data) |
378 | { |
379 | int test_index = HNAE3_LOOP_APP; |
380 | u32 i; |
381 | |
382 | for (i = HNAE3_LOOP_APP; i < HNAE3_LOOP_NONE; i++) { |
383 | enum hnae3_loop loop_type = (enum hnae3_loop)st_param[i][0]; |
384 | |
385 | if (!st_param[i][1]) |
386 | continue; |
387 | |
388 | data[test_index] = hns3_lp_up(ndev, loop_mode: loop_type); |
389 | if (!data[test_index]) |
390 | data[test_index] = hns3_lp_run_test(ndev, mode: loop_type); |
391 | |
392 | hns3_lp_down(ndev, loop_mode: loop_type); |
393 | |
394 | if (data[test_index]) |
395 | eth_test->flags |= ETH_TEST_FL_FAILED; |
396 | |
397 | test_index++; |
398 | } |
399 | } |
400 | |
401 | static void hns3_do_external_lb(struct net_device *ndev, |
402 | struct ethtool_test *eth_test, u64 *data) |
403 | { |
404 | data[HNAE3_LOOP_EXTERNAL] = hns3_lp_up(ndev, loop_mode: HNAE3_LOOP_EXTERNAL); |
405 | if (!data[HNAE3_LOOP_EXTERNAL]) |
406 | data[HNAE3_LOOP_EXTERNAL] = hns3_lp_run_test(ndev, mode: HNAE3_LOOP_EXTERNAL); |
407 | hns3_lp_down(ndev, loop_mode: HNAE3_LOOP_EXTERNAL); |
408 | |
409 | if (data[HNAE3_LOOP_EXTERNAL]) |
410 | eth_test->flags |= ETH_TEST_FL_FAILED; |
411 | |
412 | eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; |
413 | } |
414 | |
415 | /** |
416 | * hns3_self_test - self test |
417 | * @ndev: net device |
418 | * @eth_test: test cmd |
419 | * @data: test result |
420 | */ |
421 | static void hns3_self_test(struct net_device *ndev, |
422 | struct ethtool_test *eth_test, u64 *data) |
423 | { |
424 | int cnt = hns3_get_sset_count(netdev: ndev, stringset: ETH_SS_TEST); |
425 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
426 | struct hnae3_handle *h = priv->ae_handle; |
427 | int st_param[HNAE3_LOOP_NONE][2]; |
428 | bool if_running = netif_running(dev: ndev); |
429 | int i; |
430 | |
431 | /* initialize the loopback test result, avoid marking an unexcuted |
432 | * loopback test as PASS. |
433 | */ |
434 | for (i = 0; i < cnt; i++) |
435 | data[i] = HNS3_NIC_LB_TEST_UNEXECUTED; |
436 | |
437 | if (hns3_nic_resetting(netdev: ndev)) { |
438 | netdev_err(dev: ndev, format: "dev resetting!" ); |
439 | goto failure; |
440 | } |
441 | |
442 | if (!(eth_test->flags & ETH_TEST_FL_OFFLINE)) |
443 | goto failure; |
444 | |
445 | if (netif_msg_ifdown(h)) |
446 | netdev_info(dev: ndev, format: "self test start\n" ); |
447 | |
448 | hns3_set_selftest_param(h, st_param); |
449 | |
450 | /* external loopback test requires that the link is up and the duplex is |
451 | * full, do external test first to reduce the whole test time |
452 | */ |
453 | if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) { |
454 | hns3_external_lb_prepare(ndev, if_running); |
455 | hns3_do_external_lb(ndev, eth_test, data); |
456 | hns3_external_lb_restore(ndev, if_running); |
457 | } |
458 | |
459 | hns3_selftest_prepare(ndev, if_running); |
460 | hns3_do_selftest(ndev, st_param, eth_test, data); |
461 | hns3_selftest_restore(ndev, if_running); |
462 | |
463 | if (netif_msg_ifdown(h)) |
464 | netdev_info(dev: ndev, format: "self test end\n" ); |
465 | return; |
466 | |
467 | failure: |
468 | eth_test->flags |= ETH_TEST_FL_FAILED; |
469 | } |
470 | |
471 | static void hns3_update_limit_promisc_mode(struct net_device *netdev, |
472 | bool enable) |
473 | { |
474 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
475 | |
476 | if (enable) |
477 | set_bit(nr: HNAE3_PFLAG_LIMIT_PROMISC, addr: &handle->priv_flags); |
478 | else |
479 | clear_bit(nr: HNAE3_PFLAG_LIMIT_PROMISC, addr: &handle->priv_flags); |
480 | |
481 | hns3_request_update_promisc_mode(handle); |
482 | } |
483 | |
484 | static const struct hns3_pflag_desc hns3_priv_flags[HNAE3_PFLAG_MAX] = { |
485 | { "limit_promisc" , hns3_update_limit_promisc_mode } |
486 | }; |
487 | |
488 | static int hns3_get_sset_count(struct net_device *netdev, int stringset) |
489 | { |
490 | struct hnae3_handle *h = hns3_get_handle(netdev); |
491 | const struct hnae3_ae_ops *ops = h->ae_algo->ops; |
492 | |
493 | if (!ops->get_sset_count) |
494 | return -EOPNOTSUPP; |
495 | |
496 | switch (stringset) { |
497 | case ETH_SS_STATS: |
498 | return ((HNS3_TQP_STATS_COUNT * h->kinfo.num_tqps) + |
499 | ops->get_sset_count(h, stringset)); |
500 | |
501 | case ETH_SS_TEST: |
502 | return ops->get_sset_count(h, stringset); |
503 | |
504 | case ETH_SS_PRIV_FLAGS: |
505 | return HNAE3_PFLAG_MAX; |
506 | |
507 | default: |
508 | return -EOPNOTSUPP; |
509 | } |
510 | } |
511 | |
512 | static void *hns3_update_strings(u8 *data, const struct hns3_stats *stats, |
513 | u32 stat_count, u32 num_tqps, const char *prefix) |
514 | { |
515 | #define MAX_PREFIX_SIZE (6 + 4) |
516 | u32 size_left; |
517 | u32 i, j; |
518 | u32 n1; |
519 | |
520 | for (i = 0; i < num_tqps; i++) { |
521 | for (j = 0; j < stat_count; j++) { |
522 | data[ETH_GSTRING_LEN - 1] = '\0'; |
523 | |
524 | /* first, prepend the prefix string */ |
525 | n1 = scnprintf(buf: data, MAX_PREFIX_SIZE, fmt: "%s%u_" , |
526 | prefix, i); |
527 | size_left = (ETH_GSTRING_LEN - 1) - n1; |
528 | |
529 | /* now, concatenate the stats string to it */ |
530 | strncat(p: data, q: stats[j].stats_string, count: size_left); |
531 | data += ETH_GSTRING_LEN; |
532 | } |
533 | } |
534 | |
535 | return data; |
536 | } |
537 | |
538 | static u8 *hns3_get_strings_tqps(struct hnae3_handle *handle, u8 *data) |
539 | { |
540 | struct hnae3_knic_private_info *kinfo = &handle->kinfo; |
541 | const char tx_prefix[] = "txq" ; |
542 | const char rx_prefix[] = "rxq" ; |
543 | |
544 | /* get strings for Tx */ |
545 | data = hns3_update_strings(data, stats: hns3_txq_stats, HNS3_TXQ_STATS_COUNT, |
546 | num_tqps: kinfo->num_tqps, prefix: tx_prefix); |
547 | |
548 | /* get strings for Rx */ |
549 | data = hns3_update_strings(data, stats: hns3_rxq_stats, HNS3_RXQ_STATS_COUNT, |
550 | num_tqps: kinfo->num_tqps, prefix: rx_prefix); |
551 | |
552 | return data; |
553 | } |
554 | |
555 | static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data) |
556 | { |
557 | struct hnae3_handle *h = hns3_get_handle(netdev); |
558 | const struct hnae3_ae_ops *ops = h->ae_algo->ops; |
559 | char *buff = (char *)data; |
560 | int i; |
561 | |
562 | if (!ops->get_strings) |
563 | return; |
564 | |
565 | switch (stringset) { |
566 | case ETH_SS_STATS: |
567 | buff = hns3_get_strings_tqps(handle: h, data: buff); |
568 | ops->get_strings(h, stringset, (u8 *)buff); |
569 | break; |
570 | case ETH_SS_TEST: |
571 | ops->get_strings(h, stringset, data); |
572 | break; |
573 | case ETH_SS_PRIV_FLAGS: |
574 | for (i = 0; i < HNS3_PRIV_FLAGS_LEN; i++) { |
575 | snprintf(buf: buff, ETH_GSTRING_LEN, fmt: "%s" , |
576 | hns3_priv_flags[i].name); |
577 | buff += ETH_GSTRING_LEN; |
578 | } |
579 | break; |
580 | default: |
581 | break; |
582 | } |
583 | } |
584 | |
585 | static u64 *hns3_get_stats_tqps(struct hnae3_handle *handle, u64 *data) |
586 | { |
587 | struct hnae3_knic_private_info *kinfo = &handle->kinfo; |
588 | struct hns3_nic_priv *nic_priv = handle->priv; |
589 | struct hns3_enet_ring *ring; |
590 | u8 *stat; |
591 | int i, j; |
592 | |
593 | /* get stats for Tx */ |
594 | for (i = 0; i < kinfo->num_tqps; i++) { |
595 | ring = &nic_priv->ring[i]; |
596 | for (j = 0; j < HNS3_TXQ_STATS_COUNT; j++) { |
597 | stat = (u8 *)ring + hns3_txq_stats[j].stats_offset; |
598 | *data++ = *(u64 *)stat; |
599 | } |
600 | } |
601 | |
602 | /* get stats for Rx */ |
603 | for (i = 0; i < kinfo->num_tqps; i++) { |
604 | ring = &nic_priv->ring[i + kinfo->num_tqps]; |
605 | for (j = 0; j < HNS3_RXQ_STATS_COUNT; j++) { |
606 | stat = (u8 *)ring + hns3_rxq_stats[j].stats_offset; |
607 | *data++ = *(u64 *)stat; |
608 | } |
609 | } |
610 | |
611 | return data; |
612 | } |
613 | |
614 | /* hns3_get_stats - get detail statistics. |
615 | * @netdev: net device |
616 | * @stats: statistics info. |
617 | * @data: statistics data. |
618 | */ |
619 | static void hns3_get_stats(struct net_device *netdev, |
620 | struct ethtool_stats *stats, u64 *data) |
621 | { |
622 | struct hnae3_handle *h = hns3_get_handle(netdev); |
623 | u64 *p = data; |
624 | |
625 | if (hns3_nic_resetting(netdev)) { |
626 | netdev_err(dev: netdev, format: "dev resetting, could not get stats\n" ); |
627 | return; |
628 | } |
629 | |
630 | if (!h->ae_algo->ops->get_stats || !h->ae_algo->ops->update_stats) { |
631 | netdev_err(dev: netdev, format: "could not get any statistics\n" ); |
632 | return; |
633 | } |
634 | |
635 | h->ae_algo->ops->update_stats(h); |
636 | |
637 | /* get per-queue stats */ |
638 | p = hns3_get_stats_tqps(handle: h, data: p); |
639 | |
640 | /* get MAC & other misc hardware stats */ |
641 | h->ae_algo->ops->get_stats(h, p); |
642 | } |
643 | |
644 | static void hns3_get_drvinfo(struct net_device *netdev, |
645 | struct ethtool_drvinfo *drvinfo) |
646 | { |
647 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
648 | struct hnae3_handle *h = priv->ae_handle; |
649 | u32 fw_version; |
650 | |
651 | if (!h->ae_algo->ops->get_fw_version) { |
652 | netdev_err(dev: netdev, format: "could not get fw version!\n" ); |
653 | return; |
654 | } |
655 | |
656 | strscpy(drvinfo->driver, dev_driver_string(&h->pdev->dev), |
657 | sizeof(drvinfo->driver)); |
658 | |
659 | strscpy(drvinfo->bus_info, pci_name(h->pdev), |
660 | sizeof(drvinfo->bus_info)); |
661 | |
662 | fw_version = priv->ae_handle->ae_algo->ops->get_fw_version(h); |
663 | |
664 | snprintf(buf: drvinfo->fw_version, size: sizeof(drvinfo->fw_version), |
665 | fmt: "%lu.%lu.%lu.%lu" , |
666 | hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE3_MASK, |
667 | HNAE3_FW_VERSION_BYTE3_SHIFT), |
668 | hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE2_MASK, |
669 | HNAE3_FW_VERSION_BYTE2_SHIFT), |
670 | hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE1_MASK, |
671 | HNAE3_FW_VERSION_BYTE1_SHIFT), |
672 | hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE0_MASK, |
673 | HNAE3_FW_VERSION_BYTE0_SHIFT)); |
674 | } |
675 | |
676 | static u32 hns3_get_link(struct net_device *netdev) |
677 | { |
678 | struct hnae3_handle *h = hns3_get_handle(netdev); |
679 | |
680 | if (h->ae_algo->ops->get_status) |
681 | return h->ae_algo->ops->get_status(h); |
682 | else |
683 | return 0; |
684 | } |
685 | |
686 | static void hns3_get_ringparam(struct net_device *netdev, |
687 | struct ethtool_ringparam *param, |
688 | struct kernel_ethtool_ringparam *kernel_param, |
689 | struct netlink_ext_ack *extack) |
690 | { |
691 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
692 | struct hnae3_handle *h = priv->ae_handle; |
693 | int rx_queue_index = h->kinfo.num_tqps; |
694 | |
695 | if (hns3_nic_resetting(netdev) || !priv->ring) { |
696 | netdev_err(dev: netdev, format: "failed to get ringparam value, due to dev resetting or uninited\n" ); |
697 | return; |
698 | } |
699 | |
700 | param->tx_max_pending = HNS3_RING_MAX_PENDING; |
701 | param->rx_max_pending = HNS3_RING_MAX_PENDING; |
702 | |
703 | param->tx_pending = priv->ring[0].desc_num; |
704 | param->rx_pending = priv->ring[rx_queue_index].desc_num; |
705 | kernel_param->rx_buf_len = priv->ring[rx_queue_index].buf_size; |
706 | kernel_param->tx_push = test_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, |
707 | &priv->state); |
708 | } |
709 | |
710 | static void hns3_get_pauseparam(struct net_device *netdev, |
711 | struct ethtool_pauseparam *param) |
712 | { |
713 | struct hnae3_handle *h = hns3_get_handle(netdev); |
714 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
715 | |
716 | if (!test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps)) |
717 | return; |
718 | |
719 | if (h->ae_algo->ops->get_pauseparam) |
720 | h->ae_algo->ops->get_pauseparam(h, ¶m->autoneg, |
721 | ¶m->rx_pause, ¶m->tx_pause); |
722 | } |
723 | |
724 | static int hns3_set_pauseparam(struct net_device *netdev, |
725 | struct ethtool_pauseparam *param) |
726 | { |
727 | struct hnae3_handle *h = hns3_get_handle(netdev); |
728 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
729 | |
730 | if (!test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps)) |
731 | return -EOPNOTSUPP; |
732 | |
733 | netif_dbg(h, drv, netdev, |
734 | "set pauseparam: autoneg=%u, rx:%u, tx:%u\n" , |
735 | param->autoneg, param->rx_pause, param->tx_pause); |
736 | |
737 | if (h->ae_algo->ops->set_pauseparam) |
738 | return h->ae_algo->ops->set_pauseparam(h, param->autoneg, |
739 | param->rx_pause, |
740 | param->tx_pause); |
741 | return -EOPNOTSUPP; |
742 | } |
743 | |
744 | static void hns3_get_ksettings(struct hnae3_handle *h, |
745 | struct ethtool_link_ksettings *cmd) |
746 | { |
747 | const struct hnae3_ae_ops *ops = h->ae_algo->ops; |
748 | |
749 | /* 1.auto_neg & speed & duplex from cmd */ |
750 | if (ops->get_ksettings_an_result) |
751 | ops->get_ksettings_an_result(h, |
752 | &cmd->base.autoneg, |
753 | &cmd->base.speed, |
754 | &cmd->base.duplex, |
755 | &cmd->lanes); |
756 | |
757 | /* 2.get link mode */ |
758 | if (ops->get_link_mode) |
759 | ops->get_link_mode(h, |
760 | cmd->link_modes.supported, |
761 | cmd->link_modes.advertising); |
762 | |
763 | /* 3.mdix_ctrl&mdix get from phy reg */ |
764 | if (ops->get_mdix_mode) |
765 | ops->get_mdix_mode(h, &cmd->base.eth_tp_mdix_ctrl, |
766 | &cmd->base.eth_tp_mdix); |
767 | } |
768 | |
769 | static int hns3_get_link_ksettings(struct net_device *netdev, |
770 | struct ethtool_link_ksettings *cmd) |
771 | { |
772 | struct hnae3_handle *h = hns3_get_handle(netdev); |
773 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
774 | const struct hnae3_ae_ops *ops; |
775 | u8 module_type; |
776 | u8 media_type; |
777 | u8 link_stat; |
778 | |
779 | ops = h->ae_algo->ops; |
780 | if (ops->get_media_type) |
781 | ops->get_media_type(h, &media_type, &module_type); |
782 | else |
783 | return -EOPNOTSUPP; |
784 | |
785 | switch (media_type) { |
786 | case HNAE3_MEDIA_TYPE_NONE: |
787 | cmd->base.port = PORT_NONE; |
788 | hns3_get_ksettings(h, cmd); |
789 | break; |
790 | case HNAE3_MEDIA_TYPE_FIBER: |
791 | if (module_type == HNAE3_MODULE_TYPE_UNKNOWN) |
792 | cmd->base.port = PORT_OTHER; |
793 | else if (module_type == HNAE3_MODULE_TYPE_CR) |
794 | cmd->base.port = PORT_DA; |
795 | else |
796 | cmd->base.port = PORT_FIBRE; |
797 | |
798 | hns3_get_ksettings(h, cmd); |
799 | break; |
800 | case HNAE3_MEDIA_TYPE_BACKPLANE: |
801 | cmd->base.port = PORT_NONE; |
802 | hns3_get_ksettings(h, cmd); |
803 | break; |
804 | case HNAE3_MEDIA_TYPE_COPPER: |
805 | cmd->base.port = PORT_TP; |
806 | if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) && |
807 | ops->get_phy_link_ksettings) |
808 | ops->get_phy_link_ksettings(h, cmd); |
809 | else if (!netdev->phydev) |
810 | hns3_get_ksettings(h, cmd); |
811 | else |
812 | phy_ethtool_ksettings_get(phydev: netdev->phydev, cmd); |
813 | break; |
814 | default: |
815 | |
816 | netdev_warn(dev: netdev, format: "Unknown media type" ); |
817 | return 0; |
818 | } |
819 | |
820 | /* mdio_support */ |
821 | cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22; |
822 | |
823 | link_stat = hns3_get_link(netdev); |
824 | if (!link_stat) { |
825 | cmd->base.speed = SPEED_UNKNOWN; |
826 | cmd->base.duplex = DUPLEX_UNKNOWN; |
827 | } |
828 | |
829 | return 0; |
830 | } |
831 | |
832 | static int hns3_check_ksettings_param(const struct net_device *netdev, |
833 | const struct ethtool_link_ksettings *cmd) |
834 | { |
835 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
836 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
837 | u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN; |
838 | u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN; |
839 | u32 lane_num; |
840 | u8 autoneg; |
841 | u32 speed; |
842 | u8 duplex; |
843 | int ret; |
844 | |
845 | /* hw doesn't support use specified speed and duplex to negotiate, |
846 | * unnecessary to check them when autoneg on. |
847 | */ |
848 | if (cmd->base.autoneg) |
849 | return 0; |
850 | |
851 | if (ops->get_ksettings_an_result) { |
852 | ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex, &lane_num); |
853 | if (cmd->base.autoneg == autoneg && cmd->base.speed == speed && |
854 | cmd->base.duplex == duplex && cmd->lanes == lane_num) |
855 | return 0; |
856 | } |
857 | |
858 | if (ops->get_media_type) |
859 | ops->get_media_type(handle, &media_type, &module_type); |
860 | |
861 | if (cmd->base.duplex == DUPLEX_HALF && |
862 | media_type != HNAE3_MEDIA_TYPE_COPPER) { |
863 | netdev_err(dev: netdev, |
864 | format: "only copper port supports half duplex!" ); |
865 | return -EINVAL; |
866 | } |
867 | |
868 | if (ops->check_port_speed) { |
869 | ret = ops->check_port_speed(handle, cmd->base.speed); |
870 | if (ret) { |
871 | netdev_err(dev: netdev, format: "unsupported speed\n" ); |
872 | return ret; |
873 | } |
874 | } |
875 | |
876 | return 0; |
877 | } |
878 | |
879 | static int hns3_set_link_ksettings(struct net_device *netdev, |
880 | const struct ethtool_link_ksettings *cmd) |
881 | { |
882 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
883 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
884 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
885 | int ret; |
886 | |
887 | /* Chip don't support this mode. */ |
888 | if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF) |
889 | return -EINVAL; |
890 | |
891 | if (cmd->lanes && !hnae3_ae_dev_lane_num_supported(ae_dev)) |
892 | return -EOPNOTSUPP; |
893 | |
894 | netif_dbg(handle, drv, netdev, |
895 | "set link(%s): autoneg=%u, speed=%u, duplex=%u, lanes=%u\n" , |
896 | netdev->phydev ? "phy" : "mac" , |
897 | cmd->base.autoneg, cmd->base.speed, cmd->base.duplex, |
898 | cmd->lanes); |
899 | |
900 | /* Only support ksettings_set for netdev with phy attached for now */ |
901 | if (netdev->phydev) { |
902 | if (cmd->base.speed == SPEED_1000 && |
903 | cmd->base.autoneg == AUTONEG_DISABLE) |
904 | return -EINVAL; |
905 | |
906 | return phy_ethtool_ksettings_set(phydev: netdev->phydev, cmd); |
907 | } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) && |
908 | ops->set_phy_link_ksettings) { |
909 | return ops->set_phy_link_ksettings(handle, cmd); |
910 | } |
911 | |
912 | if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) |
913 | return -EOPNOTSUPP; |
914 | |
915 | ret = hns3_check_ksettings_param(netdev, cmd); |
916 | if (ret) |
917 | return ret; |
918 | |
919 | if (ops->set_autoneg) { |
920 | ret = ops->set_autoneg(handle, cmd->base.autoneg); |
921 | if (ret) |
922 | return ret; |
923 | } |
924 | |
925 | /* hw doesn't support use specified speed and duplex to negotiate, |
926 | * ignore them when autoneg on. |
927 | */ |
928 | if (cmd->base.autoneg) { |
929 | netdev_info(dev: netdev, |
930 | format: "autoneg is on, ignore the speed and duplex\n" ); |
931 | return 0; |
932 | } |
933 | |
934 | if (ops->cfg_mac_speed_dup_h) |
935 | ret = ops->cfg_mac_speed_dup_h(handle, cmd->base.speed, |
936 | cmd->base.duplex, (u8)(cmd->lanes)); |
937 | |
938 | return ret; |
939 | } |
940 | |
941 | static u32 (struct net_device *netdev) |
942 | { |
943 | struct hnae3_handle *h = hns3_get_handle(netdev); |
944 | |
945 | if (!h->ae_algo->ops->get_rss_key_size) |
946 | return 0; |
947 | |
948 | return h->ae_algo->ops->get_rss_key_size(h); |
949 | } |
950 | |
951 | static u32 (struct net_device *netdev) |
952 | { |
953 | struct hnae3_handle *h = hns3_get_handle(netdev); |
954 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
955 | |
956 | return ae_dev->dev_specs.rss_ind_tbl_size; |
957 | } |
958 | |
959 | static int (struct net_device *netdev, |
960 | struct ethtool_rxfh_param *rxfh) |
961 | { |
962 | struct hnae3_handle *h = hns3_get_handle(netdev); |
963 | |
964 | if (!h->ae_algo->ops->get_rss) |
965 | return -EOPNOTSUPP; |
966 | |
967 | return h->ae_algo->ops->get_rss(h, rxfh->indir, rxfh->key, |
968 | &rxfh->hfunc); |
969 | } |
970 | |
971 | static int (struct net_device *netdev, |
972 | struct ethtool_rxfh_param *rxfh, |
973 | struct netlink_ext_ack *extack) |
974 | { |
975 | struct hnae3_handle *h = hns3_get_handle(netdev); |
976 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
977 | |
978 | if (!h->ae_algo->ops->set_rss) |
979 | return -EOPNOTSUPP; |
980 | |
981 | if ((ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2 && |
982 | rxfh->hfunc != ETH_RSS_HASH_TOP) || |
983 | (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && |
984 | rxfh->hfunc != ETH_RSS_HASH_TOP && |
985 | rxfh->hfunc != ETH_RSS_HASH_XOR)) { |
986 | netdev_err(dev: netdev, format: "hash func not supported\n" ); |
987 | return -EOPNOTSUPP; |
988 | } |
989 | |
990 | if (!rxfh->indir) { |
991 | netdev_err(dev: netdev, |
992 | format: "set rss failed for indir is empty\n" ); |
993 | return -EOPNOTSUPP; |
994 | } |
995 | |
996 | return h->ae_algo->ops->set_rss(h, rxfh->indir, rxfh->key, |
997 | rxfh->hfunc); |
998 | } |
999 | |
1000 | static int hns3_get_rxnfc(struct net_device *netdev, |
1001 | struct ethtool_rxnfc *cmd, |
1002 | u32 *rule_locs) |
1003 | { |
1004 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1005 | |
1006 | switch (cmd->cmd) { |
1007 | case ETHTOOL_GRXRINGS: |
1008 | cmd->data = h->kinfo.num_tqps; |
1009 | return 0; |
1010 | case ETHTOOL_GRXFH: |
1011 | if (h->ae_algo->ops->get_rss_tuple) |
1012 | return h->ae_algo->ops->get_rss_tuple(h, cmd); |
1013 | return -EOPNOTSUPP; |
1014 | case ETHTOOL_GRXCLSRLCNT: |
1015 | if (h->ae_algo->ops->get_fd_rule_cnt) |
1016 | return h->ae_algo->ops->get_fd_rule_cnt(h, cmd); |
1017 | return -EOPNOTSUPP; |
1018 | case ETHTOOL_GRXCLSRULE: |
1019 | if (h->ae_algo->ops->get_fd_rule_info) |
1020 | return h->ae_algo->ops->get_fd_rule_info(h, cmd); |
1021 | return -EOPNOTSUPP; |
1022 | case ETHTOOL_GRXCLSRLALL: |
1023 | if (h->ae_algo->ops->get_fd_all_rules) |
1024 | return h->ae_algo->ops->get_fd_all_rules(h, cmd, |
1025 | rule_locs); |
1026 | return -EOPNOTSUPP; |
1027 | default: |
1028 | return -EOPNOTSUPP; |
1029 | } |
1030 | } |
1031 | |
1032 | static const struct hns3_reset_type_map hns3_reset_type[] = { |
1033 | {ETH_RESET_MGMT, HNAE3_IMP_RESET}, |
1034 | {ETH_RESET_ALL, HNAE3_GLOBAL_RESET}, |
1035 | {ETH_RESET_DEDICATED, HNAE3_FUNC_RESET}, |
1036 | }; |
1037 | |
1038 | static const struct hns3_reset_type_map hns3vf_reset_type[] = { |
1039 | {ETH_RESET_DEDICATED, HNAE3_VF_FUNC_RESET}, |
1040 | }; |
1041 | |
1042 | static int hns3_set_reset(struct net_device *netdev, u32 *flags) |
1043 | { |
1044 | enum hnae3_reset_type rst_type = HNAE3_NONE_RESET; |
1045 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1046 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
1047 | const struct hnae3_ae_ops *ops = h->ae_algo->ops; |
1048 | const struct hns3_reset_type_map *rst_type_map; |
1049 | enum ethtool_reset_flags rst_flags; |
1050 | u32 i, size; |
1051 | |
1052 | if (ops->ae_dev_resetting && ops->ae_dev_resetting(h)) |
1053 | return -EBUSY; |
1054 | |
1055 | if (!ops->set_default_reset_request || !ops->reset_event) |
1056 | return -EOPNOTSUPP; |
1057 | |
1058 | if (h->flags & HNAE3_SUPPORT_VF) { |
1059 | rst_type_map = hns3vf_reset_type; |
1060 | size = ARRAY_SIZE(hns3vf_reset_type); |
1061 | } else { |
1062 | rst_type_map = hns3_reset_type; |
1063 | size = ARRAY_SIZE(hns3_reset_type); |
1064 | } |
1065 | |
1066 | for (i = 0; i < size; i++) { |
1067 | if (rst_type_map[i].rst_flags == *flags) { |
1068 | rst_type = rst_type_map[i].rst_type; |
1069 | rst_flags = rst_type_map[i].rst_flags; |
1070 | break; |
1071 | } |
1072 | } |
1073 | |
1074 | if (rst_type == HNAE3_NONE_RESET || |
1075 | (rst_type == HNAE3_IMP_RESET && |
1076 | ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2)) |
1077 | return -EOPNOTSUPP; |
1078 | |
1079 | netdev_info(dev: netdev, format: "Setting reset type %d\n" , rst_type); |
1080 | |
1081 | ops->set_default_reset_request(ae_dev, rst_type); |
1082 | |
1083 | ops->reset_event(h->pdev, h); |
1084 | |
1085 | *flags &= ~rst_flags; |
1086 | |
1087 | return 0; |
1088 | } |
1089 | |
1090 | static void hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv, |
1091 | u32 tx_desc_num, u32 rx_desc_num) |
1092 | { |
1093 | struct hnae3_handle *h = priv->ae_handle; |
1094 | int i; |
1095 | |
1096 | h->kinfo.num_tx_desc = tx_desc_num; |
1097 | h->kinfo.num_rx_desc = rx_desc_num; |
1098 | |
1099 | for (i = 0; i < h->kinfo.num_tqps; i++) { |
1100 | priv->ring[i].desc_num = tx_desc_num; |
1101 | priv->ring[i + h->kinfo.num_tqps].desc_num = rx_desc_num; |
1102 | } |
1103 | } |
1104 | |
1105 | static struct hns3_enet_ring *hns3_backup_ringparam(struct hns3_nic_priv *priv) |
1106 | { |
1107 | struct hnae3_handle *handle = priv->ae_handle; |
1108 | struct hns3_enet_ring *tmp_rings; |
1109 | int i; |
1110 | |
1111 | tmp_rings = kcalloc(n: handle->kinfo.num_tqps * 2, |
1112 | size: sizeof(struct hns3_enet_ring), GFP_KERNEL); |
1113 | if (!tmp_rings) |
1114 | return NULL; |
1115 | |
1116 | for (i = 0; i < handle->kinfo.num_tqps * 2; i++) { |
1117 | memcpy(&tmp_rings[i], &priv->ring[i], |
1118 | sizeof(struct hns3_enet_ring)); |
1119 | tmp_rings[i].skb = NULL; |
1120 | } |
1121 | |
1122 | return tmp_rings; |
1123 | } |
1124 | |
1125 | static int hns3_check_ringparam(struct net_device *ndev, |
1126 | struct ethtool_ringparam *param, |
1127 | struct kernel_ethtool_ringparam *kernel_param) |
1128 | { |
1129 | #define RX_BUF_LEN_2K 2048 |
1130 | #define RX_BUF_LEN_4K 4096 |
1131 | |
1132 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
1133 | |
1134 | if (hns3_nic_resetting(netdev: ndev) || !priv->ring) { |
1135 | netdev_err(dev: ndev, format: "failed to set ringparam value, due to dev resetting or uninited\n" ); |
1136 | return -EBUSY; |
1137 | } |
1138 | |
1139 | |
1140 | if (param->rx_mini_pending || param->rx_jumbo_pending) |
1141 | return -EINVAL; |
1142 | |
1143 | if (kernel_param->rx_buf_len != RX_BUF_LEN_2K && |
1144 | kernel_param->rx_buf_len != RX_BUF_LEN_4K) { |
1145 | netdev_err(dev: ndev, format: "Rx buf len only support 2048 and 4096\n" ); |
1146 | return -EINVAL; |
1147 | } |
1148 | |
1149 | if (param->tx_pending > HNS3_RING_MAX_PENDING || |
1150 | param->tx_pending < HNS3_RING_MIN_PENDING || |
1151 | param->rx_pending > HNS3_RING_MAX_PENDING || |
1152 | param->rx_pending < HNS3_RING_MIN_PENDING) { |
1153 | netdev_err(dev: ndev, format: "Queue depth out of range [%d-%d]\n" , |
1154 | HNS3_RING_MIN_PENDING, HNS3_RING_MAX_PENDING); |
1155 | return -EINVAL; |
1156 | } |
1157 | |
1158 | return 0; |
1159 | } |
1160 | |
1161 | static bool |
1162 | hns3_is_ringparam_changed(struct net_device *ndev, |
1163 | struct ethtool_ringparam *param, |
1164 | struct kernel_ethtool_ringparam *kernel_param, |
1165 | struct hns3_ring_param *old_ringparam, |
1166 | struct hns3_ring_param *new_ringparam) |
1167 | { |
1168 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
1169 | struct hnae3_handle *h = priv->ae_handle; |
1170 | u16 queue_num = h->kinfo.num_tqps; |
1171 | |
1172 | new_ringparam->tx_desc_num = ALIGN(param->tx_pending, |
1173 | HNS3_RING_BD_MULTIPLE); |
1174 | new_ringparam->rx_desc_num = ALIGN(param->rx_pending, |
1175 | HNS3_RING_BD_MULTIPLE); |
1176 | old_ringparam->tx_desc_num = priv->ring[0].desc_num; |
1177 | old_ringparam->rx_desc_num = priv->ring[queue_num].desc_num; |
1178 | old_ringparam->rx_buf_len = priv->ring[queue_num].buf_size; |
1179 | new_ringparam->rx_buf_len = kernel_param->rx_buf_len; |
1180 | |
1181 | if (old_ringparam->tx_desc_num == new_ringparam->tx_desc_num && |
1182 | old_ringparam->rx_desc_num == new_ringparam->rx_desc_num && |
1183 | old_ringparam->rx_buf_len == new_ringparam->rx_buf_len) { |
1184 | netdev_info(dev: ndev, format: "descriptor number and rx buffer length not changed\n" ); |
1185 | return false; |
1186 | } |
1187 | |
1188 | return true; |
1189 | } |
1190 | |
1191 | static int hns3_change_rx_buf_len(struct net_device *ndev, u32 rx_buf_len) |
1192 | { |
1193 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
1194 | struct hnae3_handle *h = priv->ae_handle; |
1195 | int i; |
1196 | |
1197 | h->kinfo.rx_buf_len = rx_buf_len; |
1198 | |
1199 | for (i = 0; i < h->kinfo.num_tqps; i++) { |
1200 | h->kinfo.tqp[i]->buf_size = rx_buf_len; |
1201 | priv->ring[i + h->kinfo.num_tqps].buf_size = rx_buf_len; |
1202 | } |
1203 | |
1204 | return 0; |
1205 | } |
1206 | |
1207 | static int hns3_set_tx_push(struct net_device *netdev, u32 tx_push) |
1208 | { |
1209 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
1210 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1211 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: h->pdev); |
1212 | u32 old_state = test_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state); |
1213 | |
1214 | if (!test_bit(HNAE3_DEV_SUPPORT_TX_PUSH_B, ae_dev->caps) && tx_push) |
1215 | return -EOPNOTSUPP; |
1216 | |
1217 | if (tx_push == old_state) |
1218 | return 0; |
1219 | |
1220 | netdev_dbg(netdev, "Changing tx push from %s to %s\n" , |
1221 | old_state ? "on" : "off" , tx_push ? "on" : "off" ); |
1222 | |
1223 | if (tx_push) |
1224 | set_bit(nr: HNS3_NIC_STATE_TX_PUSH_ENABLE, addr: &priv->state); |
1225 | else |
1226 | clear_bit(nr: HNS3_NIC_STATE_TX_PUSH_ENABLE, addr: &priv->state); |
1227 | |
1228 | return 0; |
1229 | } |
1230 | |
1231 | static int hns3_set_ringparam(struct net_device *ndev, |
1232 | struct ethtool_ringparam *param, |
1233 | struct kernel_ethtool_ringparam *kernel_param, |
1234 | struct netlink_ext_ack *extack) |
1235 | { |
1236 | struct hns3_ring_param old_ringparam, new_ringparam; |
1237 | struct hns3_nic_priv *priv = netdev_priv(dev: ndev); |
1238 | struct hnae3_handle *h = priv->ae_handle; |
1239 | struct hns3_enet_ring *tmp_rings; |
1240 | bool if_running = netif_running(dev: ndev); |
1241 | int ret, i; |
1242 | |
1243 | ret = hns3_check_ringparam(ndev, param, kernel_param); |
1244 | if (ret) |
1245 | return ret; |
1246 | |
1247 | ret = hns3_set_tx_push(netdev: ndev, tx_push: kernel_param->tx_push); |
1248 | if (ret) |
1249 | return ret; |
1250 | |
1251 | if (!hns3_is_ringparam_changed(ndev, param, kernel_param, |
1252 | old_ringparam: &old_ringparam, new_ringparam: &new_ringparam)) |
1253 | return 0; |
1254 | |
1255 | tmp_rings = hns3_backup_ringparam(priv); |
1256 | if (!tmp_rings) { |
1257 | netdev_err(dev: ndev, format: "backup ring param failed by allocating memory fail\n" ); |
1258 | return -ENOMEM; |
1259 | } |
1260 | |
1261 | netdev_info(dev: ndev, |
1262 | format: "Changing Tx/Rx ring depth from %u/%u to %u/%u, Changing rx buffer len from %u to %u\n" , |
1263 | old_ringparam.tx_desc_num, old_ringparam.rx_desc_num, |
1264 | new_ringparam.tx_desc_num, new_ringparam.rx_desc_num, |
1265 | old_ringparam.rx_buf_len, new_ringparam.rx_buf_len); |
1266 | |
1267 | if (if_running) |
1268 | ndev->netdev_ops->ndo_stop(ndev); |
1269 | |
1270 | hns3_change_all_ring_bd_num(priv, tx_desc_num: new_ringparam.tx_desc_num, |
1271 | rx_desc_num: new_ringparam.rx_desc_num); |
1272 | hns3_change_rx_buf_len(ndev, rx_buf_len: new_ringparam.rx_buf_len); |
1273 | ret = hns3_init_all_ring(priv); |
1274 | if (ret) { |
1275 | netdev_err(dev: ndev, format: "set ringparam fail, revert to old value(%d)\n" , |
1276 | ret); |
1277 | |
1278 | hns3_change_rx_buf_len(ndev, rx_buf_len: old_ringparam.rx_buf_len); |
1279 | hns3_change_all_ring_bd_num(priv, tx_desc_num: old_ringparam.tx_desc_num, |
1280 | rx_desc_num: old_ringparam.rx_desc_num); |
1281 | for (i = 0; i < h->kinfo.num_tqps * 2; i++) |
1282 | memcpy(&priv->ring[i], &tmp_rings[i], |
1283 | sizeof(struct hns3_enet_ring)); |
1284 | } else { |
1285 | for (i = 0; i < h->kinfo.num_tqps * 2; i++) |
1286 | hns3_fini_ring(ring: &tmp_rings[i]); |
1287 | } |
1288 | |
1289 | kfree(objp: tmp_rings); |
1290 | |
1291 | if (if_running) |
1292 | ret = ndev->netdev_ops->ndo_open(ndev); |
1293 | |
1294 | return ret; |
1295 | } |
1296 | |
1297 | static int hns3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) |
1298 | { |
1299 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1300 | |
1301 | switch (cmd->cmd) { |
1302 | case ETHTOOL_SRXFH: |
1303 | if (h->ae_algo->ops->set_rss_tuple) |
1304 | return h->ae_algo->ops->set_rss_tuple(h, cmd); |
1305 | return -EOPNOTSUPP; |
1306 | case ETHTOOL_SRXCLSRLINS: |
1307 | if (h->ae_algo->ops->add_fd_entry) |
1308 | return h->ae_algo->ops->add_fd_entry(h, cmd); |
1309 | return -EOPNOTSUPP; |
1310 | case ETHTOOL_SRXCLSRLDEL: |
1311 | if (h->ae_algo->ops->del_fd_entry) |
1312 | return h->ae_algo->ops->del_fd_entry(h, cmd); |
1313 | return -EOPNOTSUPP; |
1314 | default: |
1315 | return -EOPNOTSUPP; |
1316 | } |
1317 | } |
1318 | |
1319 | static int hns3_nway_reset(struct net_device *netdev) |
1320 | { |
1321 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1322 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
1323 | struct phy_device *phy = netdev->phydev; |
1324 | int autoneg; |
1325 | |
1326 | if (!netif_running(dev: netdev)) |
1327 | return 0; |
1328 | |
1329 | if (hns3_nic_resetting(netdev)) { |
1330 | netdev_err(dev: netdev, format: "dev resetting!" ); |
1331 | return -EBUSY; |
1332 | } |
1333 | |
1334 | if (!ops->get_autoneg || !ops->restart_autoneg) |
1335 | return -EOPNOTSUPP; |
1336 | |
1337 | autoneg = ops->get_autoneg(handle); |
1338 | if (autoneg != AUTONEG_ENABLE) { |
1339 | netdev_err(dev: netdev, |
1340 | format: "Autoneg is off, don't support to restart it\n" ); |
1341 | return -EINVAL; |
1342 | } |
1343 | |
1344 | netif_dbg(handle, drv, netdev, |
1345 | "nway reset (using %s)\n" , phy ? "phy" : "mac" ); |
1346 | |
1347 | if (phy) |
1348 | return genphy_restart_aneg(phydev: phy); |
1349 | |
1350 | return ops->restart_autoneg(handle); |
1351 | } |
1352 | |
1353 | static void hns3_get_channels(struct net_device *netdev, |
1354 | struct ethtool_channels *ch) |
1355 | { |
1356 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1357 | |
1358 | if (h->ae_algo->ops->get_channels) |
1359 | h->ae_algo->ops->get_channels(h, ch); |
1360 | } |
1361 | |
1362 | static int hns3_get_coalesce(struct net_device *netdev, |
1363 | struct ethtool_coalesce *cmd, |
1364 | struct kernel_ethtool_coalesce *kernel_coal, |
1365 | struct netlink_ext_ack *extack) |
1366 | { |
1367 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
1368 | struct hns3_enet_coalesce *tx_coal = &priv->tx_coal; |
1369 | struct hns3_enet_coalesce *rx_coal = &priv->rx_coal; |
1370 | struct hnae3_handle *h = priv->ae_handle; |
1371 | |
1372 | if (hns3_nic_resetting(netdev)) |
1373 | return -EBUSY; |
1374 | |
1375 | cmd->use_adaptive_tx_coalesce = tx_coal->adapt_enable; |
1376 | cmd->use_adaptive_rx_coalesce = rx_coal->adapt_enable; |
1377 | |
1378 | cmd->tx_coalesce_usecs = tx_coal->int_gl; |
1379 | cmd->rx_coalesce_usecs = rx_coal->int_gl; |
1380 | |
1381 | cmd->tx_coalesce_usecs_high = h->kinfo.int_rl_setting; |
1382 | cmd->rx_coalesce_usecs_high = h->kinfo.int_rl_setting; |
1383 | |
1384 | cmd->tx_max_coalesced_frames = tx_coal->int_ql; |
1385 | cmd->rx_max_coalesced_frames = rx_coal->int_ql; |
1386 | |
1387 | kernel_coal->use_cqe_mode_tx = (priv->tx_cqe_mode == |
1388 | DIM_CQ_PERIOD_MODE_START_FROM_CQE); |
1389 | kernel_coal->use_cqe_mode_rx = (priv->rx_cqe_mode == |
1390 | DIM_CQ_PERIOD_MODE_START_FROM_CQE); |
1391 | |
1392 | return 0; |
1393 | } |
1394 | |
1395 | static int hns3_check_gl_coalesce_para(struct net_device *netdev, |
1396 | struct ethtool_coalesce *cmd) |
1397 | { |
1398 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1399 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1400 | u32 rx_gl, tx_gl; |
1401 | |
1402 | if (cmd->rx_coalesce_usecs > ae_dev->dev_specs.max_int_gl) { |
1403 | netdev_err(dev: netdev, |
1404 | format: "invalid rx-usecs value, rx-usecs range is 0-%u\n" , |
1405 | ae_dev->dev_specs.max_int_gl); |
1406 | return -EINVAL; |
1407 | } |
1408 | |
1409 | if (cmd->tx_coalesce_usecs > ae_dev->dev_specs.max_int_gl) { |
1410 | netdev_err(dev: netdev, |
1411 | format: "invalid tx-usecs value, tx-usecs range is 0-%u\n" , |
1412 | ae_dev->dev_specs.max_int_gl); |
1413 | return -EINVAL; |
1414 | } |
1415 | |
1416 | /* device version above V3(include V3), GL uses 1us unit, |
1417 | * so the round down is not needed. |
1418 | */ |
1419 | if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) |
1420 | return 0; |
1421 | |
1422 | rx_gl = hns3_gl_round_down(cmd->rx_coalesce_usecs); |
1423 | if (rx_gl != cmd->rx_coalesce_usecs) { |
1424 | netdev_info(dev: netdev, |
1425 | format: "rx_usecs(%u) rounded down to %u, because it must be multiple of 2.\n" , |
1426 | cmd->rx_coalesce_usecs, rx_gl); |
1427 | } |
1428 | |
1429 | tx_gl = hns3_gl_round_down(cmd->tx_coalesce_usecs); |
1430 | if (tx_gl != cmd->tx_coalesce_usecs) { |
1431 | netdev_info(dev: netdev, |
1432 | format: "tx_usecs(%u) rounded down to %u, because it must be multiple of 2.\n" , |
1433 | cmd->tx_coalesce_usecs, tx_gl); |
1434 | } |
1435 | |
1436 | return 0; |
1437 | } |
1438 | |
1439 | static int hns3_check_rl_coalesce_para(struct net_device *netdev, |
1440 | struct ethtool_coalesce *cmd) |
1441 | { |
1442 | u32 rl; |
1443 | |
1444 | if (cmd->tx_coalesce_usecs_high != cmd->rx_coalesce_usecs_high) { |
1445 | netdev_err(dev: netdev, |
1446 | format: "tx_usecs_high must be same as rx_usecs_high.\n" ); |
1447 | return -EINVAL; |
1448 | } |
1449 | |
1450 | if (cmd->rx_coalesce_usecs_high > HNS3_INT_RL_MAX) { |
1451 | netdev_err(dev: netdev, |
1452 | format: "Invalid usecs_high value, usecs_high range is 0-%d\n" , |
1453 | HNS3_INT_RL_MAX); |
1454 | return -EINVAL; |
1455 | } |
1456 | |
1457 | rl = hns3_rl_round_down(cmd->rx_coalesce_usecs_high); |
1458 | if (rl != cmd->rx_coalesce_usecs_high) { |
1459 | netdev_info(dev: netdev, |
1460 | format: "usecs_high(%u) rounded down to %u, because it must be multiple of 4.\n" , |
1461 | cmd->rx_coalesce_usecs_high, rl); |
1462 | } |
1463 | |
1464 | return 0; |
1465 | } |
1466 | |
1467 | static int hns3_check_ql_coalesce_param(struct net_device *netdev, |
1468 | struct ethtool_coalesce *cmd) |
1469 | { |
1470 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1471 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1472 | |
1473 | if ((cmd->tx_max_coalesced_frames || cmd->rx_max_coalesced_frames) && |
1474 | !ae_dev->dev_specs.int_ql_max) { |
1475 | netdev_err(dev: netdev, format: "coalesced frames is not supported\n" ); |
1476 | return -EOPNOTSUPP; |
1477 | } |
1478 | |
1479 | if (cmd->tx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max || |
1480 | cmd->rx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max) { |
1481 | netdev_err(dev: netdev, |
1482 | format: "invalid coalesced_frames value, range is 0-%u\n" , |
1483 | ae_dev->dev_specs.int_ql_max); |
1484 | return -ERANGE; |
1485 | } |
1486 | |
1487 | return 0; |
1488 | } |
1489 | |
1490 | static int |
1491 | hns3_check_cqe_coalesce_param(struct net_device *netdev, |
1492 | struct kernel_ethtool_coalesce *kernel_coal) |
1493 | { |
1494 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1495 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1496 | |
1497 | if ((kernel_coal->use_cqe_mode_tx || kernel_coal->use_cqe_mode_rx) && |
1498 | !hnae3_ae_dev_cq_supported(ae_dev)) { |
1499 | netdev_err(dev: netdev, format: "coalesced cqe mode is not supported\n" ); |
1500 | return -EOPNOTSUPP; |
1501 | } |
1502 | |
1503 | return 0; |
1504 | } |
1505 | |
1506 | static int |
1507 | hns3_check_coalesce_para(struct net_device *netdev, |
1508 | struct ethtool_coalesce *cmd, |
1509 | struct kernel_ethtool_coalesce *kernel_coal) |
1510 | { |
1511 | int ret; |
1512 | |
1513 | ret = hns3_check_cqe_coalesce_param(netdev, kernel_coal); |
1514 | if (ret) |
1515 | return ret; |
1516 | |
1517 | ret = hns3_check_gl_coalesce_para(netdev, cmd); |
1518 | if (ret) { |
1519 | netdev_err(dev: netdev, |
1520 | format: "Check gl coalesce param fail. ret = %d\n" , ret); |
1521 | return ret; |
1522 | } |
1523 | |
1524 | ret = hns3_check_rl_coalesce_para(netdev, cmd); |
1525 | if (ret) { |
1526 | netdev_err(dev: netdev, |
1527 | format: "Check rl coalesce param fail. ret = %d\n" , ret); |
1528 | return ret; |
1529 | } |
1530 | |
1531 | return hns3_check_ql_coalesce_param(netdev, cmd); |
1532 | } |
1533 | |
1534 | static void hns3_set_coalesce_per_queue(struct net_device *netdev, |
1535 | struct ethtool_coalesce *cmd, |
1536 | u32 queue) |
1537 | { |
1538 | struct hns3_enet_tqp_vector *tx_vector, *rx_vector; |
1539 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
1540 | struct hnae3_handle *h = priv->ae_handle; |
1541 | int queue_num = h->kinfo.num_tqps; |
1542 | |
1543 | tx_vector = priv->ring[queue].tqp_vector; |
1544 | rx_vector = priv->ring[queue_num + queue].tqp_vector; |
1545 | |
1546 | tx_vector->tx_group.coal.adapt_enable = |
1547 | cmd->use_adaptive_tx_coalesce; |
1548 | rx_vector->rx_group.coal.adapt_enable = |
1549 | cmd->use_adaptive_rx_coalesce; |
1550 | |
1551 | tx_vector->tx_group.coal.int_gl = cmd->tx_coalesce_usecs; |
1552 | rx_vector->rx_group.coal.int_gl = cmd->rx_coalesce_usecs; |
1553 | |
1554 | tx_vector->tx_group.coal.int_ql = cmd->tx_max_coalesced_frames; |
1555 | rx_vector->rx_group.coal.int_ql = cmd->rx_max_coalesced_frames; |
1556 | |
1557 | hns3_set_vector_coalesce_tx_gl(tqp_vector: tx_vector, |
1558 | gl_value: tx_vector->tx_group.coal.int_gl); |
1559 | hns3_set_vector_coalesce_rx_gl(tqp_vector: rx_vector, |
1560 | gl_value: rx_vector->rx_group.coal.int_gl); |
1561 | |
1562 | hns3_set_vector_coalesce_rl(tqp_vector: tx_vector, rl_value: h->kinfo.int_rl_setting); |
1563 | hns3_set_vector_coalesce_rl(tqp_vector: rx_vector, rl_value: h->kinfo.int_rl_setting); |
1564 | |
1565 | if (tx_vector->tx_group.coal.ql_enable) |
1566 | hns3_set_vector_coalesce_tx_ql(tqp_vector: tx_vector, |
1567 | ql_value: tx_vector->tx_group.coal.int_ql); |
1568 | if (rx_vector->rx_group.coal.ql_enable) |
1569 | hns3_set_vector_coalesce_rx_ql(tqp_vector: rx_vector, |
1570 | ql_value: rx_vector->rx_group.coal.int_ql); |
1571 | } |
1572 | |
1573 | static int hns3_set_coalesce(struct net_device *netdev, |
1574 | struct ethtool_coalesce *cmd, |
1575 | struct kernel_ethtool_coalesce *kernel_coal, |
1576 | struct netlink_ext_ack *extack) |
1577 | { |
1578 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1579 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
1580 | struct hns3_enet_coalesce *tx_coal = &priv->tx_coal; |
1581 | struct hns3_enet_coalesce *rx_coal = &priv->rx_coal; |
1582 | u16 queue_num = h->kinfo.num_tqps; |
1583 | enum dim_cq_period_mode tx_mode; |
1584 | enum dim_cq_period_mode rx_mode; |
1585 | int ret; |
1586 | int i; |
1587 | |
1588 | if (hns3_nic_resetting(netdev)) |
1589 | return -EBUSY; |
1590 | |
1591 | ret = hns3_check_coalesce_para(netdev, cmd, kernel_coal); |
1592 | if (ret) |
1593 | return ret; |
1594 | |
1595 | h->kinfo.int_rl_setting = |
1596 | hns3_rl_round_down(cmd->rx_coalesce_usecs_high); |
1597 | |
1598 | tx_coal->adapt_enable = cmd->use_adaptive_tx_coalesce; |
1599 | rx_coal->adapt_enable = cmd->use_adaptive_rx_coalesce; |
1600 | |
1601 | tx_coal->int_gl = cmd->tx_coalesce_usecs; |
1602 | rx_coal->int_gl = cmd->rx_coalesce_usecs; |
1603 | |
1604 | tx_coal->int_ql = cmd->tx_max_coalesced_frames; |
1605 | rx_coal->int_ql = cmd->rx_max_coalesced_frames; |
1606 | |
1607 | for (i = 0; i < queue_num; i++) |
1608 | hns3_set_coalesce_per_queue(netdev, cmd, queue: i); |
1609 | |
1610 | tx_mode = kernel_coal->use_cqe_mode_tx ? |
1611 | DIM_CQ_PERIOD_MODE_START_FROM_CQE : |
1612 | DIM_CQ_PERIOD_MODE_START_FROM_EQE; |
1613 | rx_mode = kernel_coal->use_cqe_mode_rx ? |
1614 | DIM_CQ_PERIOD_MODE_START_FROM_CQE : |
1615 | DIM_CQ_PERIOD_MODE_START_FROM_EQE; |
1616 | hns3_cq_period_mode_init(priv, tx_mode, rx_mode); |
1617 | |
1618 | return 0; |
1619 | } |
1620 | |
1621 | static int hns3_get_regs_len(struct net_device *netdev) |
1622 | { |
1623 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1624 | |
1625 | if (!h->ae_algo->ops->get_regs_len) |
1626 | return -EOPNOTSUPP; |
1627 | |
1628 | return h->ae_algo->ops->get_regs_len(h); |
1629 | } |
1630 | |
1631 | static void hns3_get_regs(struct net_device *netdev, |
1632 | struct ethtool_regs *cmd, void *data) |
1633 | { |
1634 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1635 | |
1636 | if (!h->ae_algo->ops->get_regs) |
1637 | return; |
1638 | |
1639 | h->ae_algo->ops->get_regs(h, &cmd->version, data); |
1640 | } |
1641 | |
1642 | static int hns3_set_phys_id(struct net_device *netdev, |
1643 | enum ethtool_phys_id_state state) |
1644 | { |
1645 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1646 | |
1647 | if (!h->ae_algo->ops->set_led_id) |
1648 | return -EOPNOTSUPP; |
1649 | |
1650 | return h->ae_algo->ops->set_led_id(h, state); |
1651 | } |
1652 | |
1653 | static u32 hns3_get_msglevel(struct net_device *netdev) |
1654 | { |
1655 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1656 | |
1657 | return h->msg_enable; |
1658 | } |
1659 | |
1660 | static void hns3_set_msglevel(struct net_device *netdev, u32 msg_level) |
1661 | { |
1662 | struct hnae3_handle *h = hns3_get_handle(netdev); |
1663 | |
1664 | h->msg_enable = msg_level; |
1665 | } |
1666 | |
1667 | static void hns3_get_fec_stats(struct net_device *netdev, |
1668 | struct ethtool_fec_stats *fec_stats) |
1669 | { |
1670 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1671 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1672 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
1673 | |
1674 | if (!hnae3_ae_dev_fec_stats_supported(ae_dev) || !ops->get_fec_stats) |
1675 | return; |
1676 | |
1677 | ops->get_fec_stats(handle, fec_stats); |
1678 | } |
1679 | |
1680 | /* Translate local fec value into ethtool value. */ |
1681 | static unsigned int loc_to_eth_fec(u8 loc_fec) |
1682 | { |
1683 | u32 eth_fec = 0; |
1684 | |
1685 | if (loc_fec & BIT(HNAE3_FEC_AUTO)) |
1686 | eth_fec |= ETHTOOL_FEC_AUTO; |
1687 | if (loc_fec & BIT(HNAE3_FEC_RS)) |
1688 | eth_fec |= ETHTOOL_FEC_RS; |
1689 | if (loc_fec & BIT(HNAE3_FEC_LLRS)) |
1690 | eth_fec |= ETHTOOL_FEC_LLRS; |
1691 | if (loc_fec & BIT(HNAE3_FEC_BASER)) |
1692 | eth_fec |= ETHTOOL_FEC_BASER; |
1693 | if (loc_fec & BIT(HNAE3_FEC_NONE)) |
1694 | eth_fec |= ETHTOOL_FEC_OFF; |
1695 | |
1696 | return eth_fec; |
1697 | } |
1698 | |
1699 | /* Translate ethtool fec value into local value. */ |
1700 | static unsigned int eth_to_loc_fec(unsigned int eth_fec) |
1701 | { |
1702 | u32 loc_fec = 0; |
1703 | |
1704 | if (eth_fec & ETHTOOL_FEC_OFF) |
1705 | loc_fec |= BIT(HNAE3_FEC_NONE); |
1706 | if (eth_fec & ETHTOOL_FEC_AUTO) |
1707 | loc_fec |= BIT(HNAE3_FEC_AUTO); |
1708 | if (eth_fec & ETHTOOL_FEC_RS) |
1709 | loc_fec |= BIT(HNAE3_FEC_RS); |
1710 | if (eth_fec & ETHTOOL_FEC_LLRS) |
1711 | loc_fec |= BIT(HNAE3_FEC_LLRS); |
1712 | if (eth_fec & ETHTOOL_FEC_BASER) |
1713 | loc_fec |= BIT(HNAE3_FEC_BASER); |
1714 | |
1715 | return loc_fec; |
1716 | } |
1717 | |
1718 | static int hns3_get_fecparam(struct net_device *netdev, |
1719 | struct ethtool_fecparam *fec) |
1720 | { |
1721 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1722 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1723 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
1724 | u8 fec_ability; |
1725 | u8 fec_mode; |
1726 | |
1727 | if (!test_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps)) |
1728 | return -EOPNOTSUPP; |
1729 | |
1730 | if (!ops->get_fec) |
1731 | return -EOPNOTSUPP; |
1732 | |
1733 | ops->get_fec(handle, &fec_ability, &fec_mode); |
1734 | |
1735 | fec->fec = loc_to_eth_fec(loc_fec: fec_ability); |
1736 | fec->active_fec = loc_to_eth_fec(loc_fec: fec_mode); |
1737 | if (!fec->active_fec) |
1738 | fec->active_fec = ETHTOOL_FEC_OFF; |
1739 | |
1740 | return 0; |
1741 | } |
1742 | |
1743 | static int hns3_set_fecparam(struct net_device *netdev, |
1744 | struct ethtool_fecparam *fec) |
1745 | { |
1746 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1747 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1748 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
1749 | u32 fec_mode; |
1750 | |
1751 | if (!test_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps)) |
1752 | return -EOPNOTSUPP; |
1753 | |
1754 | if (!ops->set_fec) |
1755 | return -EOPNOTSUPP; |
1756 | fec_mode = eth_to_loc_fec(eth_fec: fec->fec); |
1757 | |
1758 | netif_dbg(handle, drv, netdev, "set fecparam: mode=%u\n" , fec_mode); |
1759 | |
1760 | return ops->set_fec(handle, fec_mode); |
1761 | } |
1762 | |
1763 | static int hns3_get_module_info(struct net_device *netdev, |
1764 | struct ethtool_modinfo *modinfo) |
1765 | { |
1766 | #define HNS3_SFF_8636_V1_3 0x03 |
1767 | |
1768 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1769 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1770 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
1771 | struct hns3_sfp_type sfp_type; |
1772 | int ret; |
1773 | |
1774 | if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2 || |
1775 | !ops->get_module_eeprom) |
1776 | return -EOPNOTSUPP; |
1777 | |
1778 | memset(&sfp_type, 0, sizeof(sfp_type)); |
1779 | ret = ops->get_module_eeprom(handle, 0, sizeof(sfp_type) / sizeof(u8), |
1780 | (u8 *)&sfp_type); |
1781 | if (ret) |
1782 | return ret; |
1783 | |
1784 | switch (sfp_type.type) { |
1785 | case SFF8024_ID_SFP: |
1786 | modinfo->type = ETH_MODULE_SFF_8472; |
1787 | modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; |
1788 | break; |
1789 | case SFF8024_ID_QSFP_8438: |
1790 | modinfo->type = ETH_MODULE_SFF_8436; |
1791 | modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; |
1792 | break; |
1793 | case SFF8024_ID_QSFP_8436_8636: |
1794 | if (sfp_type.ext_type < HNS3_SFF_8636_V1_3) { |
1795 | modinfo->type = ETH_MODULE_SFF_8436; |
1796 | modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; |
1797 | } else { |
1798 | modinfo->type = ETH_MODULE_SFF_8636; |
1799 | modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; |
1800 | } |
1801 | break; |
1802 | case SFF8024_ID_QSFP28_8636: |
1803 | modinfo->type = ETH_MODULE_SFF_8636; |
1804 | modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; |
1805 | break; |
1806 | default: |
1807 | netdev_err(dev: netdev, format: "Optical module unknown: %#x\n" , |
1808 | sfp_type.type); |
1809 | return -EINVAL; |
1810 | } |
1811 | |
1812 | return 0; |
1813 | } |
1814 | |
1815 | static int hns3_get_module_eeprom(struct net_device *netdev, |
1816 | struct ethtool_eeprom *ee, u8 *data) |
1817 | { |
1818 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1819 | struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev: handle->pdev); |
1820 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
1821 | |
1822 | if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2 || |
1823 | !ops->get_module_eeprom) |
1824 | return -EOPNOTSUPP; |
1825 | |
1826 | if (!ee->len) |
1827 | return -EINVAL; |
1828 | |
1829 | memset(data, 0, ee->len); |
1830 | |
1831 | return ops->get_module_eeprom(handle, ee->offset, ee->len, data); |
1832 | } |
1833 | |
1834 | static u32 hns3_get_priv_flags(struct net_device *netdev) |
1835 | { |
1836 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1837 | |
1838 | return handle->priv_flags; |
1839 | } |
1840 | |
1841 | static int hns3_check_priv_flags(struct hnae3_handle *h, u32 changed) |
1842 | { |
1843 | u32 i; |
1844 | |
1845 | for (i = 0; i < HNAE3_PFLAG_MAX; i++) |
1846 | if ((changed & BIT(i)) && !test_bit(i, &h->supported_pflags)) { |
1847 | netdev_err(dev: h->netdev, format: "%s is unsupported\n" , |
1848 | hns3_priv_flags[i].name); |
1849 | return -EOPNOTSUPP; |
1850 | } |
1851 | |
1852 | return 0; |
1853 | } |
1854 | |
1855 | static int hns3_set_priv_flags(struct net_device *netdev, u32 pflags) |
1856 | { |
1857 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
1858 | u32 changed = pflags ^ handle->priv_flags; |
1859 | int ret; |
1860 | u32 i; |
1861 | |
1862 | ret = hns3_check_priv_flags(h: handle, changed); |
1863 | if (ret) |
1864 | return ret; |
1865 | |
1866 | for (i = 0; i < HNAE3_PFLAG_MAX; i++) { |
1867 | if (changed & BIT(i)) { |
1868 | bool enable = !(handle->priv_flags & BIT(i)); |
1869 | |
1870 | if (enable) |
1871 | handle->priv_flags |= BIT(i); |
1872 | else |
1873 | handle->priv_flags &= ~BIT(i); |
1874 | hns3_priv_flags[i].handler(netdev, enable); |
1875 | } |
1876 | } |
1877 | |
1878 | return 0; |
1879 | } |
1880 | |
1881 | static int hns3_get_tunable(struct net_device *netdev, |
1882 | const struct ethtool_tunable *tuna, |
1883 | void *data) |
1884 | { |
1885 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
1886 | struct hnae3_handle *h = priv->ae_handle; |
1887 | int ret = 0; |
1888 | |
1889 | switch (tuna->id) { |
1890 | case ETHTOOL_TX_COPYBREAK: |
1891 | /* all the tx rings have the same tx_copybreak */ |
1892 | *(u32 *)data = priv->tx_copybreak; |
1893 | break; |
1894 | case ETHTOOL_RX_COPYBREAK: |
1895 | *(u32 *)data = priv->rx_copybreak; |
1896 | break; |
1897 | case ETHTOOL_TX_COPYBREAK_BUF_SIZE: |
1898 | *(u32 *)data = h->kinfo.tx_spare_buf_size; |
1899 | break; |
1900 | default: |
1901 | ret = -EOPNOTSUPP; |
1902 | break; |
1903 | } |
1904 | |
1905 | return ret; |
1906 | } |
1907 | |
1908 | static int hns3_set_tx_spare_buf_size(struct net_device *netdev, |
1909 | u32 data) |
1910 | { |
1911 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
1912 | struct hnae3_handle *h = priv->ae_handle; |
1913 | int ret; |
1914 | |
1915 | h->kinfo.tx_spare_buf_size = data; |
1916 | |
1917 | ret = hns3_reset_notify(handle: h, type: HNAE3_DOWN_CLIENT); |
1918 | if (ret) |
1919 | return ret; |
1920 | |
1921 | ret = hns3_reset_notify(handle: h, type: HNAE3_UNINIT_CLIENT); |
1922 | if (ret) |
1923 | return ret; |
1924 | |
1925 | ret = hns3_reset_notify(handle: h, type: HNAE3_INIT_CLIENT); |
1926 | if (ret) |
1927 | return ret; |
1928 | |
1929 | ret = hns3_reset_notify(handle: h, type: HNAE3_UP_CLIENT); |
1930 | if (ret) |
1931 | hns3_reset_notify(handle: h, type: HNAE3_UNINIT_CLIENT); |
1932 | |
1933 | return ret; |
1934 | } |
1935 | |
1936 | static int hns3_set_tunable(struct net_device *netdev, |
1937 | const struct ethtool_tunable *tuna, |
1938 | const void *data) |
1939 | { |
1940 | struct hns3_nic_priv *priv = netdev_priv(dev: netdev); |
1941 | u32 old_tx_spare_buf_size, new_tx_spare_buf_size; |
1942 | struct hnae3_handle *h = priv->ae_handle; |
1943 | int i, ret = 0; |
1944 | |
1945 | if (hns3_nic_resetting(netdev) || !priv->ring) { |
1946 | netdev_err(dev: netdev, format: "failed to set tunable value, dev resetting!" ); |
1947 | return -EBUSY; |
1948 | } |
1949 | |
1950 | switch (tuna->id) { |
1951 | case ETHTOOL_TX_COPYBREAK: |
1952 | priv->tx_copybreak = *(u32 *)data; |
1953 | |
1954 | for (i = 0; i < h->kinfo.num_tqps; i++) |
1955 | priv->ring[i].tx_copybreak = priv->tx_copybreak; |
1956 | |
1957 | break; |
1958 | case ETHTOOL_RX_COPYBREAK: |
1959 | priv->rx_copybreak = *(u32 *)data; |
1960 | |
1961 | for (i = h->kinfo.num_tqps; i < h->kinfo.num_tqps * 2; i++) |
1962 | priv->ring[i].rx_copybreak = priv->rx_copybreak; |
1963 | |
1964 | break; |
1965 | case ETHTOOL_TX_COPYBREAK_BUF_SIZE: |
1966 | old_tx_spare_buf_size = h->kinfo.tx_spare_buf_size; |
1967 | new_tx_spare_buf_size = *(u32 *)data; |
1968 | netdev_info(dev: netdev, format: "request to set tx spare buf size from %u to %u\n" , |
1969 | old_tx_spare_buf_size, new_tx_spare_buf_size); |
1970 | ret = hns3_set_tx_spare_buf_size(netdev, data: new_tx_spare_buf_size); |
1971 | if (ret || |
1972 | (!priv->ring->tx_spare && new_tx_spare_buf_size != 0)) { |
1973 | int ret1; |
1974 | |
1975 | netdev_warn(dev: netdev, format: "change tx spare buf size fail, revert to old value\n" ); |
1976 | ret1 = hns3_set_tx_spare_buf_size(netdev, |
1977 | data: old_tx_spare_buf_size); |
1978 | if (ret1) { |
1979 | netdev_err(dev: netdev, format: "revert to old tx spare buf size fail\n" ); |
1980 | return ret1; |
1981 | } |
1982 | |
1983 | return ret; |
1984 | } |
1985 | |
1986 | if (!priv->ring->tx_spare) |
1987 | netdev_info(dev: netdev, format: "the active tx spare buf size is 0, disable tx spare buffer\n" ); |
1988 | else |
1989 | netdev_info(dev: netdev, format: "the active tx spare buf size is %u, due to page order\n" , |
1990 | priv->ring->tx_spare->len); |
1991 | |
1992 | break; |
1993 | default: |
1994 | ret = -EOPNOTSUPP; |
1995 | break; |
1996 | } |
1997 | |
1998 | return ret; |
1999 | } |
2000 | |
2001 | #define HNS3_ETHTOOL_COALESCE (ETHTOOL_COALESCE_USECS | \ |
2002 | ETHTOOL_COALESCE_USE_ADAPTIVE | \ |
2003 | ETHTOOL_COALESCE_RX_USECS_HIGH | \ |
2004 | ETHTOOL_COALESCE_TX_USECS_HIGH | \ |
2005 | ETHTOOL_COALESCE_MAX_FRAMES | \ |
2006 | ETHTOOL_COALESCE_USE_CQE) |
2007 | |
2008 | #define HNS3_ETHTOOL_RING (ETHTOOL_RING_USE_RX_BUF_LEN | \ |
2009 | ETHTOOL_RING_USE_TX_PUSH) |
2010 | |
2011 | static int hns3_get_ts_info(struct net_device *netdev, |
2012 | struct ethtool_ts_info *info) |
2013 | { |
2014 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
2015 | |
2016 | if (handle->ae_algo->ops->get_ts_info) |
2017 | return handle->ae_algo->ops->get_ts_info(handle, info); |
2018 | |
2019 | return ethtool_op_get_ts_info(dev: netdev, eti: info); |
2020 | } |
2021 | |
2022 | static const struct hns3_ethtool_link_ext_state_mapping |
2023 | hns3_link_ext_state_map[] = { |
2024 | {1, ETHTOOL_LINK_EXT_STATE_AUTONEG, |
2025 | ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD}, |
2026 | {2, ETHTOOL_LINK_EXT_STATE_AUTONEG, |
2027 | ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED}, |
2028 | |
2029 | {256, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, |
2030 | ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT}, |
2031 | {257, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, |
2032 | ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY}, |
2033 | {512, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, |
2034 | ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT}, |
2035 | |
2036 | {513, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, |
2037 | ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK}, |
2038 | {514, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, |
2039 | ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED}, |
2040 | {515, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, |
2041 | ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED}, |
2042 | |
2043 | {768, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, |
2044 | ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS}, |
2045 | {769, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, |
2046 | ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST}, |
2047 | {770, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, |
2048 | ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS}, |
2049 | |
2050 | {1024, ETHTOOL_LINK_EXT_STATE_NO_CABLE, 0}, |
2051 | {1025, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, |
2052 | ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE}, |
2053 | |
2054 | {1026, ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, 0}, |
2055 | }; |
2056 | |
2057 | static int hns3_get_link_ext_state(struct net_device *netdev, |
2058 | struct ethtool_link_ext_state_info *info) |
2059 | { |
2060 | const struct hns3_ethtool_link_ext_state_mapping *map; |
2061 | struct hnae3_handle *h = hns3_get_handle(netdev); |
2062 | u32 status_code, i; |
2063 | int ret; |
2064 | |
2065 | if (netif_carrier_ok(dev: netdev)) |
2066 | return -ENODATA; |
2067 | |
2068 | if (!h->ae_algo->ops->get_link_diagnosis_info) |
2069 | return -EOPNOTSUPP; |
2070 | |
2071 | ret = h->ae_algo->ops->get_link_diagnosis_info(h, &status_code); |
2072 | if (ret) |
2073 | return ret; |
2074 | |
2075 | for (i = 0; i < ARRAY_SIZE(hns3_link_ext_state_map); i++) { |
2076 | map = &hns3_link_ext_state_map[i]; |
2077 | if (map->status_code == status_code) { |
2078 | info->link_ext_state = map->link_ext_state; |
2079 | info->__link_ext_substate = map->link_ext_substate; |
2080 | return 0; |
2081 | } |
2082 | } |
2083 | |
2084 | return -ENODATA; |
2085 | } |
2086 | |
2087 | static void hns3_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) |
2088 | { |
2089 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
2090 | const struct hnae3_ae_ops *ops = hns3_get_ops(handle); |
2091 | struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle); |
2092 | |
2093 | if (!hnae3_ae_dev_wol_supported(ae_dev)) |
2094 | return; |
2095 | |
2096 | ops->get_wol(handle, wol); |
2097 | } |
2098 | |
2099 | static int hns3_set_wol(struct net_device *netdev, |
2100 | struct ethtool_wolinfo *wol) |
2101 | { |
2102 | struct hnae3_handle *handle = hns3_get_handle(netdev); |
2103 | const struct hnae3_ae_ops *ops = hns3_get_ops(handle); |
2104 | struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle); |
2105 | |
2106 | if (!hnae3_ae_dev_wol_supported(ae_dev)) |
2107 | return -EOPNOTSUPP; |
2108 | |
2109 | return ops->set_wol(handle, wol); |
2110 | } |
2111 | |
2112 | static const struct ethtool_ops hns3vf_ethtool_ops = { |
2113 | .supported_coalesce_params = HNS3_ETHTOOL_COALESCE, |
2114 | .supported_ring_params = HNS3_ETHTOOL_RING, |
2115 | .get_drvinfo = hns3_get_drvinfo, |
2116 | .get_ringparam = hns3_get_ringparam, |
2117 | .set_ringparam = hns3_set_ringparam, |
2118 | .get_strings = hns3_get_strings, |
2119 | .get_ethtool_stats = hns3_get_stats, |
2120 | .get_sset_count = hns3_get_sset_count, |
2121 | .get_rxnfc = hns3_get_rxnfc, |
2122 | .set_rxnfc = hns3_set_rxnfc, |
2123 | .get_rxfh_key_size = hns3_get_rss_key_size, |
2124 | .get_rxfh_indir_size = hns3_get_rss_indir_size, |
2125 | .get_rxfh = hns3_get_rss, |
2126 | .set_rxfh = hns3_set_rss, |
2127 | .get_link_ksettings = hns3_get_link_ksettings, |
2128 | .get_channels = hns3_get_channels, |
2129 | .set_channels = hns3_set_channels, |
2130 | .get_coalesce = hns3_get_coalesce, |
2131 | .set_coalesce = hns3_set_coalesce, |
2132 | .get_regs_len = hns3_get_regs_len, |
2133 | .get_regs = hns3_get_regs, |
2134 | .get_link = hns3_get_link, |
2135 | .get_msglevel = hns3_get_msglevel, |
2136 | .set_msglevel = hns3_set_msglevel, |
2137 | .get_priv_flags = hns3_get_priv_flags, |
2138 | .set_priv_flags = hns3_set_priv_flags, |
2139 | .get_tunable = hns3_get_tunable, |
2140 | .set_tunable = hns3_set_tunable, |
2141 | .reset = hns3_set_reset, |
2142 | }; |
2143 | |
2144 | static const struct ethtool_ops hns3_ethtool_ops = { |
2145 | .supported_coalesce_params = HNS3_ETHTOOL_COALESCE, |
2146 | .supported_ring_params = HNS3_ETHTOOL_RING, |
2147 | .cap_link_lanes_supported = true, |
2148 | .self_test = hns3_self_test, |
2149 | .get_drvinfo = hns3_get_drvinfo, |
2150 | .get_link = hns3_get_link, |
2151 | .get_ringparam = hns3_get_ringparam, |
2152 | .set_ringparam = hns3_set_ringparam, |
2153 | .get_pauseparam = hns3_get_pauseparam, |
2154 | .set_pauseparam = hns3_set_pauseparam, |
2155 | .get_strings = hns3_get_strings, |
2156 | .get_ethtool_stats = hns3_get_stats, |
2157 | .get_sset_count = hns3_get_sset_count, |
2158 | .get_rxnfc = hns3_get_rxnfc, |
2159 | .set_rxnfc = hns3_set_rxnfc, |
2160 | .get_rxfh_key_size = hns3_get_rss_key_size, |
2161 | .get_rxfh_indir_size = hns3_get_rss_indir_size, |
2162 | .get_rxfh = hns3_get_rss, |
2163 | .set_rxfh = hns3_set_rss, |
2164 | .get_link_ksettings = hns3_get_link_ksettings, |
2165 | .set_link_ksettings = hns3_set_link_ksettings, |
2166 | .nway_reset = hns3_nway_reset, |
2167 | .get_channels = hns3_get_channels, |
2168 | .set_channels = hns3_set_channels, |
2169 | .get_coalesce = hns3_get_coalesce, |
2170 | .set_coalesce = hns3_set_coalesce, |
2171 | .get_regs_len = hns3_get_regs_len, |
2172 | .get_regs = hns3_get_regs, |
2173 | .set_phys_id = hns3_set_phys_id, |
2174 | .get_msglevel = hns3_get_msglevel, |
2175 | .set_msglevel = hns3_set_msglevel, |
2176 | .get_fecparam = hns3_get_fecparam, |
2177 | .set_fecparam = hns3_set_fecparam, |
2178 | .get_fec_stats = hns3_get_fec_stats, |
2179 | .get_module_info = hns3_get_module_info, |
2180 | .get_module_eeprom = hns3_get_module_eeprom, |
2181 | .get_priv_flags = hns3_get_priv_flags, |
2182 | .set_priv_flags = hns3_set_priv_flags, |
2183 | .get_ts_info = hns3_get_ts_info, |
2184 | .get_tunable = hns3_get_tunable, |
2185 | .set_tunable = hns3_set_tunable, |
2186 | .reset = hns3_set_reset, |
2187 | .get_link_ext_state = hns3_get_link_ext_state, |
2188 | .get_wol = hns3_get_wol, |
2189 | .set_wol = hns3_set_wol, |
2190 | }; |
2191 | |
2192 | void hns3_ethtool_set_ops(struct net_device *netdev) |
2193 | { |
2194 | struct hnae3_handle *h = hns3_get_handle(netdev); |
2195 | |
2196 | if (h->flags & HNAE3_SUPPORT_VF) |
2197 | netdev->ethtool_ops = &hns3vf_ethtool_ops; |
2198 | else |
2199 | netdev->ethtool_ops = &hns3_ethtool_ops; |
2200 | } |
2201 | |