1d71d8381SJian Shen // SPDX-License-Identifier: GPL-2.0+
2d71d8381SJian Shen // Copyright (c) 2016-2017 Hisilicon Limited.
3424eb834SSalil Mehta
4424eb834SSalil Mehta #include <linux/etherdevice.h>
5424eb834SSalil Mehta #include <linux/string.h>
6424eb834SSalil Mehta #include <linux/phy.h>
7cb10228dSYonglong Liu #include <linux/sfp.h>
8424eb834SSalil Mehta
9424eb834SSalil Mehta #include "hns3_enet.h"
10edb40bbcSGuangbin Huang #include "hns3_ethtool.h"
115e7414cdSJian Shen
12424eb834SSalil Mehta /* tqp related stats */
13424eb834SSalil Mehta #define HNS3_TQP_STAT(_string, _member) { \
14424eb834SSalil Mehta .stats_string = _string, \
1557ffee73SJian Shen .stats_offset = offsetof(struct hns3_enet_ring, stats) +\
1657ffee73SJian Shen offsetof(struct ring_stats, _member), \
17b59f558cSJian Shen }
18424eb834SSalil Mehta
19424eb834SSalil Mehta static const struct hns3_stats hns3_txq_stats[] = {
20424eb834SSalil Mehta /* Tx per-queue statistics */
210c218123SJian Shen HNS3_TQP_STAT("dropped", sw_err_cnt),
22a6c51c26SJian Shen HNS3_TQP_STAT("seg_pkt_cnt", seg_pkt_cnt),
23a6c51c26SJian Shen HNS3_TQP_STAT("packets", tx_pkts),
24a6c51c26SJian Shen HNS3_TQP_STAT("bytes", tx_bytes),
25f6061a05SYunsheng Lin HNS3_TQP_STAT("more", tx_more),
2687a9b2fdSYufeng Mo HNS3_TQP_STAT("push", tx_push),
2787a9b2fdSYufeng Mo HNS3_TQP_STAT("mem_doorbell", tx_mem_doorbell),
280c218123SJian Shen HNS3_TQP_STAT("wake", restart_queue),
290c218123SJian Shen HNS3_TQP_STAT("busy", tx_busy),
303d5f3741SYunsheng Lin HNS3_TQP_STAT("copy", tx_copy),
31b20d7fe5SYunsheng Lin HNS3_TQP_STAT("vlan_err", tx_vlan_err),
32b20d7fe5SYunsheng Lin HNS3_TQP_STAT("l4_proto_err", tx_l4_proto_err),
33b20d7fe5SYunsheng Lin HNS3_TQP_STAT("l2l3l4_err", tx_l2l3l4_err),
34b20d7fe5SYunsheng Lin HNS3_TQP_STAT("tso_err", tx_tso_err),
35d5d5e019SYunsheng Lin HNS3_TQP_STAT("over_max_recursion", over_max_recursion),
36d5d5e019SYunsheng Lin HNS3_TQP_STAT("hw_limitation", hw_limitation),
37907676b1SYunsheng Lin HNS3_TQP_STAT("bounce", tx_bounce),
38907676b1SYunsheng Lin HNS3_TQP_STAT("spare_full", tx_spare_full),
39907676b1SYunsheng Lin HNS3_TQP_STAT("copy_bits_err", copy_bits_err),
407459775eSYunsheng Lin HNS3_TQP_STAT("sgl", tx_sgl),
417459775eSYunsheng Lin HNS3_TQP_STAT("skb2sgl_err", skb2sgl_err),
427459775eSYunsheng Lin HNS3_TQP_STAT("map_sg_err", map_sg_err),
43424eb834SSalil Mehta };
44424eb834SSalil Mehta
45424eb834SSalil Mehta #define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats)
46424eb834SSalil Mehta
47424eb834SSalil Mehta static const struct hns3_stats hns3_rxq_stats[] = {
48424eb834SSalil Mehta /* Rx per-queue statistics */
490c218123SJian Shen HNS3_TQP_STAT("dropped", sw_err_cnt),
50a6c51c26SJian Shen HNS3_TQP_STAT("seg_pkt_cnt", seg_pkt_cnt),
51a6c51c26SJian Shen HNS3_TQP_STAT("packets", rx_pkts),
52a6c51c26SJian Shen HNS3_TQP_STAT("bytes", rx_bytes),
53a6c51c26SJian Shen HNS3_TQP_STAT("errors", rx_err_cnt),
54a6c51c26SJian Shen HNS3_TQP_STAT("reuse_pg_cnt", reuse_pg_cnt),
55a6c51c26SJian Shen HNS3_TQP_STAT("err_pkt_len", err_pkt_len),
56a6c51c26SJian Shen HNS3_TQP_STAT("err_bd_num", err_bd_num),
57a6c51c26SJian Shen HNS3_TQP_STAT("l2_err", l2_err),
58a6c51c26SJian Shen HNS3_TQP_STAT("l3l4_csum_err", l3l4_csum_err),
594b2fe769SHuazhong Tan HNS3_TQP_STAT("csum_complete", csum_complete),
60c376fa1aSJian Shen HNS3_TQP_STAT("multicast", rx_multicast),
61d21ff4f9SYunsheng Lin HNS3_TQP_STAT("non_reuse_pg", non_reuse_pg),
6299f6b5fbSYunsheng Lin HNS3_TQP_STAT("frag_alloc_err", frag_alloc_err),
6399f6b5fbSYunsheng Lin HNS3_TQP_STAT("frag_alloc", frag_alloc),
64424eb834SSalil Mehta };
65424eb834SSalil Mehta
665e7414cdSJian Shen #define HNS3_PRIV_FLAGS_LEN ARRAY_SIZE(hns3_priv_flags)
675e7414cdSJian Shen
68424eb834SSalil Mehta #define HNS3_RXQ_STATS_COUNT ARRAY_SIZE(hns3_rxq_stats)
69424eb834SSalil Mehta
70424eb834SSalil Mehta #define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT)
71424eb834SSalil Mehta
72424eb834SSalil Mehta #define HNS3_NIC_LB_TEST_PKT_NUM 1
73424eb834SSalil Mehta #define HNS3_NIC_LB_TEST_RING_ID 0
74424eb834SSalil Mehta #define HNS3_NIC_LB_TEST_PACKET_SIZE 128
75b37ce587SYufeng Mo #define HNS3_NIC_LB_SETUP_USEC 10000
76424eb834SSalil Mehta
77424eb834SSalil Mehta /* Nic loopback test err */
78424eb834SSalil Mehta #define HNS3_NIC_LB_TEST_NO_MEM_ERR 1
79424eb834SSalil Mehta #define HNS3_NIC_LB_TEST_TX_CNT_ERR 2
80424eb834SSalil Mehta #define HNS3_NIC_LB_TEST_RX_CNT_ERR 3
81*872f574fSJian Shen #define HNS3_NIC_LB_TEST_UNEXECUTED 4
82*872f574fSJian Shen
83*872f574fSJian Shen static int hns3_get_sset_count(struct net_device *netdev, int stringset);
84424eb834SSalil Mehta
hns3_lp_setup(struct net_device * ndev,enum hnae3_loop loop,bool en)85e4d68daeSYunsheng Lin static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
86424eb834SSalil Mehta {
87424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(ndev);
88295ba232SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
89424eb834SSalil Mehta int ret;
90424eb834SSalil Mehta
91424eb834SSalil Mehta if (!h->ae_algo->ops->set_loopback ||
92424eb834SSalil Mehta !h->ae_algo->ops->set_promisc_mode)
93424eb834SSalil Mehta return -EOPNOTSUPP;
94424eb834SSalil Mehta
95424eb834SSalil Mehta switch (loop) {
964dc13b96SFuyun Liang case HNAE3_LOOP_SERIAL_SERDES:
974dc13b96SFuyun Liang case HNAE3_LOOP_PARALLEL_SERDES:
98eb66d503SFuyun Liang case HNAE3_LOOP_APP:
99c9765a89SYufeng Mo case HNAE3_LOOP_PHY:
10004b6ba14SYonglong Liu case HNAE3_LOOP_EXTERNAL:
101e4d68daeSYunsheng Lin ret = h->ae_algo->ops->set_loopback(h, loop, en);
102424eb834SSalil Mehta break;
103424eb834SSalil Mehta default:
104424eb834SSalil Mehta ret = -ENOTSUPP;
105424eb834SSalil Mehta break;
106424eb834SSalil Mehta }
107424eb834SSalil Mehta
108295ba232SGuangbin Huang if (ret || ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2)
109424eb834SSalil Mehta return ret;
110424eb834SSalil Mehta
1112ba30662SJian Shen if (en)
112829edbd8SJian Shen h->ae_algo->ops->set_promisc_mode(h, true, true);
1132ba30662SJian Shen else
114829edbd8SJian Shen /* recover promisc mode before loopback test */
115c631c696SJian Shen hns3_request_update_promisc_mode(h);
116424eb834SSalil Mehta
117424eb834SSalil Mehta return ret;
118424eb834SSalil Mehta }
119424eb834SSalil Mehta
hns3_lp_up(struct net_device * ndev,enum hnae3_loop loop_mode)120424eb834SSalil Mehta static int hns3_lp_up(struct net_device *ndev, enum hnae3_loop loop_mode)
121424eb834SSalil Mehta {
122424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(ndev);
123424eb834SSalil Mehta int ret;
124424eb834SSalil Mehta
1257b763f3fSFuyun Liang ret = hns3_nic_reset_all_ring(h);
1267b763f3fSFuyun Liang if (ret)
1277b763f3fSFuyun Liang return ret;
1287b763f3fSFuyun Liang
129e4d68daeSYunsheng Lin ret = hns3_lp_setup(ndev, loop_mode, true);
130b37ce587SYufeng Mo usleep_range(HNS3_NIC_LB_SETUP_USEC, HNS3_NIC_LB_SETUP_USEC * 2);
131424eb834SSalil Mehta
13247ef6decSJian Shen return ret;
133424eb834SSalil Mehta }
134424eb834SSalil Mehta
hns3_lp_down(struct net_device * ndev,enum hnae3_loop loop_mode)135e4d68daeSYunsheng Lin static int hns3_lp_down(struct net_device *ndev, enum hnae3_loop loop_mode)
136424eb834SSalil Mehta {
137424eb834SSalil Mehta int ret;
138424eb834SSalil Mehta
139e4d68daeSYunsheng Lin ret = hns3_lp_setup(ndev, loop_mode, false);
140424eb834SSalil Mehta if (ret) {
141424eb834SSalil Mehta netdev_err(ndev, "lb_setup return error: %d\n", ret);
142424eb834SSalil Mehta return ret;
143424eb834SSalil Mehta }
144424eb834SSalil Mehta
145b37ce587SYufeng Mo usleep_range(HNS3_NIC_LB_SETUP_USEC, HNS3_NIC_LB_SETUP_USEC * 2);
146424eb834SSalil Mehta
147424eb834SSalil Mehta return 0;
148424eb834SSalil Mehta }
149424eb834SSalil Mehta
hns3_lp_setup_skb(struct sk_buff * skb)150424eb834SSalil Mehta static void hns3_lp_setup_skb(struct sk_buff *skb)
151424eb834SSalil Mehta {
152dd2956eaSYufeng Mo #define HNS3_NIC_LB_DST_MAC_ADDR 0x1f
153dd2956eaSYufeng Mo
154424eb834SSalil Mehta struct net_device *ndev = skb->dev;
155dd2956eaSYufeng Mo struct hnae3_handle *handle;
156295ba232SGuangbin Huang struct hnae3_ae_dev *ae_dev;
157424eb834SSalil Mehta unsigned char *packet;
158424eb834SSalil Mehta struct ethhdr *ethh;
159424eb834SSalil Mehta unsigned int i;
160424eb834SSalil Mehta
161424eb834SSalil Mehta skb_reserve(skb, NET_IP_ALIGN);
162424eb834SSalil Mehta ethh = skb_put(skb, sizeof(struct ethhdr));
163424eb834SSalil Mehta packet = skb_put(skb, HNS3_NIC_LB_TEST_PACKET_SIZE);
164424eb834SSalil Mehta
165424eb834SSalil Mehta memcpy(ethh->h_dest, ndev->dev_addr, ETH_ALEN);
1669b2f3477SWeihang Li
1679b2f3477SWeihang Li /* The dst mac addr of loopback packet is the same as the host'
1689b2f3477SWeihang Li * mac addr, the SSU component may loop back the packet to host
1699b2f3477SWeihang Li * before the packet reaches mac or serdes, which will defect
1709b2f3477SWeihang Li * the purpose of mac or serdes selftest.
1719b2f3477SWeihang Li */
172dd2956eaSYufeng Mo handle = hns3_get_handle(ndev);
173295ba232SGuangbin Huang ae_dev = pci_get_drvdata(handle->pdev);
174295ba232SGuangbin Huang if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
175dd2956eaSYufeng Mo ethh->h_dest[5] += HNS3_NIC_LB_DST_MAC_ADDR;
176424eb834SSalil Mehta eth_zero_addr(ethh->h_source);
177424eb834SSalil Mehta ethh->h_proto = htons(ETH_P_ARP);
178424eb834SSalil Mehta skb_reset_mac_header(skb);
179424eb834SSalil Mehta
180424eb834SSalil Mehta for (i = 0; i < HNS3_NIC_LB_TEST_PACKET_SIZE; i++)
181424eb834SSalil Mehta packet[i] = (unsigned char)(i & 0xff);
182424eb834SSalil Mehta }
183424eb834SSalil Mehta
hns3_lb_check_skb_data(struct hns3_enet_ring * ring,struct sk_buff * skb)184424eb834SSalil Mehta static void hns3_lb_check_skb_data(struct hns3_enet_ring *ring,
185424eb834SSalil Mehta struct sk_buff *skb)
186424eb834SSalil Mehta {
187424eb834SSalil Mehta struct hns3_enet_tqp_vector *tqp_vector = ring->tqp_vector;
188424eb834SSalil Mehta unsigned char *packet = skb->data;
189a0665621SYonglong Liu u32 len = skb_headlen(skb);
190424eb834SSalil Mehta u32 i;
191424eb834SSalil Mehta
192a0665621SYonglong Liu len = min_t(u32, len, HNS3_NIC_LB_TEST_PACKET_SIZE);
193a0665621SYonglong Liu
194a0665621SYonglong Liu for (i = 0; i < len; i++)
195424eb834SSalil Mehta if (packet[i] != (unsigned char)(i & 0xff))
196424eb834SSalil Mehta break;
197424eb834SSalil Mehta
198424eb834SSalil Mehta /* The packet is correctly received */
199a0665621SYonglong Liu if (i == HNS3_NIC_LB_TEST_PACKET_SIZE)
200424eb834SSalil Mehta tqp_vector->rx_group.total_packets++;
201424eb834SSalil Mehta else
202424eb834SSalil Mehta print_hex_dump(KERN_ERR, "selftest:", DUMP_PREFIX_OFFSET, 16, 1,
203a0665621SYonglong Liu skb->data, len, true);
204424eb834SSalil Mehta
205424eb834SSalil Mehta dev_kfree_skb_any(skb);
206424eb834SSalil Mehta }
207424eb834SSalil Mehta
hns3_lb_check_rx_ring(struct hns3_nic_priv * priv,u32 budget)208424eb834SSalil Mehta static u32 hns3_lb_check_rx_ring(struct hns3_nic_priv *priv, u32 budget)
209424eb834SSalil Mehta {
210424eb834SSalil Mehta struct hnae3_handle *h = priv->ae_handle;
211424eb834SSalil Mehta struct hnae3_knic_private_info *kinfo;
212424eb834SSalil Mehta u32 i, rcv_good_pkt_total = 0;
213424eb834SSalil Mehta
214424eb834SSalil Mehta kinfo = &h->kinfo;
215424eb834SSalil Mehta for (i = kinfo->num_tqps; i < kinfo->num_tqps * 2; i++) {
2165f06b903SYunsheng Lin struct hns3_enet_ring *ring = &priv->ring[i];
217424eb834SSalil Mehta struct hns3_enet_ring_group *rx_group;
218424eb834SSalil Mehta u64 pre_rx_pkt;
219424eb834SSalil Mehta
220424eb834SSalil Mehta rx_group = &ring->tqp_vector->rx_group;
221424eb834SSalil Mehta pre_rx_pkt = rx_group->total_packets;
222424eb834SSalil Mehta
223d7099d15SYunsheng Lin preempt_disable();
224424eb834SSalil Mehta hns3_clean_rx_ring(ring, budget, hns3_lb_check_skb_data);
225d7099d15SYunsheng Lin preempt_enable();
226424eb834SSalil Mehta
227424eb834SSalil Mehta rcv_good_pkt_total += (rx_group->total_packets - pre_rx_pkt);
228424eb834SSalil Mehta rx_group->total_packets = pre_rx_pkt;
229424eb834SSalil Mehta }
230424eb834SSalil Mehta return rcv_good_pkt_total;
231424eb834SSalil Mehta }
232424eb834SSalil Mehta
hns3_lb_clear_tx_ring(struct hns3_nic_priv * priv,u32 start_ringid,u32 end_ringid)233424eb834SSalil Mehta static void hns3_lb_clear_tx_ring(struct hns3_nic_priv *priv, u32 start_ringid,
234ed1c6f35SPeiyang Wang u32 end_ringid)
235424eb834SSalil Mehta {
236424eb834SSalil Mehta u32 i;
237424eb834SSalil Mehta
238424eb834SSalil Mehta for (i = start_ringid; i <= end_ringid; i++) {
2395f06b903SYunsheng Lin struct hns3_enet_ring *ring = &priv->ring[i];
240424eb834SSalil Mehta
241619ae331SYunsheng Lin hns3_clean_tx_ring(ring, 0);
242424eb834SSalil Mehta }
243424eb834SSalil Mehta }
244424eb834SSalil Mehta
245424eb834SSalil Mehta /**
246424eb834SSalil Mehta * hns3_lp_run_test - run loopback test
247424eb834SSalil Mehta * @ndev: net device
248424eb834SSalil Mehta * @mode: loopback type
24985879f13SRandy Dunlap *
25085879f13SRandy Dunlap * Return: %0 for success or a NIC loopback test error code on failure
251424eb834SSalil Mehta */
hns3_lp_run_test(struct net_device * ndev,enum hnae3_loop mode)252424eb834SSalil Mehta static int hns3_lp_run_test(struct net_device *ndev, enum hnae3_loop mode)
253424eb834SSalil Mehta {
254424eb834SSalil Mehta struct hns3_nic_priv *priv = netdev_priv(ndev);
255424eb834SSalil Mehta struct sk_buff *skb;
256424eb834SSalil Mehta u32 i, good_cnt;
257424eb834SSalil Mehta int ret_val = 0;
258424eb834SSalil Mehta
259424eb834SSalil Mehta skb = alloc_skb(HNS3_NIC_LB_TEST_PACKET_SIZE + ETH_HLEN + NET_IP_ALIGN,
260424eb834SSalil Mehta GFP_KERNEL);
261424eb834SSalil Mehta if (!skb)
262424eb834SSalil Mehta return HNS3_NIC_LB_TEST_NO_MEM_ERR;
263424eb834SSalil Mehta
264424eb834SSalil Mehta skb->dev = ndev;
265424eb834SSalil Mehta hns3_lp_setup_skb(skb);
266424eb834SSalil Mehta skb->queue_mapping = HNS3_NIC_LB_TEST_RING_ID;
267424eb834SSalil Mehta
268424eb834SSalil Mehta good_cnt = 0;
269424eb834SSalil Mehta for (i = 0; i < HNS3_NIC_LB_TEST_PKT_NUM; i++) {
270424eb834SSalil Mehta netdev_tx_t tx_ret;
271424eb834SSalil Mehta
272424eb834SSalil Mehta skb_get(skb);
273424eb834SSalil Mehta tx_ret = hns3_nic_net_xmit(skb, ndev);
2748f9eed1aSYunsheng Lin if (tx_ret == NETDEV_TX_OK) {
275424eb834SSalil Mehta good_cnt++;
2768f9eed1aSYunsheng Lin } else {
2778f9eed1aSYunsheng Lin kfree_skb(skb);
278424eb834SSalil Mehta netdev_err(ndev, "hns3_lb_run_test xmit failed: %d\n",
279424eb834SSalil Mehta tx_ret);
280424eb834SSalil Mehta }
2818f9eed1aSYunsheng Lin }
282424eb834SSalil Mehta if (good_cnt != HNS3_NIC_LB_TEST_PKT_NUM) {
283424eb834SSalil Mehta ret_val = HNS3_NIC_LB_TEST_TX_CNT_ERR;
284424eb834SSalil Mehta netdev_err(ndev, "mode %d sent fail, cnt=0x%x, budget=0x%x\n",
285424eb834SSalil Mehta mode, good_cnt, HNS3_NIC_LB_TEST_PKT_NUM);
286424eb834SSalil Mehta goto out;
287424eb834SSalil Mehta }
288424eb834SSalil Mehta
289424eb834SSalil Mehta /* Allow 200 milliseconds for packets to go from Tx to Rx */
290424eb834SSalil Mehta msleep(200);
291424eb834SSalil Mehta
292424eb834SSalil Mehta good_cnt = hns3_lb_check_rx_ring(priv, HNS3_NIC_LB_TEST_PKT_NUM);
293424eb834SSalil Mehta if (good_cnt != HNS3_NIC_LB_TEST_PKT_NUM) {
294424eb834SSalil Mehta ret_val = HNS3_NIC_LB_TEST_RX_CNT_ERR;
295424eb834SSalil Mehta netdev_err(ndev, "mode %d recv fail, cnt=0x%x, budget=0x%x\n",
296424eb834SSalil Mehta mode, good_cnt, HNS3_NIC_LB_TEST_PKT_NUM);
297424eb834SSalil Mehta }
298424eb834SSalil Mehta
299424eb834SSalil Mehta out:
300424eb834SSalil Mehta hns3_lb_clear_tx_ring(priv, HNS3_NIC_LB_TEST_RING_ID,
301ed1c6f35SPeiyang Wang HNS3_NIC_LB_TEST_RING_ID);
302424eb834SSalil Mehta
303424eb834SSalil Mehta kfree_skb(skb);
304424eb834SSalil Mehta return ret_val;
305424eb834SSalil Mehta }
306424eb834SSalil Mehta
hns3_set_selftest_param(struct hnae3_handle * h,int (* st_param)[2])3074c8dab1cSPeng Li static void hns3_set_selftest_param(struct hnae3_handle *h, int (*st_param)[2])
308424eb834SSalil Mehta {
30904b6ba14SYonglong Liu st_param[HNAE3_LOOP_EXTERNAL][0] = HNAE3_LOOP_EXTERNAL;
31004b6ba14SYonglong Liu st_param[HNAE3_LOOP_EXTERNAL][1] =
31104b6ba14SYonglong Liu h->flags & HNAE3_SUPPORT_EXTERNAL_LOOPBACK;
31204b6ba14SYonglong Liu
313eb66d503SFuyun Liang st_param[HNAE3_LOOP_APP][0] = HNAE3_LOOP_APP;
314eb66d503SFuyun Liang st_param[HNAE3_LOOP_APP][1] =
315eb66d503SFuyun Liang h->flags & HNAE3_SUPPORT_APP_LOOPBACK;
316424eb834SSalil Mehta
3174dc13b96SFuyun Liang st_param[HNAE3_LOOP_SERIAL_SERDES][0] = HNAE3_LOOP_SERIAL_SERDES;
3184dc13b96SFuyun Liang st_param[HNAE3_LOOP_SERIAL_SERDES][1] =
3194dc13b96SFuyun Liang h->flags & HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
3204dc13b96SFuyun Liang
3214dc13b96SFuyun Liang st_param[HNAE3_LOOP_PARALLEL_SERDES][0] =
3224dc13b96SFuyun Liang HNAE3_LOOP_PARALLEL_SERDES;
3234dc13b96SFuyun Liang st_param[HNAE3_LOOP_PARALLEL_SERDES][1] =
3244dc13b96SFuyun Liang h->flags & HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
3255fd50ac3SPeng Li
326c9765a89SYufeng Mo st_param[HNAE3_LOOP_PHY][0] = HNAE3_LOOP_PHY;
327c9765a89SYufeng Mo st_param[HNAE3_LOOP_PHY][1] =
328c9765a89SYufeng Mo h->flags & HNAE3_SUPPORT_PHY_LOOPBACK;
3294c8dab1cSPeng Li }
3304c8dab1cSPeng Li
hns3_selftest_prepare(struct net_device * ndev,bool if_running)33104b6ba14SYonglong Liu static void hns3_selftest_prepare(struct net_device *ndev, bool if_running)
3324c8dab1cSPeng Li {
3334c8dab1cSPeng Li struct hns3_nic_priv *priv = netdev_priv(ndev);
3344c8dab1cSPeng Li struct hnae3_handle *h = priv->ae_handle;
3354c8dab1cSPeng Li
336424eb834SSalil Mehta if (if_running)
3373f8601f0SYunsheng Lin ndev->netdev_ops->ndo_stop(ndev);
338424eb834SSalil Mehta
339f96818a7SYunsheng Lin #if IS_ENABLED(CONFIG_VLAN_8021Q)
340f96818a7SYunsheng Lin /* Disable the vlan filter for selftest does not support it */
34127bf4af6SGuangbin Huang if (h->ae_algo->ops->enable_vlan_filter &&
34227bf4af6SGuangbin Huang ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
343f96818a7SYunsheng Lin h->ae_algo->ops->enable_vlan_filter(h, false);
344f96818a7SYunsheng Lin #endif
345f96818a7SYunsheng Lin
3467786a996SJian Shen /* Tell firmware to stop mac autoneg before loopback test start,
3477786a996SJian Shen * otherwise loopback test may be failed when the port is still
3487786a996SJian Shen * negotiating.
3497786a996SJian Shen */
3507786a996SJian Shen if (h->ae_algo->ops->halt_autoneg)
3517786a996SJian Shen h->ae_algo->ops->halt_autoneg(h, true);
3527786a996SJian Shen
353424eb834SSalil Mehta set_bit(HNS3_NIC_STATE_TESTING, &priv->state);
3544c8dab1cSPeng Li }
3554c8dab1cSPeng Li
hns3_selftest_restore(struct net_device * ndev,bool if_running)3564c8dab1cSPeng Li static void hns3_selftest_restore(struct net_device *ndev, bool if_running)
3574c8dab1cSPeng Li {
3584c8dab1cSPeng Li struct hns3_nic_priv *priv = netdev_priv(ndev);
3594c8dab1cSPeng Li struct hnae3_handle *h = priv->ae_handle;
3604c8dab1cSPeng Li
3614c8dab1cSPeng Li clear_bit(HNS3_NIC_STATE_TESTING, &priv->state);
3624c8dab1cSPeng Li
3634c8dab1cSPeng Li if (h->ae_algo->ops->halt_autoneg)
3644c8dab1cSPeng Li h->ae_algo->ops->halt_autoneg(h, false);
3654c8dab1cSPeng Li
3664c8dab1cSPeng Li #if IS_ENABLED(CONFIG_VLAN_8021Q)
36727bf4af6SGuangbin Huang if (h->ae_algo->ops->enable_vlan_filter &&
36827bf4af6SGuangbin Huang ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
3694c8dab1cSPeng Li h->ae_algo->ops->enable_vlan_filter(h, true);
3704c8dab1cSPeng Li #endif
3714c8dab1cSPeng Li
3724c8dab1cSPeng Li if (if_running)
3734c8dab1cSPeng Li ndev->netdev_ops->ndo_open(ndev);
3744c8dab1cSPeng Li }
3754c8dab1cSPeng Li
hns3_do_selftest(struct net_device * ndev,int (* st_param)[2],struct ethtool_test * eth_test,u64 * data)3764c8dab1cSPeng Li static void hns3_do_selftest(struct net_device *ndev, int (*st_param)[2],
3774c8dab1cSPeng Li struct ethtool_test *eth_test, u64 *data)
3784c8dab1cSPeng Li {
37904b6ba14SYonglong Liu int test_index = HNAE3_LOOP_APP;
3804c8dab1cSPeng Li u32 i;
381424eb834SSalil Mehta
38204b6ba14SYonglong Liu for (i = HNAE3_LOOP_APP; i < HNAE3_LOOP_NONE; i++) {
383424eb834SSalil Mehta enum hnae3_loop loop_type = (enum hnae3_loop)st_param[i][0];
384424eb834SSalil Mehta
385424eb834SSalil Mehta if (!st_param[i][1])
386424eb834SSalil Mehta continue;
387424eb834SSalil Mehta
388424eb834SSalil Mehta data[test_index] = hns3_lp_up(ndev, loop_type);
38947ef6decSJian Shen if (!data[test_index])
390424eb834SSalil Mehta data[test_index] = hns3_lp_run_test(ndev, loop_type);
39147ef6decSJian Shen
392e4d68daeSYunsheng Lin hns3_lp_down(ndev, loop_type);
393424eb834SSalil Mehta
394424eb834SSalil Mehta if (data[test_index])
395424eb834SSalil Mehta eth_test->flags |= ETH_TEST_FL_FAILED;
396424eb834SSalil Mehta
397424eb834SSalil Mehta test_index++;
398424eb834SSalil Mehta }
3994c8dab1cSPeng Li }
400424eb834SSalil Mehta
hns3_do_external_lb(struct net_device * ndev,struct ethtool_test * eth_test,u64 * data)40104b6ba14SYonglong Liu static void hns3_do_external_lb(struct net_device *ndev,
40204b6ba14SYonglong Liu struct ethtool_test *eth_test, u64 *data)
40304b6ba14SYonglong Liu {
40404b6ba14SYonglong Liu data[HNAE3_LOOP_EXTERNAL] = hns3_lp_up(ndev, HNAE3_LOOP_EXTERNAL);
40504b6ba14SYonglong Liu if (!data[HNAE3_LOOP_EXTERNAL])
40604b6ba14SYonglong Liu data[HNAE3_LOOP_EXTERNAL] = hns3_lp_run_test(ndev, HNAE3_LOOP_EXTERNAL);
40704b6ba14SYonglong Liu hns3_lp_down(ndev, HNAE3_LOOP_EXTERNAL);
40804b6ba14SYonglong Liu
40904b6ba14SYonglong Liu if (data[HNAE3_LOOP_EXTERNAL])
41004b6ba14SYonglong Liu eth_test->flags |= ETH_TEST_FL_FAILED;
41104b6ba14SYonglong Liu
41204b6ba14SYonglong Liu eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
41304b6ba14SYonglong Liu }
41404b6ba14SYonglong Liu
4154c8dab1cSPeng Li /**
41685879f13SRandy Dunlap * hns3_self_test - self test
4174c8dab1cSPeng Li * @ndev: net device
4184c8dab1cSPeng Li * @eth_test: test cmd
4194c8dab1cSPeng Li * @data: test result
4204c8dab1cSPeng Li */
hns3_self_test(struct net_device * ndev,struct ethtool_test * eth_test,u64 * data)4214c8dab1cSPeng Li static void hns3_self_test(struct net_device *ndev,
4224c8dab1cSPeng Li struct ethtool_test *eth_test, u64 *data)
4234c8dab1cSPeng Li {
424*872f574fSJian Shen int cnt = hns3_get_sset_count(ndev, ETH_SS_TEST);
42504b6ba14SYonglong Liu struct hns3_nic_priv *priv = netdev_priv(ndev);
42604b6ba14SYonglong Liu struct hnae3_handle *h = priv->ae_handle;
42704b6ba14SYonglong Liu int st_param[HNAE3_LOOP_NONE][2];
4284c8dab1cSPeng Li bool if_running = netif_running(ndev);
429*872f574fSJian Shen int i;
430*872f574fSJian Shen
431*872f574fSJian Shen /* initialize the loopback test result, avoid marking an unexcuted
432*872f574fSJian Shen * loopback test as PASS.
433*872f574fSJian Shen */
434*872f574fSJian Shen for (i = 0; i < cnt; i++)
435*872f574fSJian Shen data[i] = HNS3_NIC_LB_TEST_UNEXECUTED;
436424eb834SSalil Mehta
4374c8dab1cSPeng Li if (hns3_nic_resetting(ndev)) {
4384c8dab1cSPeng Li netdev_err(ndev, "dev resetting!");
439*872f574fSJian Shen goto failure;
4404c8dab1cSPeng Li }
4417786a996SJian Shen
44204b6ba14SYonglong Liu if (!(eth_test->flags & ETH_TEST_FL_OFFLINE))
443*872f574fSJian Shen goto failure;
444f96818a7SYunsheng Lin
44504b6ba14SYonglong Liu if (netif_msg_ifdown(h))
44604b6ba14SYonglong Liu netdev_info(ndev, "self test start\n");
44704b6ba14SYonglong Liu
44804b6ba14SYonglong Liu hns3_set_selftest_param(h, st_param);
44904b6ba14SYonglong Liu
45004b6ba14SYonglong Liu /* external loopback test requires that the link is up and the duplex is
45104b6ba14SYonglong Liu * full, do external test first to reduce the whole test time
45204b6ba14SYonglong Liu */
45304b6ba14SYonglong Liu if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
45404b6ba14SYonglong Liu hns3_external_lb_prepare(ndev, if_running);
45504b6ba14SYonglong Liu hns3_do_external_lb(ndev, eth_test, data);
45604b6ba14SYonglong Liu hns3_external_lb_restore(ndev, if_running);
45704b6ba14SYonglong Liu }
45804b6ba14SYonglong Liu
45904b6ba14SYonglong Liu hns3_selftest_prepare(ndev, if_running);
4604c8dab1cSPeng Li hns3_do_selftest(ndev, st_param, eth_test, data);
4614c8dab1cSPeng Li hns3_selftest_restore(ndev, if_running);
46204b6ba14SYonglong Liu
46304b6ba14SYonglong Liu if (netif_msg_ifdown(h))
46404b6ba14SYonglong Liu netdev_info(ndev, "self test end\n");
465*872f574fSJian Shen return;
466*872f574fSJian Shen
467*872f574fSJian Shen failure:
468*872f574fSJian Shen eth_test->flags |= ETH_TEST_FL_FAILED;
469424eb834SSalil Mehta }
470424eb834SSalil Mehta
hns3_update_limit_promisc_mode(struct net_device * netdev,bool enable)4715e7414cdSJian Shen static void hns3_update_limit_promisc_mode(struct net_device *netdev,
4725e7414cdSJian Shen bool enable)
4735e7414cdSJian Shen {
4745e7414cdSJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
4755e7414cdSJian Shen
4765e7414cdSJian Shen if (enable)
4775e7414cdSJian Shen set_bit(HNAE3_PFLAG_LIMIT_PROMISC, &handle->priv_flags);
4785e7414cdSJian Shen else
4795e7414cdSJian Shen clear_bit(HNAE3_PFLAG_LIMIT_PROMISC, &handle->priv_flags);
4805e7414cdSJian Shen
4815e7414cdSJian Shen hns3_request_update_promisc_mode(handle);
4825e7414cdSJian Shen }
4835e7414cdSJian Shen
4845e7414cdSJian Shen static const struct hns3_pflag_desc hns3_priv_flags[HNAE3_PFLAG_MAX] = {
4855e7414cdSJian Shen { "limit_promisc", hns3_update_limit_promisc_mode }
4865e7414cdSJian Shen };
4875e7414cdSJian Shen
hns3_get_sset_count(struct net_device * netdev,int stringset)488424eb834SSalil Mehta static int hns3_get_sset_count(struct net_device *netdev, int stringset)
489424eb834SSalil Mehta {
490424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
491424eb834SSalil Mehta const struct hnae3_ae_ops *ops = h->ae_algo->ops;
492424eb834SSalil Mehta
493424eb834SSalil Mehta if (!ops->get_sset_count)
494424eb834SSalil Mehta return -EOPNOTSUPP;
495424eb834SSalil Mehta
496424eb834SSalil Mehta switch (stringset) {
497424eb834SSalil Mehta case ETH_SS_STATS:
498424eb834SSalil Mehta return ((HNS3_TQP_STATS_COUNT * h->kinfo.num_tqps) +
499424eb834SSalil Mehta ops->get_sset_count(h, stringset));
500424eb834SSalil Mehta
501424eb834SSalil Mehta case ETH_SS_TEST:
502424eb834SSalil Mehta return ops->get_sset_count(h, stringset);
503424eb834SSalil Mehta
5045e7414cdSJian Shen case ETH_SS_PRIV_FLAGS:
5055e7414cdSJian Shen return HNAE3_PFLAG_MAX;
5065e7414cdSJian Shen
507fa7a4bd5SJian Shen default:
508fa7a4bd5SJian Shen return -EOPNOTSUPP;
509fa7a4bd5SJian Shen }
510424eb834SSalil Mehta }
511424eb834SSalil Mehta
hns3_update_strings(u8 * data,const struct hns3_stats * stats,u32 stat_count,u32 num_tqps,const char * prefix)512424eb834SSalil Mehta static void *hns3_update_strings(u8 *data, const struct hns3_stats *stats,
513a6c51c26SJian Shen u32 stat_count, u32 num_tqps, const char *prefix)
514424eb834SSalil Mehta {
515a6c51c26SJian Shen #define MAX_PREFIX_SIZE (6 + 4)
516424eb834SSalil Mehta u32 size_left;
517424eb834SSalil Mehta u32 i, j;
518424eb834SSalil Mehta u32 n1;
519424eb834SSalil Mehta
520424eb834SSalil Mehta for (i = 0; i < num_tqps; i++) {
521424eb834SSalil Mehta for (j = 0; j < stat_count; j++) {
522424eb834SSalil Mehta data[ETH_GSTRING_LEN - 1] = '\0';
523424eb834SSalil Mehta
524424eb834SSalil Mehta /* first, prepend the prefix string */
525c5aaf176SJiaran Zhang n1 = scnprintf(data, MAX_PREFIX_SIZE, "%s%u_",
526a6c51c26SJian Shen prefix, i);
527424eb834SSalil Mehta size_left = (ETH_GSTRING_LEN - 1) - n1;
528424eb834SSalil Mehta
529424eb834SSalil Mehta /* now, concatenate the stats string to it */
530424eb834SSalil Mehta strncat(data, stats[j].stats_string, size_left);
531424eb834SSalil Mehta data += ETH_GSTRING_LEN;
532424eb834SSalil Mehta }
533424eb834SSalil Mehta }
534424eb834SSalil Mehta
535424eb834SSalil Mehta return data;
536424eb834SSalil Mehta }
537424eb834SSalil Mehta
hns3_get_strings_tqps(struct hnae3_handle * handle,u8 * data)538424eb834SSalil Mehta static u8 *hns3_get_strings_tqps(struct hnae3_handle *handle, u8 *data)
539424eb834SSalil Mehta {
540424eb834SSalil Mehta struct hnae3_knic_private_info *kinfo = &handle->kinfo;
541a6c51c26SJian Shen const char tx_prefix[] = "txq";
542a6c51c26SJian Shen const char rx_prefix[] = "rxq";
543424eb834SSalil Mehta
544424eb834SSalil Mehta /* get strings for Tx */
545424eb834SSalil Mehta data = hns3_update_strings(data, hns3_txq_stats, HNS3_TXQ_STATS_COUNT,
546a6c51c26SJian Shen kinfo->num_tqps, tx_prefix);
547424eb834SSalil Mehta
548424eb834SSalil Mehta /* get strings for Rx */
549424eb834SSalil Mehta data = hns3_update_strings(data, hns3_rxq_stats, HNS3_RXQ_STATS_COUNT,
550a6c51c26SJian Shen kinfo->num_tqps, rx_prefix);
551424eb834SSalil Mehta
552424eb834SSalil Mehta return data;
553424eb834SSalil Mehta }
554424eb834SSalil Mehta
hns3_get_strings(struct net_device * netdev,u32 stringset,u8 * data)555424eb834SSalil Mehta static void hns3_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
556424eb834SSalil Mehta {
557424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
558424eb834SSalil Mehta const struct hnae3_ae_ops *ops = h->ae_algo->ops;
559424eb834SSalil Mehta char *buff = (char *)data;
5605e7414cdSJian Shen int i;
561424eb834SSalil Mehta
562424eb834SSalil Mehta if (!ops->get_strings)
563424eb834SSalil Mehta return;
564424eb834SSalil Mehta
565424eb834SSalil Mehta switch (stringset) {
566424eb834SSalil Mehta case ETH_SS_STATS:
567424eb834SSalil Mehta buff = hns3_get_strings_tqps(h, buff);
56863cbf7a9SYufeng Mo ops->get_strings(h, stringset, (u8 *)buff);
569424eb834SSalil Mehta break;
570424eb834SSalil Mehta case ETH_SS_TEST:
571424eb834SSalil Mehta ops->get_strings(h, stringset, data);
572424eb834SSalil Mehta break;
5735e7414cdSJian Shen case ETH_SS_PRIV_FLAGS:
5745e7414cdSJian Shen for (i = 0; i < HNS3_PRIV_FLAGS_LEN; i++) {
5755e7414cdSJian Shen snprintf(buff, ETH_GSTRING_LEN, "%s",
5765e7414cdSJian Shen hns3_priv_flags[i].name);
5775e7414cdSJian Shen buff += ETH_GSTRING_LEN;
5785e7414cdSJian Shen }
5795e7414cdSJian Shen break;
580fa7a4bd5SJian Shen default:
581fa7a4bd5SJian Shen break;
582424eb834SSalil Mehta }
583424eb834SSalil Mehta }
584424eb834SSalil Mehta
hns3_get_stats_tqps(struct hnae3_handle * handle,u64 * data)585424eb834SSalil Mehta static u64 *hns3_get_stats_tqps(struct hnae3_handle *handle, u64 *data)
586424eb834SSalil Mehta {
587424eb834SSalil Mehta struct hnae3_knic_private_info *kinfo = &handle->kinfo;
58814fbcad0SWu Yunchuan struct hns3_nic_priv *nic_priv = handle->priv;
589424eb834SSalil Mehta struct hns3_enet_ring *ring;
590424eb834SSalil Mehta u8 *stat;
59194bfaafaSJian Shen int i, j;
592424eb834SSalil Mehta
593424eb834SSalil Mehta /* get stats for Tx */
594424eb834SSalil Mehta for (i = 0; i < kinfo->num_tqps; i++) {
5955f06b903SYunsheng Lin ring = &nic_priv->ring[i];
59694bfaafaSJian Shen for (j = 0; j < HNS3_TXQ_STATS_COUNT; j++) {
59794bfaafaSJian Shen stat = (u8 *)ring + hns3_txq_stats[j].stats_offset;
598424eb834SSalil Mehta *data++ = *(u64 *)stat;
599424eb834SSalil Mehta }
600424eb834SSalil Mehta }
601424eb834SSalil Mehta
602424eb834SSalil Mehta /* get stats for Rx */
603424eb834SSalil Mehta for (i = 0; i < kinfo->num_tqps; i++) {
6045f06b903SYunsheng Lin ring = &nic_priv->ring[i + kinfo->num_tqps];
60594bfaafaSJian Shen for (j = 0; j < HNS3_RXQ_STATS_COUNT; j++) {
60694bfaafaSJian Shen stat = (u8 *)ring + hns3_rxq_stats[j].stats_offset;
607424eb834SSalil Mehta *data++ = *(u64 *)stat;
608424eb834SSalil Mehta }
609424eb834SSalil Mehta }
610424eb834SSalil Mehta
611424eb834SSalil Mehta return data;
612424eb834SSalil Mehta }
613424eb834SSalil Mehta
614424eb834SSalil Mehta /* hns3_get_stats - get detail statistics.
615424eb834SSalil Mehta * @netdev: net device
616424eb834SSalil Mehta * @stats: statistics info.
617424eb834SSalil Mehta * @data: statistics data.
618424eb834SSalil Mehta */
hns3_get_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)619424eb834SSalil Mehta static void hns3_get_stats(struct net_device *netdev,
620424eb834SSalil Mehta struct ethtool_stats *stats, u64 *data)
621424eb834SSalil Mehta {
622424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
623424eb834SSalil Mehta u64 *p = data;
624424eb834SSalil Mehta
625c4e401e5SHuazhong Tan if (hns3_nic_resetting(netdev)) {
626c4e401e5SHuazhong Tan netdev_err(netdev, "dev resetting, could not get stats\n");
627c4e401e5SHuazhong Tan return;
628c4e401e5SHuazhong Tan }
629c4e401e5SHuazhong Tan
630424eb834SSalil Mehta if (!h->ae_algo->ops->get_stats || !h->ae_algo->ops->update_stats) {
631424eb834SSalil Mehta netdev_err(netdev, "could not get any statistics\n");
632424eb834SSalil Mehta return;
633424eb834SSalil Mehta }
634424eb834SSalil Mehta
635ed1c6f35SPeiyang Wang h->ae_algo->ops->update_stats(h);
636424eb834SSalil Mehta
637424eb834SSalil Mehta /* get per-queue stats */
638424eb834SSalil Mehta p = hns3_get_stats_tqps(h, p);
639424eb834SSalil Mehta
640424eb834SSalil Mehta /* get MAC & other misc hardware stats */
641424eb834SSalil Mehta h->ae_algo->ops->get_stats(h, p);
642424eb834SSalil Mehta }
643424eb834SSalil Mehta
hns3_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * drvinfo)644424eb834SSalil Mehta static void hns3_get_drvinfo(struct net_device *netdev,
645424eb834SSalil Mehta struct ethtool_drvinfo *drvinfo)
646424eb834SSalil Mehta {
647424eb834SSalil Mehta struct hns3_nic_priv *priv = netdev_priv(netdev);
648424eb834SSalil Mehta struct hnae3_handle *h = priv->ae_handle;
64992371373SYufeng Mo u32 fw_version;
650424eb834SSalil Mehta
65163cbf7a9SYufeng Mo if (!h->ae_algo->ops->get_fw_version) {
65263cbf7a9SYufeng Mo netdev_err(netdev, "could not get fw version!\n");
65363cbf7a9SYufeng Mo return;
65463cbf7a9SYufeng Mo }
65563cbf7a9SYufeng Mo
65680a464d8SXu Panda strscpy(drvinfo->driver, dev_driver_string(&h->pdev->dev),
657424eb834SSalil Mehta sizeof(drvinfo->driver));
658424eb834SSalil Mehta
65980a464d8SXu Panda strscpy(drvinfo->bus_info, pci_name(h->pdev),
660424eb834SSalil Mehta sizeof(drvinfo->bus_info));
661424eb834SSalil Mehta
66292371373SYufeng Mo fw_version = priv->ae_handle->ae_algo->ops->get_fw_version(h);
66392371373SYufeng Mo
66492371373SYufeng Mo snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
66592371373SYufeng Mo "%lu.%lu.%lu.%lu",
66692371373SYufeng Mo hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE3_MASK,
66792371373SYufeng Mo HNAE3_FW_VERSION_BYTE3_SHIFT),
66892371373SYufeng Mo hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE2_MASK,
66992371373SYufeng Mo HNAE3_FW_VERSION_BYTE2_SHIFT),
67092371373SYufeng Mo hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE1_MASK,
67192371373SYufeng Mo HNAE3_FW_VERSION_BYTE1_SHIFT),
67292371373SYufeng Mo hnae3_get_field(fw_version, HNAE3_FW_VERSION_BYTE0_MASK,
67392371373SYufeng Mo HNAE3_FW_VERSION_BYTE0_SHIFT));
674424eb834SSalil Mehta }
675424eb834SSalil Mehta
hns3_get_link(struct net_device * netdev)676424eb834SSalil Mehta static u32 hns3_get_link(struct net_device *netdev)
677424eb834SSalil Mehta {
678424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
679424eb834SSalil Mehta
68063cbf7a9SYufeng Mo if (h->ae_algo->ops->get_status)
681424eb834SSalil Mehta return h->ae_algo->ops->get_status(h);
682424eb834SSalil Mehta else
683424eb834SSalil Mehta return 0;
684424eb834SSalil Mehta }
685424eb834SSalil Mehta
hns3_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * param,struct kernel_ethtool_ringparam * kernel_param,struct netlink_ext_ack * extack)686424eb834SSalil Mehta static void hns3_get_ringparam(struct net_device *netdev,
68774624944SHao Chen struct ethtool_ringparam *param,
68874624944SHao Chen struct kernel_ethtool_ringparam *kernel_param,
68974624944SHao Chen struct netlink_ext_ack *extack)
690424eb834SSalil Mehta {
691424eb834SSalil Mehta struct hns3_nic_priv *priv = netdev_priv(netdev);
692424eb834SSalil Mehta struct hnae3_handle *h = priv->ae_handle;
693e65a0231SHao Chen int rx_queue_index = h->kinfo.num_tqps;
694424eb834SSalil Mehta
6954d07c593SHao Chen if (hns3_nic_resetting(netdev) || !priv->ring) {
6964d07c593SHao Chen netdev_err(netdev, "failed to get ringparam value, due to dev resetting or uninited\n");
697257e4f29SHuazhong Tan return;
698257e4f29SHuazhong Tan }
699257e4f29SHuazhong Tan
700424eb834SSalil Mehta param->tx_max_pending = HNS3_RING_MAX_PENDING;
701424eb834SSalil Mehta param->rx_max_pending = HNS3_RING_MAX_PENDING;
702424eb834SSalil Mehta
7035f06b903SYunsheng Lin param->tx_pending = priv->ring[0].desc_num;
704e65a0231SHao Chen param->rx_pending = priv->ring[rx_queue_index].desc_num;
705e65a0231SHao Chen kernel_param->rx_buf_len = priv->ring[rx_queue_index].buf_size;
7061f702c16SJie Wang kernel_param->tx_push = test_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE,
7071f702c16SJie Wang &priv->state);
708424eb834SSalil Mehta }
709424eb834SSalil Mehta
hns3_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * param)710424eb834SSalil Mehta static void hns3_get_pauseparam(struct net_device *netdev,
711424eb834SSalil Mehta struct ethtool_pauseparam *param)
712424eb834SSalil Mehta {
713424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
714e8194f32SYufeng Mo struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
715e8194f32SYufeng Mo
716e8194f32SYufeng Mo if (!test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps))
717e8194f32SYufeng Mo return;
718424eb834SSalil Mehta
71963cbf7a9SYufeng Mo if (h->ae_algo->ops->get_pauseparam)
720424eb834SSalil Mehta h->ae_algo->ops->get_pauseparam(h, ¶m->autoneg,
721424eb834SSalil Mehta ¶m->rx_pause, ¶m->tx_pause);
722424eb834SSalil Mehta }
723424eb834SSalil Mehta
hns3_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * param)72461387774SPeng Li static int hns3_set_pauseparam(struct net_device *netdev,
72561387774SPeng Li struct ethtool_pauseparam *param)
72661387774SPeng Li {
72761387774SPeng Li struct hnae3_handle *h = hns3_get_handle(netdev);
728e8194f32SYufeng Mo struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
729e8194f32SYufeng Mo
730e8194f32SYufeng Mo if (!test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps))
731e8194f32SYufeng Mo return -EOPNOTSUPP;
73261387774SPeng Li
7331c822948SYonglong Liu netif_dbg(h, drv, netdev,
7341c822948SYonglong Liu "set pauseparam: autoneg=%u, rx:%u, tx:%u\n",
7351c822948SYonglong Liu param->autoneg, param->rx_pause, param->tx_pause);
7361c822948SYonglong Liu
73761387774SPeng Li if (h->ae_algo->ops->set_pauseparam)
73861387774SPeng Li return h->ae_algo->ops->set_pauseparam(h, param->autoneg,
73961387774SPeng Li param->rx_pause,
74061387774SPeng Li param->tx_pause);
74161387774SPeng Li return -EOPNOTSUPP;
74261387774SPeng Li }
74361387774SPeng Li
hns3_get_ksettings(struct hnae3_handle * h,struct ethtool_link_ksettings * cmd)7445f373b15SFuyun Liang static void hns3_get_ksettings(struct hnae3_handle *h,
745424eb834SSalil Mehta struct ethtool_link_ksettings *cmd)
746424eb834SSalil Mehta {
7475f373b15SFuyun Liang const struct hnae3_ae_ops *ops = h->ae_algo->ops;
748424eb834SSalil Mehta
749424eb834SSalil Mehta /* 1.auto_neg & speed & duplex from cmd */
75012f46bc1SJian Shen if (ops->get_ksettings_an_result)
75112f46bc1SJian Shen ops->get_ksettings_an_result(h,
752424eb834SSalil Mehta &cmd->base.autoneg,
753424eb834SSalil Mehta &cmd->base.speed,
7540f032f93SHao Chen &cmd->base.duplex,
7550f032f93SHao Chen &cmd->lanes);
756424eb834SSalil Mehta
75712f46bc1SJian Shen /* 2.get link mode */
75812f46bc1SJian Shen if (ops->get_link_mode)
75912f46bc1SJian Shen ops->get_link_mode(h,
76012f46bc1SJian Shen cmd->link_modes.supported,
76112f46bc1SJian Shen cmd->link_modes.advertising);
76212f46bc1SJian Shen
76312f46bc1SJian Shen /* 3.mdix_ctrl&mdix get from phy reg */
76412f46bc1SJian Shen if (ops->get_mdix_mode)
76512f46bc1SJian Shen ops->get_mdix_mode(h, &cmd->base.eth_tp_mdix_ctrl,
76612f46bc1SJian Shen &cmd->base.eth_tp_mdix);
7675f373b15SFuyun Liang }
76812f46bc1SJian Shen
hns3_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)7695f373b15SFuyun Liang static int hns3_get_link_ksettings(struct net_device *netdev,
7705f373b15SFuyun Liang struct ethtool_link_ksettings *cmd)
7715f373b15SFuyun Liang {
7725f373b15SFuyun Liang struct hnae3_handle *h = hns3_get_handle(netdev);
773f5f2b3e4SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
7745f373b15SFuyun Liang const struct hnae3_ae_ops *ops;
77588d10bd6SJian Shen u8 module_type;
7765f373b15SFuyun Liang u8 media_type;
7775f373b15SFuyun Liang u8 link_stat;
7785f373b15SFuyun Liang
7795f373b15SFuyun Liang ops = h->ae_algo->ops;
7805f373b15SFuyun Liang if (ops->get_media_type)
78188d10bd6SJian Shen ops->get_media_type(h, &media_type, &module_type);
7825f373b15SFuyun Liang else
7835f373b15SFuyun Liang return -EOPNOTSUPP;
7845f373b15SFuyun Liang
7855f373b15SFuyun Liang switch (media_type) {
7865f373b15SFuyun Liang case HNAE3_MEDIA_TYPE_NONE:
7875f373b15SFuyun Liang cmd->base.port = PORT_NONE;
7885f373b15SFuyun Liang hns3_get_ksettings(h, cmd);
78912f46bc1SJian Shen break;
7905f373b15SFuyun Liang case HNAE3_MEDIA_TYPE_FIBER:
791674d9591SYisen Zhuang if (module_type == HNAE3_MODULE_TYPE_UNKNOWN)
792674d9591SYisen Zhuang cmd->base.port = PORT_OTHER;
793674d9591SYisen Zhuang else if (module_type == HNAE3_MODULE_TYPE_CR)
79488d10bd6SJian Shen cmd->base.port = PORT_DA;
79588d10bd6SJian Shen else
7965f373b15SFuyun Liang cmd->base.port = PORT_FIBRE;
79788d10bd6SJian Shen
79888d10bd6SJian Shen hns3_get_ksettings(h, cmd);
79988d10bd6SJian Shen break;
80088d10bd6SJian Shen case HNAE3_MEDIA_TYPE_BACKPLANE:
80188d10bd6SJian Shen cmd->base.port = PORT_NONE;
8025f373b15SFuyun Liang hns3_get_ksettings(h, cmd);
8035f373b15SFuyun Liang break;
8045f373b15SFuyun Liang case HNAE3_MEDIA_TYPE_COPPER:
8055f373b15SFuyun Liang cmd->base.port = PORT_TP;
806f5f2b3e4SGuangbin Huang if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
807f5f2b3e4SGuangbin Huang ops->get_phy_link_ksettings)
808f5f2b3e4SGuangbin Huang ops->get_phy_link_ksettings(h, cmd);
809f5f2b3e4SGuangbin Huang else if (!netdev->phydev)
810f18635d5SJian Shen hns3_get_ksettings(h, cmd);
811f18635d5SJian Shen else
81212f46bc1SJian Shen phy_ethtool_ksettings_get(netdev->phydev, cmd);
81312f46bc1SJian Shen break;
81412f46bc1SJian Shen default:
8155f373b15SFuyun Liang
8165f373b15SFuyun Liang netdev_warn(netdev, "Unknown media type");
81712f46bc1SJian Shen return 0;
81812f46bc1SJian Shen }
81912f46bc1SJian Shen
82012f46bc1SJian Shen /* mdio_support */
82112f46bc1SJian Shen cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22;
82212f46bc1SJian Shen
823424eb834SSalil Mehta link_stat = hns3_get_link(netdev);
824424eb834SSalil Mehta if (!link_stat) {
825424eb834SSalil Mehta cmd->base.speed = SPEED_UNKNOWN;
826424eb834SSalil Mehta cmd->base.duplex = DUPLEX_UNKNOWN;
827424eb834SSalil Mehta }
828424eb834SSalil Mehta
829424eb834SSalil Mehta return 0;
830424eb834SSalil Mehta }
831424eb834SSalil Mehta
hns3_check_ksettings_param(const struct net_device * netdev,const struct ethtool_link_ksettings * cmd)83237417c66SGuojia Liao static int hns3_check_ksettings_param(const struct net_device *netdev,
83322f48e24SJian Shen const struct ethtool_link_ksettings *cmd)
83422f48e24SJian Shen {
83522f48e24SJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
83622f48e24SJian Shen const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
83722f48e24SJian Shen u8 module_type = HNAE3_MODULE_TYPE_UNKNOWN;
83822f48e24SJian Shen u8 media_type = HNAE3_MEDIA_TYPE_UNKNOWN;
8390f032f93SHao Chen u32 lane_num;
84022f48e24SJian Shen u8 autoneg;
84122f48e24SJian Shen u32 speed;
84222f48e24SJian Shen u8 duplex;
84322f48e24SJian Shen int ret;
84422f48e24SJian Shen
84524283eceSGuangbin Huang /* hw doesn't support use specified speed and duplex to negotiate,
84624283eceSGuangbin Huang * unnecessary to check them when autoneg on.
84724283eceSGuangbin Huang */
84824283eceSGuangbin Huang if (cmd->base.autoneg)
84924283eceSGuangbin Huang return 0;
85024283eceSGuangbin Huang
85122f48e24SJian Shen if (ops->get_ksettings_an_result) {
8520f032f93SHao Chen ops->get_ksettings_an_result(handle, &autoneg, &speed, &duplex, &lane_num);
85322f48e24SJian Shen if (cmd->base.autoneg == autoneg && cmd->base.speed == speed &&
8540f032f93SHao Chen cmd->base.duplex == duplex && cmd->lanes == lane_num)
85522f48e24SJian Shen return 0;
85622f48e24SJian Shen }
85722f48e24SJian Shen
85822f48e24SJian Shen if (ops->get_media_type)
85922f48e24SJian Shen ops->get_media_type(handle, &media_type, &module_type);
86022f48e24SJian Shen
8612d3db26dSGuangbin Huang if (cmd->base.duplex == DUPLEX_HALF &&
86222f48e24SJian Shen media_type != HNAE3_MEDIA_TYPE_COPPER) {
86322f48e24SJian Shen netdev_err(netdev,
86422f48e24SJian Shen "only copper port supports half duplex!");
86522f48e24SJian Shen return -EINVAL;
86622f48e24SJian Shen }
86722f48e24SJian Shen
86822f48e24SJian Shen if (ops->check_port_speed) {
86922f48e24SJian Shen ret = ops->check_port_speed(handle, cmd->base.speed);
87022f48e24SJian Shen if (ret) {
87122f48e24SJian Shen netdev_err(netdev, "unsupported speed\n");
87222f48e24SJian Shen return ret;
87322f48e24SJian Shen }
87422f48e24SJian Shen }
87522f48e24SJian Shen
87622f48e24SJian Shen return 0;
87722f48e24SJian Shen }
87822f48e24SJian Shen
hns3_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * cmd)879424eb834SSalil Mehta static int hns3_set_link_ksettings(struct net_device *netdev,
880424eb834SSalil Mehta const struct ethtool_link_ksettings *cmd)
881424eb834SSalil Mehta {
88222f48e24SJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
883295ba232SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
88422f48e24SJian Shen const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
885cdd332acSGuojia Liao int ret;
88622f48e24SJian Shen
88722f48e24SJian Shen /* Chip don't support this mode. */
88895dbab9fSPeng Li if (cmd->base.speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
88995dbab9fSPeng Li return -EINVAL;
89095dbab9fSPeng Li
8910f032f93SHao Chen if (cmd->lanes && !hnae3_ae_dev_lane_num_supported(ae_dev))
8920f032f93SHao Chen return -EOPNOTSUPP;
8930f032f93SHao Chen
8941c822948SYonglong Liu netif_dbg(handle, drv, netdev,
8950f032f93SHao Chen "set link(%s): autoneg=%u, speed=%u, duplex=%u, lanes=%u\n",
8961c822948SYonglong Liu netdev->phydev ? "phy" : "mac",
8970f032f93SHao Chen cmd->base.autoneg, cmd->base.speed, cmd->base.duplex,
8980f032f93SHao Chen cmd->lanes);
8991c822948SYonglong Liu
900424eb834SSalil Mehta /* Only support ksettings_set for netdev with phy attached for now */
90181c287e3SYufeng Mo if (netdev->phydev) {
90281c287e3SYufeng Mo if (cmd->base.speed == SPEED_1000 &&
90381c287e3SYufeng Mo cmd->base.autoneg == AUTONEG_DISABLE)
90481c287e3SYufeng Mo return -EINVAL;
90581c287e3SYufeng Mo
906424eb834SSalil Mehta return phy_ethtool_ksettings_set(netdev->phydev, cmd);
907f5f2b3e4SGuangbin Huang } else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
908f5f2b3e4SGuangbin Huang ops->set_phy_link_ksettings) {
909f5f2b3e4SGuangbin Huang return ops->set_phy_link_ksettings(handle, cmd);
91081c287e3SYufeng Mo }
911424eb834SSalil Mehta
912295ba232SGuangbin Huang if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
913424eb834SSalil Mehta return -EOPNOTSUPP;
91422f48e24SJian Shen
91522f48e24SJian Shen ret = hns3_check_ksettings_param(netdev, cmd);
91622f48e24SJian Shen if (ret)
91722f48e24SJian Shen return ret;
91822f48e24SJian Shen
91922f48e24SJian Shen if (ops->set_autoneg) {
92022f48e24SJian Shen ret = ops->set_autoneg(handle, cmd->base.autoneg);
92122f48e24SJian Shen if (ret)
92222f48e24SJian Shen return ret;
92322f48e24SJian Shen }
92422f48e24SJian Shen
92524283eceSGuangbin Huang /* hw doesn't support use specified speed and duplex to negotiate,
92624283eceSGuangbin Huang * ignore them when autoneg on.
92724283eceSGuangbin Huang */
92824283eceSGuangbin Huang if (cmd->base.autoneg) {
92924283eceSGuangbin Huang netdev_info(netdev,
93024283eceSGuangbin Huang "autoneg is on, ignore the speed and duplex\n");
93124283eceSGuangbin Huang return 0;
93224283eceSGuangbin Huang }
93324283eceSGuangbin Huang
93422f48e24SJian Shen if (ops->cfg_mac_speed_dup_h)
93522f48e24SJian Shen ret = ops->cfg_mac_speed_dup_h(handle, cmd->base.speed,
9360f032f93SHao Chen cmd->base.duplex, (u8)(cmd->lanes));
93722f48e24SJian Shen
93822f48e24SJian Shen return ret;
939424eb834SSalil Mehta }
940424eb834SSalil Mehta
hns3_get_rss_key_size(struct net_device * netdev)941424eb834SSalil Mehta static u32 hns3_get_rss_key_size(struct net_device *netdev)
942424eb834SSalil Mehta {
943424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
944424eb834SSalil Mehta
94563cbf7a9SYufeng Mo if (!h->ae_algo->ops->get_rss_key_size)
9463bd6d258SFuyun Liang return 0;
947424eb834SSalil Mehta
948424eb834SSalil Mehta return h->ae_algo->ops->get_rss_key_size(h);
949424eb834SSalil Mehta }
950424eb834SSalil Mehta
hns3_get_rss_indir_size(struct net_device * netdev)951424eb834SSalil Mehta static u32 hns3_get_rss_indir_size(struct net_device *netdev)
952424eb834SSalil Mehta {
953424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
95487ce161eSGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
955424eb834SSalil Mehta
95687ce161eSGuangbin Huang return ae_dev->dev_specs.rss_ind_tbl_size;
957424eb834SSalil Mehta }
958424eb834SSalil Mehta
hns3_get_rss(struct net_device * netdev,u32 * indir,u8 * key,u8 * hfunc)959424eb834SSalil Mehta static int hns3_get_rss(struct net_device *netdev, u32 *indir, u8 *key,
960424eb834SSalil Mehta u8 *hfunc)
961424eb834SSalil Mehta {
962424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
963424eb834SSalil Mehta
96463cbf7a9SYufeng Mo if (!h->ae_algo->ops->get_rss)
965424eb834SSalil Mehta return -EOPNOTSUPP;
966424eb834SSalil Mehta
967424eb834SSalil Mehta return h->ae_algo->ops->get_rss(h, indir, key, hfunc);
968424eb834SSalil Mehta }
969424eb834SSalil Mehta
hns3_set_rss(struct net_device * netdev,const u32 * indir,const u8 * key,const u8 hfunc)970424eb834SSalil Mehta static int hns3_set_rss(struct net_device *netdev, const u32 *indir,
971424eb834SSalil Mehta const u8 *key, const u8 hfunc)
972424eb834SSalil Mehta {
973424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
974295ba232SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
975424eb834SSalil Mehta
97663cbf7a9SYufeng Mo if (!h->ae_algo->ops->set_rss)
977424eb834SSalil Mehta return -EOPNOTSUPP;
978424eb834SSalil Mehta
979295ba232SGuangbin Huang if ((ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2 &&
980775501a1SJian Shen hfunc != ETH_RSS_HASH_TOP) || (hfunc != ETH_RSS_HASH_NO_CHANGE &&
981775501a1SJian Shen hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR)) {
982775501a1SJian Shen netdev_err(netdev, "hash func not supported\n");
983424eb834SSalil Mehta return -EOPNOTSUPP;
984424eb834SSalil Mehta }
985775501a1SJian Shen
986424eb834SSalil Mehta if (!indir) {
987424eb834SSalil Mehta netdev_err(netdev,
988424eb834SSalil Mehta "set rss failed for indir is empty\n");
989424eb834SSalil Mehta return -EOPNOTSUPP;
990424eb834SSalil Mehta }
991424eb834SSalil Mehta
992424eb834SSalil Mehta return h->ae_algo->ops->set_rss(h, indir, key, hfunc);
993424eb834SSalil Mehta }
994424eb834SSalil Mehta
hns3_get_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * cmd,u32 * rule_locs)995424eb834SSalil Mehta static int hns3_get_rxnfc(struct net_device *netdev,
996424eb834SSalil Mehta struct ethtool_rxnfc *cmd,
997424eb834SSalil Mehta u32 *rule_locs)
998424eb834SSalil Mehta {
999424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
1000424eb834SSalil Mehta
1001424eb834SSalil Mehta switch (cmd->cmd) {
1002424eb834SSalil Mehta case ETHTOOL_GRXRINGS:
100305c2314fSJian Shen cmd->data = h->kinfo.num_tqps;
100405c2314fSJian Shen return 0;
1005424eb834SSalil Mehta case ETHTOOL_GRXFH:
100605c2314fSJian Shen if (h->ae_algo->ops->get_rss_tuple)
1007424eb834SSalil Mehta return h->ae_algo->ops->get_rss_tuple(h, cmd);
100805c2314fSJian Shen return -EOPNOTSUPP;
100905c2314fSJian Shen case ETHTOOL_GRXCLSRLCNT:
101005c2314fSJian Shen if (h->ae_algo->ops->get_fd_rule_cnt)
101105c2314fSJian Shen return h->ae_algo->ops->get_fd_rule_cnt(h, cmd);
101205c2314fSJian Shen return -EOPNOTSUPP;
101305c2314fSJian Shen case ETHTOOL_GRXCLSRULE:
101405c2314fSJian Shen if (h->ae_algo->ops->get_fd_rule_info)
101505c2314fSJian Shen return h->ae_algo->ops->get_fd_rule_info(h, cmd);
101605c2314fSJian Shen return -EOPNOTSUPP;
101705c2314fSJian Shen case ETHTOOL_GRXCLSRLALL:
101805c2314fSJian Shen if (h->ae_algo->ops->get_fd_all_rules)
101905c2314fSJian Shen return h->ae_algo->ops->get_fd_all_rules(h, cmd,
102005c2314fSJian Shen rule_locs);
102105c2314fSJian Shen return -EOPNOTSUPP;
1022424eb834SSalil Mehta default:
1023424eb834SSalil Mehta return -EOPNOTSUPP;
1024424eb834SSalil Mehta }
1025424eb834SSalil Mehta }
1026424eb834SSalil Mehta
1027ddccc5e3SYufeng Mo static const struct hns3_reset_type_map hns3_reset_type[] = {
1028ddccc5e3SYufeng Mo {ETH_RESET_MGMT, HNAE3_IMP_RESET},
1029ddccc5e3SYufeng Mo {ETH_RESET_ALL, HNAE3_GLOBAL_RESET},
1030ddccc5e3SYufeng Mo {ETH_RESET_DEDICATED, HNAE3_FUNC_RESET},
1031ddccc5e3SYufeng Mo };
1032ddccc5e3SYufeng Mo
1033ddccc5e3SYufeng Mo static const struct hns3_reset_type_map hns3vf_reset_type[] = {
1034ddccc5e3SYufeng Mo {ETH_RESET_DEDICATED, HNAE3_VF_FUNC_RESET},
1035ddccc5e3SYufeng Mo };
1036ddccc5e3SYufeng Mo
hns3_set_reset(struct net_device * netdev,u32 * flags)1037ddccc5e3SYufeng Mo static int hns3_set_reset(struct net_device *netdev, u32 *flags)
1038ddccc5e3SYufeng Mo {
1039ddccc5e3SYufeng Mo enum hnae3_reset_type rst_type = HNAE3_NONE_RESET;
1040ddccc5e3SYufeng Mo struct hnae3_handle *h = hns3_get_handle(netdev);
1041ddccc5e3SYufeng Mo struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
1042ddccc5e3SYufeng Mo const struct hnae3_ae_ops *ops = h->ae_algo->ops;
1043ddccc5e3SYufeng Mo const struct hns3_reset_type_map *rst_type_map;
104482229c4dSJie Wang enum ethtool_reset_flags rst_flags;
1045ddccc5e3SYufeng Mo u32 i, size;
1046ddccc5e3SYufeng Mo
1047ddccc5e3SYufeng Mo if (ops->ae_dev_resetting && ops->ae_dev_resetting(h))
1048ddccc5e3SYufeng Mo return -EBUSY;
1049ddccc5e3SYufeng Mo
1050ddccc5e3SYufeng Mo if (!ops->set_default_reset_request || !ops->reset_event)
1051ddccc5e3SYufeng Mo return -EOPNOTSUPP;
1052ddccc5e3SYufeng Mo
1053ddccc5e3SYufeng Mo if (h->flags & HNAE3_SUPPORT_VF) {
1054ddccc5e3SYufeng Mo rst_type_map = hns3vf_reset_type;
1055ddccc5e3SYufeng Mo size = ARRAY_SIZE(hns3vf_reset_type);
1056ddccc5e3SYufeng Mo } else {
1057ddccc5e3SYufeng Mo rst_type_map = hns3_reset_type;
1058ddccc5e3SYufeng Mo size = ARRAY_SIZE(hns3_reset_type);
1059ddccc5e3SYufeng Mo }
1060ddccc5e3SYufeng Mo
1061ddccc5e3SYufeng Mo for (i = 0; i < size; i++) {
1062ddccc5e3SYufeng Mo if (rst_type_map[i].rst_flags == *flags) {
1063ddccc5e3SYufeng Mo rst_type = rst_type_map[i].rst_type;
106482229c4dSJie Wang rst_flags = rst_type_map[i].rst_flags;
1065ddccc5e3SYufeng Mo break;
1066ddccc5e3SYufeng Mo }
1067ddccc5e3SYufeng Mo }
1068ddccc5e3SYufeng Mo
1069ddccc5e3SYufeng Mo if (rst_type == HNAE3_NONE_RESET ||
1070ddccc5e3SYufeng Mo (rst_type == HNAE3_IMP_RESET &&
1071ddccc5e3SYufeng Mo ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2))
1072ddccc5e3SYufeng Mo return -EOPNOTSUPP;
1073ddccc5e3SYufeng Mo
1074ddccc5e3SYufeng Mo netdev_info(netdev, "Setting reset type %d\n", rst_type);
1075ddccc5e3SYufeng Mo
1076ddccc5e3SYufeng Mo ops->set_default_reset_request(ae_dev, rst_type);
1077ddccc5e3SYufeng Mo
1078ddccc5e3SYufeng Mo ops->reset_event(h->pdev, h);
1079ddccc5e3SYufeng Mo
108082229c4dSJie Wang *flags &= ~rst_flags;
108182229c4dSJie Wang
1082ddccc5e3SYufeng Mo return 0;
1083ddccc5e3SYufeng Mo }
1084ddccc5e3SYufeng Mo
hns3_change_all_ring_bd_num(struct hns3_nic_priv * priv,u32 tx_desc_num,u32 rx_desc_num)1085a723fb8eSJian Shen static void hns3_change_all_ring_bd_num(struct hns3_nic_priv *priv,
1086c0425944SPeng Li u32 tx_desc_num, u32 rx_desc_num)
1087424eb834SSalil Mehta {
1088424eb834SSalil Mehta struct hnae3_handle *h = priv->ae_handle;
1089424eb834SSalil Mehta int i;
1090424eb834SSalil Mehta
1091c0425944SPeng Li h->kinfo.num_tx_desc = tx_desc_num;
1092c0425944SPeng Li h->kinfo.num_rx_desc = rx_desc_num;
1093424eb834SSalil Mehta
1094c0425944SPeng Li for (i = 0; i < h->kinfo.num_tqps; i++) {
10955f06b903SYunsheng Lin priv->ring[i].desc_num = tx_desc_num;
10965f06b903SYunsheng Lin priv->ring[i + h->kinfo.num_tqps].desc_num = rx_desc_num;
1097c0425944SPeng Li }
1098424eb834SSalil Mehta }
1099424eb834SSalil Mehta
hns3_backup_ringparam(struct hns3_nic_priv * priv)1100a723fb8eSJian Shen static struct hns3_enet_ring *hns3_backup_ringparam(struct hns3_nic_priv *priv)
1101a723fb8eSJian Shen {
1102a723fb8eSJian Shen struct hnae3_handle *handle = priv->ae_handle;
1103a723fb8eSJian Shen struct hns3_enet_ring *tmp_rings;
1104a723fb8eSJian Shen int i;
1105a723fb8eSJian Shen
1106a723fb8eSJian Shen tmp_rings = kcalloc(handle->kinfo.num_tqps * 2,
1107a723fb8eSJian Shen sizeof(struct hns3_enet_ring), GFP_KERNEL);
1108a723fb8eSJian Shen if (!tmp_rings)
1109a723fb8eSJian Shen return NULL;
1110a723fb8eSJian Shen
1111323a2ac5SHuazhong Tan for (i = 0; i < handle->kinfo.num_tqps * 2; i++) {
11125f06b903SYunsheng Lin memcpy(&tmp_rings[i], &priv->ring[i],
1113a723fb8eSJian Shen sizeof(struct hns3_enet_ring));
1114323a2ac5SHuazhong Tan tmp_rings[i].skb = NULL;
1115323a2ac5SHuazhong Tan }
1116a723fb8eSJian Shen
1117a723fb8eSJian Shen return tmp_rings;
1118a723fb8eSJian Shen }
1119a723fb8eSJian Shen
hns3_check_ringparam(struct net_device * ndev,struct ethtool_ringparam * param,struct kernel_ethtool_ringparam * kernel_param)1120a723fb8eSJian Shen static int hns3_check_ringparam(struct net_device *ndev,
1121e65a0231SHao Chen struct ethtool_ringparam *param,
1122e65a0231SHao Chen struct kernel_ethtool_ringparam *kernel_param)
1123424eb834SSalil Mehta {
1124e65a0231SHao Chen #define RX_BUF_LEN_2K 2048
1125e65a0231SHao Chen #define RX_BUF_LEN_4K 4096
11264d07c593SHao Chen
11274d07c593SHao Chen struct hns3_nic_priv *priv = netdev_priv(ndev);
11284d07c593SHao Chen
11294d07c593SHao Chen if (hns3_nic_resetting(ndev) || !priv->ring) {
11304d07c593SHao Chen netdev_err(ndev, "failed to set ringparam value, due to dev resetting or uninited\n");
1131257e4f29SHuazhong Tan return -EBUSY;
11324d07c593SHao Chen }
11334d07c593SHao Chen
1134257e4f29SHuazhong Tan
1135424eb834SSalil Mehta if (param->rx_mini_pending || param->rx_jumbo_pending)
1136424eb834SSalil Mehta return -EINVAL;
1137424eb834SSalil Mehta
1138e65a0231SHao Chen if (kernel_param->rx_buf_len != RX_BUF_LEN_2K &&
1139e65a0231SHao Chen kernel_param->rx_buf_len != RX_BUF_LEN_4K) {
1140e65a0231SHao Chen netdev_err(ndev, "Rx buf len only support 2048 and 4096\n");
1141e65a0231SHao Chen return -EINVAL;
1142e65a0231SHao Chen }
1143e65a0231SHao Chen
1144424eb834SSalil Mehta if (param->tx_pending > HNS3_RING_MAX_PENDING ||
1145c0425944SPeng Li param->tx_pending < HNS3_RING_MIN_PENDING ||
1146c0425944SPeng Li param->rx_pending > HNS3_RING_MAX_PENDING ||
1147c0425944SPeng Li param->rx_pending < HNS3_RING_MIN_PENDING) {
1148c0425944SPeng Li netdev_err(ndev, "Queue depth out of range [%d-%d]\n",
1149c0425944SPeng Li HNS3_RING_MIN_PENDING, HNS3_RING_MAX_PENDING);
1150424eb834SSalil Mehta return -EINVAL;
1151424eb834SSalil Mehta }
1152424eb834SSalil Mehta
1153a723fb8eSJian Shen return 0;
1154a723fb8eSJian Shen }
1155a723fb8eSJian Shen
115607fdc163SHao Chen static bool
hns3_is_ringparam_changed(struct net_device * ndev,struct ethtool_ringparam * param,struct kernel_ethtool_ringparam * kernel_param,struct hns3_ring_param * old_ringparam,struct hns3_ring_param * new_ringparam)115707fdc163SHao Chen hns3_is_ringparam_changed(struct net_device *ndev,
115807fdc163SHao Chen struct ethtool_ringparam *param,
115907fdc163SHao Chen struct kernel_ethtool_ringparam *kernel_param,
116007fdc163SHao Chen struct hns3_ring_param *old_ringparam,
116107fdc163SHao Chen struct hns3_ring_param *new_ringparam)
116207fdc163SHao Chen {
116307fdc163SHao Chen struct hns3_nic_priv *priv = netdev_priv(ndev);
116407fdc163SHao Chen struct hnae3_handle *h = priv->ae_handle;
116507fdc163SHao Chen u16 queue_num = h->kinfo.num_tqps;
116607fdc163SHao Chen
116707fdc163SHao Chen new_ringparam->tx_desc_num = ALIGN(param->tx_pending,
116807fdc163SHao Chen HNS3_RING_BD_MULTIPLE);
116907fdc163SHao Chen new_ringparam->rx_desc_num = ALIGN(param->rx_pending,
117007fdc163SHao Chen HNS3_RING_BD_MULTIPLE);
117107fdc163SHao Chen old_ringparam->tx_desc_num = priv->ring[0].desc_num;
117207fdc163SHao Chen old_ringparam->rx_desc_num = priv->ring[queue_num].desc_num;
117307fdc163SHao Chen old_ringparam->rx_buf_len = priv->ring[queue_num].buf_size;
117407fdc163SHao Chen new_ringparam->rx_buf_len = kernel_param->rx_buf_len;
117507fdc163SHao Chen
117607fdc163SHao Chen if (old_ringparam->tx_desc_num == new_ringparam->tx_desc_num &&
117707fdc163SHao Chen old_ringparam->rx_desc_num == new_ringparam->rx_desc_num &&
117807fdc163SHao Chen old_ringparam->rx_buf_len == new_ringparam->rx_buf_len) {
1179cfd80687SJie Wang netdev_info(ndev, "descriptor number and rx buffer length not changed\n");
118007fdc163SHao Chen return false;
118107fdc163SHao Chen }
118207fdc163SHao Chen
118307fdc163SHao Chen return true;
118407fdc163SHao Chen }
118507fdc163SHao Chen
hns3_change_rx_buf_len(struct net_device * ndev,u32 rx_buf_len)1186e65a0231SHao Chen static int hns3_change_rx_buf_len(struct net_device *ndev, u32 rx_buf_len)
1187e65a0231SHao Chen {
1188e65a0231SHao Chen struct hns3_nic_priv *priv = netdev_priv(ndev);
1189e65a0231SHao Chen struct hnae3_handle *h = priv->ae_handle;
1190e65a0231SHao Chen int i;
1191e65a0231SHao Chen
1192e65a0231SHao Chen h->kinfo.rx_buf_len = rx_buf_len;
1193e65a0231SHao Chen
1194e65a0231SHao Chen for (i = 0; i < h->kinfo.num_tqps; i++) {
1195e65a0231SHao Chen h->kinfo.tqp[i]->buf_size = rx_buf_len;
1196e65a0231SHao Chen priv->ring[i + h->kinfo.num_tqps].buf_size = rx_buf_len;
1197e65a0231SHao Chen }
1198e65a0231SHao Chen
1199e65a0231SHao Chen return 0;
1200e65a0231SHao Chen }
1201e65a0231SHao Chen
hns3_set_tx_push(struct net_device * netdev,u32 tx_push)12021f702c16SJie Wang static int hns3_set_tx_push(struct net_device *netdev, u32 tx_push)
12031f702c16SJie Wang {
12041f702c16SJie Wang struct hns3_nic_priv *priv = netdev_priv(netdev);
12051f702c16SJie Wang struct hnae3_handle *h = hns3_get_handle(netdev);
12061f702c16SJie Wang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
12071f702c16SJie Wang u32 old_state = test_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state);
12081f702c16SJie Wang
12091f702c16SJie Wang if (!test_bit(HNAE3_DEV_SUPPORT_TX_PUSH_B, ae_dev->caps) && tx_push)
12101f702c16SJie Wang return -EOPNOTSUPP;
12111f702c16SJie Wang
12121f702c16SJie Wang if (tx_push == old_state)
12131f702c16SJie Wang return 0;
12141f702c16SJie Wang
12151f702c16SJie Wang netdev_dbg(netdev, "Changing tx push from %s to %s\n",
12161f702c16SJie Wang old_state ? "on" : "off", tx_push ? "on" : "off");
12171f702c16SJie Wang
12181f702c16SJie Wang if (tx_push)
12191f702c16SJie Wang set_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state);
12201f702c16SJie Wang else
12211f702c16SJie Wang clear_bit(HNS3_NIC_STATE_TX_PUSH_ENABLE, &priv->state);
12221f702c16SJie Wang
12231f702c16SJie Wang return 0;
12241f702c16SJie Wang }
12251f702c16SJie Wang
hns3_set_ringparam(struct net_device * ndev,struct ethtool_ringparam * param,struct kernel_ethtool_ringparam * kernel_param,struct netlink_ext_ack * extack)1226a723fb8eSJian Shen static int hns3_set_ringparam(struct net_device *ndev,
122774624944SHao Chen struct ethtool_ringparam *param,
122874624944SHao Chen struct kernel_ethtool_ringparam *kernel_param,
122974624944SHao Chen struct netlink_ext_ack *extack)
1230a723fb8eSJian Shen {
123107fdc163SHao Chen struct hns3_ring_param old_ringparam, new_ringparam;
1232a723fb8eSJian Shen struct hns3_nic_priv *priv = netdev_priv(ndev);
1233a723fb8eSJian Shen struct hnae3_handle *h = priv->ae_handle;
1234a723fb8eSJian Shen struct hns3_enet_ring *tmp_rings;
1235a723fb8eSJian Shen bool if_running = netif_running(ndev);
1236a723fb8eSJian Shen int ret, i;
1237a723fb8eSJian Shen
1238e65a0231SHao Chen ret = hns3_check_ringparam(ndev, param, kernel_param);
1239a723fb8eSJian Shen if (ret)
1240a723fb8eSJian Shen return ret;
1241a723fb8eSJian Shen
12421f702c16SJie Wang ret = hns3_set_tx_push(ndev, kernel_param->tx_push);
12431f702c16SJie Wang if (ret)
12441f702c16SJie Wang return ret;
12451f702c16SJie Wang
124607fdc163SHao Chen if (!hns3_is_ringparam_changed(ndev, param, kernel_param,
124707fdc163SHao Chen &old_ringparam, &new_ringparam))
1248424eb834SSalil Mehta return 0;
1249424eb834SSalil Mehta
1250a723fb8eSJian Shen tmp_rings = hns3_backup_ringparam(priv);
1251a723fb8eSJian Shen if (!tmp_rings) {
125229c17cb6SHao Chen netdev_err(ndev, "backup ring param failed by allocating memory fail\n");
1253a723fb8eSJian Shen return -ENOMEM;
1254a723fb8eSJian Shen }
1255a723fb8eSJian Shen
1256424eb834SSalil Mehta netdev_info(ndev,
125707fdc163SHao Chen "Changing Tx/Rx ring depth from %u/%u to %u/%u, Changing rx buffer len from %u to %u\n",
125807fdc163SHao Chen old_ringparam.tx_desc_num, old_ringparam.rx_desc_num,
125907fdc163SHao Chen new_ringparam.tx_desc_num, new_ringparam.rx_desc_num,
126007fdc163SHao Chen old_ringparam.rx_buf_len, new_ringparam.rx_buf_len);
1261424eb834SSalil Mehta
1262424eb834SSalil Mehta if (if_running)
1263fc0c174fSPeng Li ndev->netdev_ops->ndo_stop(ndev);
1264424eb834SSalil Mehta
126507fdc163SHao Chen hns3_change_all_ring_bd_num(priv, new_ringparam.tx_desc_num,
126607fdc163SHao Chen new_ringparam.rx_desc_num);
126707fdc163SHao Chen hns3_change_rx_buf_len(ndev, new_ringparam.rx_buf_len);
1268a723fb8eSJian Shen ret = hns3_init_all_ring(priv);
1269a723fb8eSJian Shen if (ret) {
1270e65a0231SHao Chen netdev_err(ndev, "set ringparam fail, revert to old value(%d)\n",
1271a723fb8eSJian Shen ret);
1272424eb834SSalil Mehta
127307fdc163SHao Chen hns3_change_rx_buf_len(ndev, old_ringparam.rx_buf_len);
127407fdc163SHao Chen hns3_change_all_ring_bd_num(priv, old_ringparam.tx_desc_num,
127507fdc163SHao Chen old_ringparam.rx_desc_num);
1276a723fb8eSJian Shen for (i = 0; i < h->kinfo.num_tqps * 2; i++)
12775f06b903SYunsheng Lin memcpy(&priv->ring[i], &tmp_rings[i],
1278a723fb8eSJian Shen sizeof(struct hns3_enet_ring));
1279a723fb8eSJian Shen } else {
1280a723fb8eSJian Shen for (i = 0; i < h->kinfo.num_tqps * 2; i++)
1281a723fb8eSJian Shen hns3_fini_ring(&tmp_rings[i]);
1282424eb834SSalil Mehta }
1283a723fb8eSJian Shen
1284a723fb8eSJian Shen kfree(tmp_rings);
1285424eb834SSalil Mehta
1286424eb834SSalil Mehta if (if_running)
1287fc0c174fSPeng Li ret = ndev->netdev_ops->ndo_open(ndev);
1288424eb834SSalil Mehta
1289424eb834SSalil Mehta return ret;
1290424eb834SSalil Mehta }
1291424eb834SSalil Mehta
hns3_set_rxnfc(struct net_device * netdev,struct ethtool_rxnfc * cmd)1292424eb834SSalil Mehta static int hns3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
1293424eb834SSalil Mehta {
1294424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
1295424eb834SSalil Mehta
1296424eb834SSalil Mehta switch (cmd->cmd) {
1297424eb834SSalil Mehta case ETHTOOL_SRXFH:
1298dd74f815SJian Shen if (h->ae_algo->ops->set_rss_tuple)
1299424eb834SSalil Mehta return h->ae_algo->ops->set_rss_tuple(h, cmd);
1300dd74f815SJian Shen return -EOPNOTSUPP;
1301dd74f815SJian Shen case ETHTOOL_SRXCLSRLINS:
1302dd74f815SJian Shen if (h->ae_algo->ops->add_fd_entry)
1303dd74f815SJian Shen return h->ae_algo->ops->add_fd_entry(h, cmd);
1304dd74f815SJian Shen return -EOPNOTSUPP;
1305dd74f815SJian Shen case ETHTOOL_SRXCLSRLDEL:
1306dd74f815SJian Shen if (h->ae_algo->ops->del_fd_entry)
1307dd74f815SJian Shen return h->ae_algo->ops->del_fd_entry(h, cmd);
1308dd74f815SJian Shen return -EOPNOTSUPP;
1309424eb834SSalil Mehta default:
1310424eb834SSalil Mehta return -EOPNOTSUPP;
1311424eb834SSalil Mehta }
1312424eb834SSalil Mehta }
1313424eb834SSalil Mehta
hns3_nway_reset(struct net_device * netdev)1314424eb834SSalil Mehta static int hns3_nway_reset(struct net_device *netdev)
1315424eb834SSalil Mehta {
131622f48e24SJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
131722f48e24SJian Shen const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
1318424eb834SSalil Mehta struct phy_device *phy = netdev->phydev;
131922f48e24SJian Shen int autoneg;
1320424eb834SSalil Mehta
1321424eb834SSalil Mehta if (!netif_running(netdev))
1322424eb834SSalil Mehta return 0;
1323424eb834SSalil Mehta
132422f48e24SJian Shen if (hns3_nic_resetting(netdev)) {
132522f48e24SJian Shen netdev_err(netdev, "dev resetting!");
132622f48e24SJian Shen return -EBUSY;
132722f48e24SJian Shen }
132822f48e24SJian Shen
132922f48e24SJian Shen if (!ops->get_autoneg || !ops->restart_autoneg)
1330424eb834SSalil Mehta return -EOPNOTSUPP;
1331424eb834SSalil Mehta
133222f48e24SJian Shen autoneg = ops->get_autoneg(handle);
133322f48e24SJian Shen if (autoneg != AUTONEG_ENABLE) {
133422f48e24SJian Shen netdev_err(netdev,
133522f48e24SJian Shen "Autoneg is off, don't support to restart it\n");
1336424eb834SSalil Mehta return -EINVAL;
133722f48e24SJian Shen }
1338424eb834SSalil Mehta
13391c822948SYonglong Liu netif_dbg(handle, drv, netdev,
13401c822948SYonglong Liu "nway reset (using %s)\n", phy ? "phy" : "mac");
13411c822948SYonglong Liu
134222f48e24SJian Shen if (phy)
1343424eb834SSalil Mehta return genphy_restart_aneg(phy);
134422f48e24SJian Shen
134522f48e24SJian Shen return ops->restart_autoneg(handle);
1346424eb834SSalil Mehta }
1347424eb834SSalil Mehta
hns3_get_channels(struct net_device * netdev,struct ethtool_channels * ch)1348836df24aSkbuild test robot static void hns3_get_channels(struct net_device *netdev,
1349482d2e9cSPeng Li struct ethtool_channels *ch)
1350482d2e9cSPeng Li {
1351482d2e9cSPeng Li struct hnae3_handle *h = hns3_get_handle(netdev);
1352482d2e9cSPeng Li
1353482d2e9cSPeng Li if (h->ae_algo->ops->get_channels)
1354482d2e9cSPeng Li h->ae_algo->ops->get_channels(h, ch);
1355482d2e9cSPeng Li }
1356482d2e9cSPeng Li
hns3_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * cmd,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)135773a13d8dSHuazhong Tan static int hns3_get_coalesce(struct net_device *netdev,
1358f3ccfda1SYufeng Mo struct ethtool_coalesce *cmd,
1359f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
1360f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
13617e96adc4SFuyun Liang {
13627e96adc4SFuyun Liang struct hns3_nic_priv *priv = netdev_priv(netdev);
136373a13d8dSHuazhong Tan struct hns3_enet_coalesce *tx_coal = &priv->tx_coal;
136473a13d8dSHuazhong Tan struct hns3_enet_coalesce *rx_coal = &priv->rx_coal;
13657e96adc4SFuyun Liang struct hnae3_handle *h = priv->ae_handle;
13667e96adc4SFuyun Liang
1367257e4f29SHuazhong Tan if (hns3_nic_resetting(netdev))
1368257e4f29SHuazhong Tan return -EBUSY;
1369257e4f29SHuazhong Tan
137073a13d8dSHuazhong Tan cmd->use_adaptive_tx_coalesce = tx_coal->adapt_enable;
137173a13d8dSHuazhong Tan cmd->use_adaptive_rx_coalesce = rx_coal->adapt_enable;
13727e96adc4SFuyun Liang
137373a13d8dSHuazhong Tan cmd->tx_coalesce_usecs = tx_coal->int_gl;
137473a13d8dSHuazhong Tan cmd->rx_coalesce_usecs = rx_coal->int_gl;
13757e96adc4SFuyun Liang
13767e96adc4SFuyun Liang cmd->tx_coalesce_usecs_high = h->kinfo.int_rl_setting;
13777e96adc4SFuyun Liang cmd->rx_coalesce_usecs_high = h->kinfo.int_rl_setting;
13787e96adc4SFuyun Liang
137973a13d8dSHuazhong Tan cmd->tx_max_coalesced_frames = tx_coal->int_ql;
138073a13d8dSHuazhong Tan cmd->rx_max_coalesced_frames = rx_coal->int_ql;
138191bfae25SHuazhong Tan
1382cce1689eSYufeng Mo kernel_coal->use_cqe_mode_tx = (priv->tx_cqe_mode ==
1383cce1689eSYufeng Mo DIM_CQ_PERIOD_MODE_START_FROM_CQE);
1384cce1689eSYufeng Mo kernel_coal->use_cqe_mode_rx = (priv->rx_cqe_mode ==
1385cce1689eSYufeng Mo DIM_CQ_PERIOD_MODE_START_FROM_CQE);
1386cce1689eSYufeng Mo
13877e96adc4SFuyun Liang return 0;
13887e96adc4SFuyun Liang }
13897e96adc4SFuyun Liang
hns3_check_gl_coalesce_para(struct net_device * netdev,struct ethtool_coalesce * cmd)1390434776a5SFuyun Liang static int hns3_check_gl_coalesce_para(struct net_device *netdev,
1391434776a5SFuyun Liang struct ethtool_coalesce *cmd)
1392434776a5SFuyun Liang {
1393ab16b49cSHuazhong Tan struct hnae3_handle *handle = hns3_get_handle(netdev);
1394ab16b49cSHuazhong Tan struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
1395434776a5SFuyun Liang u32 rx_gl, tx_gl;
1396434776a5SFuyun Liang
1397ab16b49cSHuazhong Tan if (cmd->rx_coalesce_usecs > ae_dev->dev_specs.max_int_gl) {
1398434776a5SFuyun Liang netdev_err(netdev,
1399ab16b49cSHuazhong Tan "invalid rx-usecs value, rx-usecs range is 0-%u\n",
1400ab16b49cSHuazhong Tan ae_dev->dev_specs.max_int_gl);
1401434776a5SFuyun Liang return -EINVAL;
1402434776a5SFuyun Liang }
1403434776a5SFuyun Liang
1404ab16b49cSHuazhong Tan if (cmd->tx_coalesce_usecs > ae_dev->dev_specs.max_int_gl) {
1405434776a5SFuyun Liang netdev_err(netdev,
1406ab16b49cSHuazhong Tan "invalid tx-usecs value, tx-usecs range is 0-%u\n",
1407ab16b49cSHuazhong Tan ae_dev->dev_specs.max_int_gl);
1408434776a5SFuyun Liang return -EINVAL;
1409434776a5SFuyun Liang }
1410434776a5SFuyun Liang
14115ac84b02SHuazhong Tan /* device version above V3(include V3), GL uses 1us unit,
14125ac84b02SHuazhong Tan * so the round down is not needed.
14135ac84b02SHuazhong Tan */
14145ac84b02SHuazhong Tan if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3)
14155ac84b02SHuazhong Tan return 0;
14165ac84b02SHuazhong Tan
1417434776a5SFuyun Liang rx_gl = hns3_gl_round_down(cmd->rx_coalesce_usecs);
1418434776a5SFuyun Liang if (rx_gl != cmd->rx_coalesce_usecs) {
1419434776a5SFuyun Liang netdev_info(netdev,
1420adcf738bSGuojia Liao "rx_usecs(%u) rounded down to %u, because it must be multiple of 2.\n",
1421434776a5SFuyun Liang cmd->rx_coalesce_usecs, rx_gl);
1422434776a5SFuyun Liang }
1423434776a5SFuyun Liang
1424434776a5SFuyun Liang tx_gl = hns3_gl_round_down(cmd->tx_coalesce_usecs);
1425434776a5SFuyun Liang if (tx_gl != cmd->tx_coalesce_usecs) {
1426434776a5SFuyun Liang netdev_info(netdev,
1427adcf738bSGuojia Liao "tx_usecs(%u) rounded down to %u, because it must be multiple of 2.\n",
1428434776a5SFuyun Liang cmd->tx_coalesce_usecs, tx_gl);
1429434776a5SFuyun Liang }
1430434776a5SFuyun Liang
1431434776a5SFuyun Liang return 0;
1432434776a5SFuyun Liang }
1433434776a5SFuyun Liang
hns3_check_rl_coalesce_para(struct net_device * netdev,struct ethtool_coalesce * cmd)1434434776a5SFuyun Liang static int hns3_check_rl_coalesce_para(struct net_device *netdev,
1435434776a5SFuyun Liang struct ethtool_coalesce *cmd)
1436434776a5SFuyun Liang {
1437434776a5SFuyun Liang u32 rl;
1438434776a5SFuyun Liang
1439434776a5SFuyun Liang if (cmd->tx_coalesce_usecs_high != cmd->rx_coalesce_usecs_high) {
1440434776a5SFuyun Liang netdev_err(netdev,
1441434776a5SFuyun Liang "tx_usecs_high must be same as rx_usecs_high.\n");
1442434776a5SFuyun Liang return -EINVAL;
1443434776a5SFuyun Liang }
1444434776a5SFuyun Liang
1445434776a5SFuyun Liang if (cmd->rx_coalesce_usecs_high > HNS3_INT_RL_MAX) {
1446434776a5SFuyun Liang netdev_err(netdev,
1447434776a5SFuyun Liang "Invalid usecs_high value, usecs_high range is 0-%d\n",
1448434776a5SFuyun Liang HNS3_INT_RL_MAX);
1449434776a5SFuyun Liang return -EINVAL;
1450434776a5SFuyun Liang }
1451434776a5SFuyun Liang
1452434776a5SFuyun Liang rl = hns3_rl_round_down(cmd->rx_coalesce_usecs_high);
1453434776a5SFuyun Liang if (rl != cmd->rx_coalesce_usecs_high) {
1454434776a5SFuyun Liang netdev_info(netdev,
1455adcf738bSGuojia Liao "usecs_high(%u) rounded down to %u, because it must be multiple of 4.\n",
1456434776a5SFuyun Liang cmd->rx_coalesce_usecs_high, rl);
1457434776a5SFuyun Liang }
1458434776a5SFuyun Liang
1459434776a5SFuyun Liang return 0;
1460434776a5SFuyun Liang }
1461434776a5SFuyun Liang
hns3_check_ql_coalesce_param(struct net_device * netdev,struct ethtool_coalesce * cmd)146291bfae25SHuazhong Tan static int hns3_check_ql_coalesce_param(struct net_device *netdev,
146391bfae25SHuazhong Tan struct ethtool_coalesce *cmd)
146491bfae25SHuazhong Tan {
146591bfae25SHuazhong Tan struct hnae3_handle *handle = hns3_get_handle(netdev);
146691bfae25SHuazhong Tan struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
146791bfae25SHuazhong Tan
146891bfae25SHuazhong Tan if ((cmd->tx_max_coalesced_frames || cmd->rx_max_coalesced_frames) &&
146991bfae25SHuazhong Tan !ae_dev->dev_specs.int_ql_max) {
147091bfae25SHuazhong Tan netdev_err(netdev, "coalesced frames is not supported\n");
147191bfae25SHuazhong Tan return -EOPNOTSUPP;
147291bfae25SHuazhong Tan }
147391bfae25SHuazhong Tan
147491bfae25SHuazhong Tan if (cmd->tx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max ||
147591bfae25SHuazhong Tan cmd->rx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max) {
147691bfae25SHuazhong Tan netdev_err(netdev,
147791bfae25SHuazhong Tan "invalid coalesced_frames value, range is 0-%u\n",
147891bfae25SHuazhong Tan ae_dev->dev_specs.int_ql_max);
147991bfae25SHuazhong Tan return -ERANGE;
148091bfae25SHuazhong Tan }
148191bfae25SHuazhong Tan
148291bfae25SHuazhong Tan return 0;
148391bfae25SHuazhong Tan }
148491bfae25SHuazhong Tan
1485286c61e7SYufeng Mo static int
hns3_check_cqe_coalesce_param(struct net_device * netdev,struct kernel_ethtool_coalesce * kernel_coal)1486286c61e7SYufeng Mo hns3_check_cqe_coalesce_param(struct net_device *netdev,
1487286c61e7SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal)
1488286c61e7SYufeng Mo {
1489286c61e7SYufeng Mo struct hnae3_handle *handle = hns3_get_handle(netdev);
1490286c61e7SYufeng Mo struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
1491286c61e7SYufeng Mo
1492286c61e7SYufeng Mo if ((kernel_coal->use_cqe_mode_tx || kernel_coal->use_cqe_mode_rx) &&
1493286c61e7SYufeng Mo !hnae3_ae_dev_cq_supported(ae_dev)) {
1494286c61e7SYufeng Mo netdev_err(netdev, "coalesced cqe mode is not supported\n");
1495286c61e7SYufeng Mo return -EOPNOTSUPP;
1496286c61e7SYufeng Mo }
1497286c61e7SYufeng Mo
1498286c61e7SYufeng Mo return 0;
1499286c61e7SYufeng Mo }
1500286c61e7SYufeng Mo
1501286c61e7SYufeng Mo static int
hns3_check_coalesce_para(struct net_device * netdev,struct ethtool_coalesce * cmd,struct kernel_ethtool_coalesce * kernel_coal)1502286c61e7SYufeng Mo hns3_check_coalesce_para(struct net_device *netdev,
1503286c61e7SYufeng Mo struct ethtool_coalesce *cmd,
1504286c61e7SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal)
1505434776a5SFuyun Liang {
1506434776a5SFuyun Liang int ret;
1507434776a5SFuyun Liang
1508286c61e7SYufeng Mo ret = hns3_check_cqe_coalesce_param(netdev, kernel_coal);
1509286c61e7SYufeng Mo if (ret)
1510286c61e7SYufeng Mo return ret;
1511286c61e7SYufeng Mo
1512434776a5SFuyun Liang ret = hns3_check_gl_coalesce_para(netdev, cmd);
1513434776a5SFuyun Liang if (ret) {
1514434776a5SFuyun Liang netdev_err(netdev,
1515434776a5SFuyun Liang "Check gl coalesce param fail. ret = %d\n", ret);
1516434776a5SFuyun Liang return ret;
1517434776a5SFuyun Liang }
1518434776a5SFuyun Liang
1519434776a5SFuyun Liang ret = hns3_check_rl_coalesce_para(netdev, cmd);
1520434776a5SFuyun Liang if (ret) {
1521434776a5SFuyun Liang netdev_err(netdev,
1522434776a5SFuyun Liang "Check rl coalesce param fail. ret = %d\n", ret);
1523434776a5SFuyun Liang return ret;
1524434776a5SFuyun Liang }
1525434776a5SFuyun Liang
152673a13d8dSHuazhong Tan return hns3_check_ql_coalesce_param(netdev, cmd);
1527434776a5SFuyun Liang }
1528434776a5SFuyun Liang
hns3_set_coalesce_per_queue(struct net_device * netdev,struct ethtool_coalesce * cmd,u32 queue)1529434776a5SFuyun Liang static void hns3_set_coalesce_per_queue(struct net_device *netdev,
1530434776a5SFuyun Liang struct ethtool_coalesce *cmd,
1531434776a5SFuyun Liang u32 queue)
1532434776a5SFuyun Liang {
1533434776a5SFuyun Liang struct hns3_enet_tqp_vector *tx_vector, *rx_vector;
1534434776a5SFuyun Liang struct hns3_nic_priv *priv = netdev_priv(netdev);
1535434776a5SFuyun Liang struct hnae3_handle *h = priv->ae_handle;
1536434776a5SFuyun Liang int queue_num = h->kinfo.num_tqps;
1537434776a5SFuyun Liang
15385f06b903SYunsheng Lin tx_vector = priv->ring[queue].tqp_vector;
15395f06b903SYunsheng Lin rx_vector = priv->ring[queue_num + queue].tqp_vector;
1540434776a5SFuyun Liang
1541de25bcc4SHuazhong Tan tx_vector->tx_group.coal.adapt_enable =
15429bc727a9SYunsheng Lin cmd->use_adaptive_tx_coalesce;
1543de25bcc4SHuazhong Tan rx_vector->rx_group.coal.adapt_enable =
15449bc727a9SYunsheng Lin cmd->use_adaptive_rx_coalesce;
1545434776a5SFuyun Liang
15469bc727a9SYunsheng Lin tx_vector->tx_group.coal.int_gl = cmd->tx_coalesce_usecs;
15479bc727a9SYunsheng Lin rx_vector->rx_group.coal.int_gl = cmd->rx_coalesce_usecs;
1548434776a5SFuyun Liang
154991bfae25SHuazhong Tan tx_vector->tx_group.coal.int_ql = cmd->tx_max_coalesced_frames;
155091bfae25SHuazhong Tan rx_vector->rx_group.coal.int_ql = cmd->rx_max_coalesced_frames;
155191bfae25SHuazhong Tan
15529bc727a9SYunsheng Lin hns3_set_vector_coalesce_tx_gl(tx_vector,
15539bc727a9SYunsheng Lin tx_vector->tx_group.coal.int_gl);
15549bc727a9SYunsheng Lin hns3_set_vector_coalesce_rx_gl(rx_vector,
15559bc727a9SYunsheng Lin rx_vector->rx_group.coal.int_gl);
1556434776a5SFuyun Liang
1557434776a5SFuyun Liang hns3_set_vector_coalesce_rl(tx_vector, h->kinfo.int_rl_setting);
1558434776a5SFuyun Liang hns3_set_vector_coalesce_rl(rx_vector, h->kinfo.int_rl_setting);
155991bfae25SHuazhong Tan
156091bfae25SHuazhong Tan if (tx_vector->tx_group.coal.ql_enable)
156191bfae25SHuazhong Tan hns3_set_vector_coalesce_tx_ql(tx_vector,
156291bfae25SHuazhong Tan tx_vector->tx_group.coal.int_ql);
156391bfae25SHuazhong Tan if (rx_vector->rx_group.coal.ql_enable)
156491bfae25SHuazhong Tan hns3_set_vector_coalesce_rx_ql(rx_vector,
156591bfae25SHuazhong Tan rx_vector->rx_group.coal.int_ql);
1566434776a5SFuyun Liang }
1567434776a5SFuyun Liang
hns3_set_coalesce(struct net_device * netdev,struct ethtool_coalesce * cmd,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)1568434776a5SFuyun Liang static int hns3_set_coalesce(struct net_device *netdev,
1569f3ccfda1SYufeng Mo struct ethtool_coalesce *cmd,
1570f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
1571f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
1572434776a5SFuyun Liang {
1573434776a5SFuyun Liang struct hnae3_handle *h = hns3_get_handle(netdev);
157473a13d8dSHuazhong Tan struct hns3_nic_priv *priv = netdev_priv(netdev);
157573a13d8dSHuazhong Tan struct hns3_enet_coalesce *tx_coal = &priv->tx_coal;
157673a13d8dSHuazhong Tan struct hns3_enet_coalesce *rx_coal = &priv->rx_coal;
1577434776a5SFuyun Liang u16 queue_num = h->kinfo.num_tqps;
1578cce1689eSYufeng Mo enum dim_cq_period_mode tx_mode;
1579cce1689eSYufeng Mo enum dim_cq_period_mode rx_mode;
1580434776a5SFuyun Liang int ret;
1581434776a5SFuyun Liang int i;
1582434776a5SFuyun Liang
1583257e4f29SHuazhong Tan if (hns3_nic_resetting(netdev))
1584257e4f29SHuazhong Tan return -EBUSY;
1585257e4f29SHuazhong Tan
1586286c61e7SYufeng Mo ret = hns3_check_coalesce_para(netdev, cmd, kernel_coal);
1587434776a5SFuyun Liang if (ret)
1588434776a5SFuyun Liang return ret;
1589434776a5SFuyun Liang
1590434776a5SFuyun Liang h->kinfo.int_rl_setting =
1591434776a5SFuyun Liang hns3_rl_round_down(cmd->rx_coalesce_usecs_high);
1592434776a5SFuyun Liang
159373a13d8dSHuazhong Tan tx_coal->adapt_enable = cmd->use_adaptive_tx_coalesce;
159473a13d8dSHuazhong Tan rx_coal->adapt_enable = cmd->use_adaptive_rx_coalesce;
159573a13d8dSHuazhong Tan
159673a13d8dSHuazhong Tan tx_coal->int_gl = cmd->tx_coalesce_usecs;
159773a13d8dSHuazhong Tan rx_coal->int_gl = cmd->rx_coalesce_usecs;
159873a13d8dSHuazhong Tan
159973a13d8dSHuazhong Tan tx_coal->int_ql = cmd->tx_max_coalesced_frames;
160073a13d8dSHuazhong Tan rx_coal->int_ql = cmd->rx_max_coalesced_frames;
160173a13d8dSHuazhong Tan
1602434776a5SFuyun Liang for (i = 0; i < queue_num; i++)
1603434776a5SFuyun Liang hns3_set_coalesce_per_queue(netdev, cmd, i);
1604434776a5SFuyun Liang
1605cce1689eSYufeng Mo tx_mode = kernel_coal->use_cqe_mode_tx ?
1606cce1689eSYufeng Mo DIM_CQ_PERIOD_MODE_START_FROM_CQE :
1607cce1689eSYufeng Mo DIM_CQ_PERIOD_MODE_START_FROM_EQE;
1608cce1689eSYufeng Mo rx_mode = kernel_coal->use_cqe_mode_rx ?
1609cce1689eSYufeng Mo DIM_CQ_PERIOD_MODE_START_FROM_CQE :
1610cce1689eSYufeng Mo DIM_CQ_PERIOD_MODE_START_FROM_EQE;
1611cce1689eSYufeng Mo hns3_cq_period_mode_init(priv, tx_mode, rx_mode);
1612cce1689eSYufeng Mo
1613434776a5SFuyun Liang return 0;
1614434776a5SFuyun Liang }
1615434776a5SFuyun Liang
hns3_get_regs_len(struct net_device * netdev)161677b34110SFuyun Liang static int hns3_get_regs_len(struct net_device *netdev)
161777b34110SFuyun Liang {
161877b34110SFuyun Liang struct hnae3_handle *h = hns3_get_handle(netdev);
161977b34110SFuyun Liang
162077b34110SFuyun Liang if (!h->ae_algo->ops->get_regs_len)
162177b34110SFuyun Liang return -EOPNOTSUPP;
162277b34110SFuyun Liang
162377b34110SFuyun Liang return h->ae_algo->ops->get_regs_len(h);
162477b34110SFuyun Liang }
162577b34110SFuyun Liang
hns3_get_regs(struct net_device * netdev,struct ethtool_regs * cmd,void * data)162677b34110SFuyun Liang static void hns3_get_regs(struct net_device *netdev,
162777b34110SFuyun Liang struct ethtool_regs *cmd, void *data)
162877b34110SFuyun Liang {
162977b34110SFuyun Liang struct hnae3_handle *h = hns3_get_handle(netdev);
163077b34110SFuyun Liang
163177b34110SFuyun Liang if (!h->ae_algo->ops->get_regs)
163277b34110SFuyun Liang return;
163377b34110SFuyun Liang
163477b34110SFuyun Liang h->ae_algo->ops->get_regs(h, &cmd->version, data);
163577b34110SFuyun Liang }
163677b34110SFuyun Liang
hns3_set_phys_id(struct net_device * netdev,enum ethtool_phys_id_state state)163707f8e940SJian Shen static int hns3_set_phys_id(struct net_device *netdev,
163807f8e940SJian Shen enum ethtool_phys_id_state state)
163907f8e940SJian Shen {
164007f8e940SJian Shen struct hnae3_handle *h = hns3_get_handle(netdev);
164107f8e940SJian Shen
164263cbf7a9SYufeng Mo if (!h->ae_algo->ops->set_led_id)
164307f8e940SJian Shen return -EOPNOTSUPP;
164407f8e940SJian Shen
164507f8e940SJian Shen return h->ae_algo->ops->set_led_id(h, state);
164607f8e940SJian Shen }
164707f8e940SJian Shen
hns3_get_msglevel(struct net_device * netdev)1648bb87be87SYonglong Liu static u32 hns3_get_msglevel(struct net_device *netdev)
1649bb87be87SYonglong Liu {
1650bb87be87SYonglong Liu struct hnae3_handle *h = hns3_get_handle(netdev);
1651bb87be87SYonglong Liu
1652bb87be87SYonglong Liu return h->msg_enable;
1653bb87be87SYonglong Liu }
1654bb87be87SYonglong Liu
hns3_set_msglevel(struct net_device * netdev,u32 msg_level)1655bb87be87SYonglong Liu static void hns3_set_msglevel(struct net_device *netdev, u32 msg_level)
1656bb87be87SYonglong Liu {
1657bb87be87SYonglong Liu struct hnae3_handle *h = hns3_get_handle(netdev);
1658bb87be87SYonglong Liu
1659bb87be87SYonglong Liu h->msg_enable = msg_level;
1660bb87be87SYonglong Liu }
1661bb87be87SYonglong Liu
hns3_get_fec_stats(struct net_device * netdev,struct ethtool_fec_stats * fec_stats)16622cb343b9SHao Lan static void hns3_get_fec_stats(struct net_device *netdev,
16632cb343b9SHao Lan struct ethtool_fec_stats *fec_stats)
16642cb343b9SHao Lan {
16652cb343b9SHao Lan struct hnae3_handle *handle = hns3_get_handle(netdev);
16662cb343b9SHao Lan struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
16672cb343b9SHao Lan const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
16682cb343b9SHao Lan
16692cb343b9SHao Lan if (!hnae3_ae_dev_fec_stats_supported(ae_dev) || !ops->get_fec_stats)
16702cb343b9SHao Lan return;
16712cb343b9SHao Lan
16722cb343b9SHao Lan ops->get_fec_stats(handle, fec_stats);
16732cb343b9SHao Lan }
16742cb343b9SHao Lan
16757e6ec914SJian Shen /* Translate local fec value into ethtool value. */
loc_to_eth_fec(u8 loc_fec)16767e6ec914SJian Shen static unsigned int loc_to_eth_fec(u8 loc_fec)
16777e6ec914SJian Shen {
16787e6ec914SJian Shen u32 eth_fec = 0;
16797e6ec914SJian Shen
16807e6ec914SJian Shen if (loc_fec & BIT(HNAE3_FEC_AUTO))
16817e6ec914SJian Shen eth_fec |= ETHTOOL_FEC_AUTO;
16827e6ec914SJian Shen if (loc_fec & BIT(HNAE3_FEC_RS))
16837e6ec914SJian Shen eth_fec |= ETHTOOL_FEC_RS;
16845c4f7284SHao Lan if (loc_fec & BIT(HNAE3_FEC_LLRS))
16855c4f7284SHao Lan eth_fec |= ETHTOOL_FEC_LLRS;
16867e6ec914SJian Shen if (loc_fec & BIT(HNAE3_FEC_BASER))
16877e6ec914SJian Shen eth_fec |= ETHTOOL_FEC_BASER;
168808aa17a0SGuangbin Huang if (loc_fec & BIT(HNAE3_FEC_NONE))
168908aa17a0SGuangbin Huang eth_fec |= ETHTOOL_FEC_OFF;
16907e6ec914SJian Shen
16917e6ec914SJian Shen return eth_fec;
16927e6ec914SJian Shen }
16937e6ec914SJian Shen
16947e6ec914SJian Shen /* Translate ethtool fec value into local value. */
eth_to_loc_fec(unsigned int eth_fec)16957e6ec914SJian Shen static unsigned int eth_to_loc_fec(unsigned int eth_fec)
16967e6ec914SJian Shen {
16977e6ec914SJian Shen u32 loc_fec = 0;
16987e6ec914SJian Shen
16997e6ec914SJian Shen if (eth_fec & ETHTOOL_FEC_OFF)
170008aa17a0SGuangbin Huang loc_fec |= BIT(HNAE3_FEC_NONE);
17017e6ec914SJian Shen if (eth_fec & ETHTOOL_FEC_AUTO)
17027e6ec914SJian Shen loc_fec |= BIT(HNAE3_FEC_AUTO);
17037e6ec914SJian Shen if (eth_fec & ETHTOOL_FEC_RS)
17047e6ec914SJian Shen loc_fec |= BIT(HNAE3_FEC_RS);
17055c4f7284SHao Lan if (eth_fec & ETHTOOL_FEC_LLRS)
17065c4f7284SHao Lan loc_fec |= BIT(HNAE3_FEC_LLRS);
17077e6ec914SJian Shen if (eth_fec & ETHTOOL_FEC_BASER)
17087e6ec914SJian Shen loc_fec |= BIT(HNAE3_FEC_BASER);
17097e6ec914SJian Shen
17107e6ec914SJian Shen return loc_fec;
17117e6ec914SJian Shen }
17127e6ec914SJian Shen
hns3_get_fecparam(struct net_device * netdev,struct ethtool_fecparam * fec)17137e6ec914SJian Shen static int hns3_get_fecparam(struct net_device *netdev,
17147e6ec914SJian Shen struct ethtool_fecparam *fec)
17157e6ec914SJian Shen {
17167e6ec914SJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
171774ba23a1SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
17187e6ec914SJian Shen const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
17197e6ec914SJian Shen u8 fec_ability;
17207e6ec914SJian Shen u8 fec_mode;
17217e6ec914SJian Shen
17224cc86cb5SGuangbin Huang if (!test_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps))
17237e6ec914SJian Shen return -EOPNOTSUPP;
17247e6ec914SJian Shen
17257e6ec914SJian Shen if (!ops->get_fec)
17267e6ec914SJian Shen return -EOPNOTSUPP;
17277e6ec914SJian Shen
17287e6ec914SJian Shen ops->get_fec(handle, &fec_ability, &fec_mode);
17297e6ec914SJian Shen
17307e6ec914SJian Shen fec->fec = loc_to_eth_fec(fec_ability);
17317e6ec914SJian Shen fec->active_fec = loc_to_eth_fec(fec_mode);
173208aa17a0SGuangbin Huang if (!fec->active_fec)
173308aa17a0SGuangbin Huang fec->active_fec = ETHTOOL_FEC_OFF;
17347e6ec914SJian Shen
17357e6ec914SJian Shen return 0;
17367e6ec914SJian Shen }
17377e6ec914SJian Shen
hns3_set_fecparam(struct net_device * netdev,struct ethtool_fecparam * fec)17387e6ec914SJian Shen static int hns3_set_fecparam(struct net_device *netdev,
17397e6ec914SJian Shen struct ethtool_fecparam *fec)
17407e6ec914SJian Shen {
17417e6ec914SJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
174274ba23a1SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
17437e6ec914SJian Shen const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
17447e6ec914SJian Shen u32 fec_mode;
17457e6ec914SJian Shen
17464cc86cb5SGuangbin Huang if (!test_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps))
17477e6ec914SJian Shen return -EOPNOTSUPP;
17487e6ec914SJian Shen
17497e6ec914SJian Shen if (!ops->set_fec)
17507e6ec914SJian Shen return -EOPNOTSUPP;
17517e6ec914SJian Shen fec_mode = eth_to_loc_fec(fec->fec);
17521c822948SYonglong Liu
17531c822948SYonglong Liu netif_dbg(handle, drv, netdev, "set fecparam: mode=%u\n", fec_mode);
17541c822948SYonglong Liu
17557e6ec914SJian Shen return ops->set_fec(handle, fec_mode);
17567e6ec914SJian Shen }
17577e6ec914SJian Shen
hns3_get_module_info(struct net_device * netdev,struct ethtool_modinfo * modinfo)1758cb10228dSYonglong Liu static int hns3_get_module_info(struct net_device *netdev,
1759cb10228dSYonglong Liu struct ethtool_modinfo *modinfo)
1760cb10228dSYonglong Liu {
1761cb10228dSYonglong Liu #define HNS3_SFF_8636_V1_3 0x03
1762cb10228dSYonglong Liu
1763cb10228dSYonglong Liu struct hnae3_handle *handle = hns3_get_handle(netdev);
1764295ba232SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
1765cb10228dSYonglong Liu const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
1766cb10228dSYonglong Liu struct hns3_sfp_type sfp_type;
1767cb10228dSYonglong Liu int ret;
1768cb10228dSYonglong Liu
1769295ba232SGuangbin Huang if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2 ||
1770295ba232SGuangbin Huang !ops->get_module_eeprom)
1771cb10228dSYonglong Liu return -EOPNOTSUPP;
1772cb10228dSYonglong Liu
1773cb10228dSYonglong Liu memset(&sfp_type, 0, sizeof(sfp_type));
1774cb10228dSYonglong Liu ret = ops->get_module_eeprom(handle, 0, sizeof(sfp_type) / sizeof(u8),
1775cb10228dSYonglong Liu (u8 *)&sfp_type);
1776cb10228dSYonglong Liu if (ret)
1777cb10228dSYonglong Liu return ret;
1778cb10228dSYonglong Liu
1779cb10228dSYonglong Liu switch (sfp_type.type) {
1780cb10228dSYonglong Liu case SFF8024_ID_SFP:
1781cb10228dSYonglong Liu modinfo->type = ETH_MODULE_SFF_8472;
1782cb10228dSYonglong Liu modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
1783cb10228dSYonglong Liu break;
1784cb10228dSYonglong Liu case SFF8024_ID_QSFP_8438:
1785cb10228dSYonglong Liu modinfo->type = ETH_MODULE_SFF_8436;
1786cb10228dSYonglong Liu modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
1787cb10228dSYonglong Liu break;
1788cb10228dSYonglong Liu case SFF8024_ID_QSFP_8436_8636:
1789cb10228dSYonglong Liu if (sfp_type.ext_type < HNS3_SFF_8636_V1_3) {
1790cb10228dSYonglong Liu modinfo->type = ETH_MODULE_SFF_8436;
1791cb10228dSYonglong Liu modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
1792cb10228dSYonglong Liu } else {
1793cb10228dSYonglong Liu modinfo->type = ETH_MODULE_SFF_8636;
1794cb10228dSYonglong Liu modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
1795cb10228dSYonglong Liu }
1796cb10228dSYonglong Liu break;
1797cb10228dSYonglong Liu case SFF8024_ID_QSFP28_8636:
1798cb10228dSYonglong Liu modinfo->type = ETH_MODULE_SFF_8636;
1799cb10228dSYonglong Liu modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
1800cb10228dSYonglong Liu break;
1801cb10228dSYonglong Liu default:
1802cb10228dSYonglong Liu netdev_err(netdev, "Optical module unknown: %#x\n",
1803cb10228dSYonglong Liu sfp_type.type);
1804cb10228dSYonglong Liu return -EINVAL;
1805cb10228dSYonglong Liu }
1806cb10228dSYonglong Liu
1807cb10228dSYonglong Liu return 0;
1808cb10228dSYonglong Liu }
1809cb10228dSYonglong Liu
hns3_get_module_eeprom(struct net_device * netdev,struct ethtool_eeprom * ee,u8 * data)1810cb10228dSYonglong Liu static int hns3_get_module_eeprom(struct net_device *netdev,
1811cb10228dSYonglong Liu struct ethtool_eeprom *ee, u8 *data)
1812cb10228dSYonglong Liu {
1813cb10228dSYonglong Liu struct hnae3_handle *handle = hns3_get_handle(netdev);
1814295ba232SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
1815cb10228dSYonglong Liu const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
1816cb10228dSYonglong Liu
1817295ba232SGuangbin Huang if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2 ||
1818295ba232SGuangbin Huang !ops->get_module_eeprom)
1819cb10228dSYonglong Liu return -EOPNOTSUPP;
1820cb10228dSYonglong Liu
1821cb10228dSYonglong Liu if (!ee->len)
1822cb10228dSYonglong Liu return -EINVAL;
1823cb10228dSYonglong Liu
1824cb10228dSYonglong Liu memset(data, 0, ee->len);
1825cb10228dSYonglong Liu
1826cb10228dSYonglong Liu return ops->get_module_eeprom(handle, ee->offset, ee->len, data);
1827cb10228dSYonglong Liu }
1828cb10228dSYonglong Liu
hns3_get_priv_flags(struct net_device * netdev)18295e7414cdSJian Shen static u32 hns3_get_priv_flags(struct net_device *netdev)
18305e7414cdSJian Shen {
18315e7414cdSJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
18325e7414cdSJian Shen
18335e7414cdSJian Shen return handle->priv_flags;
18345e7414cdSJian Shen }
18355e7414cdSJian Shen
hns3_check_priv_flags(struct hnae3_handle * h,u32 changed)18365e7414cdSJian Shen static int hns3_check_priv_flags(struct hnae3_handle *h, u32 changed)
18375e7414cdSJian Shen {
18385e7414cdSJian Shen u32 i;
18395e7414cdSJian Shen
18405e7414cdSJian Shen for (i = 0; i < HNAE3_PFLAG_MAX; i++)
18415e7414cdSJian Shen if ((changed & BIT(i)) && !test_bit(i, &h->supported_pflags)) {
18425e7414cdSJian Shen netdev_err(h->netdev, "%s is unsupported\n",
18435e7414cdSJian Shen hns3_priv_flags[i].name);
18445e7414cdSJian Shen return -EOPNOTSUPP;
18455e7414cdSJian Shen }
18465e7414cdSJian Shen
18475e7414cdSJian Shen return 0;
18485e7414cdSJian Shen }
18495e7414cdSJian Shen
hns3_set_priv_flags(struct net_device * netdev,u32 pflags)18505e7414cdSJian Shen static int hns3_set_priv_flags(struct net_device *netdev, u32 pflags)
18515e7414cdSJian Shen {
18525e7414cdSJian Shen struct hnae3_handle *handle = hns3_get_handle(netdev);
18535e7414cdSJian Shen u32 changed = pflags ^ handle->priv_flags;
18545e7414cdSJian Shen int ret;
18555e7414cdSJian Shen u32 i;
18565e7414cdSJian Shen
18575e7414cdSJian Shen ret = hns3_check_priv_flags(handle, changed);
18585e7414cdSJian Shen if (ret)
18595e7414cdSJian Shen return ret;
18605e7414cdSJian Shen
18615e7414cdSJian Shen for (i = 0; i < HNAE3_PFLAG_MAX; i++) {
18625e7414cdSJian Shen if (changed & BIT(i)) {
18635e7414cdSJian Shen bool enable = !(handle->priv_flags & BIT(i));
18645e7414cdSJian Shen
18655e7414cdSJian Shen if (enable)
18665e7414cdSJian Shen handle->priv_flags |= BIT(i);
18675e7414cdSJian Shen else
18685e7414cdSJian Shen handle->priv_flags &= ~BIT(i);
18695e7414cdSJian Shen hns3_priv_flags[i].handler(netdev, enable);
18705e7414cdSJian Shen }
18715e7414cdSJian Shen }
18725e7414cdSJian Shen
18735e7414cdSJian Shen return 0;
18745e7414cdSJian Shen }
18755e7414cdSJian Shen
hns3_get_tunable(struct net_device * netdev,const struct ethtool_tunable * tuna,void * data)1876907676b1SYunsheng Lin static int hns3_get_tunable(struct net_device *netdev,
1877907676b1SYunsheng Lin const struct ethtool_tunable *tuna,
1878907676b1SYunsheng Lin void *data)
1879907676b1SYunsheng Lin {
1880907676b1SYunsheng Lin struct hns3_nic_priv *priv = netdev_priv(netdev);
1881e445f08aSHao Chen struct hnae3_handle *h = priv->ae_handle;
1882907676b1SYunsheng Lin int ret = 0;
1883907676b1SYunsheng Lin
1884907676b1SYunsheng Lin switch (tuna->id) {
1885907676b1SYunsheng Lin case ETHTOOL_TX_COPYBREAK:
1886907676b1SYunsheng Lin /* all the tx rings have the same tx_copybreak */
1887907676b1SYunsheng Lin *(u32 *)data = priv->tx_copybreak;
1888907676b1SYunsheng Lin break;
188999f6b5fbSYunsheng Lin case ETHTOOL_RX_COPYBREAK:
189099f6b5fbSYunsheng Lin *(u32 *)data = priv->rx_copybreak;
189199f6b5fbSYunsheng Lin break;
1892e445f08aSHao Chen case ETHTOOL_TX_COPYBREAK_BUF_SIZE:
1893e445f08aSHao Chen *(u32 *)data = h->kinfo.tx_spare_buf_size;
1894e445f08aSHao Chen break;
1895907676b1SYunsheng Lin default:
1896907676b1SYunsheng Lin ret = -EOPNOTSUPP;
1897907676b1SYunsheng Lin break;
1898907676b1SYunsheng Lin }
1899907676b1SYunsheng Lin
1900907676b1SYunsheng Lin return ret;
1901907676b1SYunsheng Lin }
1902907676b1SYunsheng Lin
hns3_set_tx_spare_buf_size(struct net_device * netdev,u32 data)1903e445f08aSHao Chen static int hns3_set_tx_spare_buf_size(struct net_device *netdev,
1904e445f08aSHao Chen u32 data)
1905e445f08aSHao Chen {
1906e445f08aSHao Chen struct hns3_nic_priv *priv = netdev_priv(netdev);
1907e445f08aSHao Chen struct hnae3_handle *h = priv->ae_handle;
1908e445f08aSHao Chen int ret;
1909e445f08aSHao Chen
1910e445f08aSHao Chen h->kinfo.tx_spare_buf_size = data;
1911e445f08aSHao Chen
1912e445f08aSHao Chen ret = hns3_reset_notify(h, HNAE3_DOWN_CLIENT);
1913e445f08aSHao Chen if (ret)
1914e445f08aSHao Chen return ret;
1915e445f08aSHao Chen
1916e445f08aSHao Chen ret = hns3_reset_notify(h, HNAE3_UNINIT_CLIENT);
1917e445f08aSHao Chen if (ret)
1918e445f08aSHao Chen return ret;
1919e445f08aSHao Chen
1920e445f08aSHao Chen ret = hns3_reset_notify(h, HNAE3_INIT_CLIENT);
1921e445f08aSHao Chen if (ret)
1922e445f08aSHao Chen return ret;
1923e445f08aSHao Chen
1924e445f08aSHao Chen ret = hns3_reset_notify(h, HNAE3_UP_CLIENT);
1925e445f08aSHao Chen if (ret)
1926e445f08aSHao Chen hns3_reset_notify(h, HNAE3_UNINIT_CLIENT);
1927e445f08aSHao Chen
1928e445f08aSHao Chen return ret;
1929e445f08aSHao Chen }
1930e445f08aSHao Chen
hns3_set_tunable(struct net_device * netdev,const struct ethtool_tunable * tuna,const void * data)1931907676b1SYunsheng Lin static int hns3_set_tunable(struct net_device *netdev,
1932907676b1SYunsheng Lin const struct ethtool_tunable *tuna,
1933907676b1SYunsheng Lin const void *data)
1934907676b1SYunsheng Lin {
1935907676b1SYunsheng Lin struct hns3_nic_priv *priv = netdev_priv(netdev);
1936e445f08aSHao Chen u32 old_tx_spare_buf_size, new_tx_spare_buf_size;
1937907676b1SYunsheng Lin struct hnae3_handle *h = priv->ae_handle;
1938907676b1SYunsheng Lin int i, ret = 0;
1939907676b1SYunsheng Lin
1940f5cd6016SHao Chen if (hns3_nic_resetting(netdev) || !priv->ring) {
1941f5cd6016SHao Chen netdev_err(netdev, "failed to set tunable value, dev resetting!");
1942f5cd6016SHao Chen return -EBUSY;
1943f5cd6016SHao Chen }
1944f5cd6016SHao Chen
1945907676b1SYunsheng Lin switch (tuna->id) {
1946907676b1SYunsheng Lin case ETHTOOL_TX_COPYBREAK:
1947907676b1SYunsheng Lin priv->tx_copybreak = *(u32 *)data;
1948907676b1SYunsheng Lin
1949907676b1SYunsheng Lin for (i = 0; i < h->kinfo.num_tqps; i++)
1950907676b1SYunsheng Lin priv->ring[i].tx_copybreak = priv->tx_copybreak;
1951907676b1SYunsheng Lin
1952907676b1SYunsheng Lin break;
195399f6b5fbSYunsheng Lin case ETHTOOL_RX_COPYBREAK:
195499f6b5fbSYunsheng Lin priv->rx_copybreak = *(u32 *)data;
195599f6b5fbSYunsheng Lin
195699f6b5fbSYunsheng Lin for (i = h->kinfo.num_tqps; i < h->kinfo.num_tqps * 2; i++)
195799f6b5fbSYunsheng Lin priv->ring[i].rx_copybreak = priv->rx_copybreak;
195899f6b5fbSYunsheng Lin
195999f6b5fbSYunsheng Lin break;
1960e445f08aSHao Chen case ETHTOOL_TX_COPYBREAK_BUF_SIZE:
1961e445f08aSHao Chen old_tx_spare_buf_size = h->kinfo.tx_spare_buf_size;
1962e445f08aSHao Chen new_tx_spare_buf_size = *(u32 *)data;
19632373b35cSHao Chen netdev_info(netdev, "request to set tx spare buf size from %u to %u\n",
19642373b35cSHao Chen old_tx_spare_buf_size, new_tx_spare_buf_size);
1965e445f08aSHao Chen ret = hns3_set_tx_spare_buf_size(netdev, new_tx_spare_buf_size);
196687783721SHao Chen if (ret ||
196787783721SHao Chen (!priv->ring->tx_spare && new_tx_spare_buf_size != 0)) {
1968e445f08aSHao Chen int ret1;
1969e445f08aSHao Chen
197029c17cb6SHao Chen netdev_warn(netdev, "change tx spare buf size fail, revert to old value\n");
1971e445f08aSHao Chen ret1 = hns3_set_tx_spare_buf_size(netdev,
1972e445f08aSHao Chen old_tx_spare_buf_size);
1973e445f08aSHao Chen if (ret1) {
197429c17cb6SHao Chen netdev_err(netdev, "revert to old tx spare buf size fail\n");
1975e445f08aSHao Chen return ret1;
1976e445f08aSHao Chen }
1977e445f08aSHao Chen
1978e445f08aSHao Chen return ret;
1979e445f08aSHao Chen }
19802373b35cSHao Chen
1981a4fe9b6dSHao Chen if (!priv->ring->tx_spare)
1982a4fe9b6dSHao Chen netdev_info(netdev, "the active tx spare buf size is 0, disable tx spare buffer\n");
1983a4fe9b6dSHao Chen else
198431693d02SColin Ian King netdev_info(netdev, "the active tx spare buf size is %u, due to page order\n",
19852373b35cSHao Chen priv->ring->tx_spare->len);
19862373b35cSHao Chen
1987e445f08aSHao Chen break;
1988907676b1SYunsheng Lin default:
1989907676b1SYunsheng Lin ret = -EOPNOTSUPP;
1990907676b1SYunsheng Lin break;
1991907676b1SYunsheng Lin }
1992907676b1SYunsheng Lin
1993907676b1SYunsheng Lin return ret;
1994907676b1SYunsheng Lin }
1995907676b1SYunsheng Lin
19967b8fda64SJakub Kicinski #define HNS3_ETHTOOL_COALESCE (ETHTOOL_COALESCE_USECS | \
19977b8fda64SJakub Kicinski ETHTOOL_COALESCE_USE_ADAPTIVE | \
19987b8fda64SJakub Kicinski ETHTOOL_COALESCE_RX_USECS_HIGH | \
199991bfae25SHuazhong Tan ETHTOOL_COALESCE_TX_USECS_HIGH | \
2000cce1689eSYufeng Mo ETHTOOL_COALESCE_MAX_FRAMES | \
2001cce1689eSYufeng Mo ETHTOOL_COALESCE_USE_CQE)
20027b8fda64SJakub Kicinski
20031f702c16SJie Wang #define HNS3_ETHTOOL_RING (ETHTOOL_RING_USE_RX_BUF_LEN | \
20041f702c16SJie Wang ETHTOOL_RING_USE_TX_PUSH)
2005e65a0231SHao Chen
hns3_get_ts_info(struct net_device * netdev,struct ethtool_ts_info * info)20060bf5eb78SHuazhong Tan static int hns3_get_ts_info(struct net_device *netdev,
20070bf5eb78SHuazhong Tan struct ethtool_ts_info *info)
20080bf5eb78SHuazhong Tan {
20090bf5eb78SHuazhong Tan struct hnae3_handle *handle = hns3_get_handle(netdev);
20100bf5eb78SHuazhong Tan
20110bf5eb78SHuazhong Tan if (handle->ae_algo->ops->get_ts_info)
20120bf5eb78SHuazhong Tan return handle->ae_algo->ops->get_ts_info(handle, info);
20130bf5eb78SHuazhong Tan
20140bf5eb78SHuazhong Tan return ethtool_op_get_ts_info(netdev, info);
20150bf5eb78SHuazhong Tan }
20160bf5eb78SHuazhong Tan
2017f5c2b9f0SGuangbin Huang static const struct hns3_ethtool_link_ext_state_mapping
2018f5c2b9f0SGuangbin Huang hns3_link_ext_state_map[] = {
2019f5c2b9f0SGuangbin Huang {1, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2020f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD},
2021f5c2b9f0SGuangbin Huang {2, ETHTOOL_LINK_EXT_STATE_AUTONEG,
2022f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED},
2023f5c2b9f0SGuangbin Huang
2024f5c2b9f0SGuangbin Huang {256, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
2025f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT},
2026f5c2b9f0SGuangbin Huang {257, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
2027f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY},
2028f5c2b9f0SGuangbin Huang {512, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
2029f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT},
2030f5c2b9f0SGuangbin Huang
2031f5c2b9f0SGuangbin Huang {513, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2032f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK},
2033f5c2b9f0SGuangbin Huang {514, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2034f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED},
2035f5c2b9f0SGuangbin Huang {515, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
2036f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED},
2037f5c2b9f0SGuangbin Huang
2038f5c2b9f0SGuangbin Huang {768, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
2039f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS},
2040f5c2b9f0SGuangbin Huang {769, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
2041f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST},
2042f5c2b9f0SGuangbin Huang {770, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
2043f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS},
2044f5c2b9f0SGuangbin Huang
2045f5c2b9f0SGuangbin Huang {1024, ETHTOOL_LINK_EXT_STATE_NO_CABLE, 0},
2046f5c2b9f0SGuangbin Huang {1025, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
2047f5c2b9f0SGuangbin Huang ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
2048f5c2b9f0SGuangbin Huang
2049f5c2b9f0SGuangbin Huang {1026, ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, 0},
2050f5c2b9f0SGuangbin Huang };
2051f5c2b9f0SGuangbin Huang
hns3_get_link_ext_state(struct net_device * netdev,struct ethtool_link_ext_state_info * info)2052f5c2b9f0SGuangbin Huang static int hns3_get_link_ext_state(struct net_device *netdev,
2053f5c2b9f0SGuangbin Huang struct ethtool_link_ext_state_info *info)
2054f5c2b9f0SGuangbin Huang {
2055f5c2b9f0SGuangbin Huang const struct hns3_ethtool_link_ext_state_mapping *map;
2056f5c2b9f0SGuangbin Huang struct hnae3_handle *h = hns3_get_handle(netdev);
2057f5c2b9f0SGuangbin Huang u32 status_code, i;
2058f5c2b9f0SGuangbin Huang int ret;
2059f5c2b9f0SGuangbin Huang
2060f5c2b9f0SGuangbin Huang if (netif_carrier_ok(netdev))
2061f5c2b9f0SGuangbin Huang return -ENODATA;
2062f5c2b9f0SGuangbin Huang
2063f5c2b9f0SGuangbin Huang if (!h->ae_algo->ops->get_link_diagnosis_info)
2064f5c2b9f0SGuangbin Huang return -EOPNOTSUPP;
2065f5c2b9f0SGuangbin Huang
2066f5c2b9f0SGuangbin Huang ret = h->ae_algo->ops->get_link_diagnosis_info(h, &status_code);
2067f5c2b9f0SGuangbin Huang if (ret)
2068f5c2b9f0SGuangbin Huang return ret;
2069f5c2b9f0SGuangbin Huang
2070f5c2b9f0SGuangbin Huang for (i = 0; i < ARRAY_SIZE(hns3_link_ext_state_map); i++) {
2071f5c2b9f0SGuangbin Huang map = &hns3_link_ext_state_map[i];
2072f5c2b9f0SGuangbin Huang if (map->status_code == status_code) {
2073f5c2b9f0SGuangbin Huang info->link_ext_state = map->link_ext_state;
2074f5c2b9f0SGuangbin Huang info->__link_ext_substate = map->link_ext_substate;
2075f5c2b9f0SGuangbin Huang return 0;
2076f5c2b9f0SGuangbin Huang }
2077f5c2b9f0SGuangbin Huang }
2078f5c2b9f0SGuangbin Huang
2079f5c2b9f0SGuangbin Huang return -ENODATA;
2080f5c2b9f0SGuangbin Huang }
2081f5c2b9f0SGuangbin Huang
hns3_get_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)20823b064f54SHao Lan static void hns3_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
20833b064f54SHao Lan {
20843b064f54SHao Lan struct hnae3_handle *handle = hns3_get_handle(netdev);
20853b064f54SHao Lan const struct hnae3_ae_ops *ops = hns3_get_ops(handle);
20863b064f54SHao Lan struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle);
20873b064f54SHao Lan
20883b064f54SHao Lan if (!hnae3_ae_dev_wol_supported(ae_dev))
20893b064f54SHao Lan return;
20903b064f54SHao Lan
20913b064f54SHao Lan ops->get_wol(handle, wol);
20923b064f54SHao Lan }
20933b064f54SHao Lan
hns3_set_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)20943b064f54SHao Lan static int hns3_set_wol(struct net_device *netdev,
20953b064f54SHao Lan struct ethtool_wolinfo *wol)
20963b064f54SHao Lan {
20973b064f54SHao Lan struct hnae3_handle *handle = hns3_get_handle(netdev);
20983b064f54SHao Lan const struct hnae3_ae_ops *ops = hns3_get_ops(handle);
20993b064f54SHao Lan struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(handle);
21003b064f54SHao Lan
21013b064f54SHao Lan if (!hnae3_ae_dev_wol_supported(ae_dev))
21023b064f54SHao Lan return -EOPNOTSUPP;
21033b064f54SHao Lan
21043b064f54SHao Lan return ops->set_wol(handle, wol);
21053b064f54SHao Lan }
21063b064f54SHao Lan
2107424eb834SSalil Mehta static const struct ethtool_ops hns3vf_ethtool_ops = {
21087b8fda64SJakub Kicinski .supported_coalesce_params = HNS3_ETHTOOL_COALESCE,
2109e65a0231SHao Chen .supported_ring_params = HNS3_ETHTOOL_RING,
2110424eb834SSalil Mehta .get_drvinfo = hns3_get_drvinfo,
2111424eb834SSalil Mehta .get_ringparam = hns3_get_ringparam,
2112424eb834SSalil Mehta .set_ringparam = hns3_set_ringparam,
2113424eb834SSalil Mehta .get_strings = hns3_get_strings,
2114424eb834SSalil Mehta .get_ethtool_stats = hns3_get_stats,
2115424eb834SSalil Mehta .get_sset_count = hns3_get_sset_count,
2116424eb834SSalil Mehta .get_rxnfc = hns3_get_rxnfc,
2117d97b3072SJian Shen .set_rxnfc = hns3_set_rxnfc,
2118424eb834SSalil Mehta .get_rxfh_key_size = hns3_get_rss_key_size,
2119424eb834SSalil Mehta .get_rxfh_indir_size = hns3_get_rss_indir_size,
2120424eb834SSalil Mehta .get_rxfh = hns3_get_rss,
2121424eb834SSalil Mehta .set_rxfh = hns3_set_rss,
2122424eb834SSalil Mehta .get_link_ksettings = hns3_get_link_ksettings,
2123849e4607SPeng Li .get_channels = hns3_get_channels,
21244093d1a2SGuangbin Huang .set_channels = hns3_set_channels,
2125ad31c732SFuyun Liang .get_coalesce = hns3_get_coalesce,
2126ad31c732SFuyun Liang .set_coalesce = hns3_set_coalesce,
21278e1445a6SJian Shen .get_regs_len = hns3_get_regs_len,
21288e1445a6SJian Shen .get_regs = hns3_get_regs,
2129175ec96bSFuyun Liang .get_link = hns3_get_link,
2130bb87be87SYonglong Liu .get_msglevel = hns3_get_msglevel,
2131bb87be87SYonglong Liu .set_msglevel = hns3_set_msglevel,
21325e7414cdSJian Shen .get_priv_flags = hns3_get_priv_flags,
21335e7414cdSJian Shen .set_priv_flags = hns3_set_priv_flags,
2134907676b1SYunsheng Lin .get_tunable = hns3_get_tunable,
2135907676b1SYunsheng Lin .set_tunable = hns3_set_tunable,
2136ddccc5e3SYufeng Mo .reset = hns3_set_reset,
2137424eb834SSalil Mehta };
2138424eb834SSalil Mehta
2139424eb834SSalil Mehta static const struct ethtool_ops hns3_ethtool_ops = {
21407b8fda64SJakub Kicinski .supported_coalesce_params = HNS3_ETHTOOL_COALESCE,
2141e65a0231SHao Chen .supported_ring_params = HNS3_ETHTOOL_RING,
21420f032f93SHao Chen .cap_link_lanes_supported = true,
2143424eb834SSalil Mehta .self_test = hns3_self_test,
2144424eb834SSalil Mehta .get_drvinfo = hns3_get_drvinfo,
2145424eb834SSalil Mehta .get_link = hns3_get_link,
2146424eb834SSalil Mehta .get_ringparam = hns3_get_ringparam,
2147424eb834SSalil Mehta .set_ringparam = hns3_set_ringparam,
2148424eb834SSalil Mehta .get_pauseparam = hns3_get_pauseparam,
214961387774SPeng Li .set_pauseparam = hns3_set_pauseparam,
2150424eb834SSalil Mehta .get_strings = hns3_get_strings,
2151424eb834SSalil Mehta .get_ethtool_stats = hns3_get_stats,
2152424eb834SSalil Mehta .get_sset_count = hns3_get_sset_count,
2153424eb834SSalil Mehta .get_rxnfc = hns3_get_rxnfc,
2154424eb834SSalil Mehta .set_rxnfc = hns3_set_rxnfc,
2155424eb834SSalil Mehta .get_rxfh_key_size = hns3_get_rss_key_size,
2156424eb834SSalil Mehta .get_rxfh_indir_size = hns3_get_rss_indir_size,
2157424eb834SSalil Mehta .get_rxfh = hns3_get_rss,
2158424eb834SSalil Mehta .set_rxfh = hns3_set_rss,
2159424eb834SSalil Mehta .get_link_ksettings = hns3_get_link_ksettings,
2160424eb834SSalil Mehta .set_link_ksettings = hns3_set_link_ksettings,
2161424eb834SSalil Mehta .nway_reset = hns3_nway_reset,
2162482d2e9cSPeng Li .get_channels = hns3_get_channels,
216309f2af64SPeng Li .set_channels = hns3_set_channels,
21647e96adc4SFuyun Liang .get_coalesce = hns3_get_coalesce,
2165434776a5SFuyun Liang .set_coalesce = hns3_set_coalesce,
216677b34110SFuyun Liang .get_regs_len = hns3_get_regs_len,
216777b34110SFuyun Liang .get_regs = hns3_get_regs,
216807f8e940SJian Shen .set_phys_id = hns3_set_phys_id,
2169bb87be87SYonglong Liu .get_msglevel = hns3_get_msglevel,
2170bb87be87SYonglong Liu .set_msglevel = hns3_set_msglevel,
21717e6ec914SJian Shen .get_fecparam = hns3_get_fecparam,
21727e6ec914SJian Shen .set_fecparam = hns3_set_fecparam,
21732cb343b9SHao Lan .get_fec_stats = hns3_get_fec_stats,
2174cb10228dSYonglong Liu .get_module_info = hns3_get_module_info,
2175cb10228dSYonglong Liu .get_module_eeprom = hns3_get_module_eeprom,
21765e7414cdSJian Shen .get_priv_flags = hns3_get_priv_flags,
21775e7414cdSJian Shen .set_priv_flags = hns3_set_priv_flags,
21780bf5eb78SHuazhong Tan .get_ts_info = hns3_get_ts_info,
2179907676b1SYunsheng Lin .get_tunable = hns3_get_tunable,
2180907676b1SYunsheng Lin .set_tunable = hns3_set_tunable,
2181ddccc5e3SYufeng Mo .reset = hns3_set_reset,
2182f5c2b9f0SGuangbin Huang .get_link_ext_state = hns3_get_link_ext_state,
21833b064f54SHao Lan .get_wol = hns3_get_wol,
21843b064f54SHao Lan .set_wol = hns3_set_wol,
2185424eb834SSalil Mehta };
2186424eb834SSalil Mehta
hns3_ethtool_set_ops(struct net_device * netdev)2187424eb834SSalil Mehta void hns3_ethtool_set_ops(struct net_device *netdev)
2188424eb834SSalil Mehta {
2189424eb834SSalil Mehta struct hnae3_handle *h = hns3_get_handle(netdev);
2190424eb834SSalil Mehta
2191424eb834SSalil Mehta if (h->flags & HNAE3_SUPPORT_VF)
2192424eb834SSalil Mehta netdev->ethtool_ops = &hns3vf_ethtool_ops;
2193424eb834SSalil Mehta else
2194424eb834SSalil Mehta netdev->ethtool_ops = &hns3_ethtool_ops;
2195424eb834SSalil Mehta }
2196