]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152
[mirror_ubuntu-focal-kernel.git] / drivers / net / ethernet / hisilicon / hns / hns_ethtool.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
b5996f11 2/*
3 * Copyright (c) 2014-2015 Hisilicon Limited.
b5996f11 4 */
5
6#include <linux/etherdevice.h>
7#include <linux/interrupt.h>
8#include <linux/module.h>
9#include <linux/platform_device.h>
b5996f11 10#include "hns_enet.h"
11
12#define HNS_PHY_PAGE_MDIX 0
13#define HNS_PHY_PAGE_LED 3
14#define HNS_PHY_PAGE_COPPER 0
15
16#define HNS_PHY_PAGE_REG 22 /* Page Selection Reg. */
17#define HNS_PHY_CSC_REG 16 /* Copper Specific Control Register */
18#define HNS_PHY_CSS_REG 17 /* Copper Specific Status Register */
19#define HNS_LED_FC_REG 16 /* LED Function Control Reg. */
20#define HNS_LED_PC_REG 17 /* LED Polarity Control Reg. */
21
22#define HNS_LED_FORCE_ON 9
23#define HNS_LED_FORCE_OFF 8
24
25#define HNS_CHIP_VERSION 660
26#define HNS_NET_STATS_CNT 26
27
28#define PHY_MDIX_CTRL_S (5)
29#define PHY_MDIX_CTRL_M (3 << PHY_MDIX_CTRL_S)
30
31#define PHY_MDIX_STATUS_B (6)
32#define PHY_SPEED_DUP_RESOLVE_B (11)
33
34/**
35 *hns_nic_get_link - get current link status
36 *@net_dev: net_device
37 *retuen 0 - success , negative --fail
38 */
39static u32 hns_nic_get_link(struct net_device *net_dev)
40{
41 struct hns_nic_priv *priv = netdev_priv(net_dev);
42 u32 link_stat = priv->link;
43 struct hnae_handle *h;
44
b5996f11 45 h = priv->ae_handle;
46
262b38cd
PR
47 if (net_dev->phydev) {
48 if (!genphy_read_status(net_dev->phydev))
49 link_stat = net_dev->phydev->link;
b5996f11 50 else
51 link_stat = 0;
52 }
53
54 if (h->dev && h->dev->ops && h->dev->ops->get_status)
55 link_stat = link_stat && h->dev->ops->get_status(h);
56 else
57 link_stat = 0;
58
59 return link_stat;
60}
61
62static void hns_get_mdix_mode(struct net_device *net_dev,
d270f76c 63 struct ethtool_link_ksettings *cmd)
b5996f11 64{
65 int mdix_ctrl, mdix, retval, is_resolved;
262b38cd 66 struct phy_device *phy_dev = net_dev->phydev;
b5996f11 67
e5a03bfd 68 if (!phy_dev || !phy_dev->mdio.bus) {
d270f76c
PR
69 cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
70 cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
b5996f11 71 return;
72 }
73
cd690e48 74 phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_MDIX);
b5996f11 75
cd690e48 76 retval = phy_read(phy_dev, HNS_PHY_CSC_REG);
b5996f11 77 mdix_ctrl = hnae_get_field(retval, PHY_MDIX_CTRL_M, PHY_MDIX_CTRL_S);
78
cd690e48 79 retval = phy_read(phy_dev, HNS_PHY_CSS_REG);
b5996f11 80 mdix = hnae_get_bit(retval, PHY_MDIX_STATUS_B);
81 is_resolved = hnae_get_bit(retval, PHY_SPEED_DUP_RESOLVE_B);
82
cd690e48 83 phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER);
b5996f11 84
85 switch (mdix_ctrl) {
86 case 0x0:
d270f76c 87 cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI;
b5996f11 88 break;
89 case 0x1:
d270f76c 90 cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_X;
b5996f11 91 break;
92 case 0x3:
d270f76c 93 cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
b5996f11 94 break;
95 default:
d270f76c 96 cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
b5996f11 97 break;
98 }
99
100 if (!is_resolved)
d270f76c 101 cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
b5996f11 102 else if (mdix)
d270f76c 103 cmd->base.eth_tp_mdix = ETH_TP_MDI_X;
b5996f11 104 else
d270f76c 105 cmd->base.eth_tp_mdix = ETH_TP_MDI;
b5996f11 106}
107
108/**
d270f76c 109 *hns_nic_get_link_ksettings - implement ethtool get link ksettings
b5996f11 110 *@net_dev: net_device
d270f76c 111 *@cmd: ethtool_link_ksettings
b5996f11 112 *retuen 0 - success , negative --fail
113 */
d270f76c
PR
114static int hns_nic_get_link_ksettings(struct net_device *net_dev,
115 struct ethtool_link_ksettings *cmd)
b5996f11 116{
117 struct hns_nic_priv *priv = netdev_priv(net_dev);
118 struct hnae_handle *h;
119 u32 link_stat;
120 int ret;
121 u8 duplex;
122 u16 speed;
d270f76c 123 u32 supported, advertising;
b5996f11 124
125 if (!priv || !priv->ae_handle)
126 return -ESRCH;
127
128 h = priv->ae_handle;
129 if (!h->dev || !h->dev->ops || !h->dev->ops->get_info)
130 return -ESRCH;
131
132 ret = h->dev->ops->get_info(h, NULL, &speed, &duplex);
133 if (ret < 0) {
134 netdev_err(net_dev, "%s get_info error!\n", __func__);
135 return -EINVAL;
136 }
137
d270f76c
PR
138 ethtool_convert_link_mode_to_legacy_u32(&supported,
139 cmd->link_modes.supported);
140 ethtool_convert_link_mode_to_legacy_u32(&advertising,
141 cmd->link_modes.advertising);
142
b5996f11 143 /* When there is no phy, autoneg is off. */
d270f76c 144 cmd->base.autoneg = false;
4b7cdeca 145 cmd->base.speed = speed;
d270f76c 146 cmd->base.duplex = duplex;
b5996f11 147
262b38cd 148 if (net_dev->phydev)
5514174f 149 phy_ethtool_ksettings_get(net_dev->phydev, cmd);
b5996f11 150
151 link_stat = hns_nic_get_link(net_dev);
152 if (!link_stat) {
d270f76c
PR
153 cmd->base.speed = (u32)SPEED_UNKNOWN;
154 cmd->base.duplex = DUPLEX_UNKNOWN;
b5996f11 155 }
156
d270f76c
PR
157 if (cmd->base.autoneg)
158 advertising |= ADVERTISED_Autoneg;
b5996f11 159
d270f76c 160 supported |= h->if_support;
b5996f11 161 if (h->phy_if == PHY_INTERFACE_MODE_SGMII) {
d270f76c
PR
162 supported |= SUPPORTED_TP;
163 advertising |= ADVERTISED_1000baseT_Full;
b5996f11 164 } else if (h->phy_if == PHY_INTERFACE_MODE_XGMII) {
d270f76c
PR
165 supported |= SUPPORTED_FIBRE;
166 advertising |= ADVERTISED_10000baseKR_Full;
b5996f11 167 }
168
5d2525f7
KY
169 switch (h->media_type) {
170 case HNAE_MEDIA_TYPE_FIBER:
d270f76c 171 cmd->base.port = PORT_FIBRE;
5d2525f7
KY
172 break;
173 case HNAE_MEDIA_TYPE_COPPER:
d270f76c 174 cmd->base.port = PORT_TP;
5d2525f7
KY
175 break;
176 case HNAE_MEDIA_TYPE_UNKNOWN:
177 default:
178 break;
b5996f11 179 }
180
5d2525f7 181 if (!(AE_IS_VER1(priv->enet_ver) && h->port_type == HNAE_PORT_DEBUG))
d270f76c
PR
182 supported |= SUPPORTED_Pause;
183
184 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
185 supported);
186 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
187 advertising);
5d2525f7 188
d270f76c 189 cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C45 | ETH_MDIO_SUPPORTS_C22;
b5996f11 190 hns_get_mdix_mode(net_dev, cmd);
191
192 return 0;
193}
194
195/**
d270f76c 196 *hns_nic_set_link_settings - implement ethtool set link ksettings
b5996f11 197 *@net_dev: net_device
d270f76c 198 *@cmd: ethtool_link_ksettings
b5996f11 199 *retuen 0 - success , negative --fail
200 */
d270f76c
PR
201static int hns_nic_set_link_ksettings(struct net_device *net_dev,
202 const struct ethtool_link_ksettings *cmd)
b5996f11 203{
204 struct hns_nic_priv *priv = netdev_priv(net_dev);
205 struct hnae_handle *h;
b5996f11 206 u32 speed;
b5996f11 207
208 if (!netif_running(net_dev))
209 return -ESRCH;
210
211 if (!priv || !priv->ae_handle || !priv->ae_handle->dev ||
212 !priv->ae_handle->dev->ops)
213 return -ENODEV;
214
215 h = priv->ae_handle;
d270f76c 216 speed = cmd->base.speed;
b5996f11 217
218 if (h->phy_if == PHY_INTERFACE_MODE_XGMII) {
d270f76c
PR
219 if (cmd->base.autoneg == AUTONEG_ENABLE ||
220 speed != SPEED_10000 ||
221 cmd->base.duplex != DUPLEX_FULL)
b5996f11 222 return -EINVAL;
223 } else if (h->phy_if == PHY_INTERFACE_MODE_SGMII) {
d270f76c 224 if (!net_dev->phydev && cmd->base.autoneg == AUTONEG_ENABLE)
b5996f11 225 return -EINVAL;
226
d270f76c 227 if (speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
b5996f11 228 return -EINVAL;
262b38cd 229 if (net_dev->phydev)
d270f76c 230 return phy_ethtool_ksettings_set(net_dev->phydev, cmd);
b5996f11 231
20ddb1d3 232 if ((speed != SPEED_10 && speed != SPEED_100 &&
d270f76c
PR
233 speed != SPEED_1000) || (cmd->base.duplex != DUPLEX_HALF &&
234 cmd->base.duplex != DUPLEX_FULL))
b5996f11 235 return -EINVAL;
236 } else {
237 netdev_err(net_dev, "Not supported!");
238 return -ENOTSUPP;
239 }
240
20ddb1d3 241 if (h->dev->ops->adjust_link) {
455c4401 242 netif_carrier_off(net_dev);
d270f76c 243 h->dev->ops->adjust_link(h, (int)speed, cmd->base.duplex);
455c4401 244 netif_carrier_on(net_dev);
b5996f11 245 return 0;
246 }
20ddb1d3 247
b5996f11 248 netdev_err(net_dev, "Not supported!");
249 return -ENOTSUPP;
250}
251
252static const char hns_nic_test_strs[][ETH_GSTRING_LEN] = {
253 "Mac Loopback test",
254 "Serdes Loopback test",
255 "Phy Loopback test"
256};
257
258static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
259{
67cd9a99 260 int err;
b5996f11 261
262 if (en) {
67cd9a99
LYS
263 /* Doing phy loopback in offline state, phy resuming is
264 * needed to power up the device.
265 */
266 err = phy_resume(phy_dev);
267 if (err)
268 goto out;
269
270 err = phy_loopback(phy_dev, true);
b5996f11 271 } else {
67cd9a99
LYS
272 err = phy_loopback(phy_dev, false);
273 if (err)
274 goto out;
275
276 err = phy_suspend(phy_dev);
b5996f11 277 }
67cd9a99
LYS
278
279out:
280 return err;
b5996f11 281}
282
283static int __lb_setup(struct net_device *ndev,
284 enum hnae_loop loop)
285{
286 int ret = 0;
287 struct hns_nic_priv *priv = netdev_priv(ndev);
262b38cd 288 struct phy_device *phy_dev = ndev->phydev;
b5996f11 289 struct hnae_handle *h = priv->ae_handle;
290
291 switch (loop) {
292 case MAC_INTERNALLOOP_PHY:
67cd9a99
LYS
293 ret = hns_nic_config_phy_loopback(phy_dev, 0x1);
294 if (!ret)
295 ret = h->dev->ops->set_loopback(h, loop, 0x1);
b5996f11 296 break;
297 case MAC_INTERNALLOOP_MAC:
298 if ((h->dev->ops->set_loopback) &&
299 (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII))
300 ret = h->dev->ops->set_loopback(h, loop, 0x1);
301 break;
302 case MAC_INTERNALLOOP_SERDES:
303 if (h->dev->ops->set_loopback)
304 ret = h->dev->ops->set_loopback(h, loop, 0x1);
305 break;
67cd9a99
LYS
306 case MAC_LOOP_PHY_NONE:
307 ret = hns_nic_config_phy_loopback(phy_dev, 0x0);
1e14ef19 308 /* fall through */
b5996f11 309 case MAC_LOOP_NONE:
67cd9a99 310 if (!ret && h->dev->ops->set_loopback) {
b5996f11 311 if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)
67cd9a99 312 ret = h->dev->ops->set_loopback(h,
b5996f11 313 MAC_INTERNALLOOP_MAC, 0x0);
314
67cd9a99
LYS
315 if (!ret)
316 ret = h->dev->ops->set_loopback(h,
317 MAC_INTERNALLOOP_SERDES, 0x0);
b5996f11 318 }
319 break;
320 default:
321 ret = -EINVAL;
322 break;
323 }
324
ea870bf9
KY
325 if (!ret) {
326 if (loop == MAC_LOOP_NONE)
327 h->dev->ops->set_promisc_mode(
328 h, ndev->flags & IFF_PROMISC);
329 else
330 h->dev->ops->set_promisc_mode(h, 1);
331 }
b5996f11 332 return ret;
333}
334
335static int __lb_up(struct net_device *ndev,
336 enum hnae_loop loop_mode)
337{
338 struct hns_nic_priv *priv = netdev_priv(ndev);
339 struct hnae_handle *h = priv->ae_handle;
340 int speed, duplex;
341 int ret;
342
343 hns_nic_net_reset(ndev);
344
b5996f11 345 ret = __lb_setup(ndev, loop_mode);
346 if (ret)
347 return ret;
348
cba80bde 349 msleep(200);
b5996f11 350
351 ret = h->dev->ops->start ? h->dev->ops->start(h) : 0;
352 if (ret)
353 return ret;
354
b5996f11 355 /* link adjust duplex*/
356 if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)
357 speed = 1000;
358 else
359 speed = 10000;
360 duplex = 1;
361
362 h->dev->ops->adjust_link(h, speed, duplex);
363
364 return 0;
365}
366
367static void __lb_other_process(struct hns_nic_ring_data *ring_data,
368 struct sk_buff *skb)
369{
370 struct net_device *ndev;
68c222a6 371 struct hns_nic_priv *priv;
b5996f11 372 struct hnae_ring *ring;
373 struct netdev_queue *dev_queue;
374 struct sk_buff *new_skb;
375 unsigned int frame_size;
376 int check_ok;
377 u32 i;
378 char buff[33]; /* 32B data and the last character '\0' */
379
380 if (!ring_data) { /* Just for doing create frame*/
68c222a6 381 ndev = skb->dev;
382 priv = netdev_priv(ndev);
383
b5996f11 384 frame_size = skb->len;
385 memset(skb->data, 0xFF, frame_size);
68c222a6 386 if ((!AE_IS_VER1(priv->enet_ver)) &&
387 (priv->ae_handle->port_type == HNAE_PORT_SERVICE)) {
388 memcpy(skb->data, ndev->dev_addr, 6);
389 skb->data[5] += 0x1f;
390 }
391
b5996f11 392 frame_size &= ~1ul;
393 memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
394 memset(&skb->data[frame_size / 2 + 10], 0xBE,
395 frame_size / 2 - 11);
396 memset(&skb->data[frame_size / 2 + 12], 0xAF,
397 frame_size / 2 - 13);
398 return;
399 }
400
401 ring = ring_data->ring;
402 ndev = ring_data->napi.dev;
403 if (is_tx_ring(ring)) { /* for tx queue reset*/
404 dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index);
405 netdev_tx_reset_queue(dev_queue);
406 return;
407 }
408
409 frame_size = skb->len;
410 frame_size &= ~1ul;
411 /* for mutl buffer*/
412 new_skb = skb_copy(skb, GFP_ATOMIC);
413 dev_kfree_skb_any(skb);
414 skb = new_skb;
415
416 check_ok = 0;
417 if (*(skb->data + 10) == 0xFF) { /* for rx check frame*/
418 if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
419 (*(skb->data + frame_size / 2 + 12) == 0xAF))
420 check_ok = 1;
421 }
422
423 if (check_ok) {
424 ndev->stats.rx_packets++;
425 ndev->stats.rx_bytes += skb->len;
426 } else {
427 ndev->stats.rx_frame_errors++;
428 for (i = 0; i < skb->len; i++) {
429 snprintf(buff + i % 16 * 2, 3, /* tailing \0*/
430 "%02x", *(skb->data + i));
431 if ((i % 16 == 15) || (i == skb->len - 1))
432 pr_info("%s\n", buff);
433 }
434 }
435 dev_kfree_skb_any(skb);
436}
437
438static int __lb_clean_rings(struct hns_nic_priv *priv,
439 int ringid0, int ringid1, int budget)
440{
441 int i, ret;
442 struct hns_nic_ring_data *ring_data;
443 struct net_device *ndev = priv->netdev;
444 unsigned long rx_packets = ndev->stats.rx_packets;
445 unsigned long rx_bytes = ndev->stats.rx_bytes;
446 unsigned long rx_frame_errors = ndev->stats.rx_frame_errors;
447
448 for (i = ringid0; i <= ringid1; i++) {
449 ring_data = &priv->ring_data[i];
450 (void)ring_data->poll_one(ring_data,
451 budget, __lb_other_process);
452 }
453 ret = (int)(ndev->stats.rx_packets - rx_packets);
454 ndev->stats.rx_packets = rx_packets;
455 ndev->stats.rx_bytes = rx_bytes;
456 ndev->stats.rx_frame_errors = rx_frame_errors;
457 return ret;
458}
459
460/**
461 * nic_run_loopback_test - run loopback test
462 * @nic_dev: net device
463 * @loopback_type: loopback type
464 */
465static int __lb_run_test(struct net_device *ndev,
466 enum hnae_loop loop_mode)
467{
468#define NIC_LB_TEST_PKT_NUM_PER_CYCLE 1
469#define NIC_LB_TEST_RING_ID 0
470#define NIC_LB_TEST_FRAME_SIZE 128
471/* nic loopback test err */
472#define NIC_LB_TEST_NO_MEM_ERR 1
473#define NIC_LB_TEST_TX_CNT_ERR 2
474#define NIC_LB_TEST_RX_CNT_ERR 3
475#define NIC_LB_TEST_RX_PKG_ERR 4
476 struct hns_nic_priv *priv = netdev_priv(ndev);
477 struct hnae_handle *h = priv->ae_handle;
478 int i, j, lc, good_cnt, ret_val = 0;
479 unsigned int size;
480 netdev_tx_t tx_ret_val;
481 struct sk_buff *skb;
482
483 size = NIC_LB_TEST_FRAME_SIZE;
484 /* allocate test skb */
485 skb = alloc_skb(size, GFP_KERNEL);
486 if (!skb)
487 return NIC_LB_TEST_NO_MEM_ERR;
488
489 /* place data into test skb */
490 (void)skb_put(skb, size);
68c222a6 491 skb->dev = ndev;
b5996f11 492 __lb_other_process(NULL, skb);
493 skb->queue_mapping = NIC_LB_TEST_RING_ID;
494
495 lc = 1;
496 for (j = 0; j < lc; j++) {
497 /* reset count of good packets */
498 good_cnt = 0;
499 /* place 64 packets on the transmit queue*/
500 for (i = 0; i < NIC_LB_TEST_PKT_NUM_PER_CYCLE; i++) {
501 (void)skb_get(skb);
502
503 tx_ret_val = (netdev_tx_t)hns_nic_net_xmit_hw(
504 ndev, skb,
505 &tx_ring_data(priv, skb->queue_mapping));
506 if (tx_ret_val == NETDEV_TX_OK)
507 good_cnt++;
508 else
509 break;
510 }
511 if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) {
512 ret_val = NIC_LB_TEST_TX_CNT_ERR;
513 dev_err(priv->dev, "%s sent fail, cnt=0x%x, budget=0x%x\n",
514 hns_nic_test_strs[loop_mode], good_cnt,
515 NIC_LB_TEST_PKT_NUM_PER_CYCLE);
516 break;
517 }
518
519 /* allow 100 milliseconds for packets to go from Tx to Rx */
520 msleep(100);
521
522 good_cnt = __lb_clean_rings(priv,
523 h->q_num, h->q_num * 2 - 1,
524 NIC_LB_TEST_PKT_NUM_PER_CYCLE);
525 if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) {
526 ret_val = NIC_LB_TEST_RX_CNT_ERR;
527 dev_err(priv->dev, "%s recv fail, cnt=0x%x, budget=0x%x\n",
528 hns_nic_test_strs[loop_mode], good_cnt,
529 NIC_LB_TEST_PKT_NUM_PER_CYCLE);
530 break;
531 }
532 (void)__lb_clean_rings(priv,
533 NIC_LB_TEST_RING_ID, NIC_LB_TEST_RING_ID,
534 NIC_LB_TEST_PKT_NUM_PER_CYCLE);
535 }
536
537 /* free the original skb */
538 kfree_skb(skb);
539
540 return ret_val;
541}
542
67cd9a99 543static int __lb_down(struct net_device *ndev, enum hnae_loop loop)
b5996f11 544{
545 struct hns_nic_priv *priv = netdev_priv(ndev);
546 struct hnae_handle *h = priv->ae_handle;
547 int ret;
548
67cd9a99
LYS
549 if (loop == MAC_INTERNALLOOP_PHY)
550 ret = __lb_setup(ndev, MAC_LOOP_PHY_NONE);
551 else
552 ret = __lb_setup(ndev, MAC_LOOP_NONE);
b5996f11 553 if (ret)
554 netdev_err(ndev, "%s: __lb_setup return error(%d)!\n",
555 __func__,
556 ret);
557
b5996f11 558 if (h->dev->ops->stop)
559 h->dev->ops->stop(h);
560
561 usleep_range(10000, 20000);
562 (void)__lb_clean_rings(priv, 0, h->q_num - 1, 256);
563
564 hns_nic_net_reset(ndev);
565
566 return 0;
567}
568
569/**
570 * hns_nic_self_test - self test
571 * @dev: net device
572 * @eth_test: test cmd
573 * @data: test result
574 */
575static void hns_nic_self_test(struct net_device *ndev,
576 struct ethtool_test *eth_test, u64 *data)
577{
578 struct hns_nic_priv *priv = netdev_priv(ndev);
579 bool if_running = netif_running(ndev);
580#define SELF_TEST_TPYE_NUM 3
581 int st_param[SELF_TEST_TPYE_NUM][2];
582 int i;
583 int test_index = 0;
584
585 st_param[0][0] = MAC_INTERNALLOOP_MAC; /* XGE not supported lb */
586 st_param[0][1] = (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII);
587 st_param[1][0] = MAC_INTERNALLOOP_SERDES;
588 st_param[1][1] = 1; /*serdes must exist*/
589 st_param[2][0] = MAC_INTERNALLOOP_PHY; /* only supporte phy node*/
652d39b0 590 st_param[2][1] = ((!!(priv->ae_handle->phy_dev)) &&
b5996f11 591 (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII));
592
593 if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
594 set_bit(NIC_STATE_TESTING, &priv->state);
595
596 if (if_running)
4a614dd3 597 dev_close(ndev);
b5996f11 598
599 for (i = 0; i < SELF_TEST_TPYE_NUM; i++) {
600 if (!st_param[i][1])
601 continue; /* NEXT testing */
602
603 data[test_index] = __lb_up(ndev,
604 (enum hnae_loop)st_param[i][0]);
605 if (!data[test_index]) {
606 data[test_index] = __lb_run_test(
607 ndev, (enum hnae_loop)st_param[i][0]);
67cd9a99
LYS
608 (void)__lb_down(ndev,
609 (enum hnae_loop)st_param[i][0]);
b5996f11 610 }
611
612 if (data[test_index])
613 eth_test->flags |= ETH_TEST_FL_FAILED;
614
615 test_index++;
616 }
617
618 hns_nic_net_reset(priv->netdev);
619
620 clear_bit(NIC_STATE_TESTING, &priv->state);
621
622 if (if_running)
00f54e68 623 (void)dev_open(ndev, NULL);
b5996f11 624 }
625 /* Online tests aren't run; pass by default */
626
627 (void)msleep_interruptible(4 * 1000);
628}
629
630/**
631 * hns_nic_get_drvinfo - get net driver info
632 * @dev: net device
633 * @drvinfo: driver info
634 */
635static void hns_nic_get_drvinfo(struct net_device *net_dev,
636 struct ethtool_drvinfo *drvinfo)
637{
638 struct hns_nic_priv *priv = netdev_priv(net_dev);
639
b5996f11 640 strncpy(drvinfo->version, HNAE_DRIVER_VERSION,
641 sizeof(drvinfo->version));
642 drvinfo->version[sizeof(drvinfo->version) - 1] = '\0';
643
644 strncpy(drvinfo->driver, HNAE_DRIVER_NAME, sizeof(drvinfo->driver));
645 drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0';
646
647 strncpy(drvinfo->bus_info, priv->dev->bus->name,
648 sizeof(drvinfo->bus_info));
649 drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0';
650
651 strncpy(drvinfo->fw_version, "N/A", ETHTOOL_FWVERS_LEN);
13ac695e 652 drvinfo->eedump_len = 0;
b5996f11 653}
654
655/**
656 * hns_get_ringparam - get ring parameter
657 * @dev: net device
658 * @param: ethtool parameter
659 */
336a443b
Y
660static void hns_get_ringparam(struct net_device *net_dev,
661 struct ethtool_ringparam *param)
b5996f11 662{
663 struct hns_nic_priv *priv = netdev_priv(net_dev);
664 struct hnae_ae_ops *ops;
665 struct hnae_queue *queue;
666 u32 uplimit = 0;
667
668 queue = priv->ae_handle->qs[0];
669 ops = priv->ae_handle->dev->ops;
670
671 if (ops->get_ring_bdnum_limit)
672 ops->get_ring_bdnum_limit(queue, &uplimit);
673
674 param->rx_max_pending = uplimit;
675 param->tx_max_pending = uplimit;
676 param->rx_pending = queue->rx_ring.desc_num;
677 param->tx_pending = queue->tx_ring.desc_num;
678}
679
680/**
681 * hns_get_pauseparam - get pause parameter
682 * @dev: net device
683 * @param: pause parameter
684 */
685static void hns_get_pauseparam(struct net_device *net_dev,
686 struct ethtool_pauseparam *param)
687{
688 struct hns_nic_priv *priv = netdev_priv(net_dev);
689 struct hnae_ae_ops *ops;
690
691 ops = priv->ae_handle->dev->ops;
692
693 if (ops->get_pauseparam)
694 ops->get_pauseparam(priv->ae_handle, &param->autoneg,
695 &param->rx_pause, &param->tx_pause);
696}
697
698/**
699 * hns_set_pauseparam - set pause parameter
700 * @dev: net device
701 * @param: pause parameter
702 *
703 * Return 0 on success, negative on failure
704 */
705static int hns_set_pauseparam(struct net_device *net_dev,
706 struct ethtool_pauseparam *param)
707{
708 struct hns_nic_priv *priv = netdev_priv(net_dev);
709 struct hnae_handle *h;
710 struct hnae_ae_ops *ops;
711
b5996f11 712 h = priv->ae_handle;
713 ops = h->dev->ops;
714
715 if (!ops->set_pauseparam)
716 return -ESRCH;
717
718 return ops->set_pauseparam(priv->ae_handle, param->autoneg,
719 param->rx_pause, param->tx_pause);
720}
721
722/**
723 * hns_get_coalesce - get coalesce info.
724 * @dev: net device
725 * @ec: coalesce info.
726 *
727 * Return 0 on success, negative on failure.
728 */
729static int hns_get_coalesce(struct net_device *net_dev,
730 struct ethtool_coalesce *ec)
731{
732 struct hns_nic_priv *priv = netdev_priv(net_dev);
733 struct hnae_ae_ops *ops;
734
735 ops = priv->ae_handle->dev->ops;
736
b8c17f70
LYS
737 ec->use_adaptive_rx_coalesce = priv->ae_handle->coal_adapt_en;
738 ec->use_adaptive_tx_coalesce = priv->ae_handle->coal_adapt_en;
b5996f11 739
740 if ((!ops->get_coalesce_usecs) ||
820c90cb 741 (!ops->get_max_coalesced_frames))
b5996f11 742 return -ESRCH;
743
744 ops->get_coalesce_usecs(priv->ae_handle,
745 &ec->tx_coalesce_usecs,
746 &ec->rx_coalesce_usecs);
747
820c90cb 748 ops->get_max_coalesced_frames(
b5996f11 749 priv->ae_handle,
750 &ec->tx_max_coalesced_frames,
751 &ec->rx_max_coalesced_frames);
752
ad59a17f
DH
753 ops->get_coalesce_range(priv->ae_handle,
754 &ec->tx_max_coalesced_frames_low,
755 &ec->rx_max_coalesced_frames_low,
756 &ec->tx_max_coalesced_frames_high,
757 &ec->rx_max_coalesced_frames_high,
758 &ec->tx_coalesce_usecs_low,
759 &ec->rx_coalesce_usecs_low,
760 &ec->tx_coalesce_usecs_high,
761 &ec->rx_coalesce_usecs_high);
762
b5996f11 763 return 0;
764}
765
766/**
767 * hns_set_coalesce - set coalesce info.
768 * @dev: net device
769 * @ec: coalesce info.
770 *
771 * Return 0 on success, negative on failure.
772 */
773static int hns_set_coalesce(struct net_device *net_dev,
774 struct ethtool_coalesce *ec)
775{
776 struct hns_nic_priv *priv = netdev_priv(net_dev);
777 struct hnae_ae_ops *ops;
820c90cb 778 int rc1, rc2;
b5996f11 779
b5996f11 780 ops = priv->ae_handle->dev->ops;
781
782 if (ec->tx_coalesce_usecs != ec->rx_coalesce_usecs)
783 return -EINVAL;
784
b5996f11 785 if ((!ops->set_coalesce_usecs) ||
786 (!ops->set_coalesce_frames))
787 return -ESRCH;
788
b8c17f70
LYS
789 if (ec->use_adaptive_rx_coalesce != priv->ae_handle->coal_adapt_en)
790 priv->ae_handle->coal_adapt_en = ec->use_adaptive_rx_coalesce;
791
820c90cb 792 rc1 = ops->set_coalesce_usecs(priv->ae_handle,
9832ce4c 793 ec->rx_coalesce_usecs);
b5996f11 794
820c90cb 795 rc2 = ops->set_coalesce_frames(priv->ae_handle,
796 ec->tx_max_coalesced_frames,
797 ec->rx_max_coalesced_frames);
b5996f11 798
820c90cb 799 if (rc1 || rc2)
800 return -EINVAL;
801
802 return 0;
b5996f11 803}
804
805/**
806 * hns_get_channels - get channel info.
807 * @dev: net device
808 * @ch: channel info.
809 */
336a443b
Y
810static void
811hns_get_channels(struct net_device *net_dev, struct ethtool_channels *ch)
b5996f11 812{
813 struct hns_nic_priv *priv = netdev_priv(net_dev);
814
815 ch->max_rx = priv->ae_handle->q_num;
816 ch->max_tx = priv->ae_handle->q_num;
817
818 ch->rx_count = priv->ae_handle->q_num;
819 ch->tx_count = priv->ae_handle->q_num;
820}
821
822/**
823 * get_ethtool_stats - get detail statistics.
824 * @dev: net device
825 * @stats: statistics info.
826 * @data: statistics data.
827 */
336a443b
Y
828static void hns_get_ethtool_stats(struct net_device *netdev,
829 struct ethtool_stats *stats, u64 *data)
b5996f11 830{
831 u64 *p = data;
832 struct hns_nic_priv *priv = netdev_priv(netdev);
833 struct hnae_handle *h = priv->ae_handle;
834 const struct rtnl_link_stats64 *net_stats;
835 struct rtnl_link_stats64 temp;
836
837 if (!h->dev->ops->get_stats || !h->dev->ops->update_stats) {
838 netdev_err(netdev, "get_stats or update_stats is null!\n");
839 return;
840 }
841
842 h->dev->ops->update_stats(h, &netdev->stats);
843
844 net_stats = dev_get_stats(netdev, &temp);
845
846 /* get netdev statistics */
847 p[0] = net_stats->rx_packets;
848 p[1] = net_stats->tx_packets;
849 p[2] = net_stats->rx_bytes;
850 p[3] = net_stats->tx_bytes;
851 p[4] = net_stats->rx_errors;
852 p[5] = net_stats->tx_errors;
853 p[6] = net_stats->rx_dropped;
854 p[7] = net_stats->tx_dropped;
855 p[8] = net_stats->multicast;
856 p[9] = net_stats->collisions;
857 p[10] = net_stats->rx_over_errors;
858 p[11] = net_stats->rx_crc_errors;
859 p[12] = net_stats->rx_frame_errors;
860 p[13] = net_stats->rx_fifo_errors;
861 p[14] = net_stats->rx_missed_errors;
862 p[15] = net_stats->tx_aborted_errors;
863 p[16] = net_stats->tx_carrier_errors;
864 p[17] = net_stats->tx_fifo_errors;
865 p[18] = net_stats->tx_heartbeat_errors;
866 p[19] = net_stats->rx_length_errors;
867 p[20] = net_stats->tx_window_errors;
868 p[21] = net_stats->rx_compressed;
869 p[22] = net_stats->tx_compressed;
870
871 p[23] = netdev->rx_dropped.counter;
872 p[24] = netdev->tx_dropped.counter;
873
874 p[25] = priv->tx_timeout_count;
875
876 /* get driver statistics */
877 h->dev->ops->get_stats(h, &p[26]);
878}
879
880/**
881 * get_strings: Return a set of strings that describe the requested objects
882 * @dev: net device
883 * @stats: string set ID.
884 * @data: objects data.
885 */
336a443b 886static void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
b5996f11 887{
888 struct hns_nic_priv *priv = netdev_priv(netdev);
889 struct hnae_handle *h = priv->ae_handle;
890 char *buff = (char *)data;
891
892 if (!h->dev->ops->get_strings) {
893 netdev_err(netdev, "h->dev->ops->get_strings is null!\n");
894 return;
895 }
896
897 if (stringset == ETH_SS_TEST) {
898 if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) {
899 memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_MAC],
900 ETH_GSTRING_LEN);
901 buff += ETH_GSTRING_LEN;
902 }
903 memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_SERDES],
904 ETH_GSTRING_LEN);
905 buff += ETH_GSTRING_LEN;
262b38cd 906 if ((netdev->phydev) && (!netdev->phydev->is_c45))
b5996f11 907 memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_PHY],
908 ETH_GSTRING_LEN);
909
910 } else {
911 snprintf(buff, ETH_GSTRING_LEN, "rx_packets");
912 buff = buff + ETH_GSTRING_LEN;
913 snprintf(buff, ETH_GSTRING_LEN, "tx_packets");
914 buff = buff + ETH_GSTRING_LEN;
915 snprintf(buff, ETH_GSTRING_LEN, "rx_bytes");
916 buff = buff + ETH_GSTRING_LEN;
917 snprintf(buff, ETH_GSTRING_LEN, "tx_bytes");
918 buff = buff + ETH_GSTRING_LEN;
919 snprintf(buff, ETH_GSTRING_LEN, "rx_errors");
920 buff = buff + ETH_GSTRING_LEN;
921 snprintf(buff, ETH_GSTRING_LEN, "tx_errors");
922 buff = buff + ETH_GSTRING_LEN;
923 snprintf(buff, ETH_GSTRING_LEN, "rx_dropped");
924 buff = buff + ETH_GSTRING_LEN;
925 snprintf(buff, ETH_GSTRING_LEN, "tx_dropped");
926 buff = buff + ETH_GSTRING_LEN;
927 snprintf(buff, ETH_GSTRING_LEN, "multicast");
928 buff = buff + ETH_GSTRING_LEN;
929 snprintf(buff, ETH_GSTRING_LEN, "collisions");
930 buff = buff + ETH_GSTRING_LEN;
931 snprintf(buff, ETH_GSTRING_LEN, "rx_over_errors");
932 buff = buff + ETH_GSTRING_LEN;
933 snprintf(buff, ETH_GSTRING_LEN, "rx_crc_errors");
934 buff = buff + ETH_GSTRING_LEN;
935 snprintf(buff, ETH_GSTRING_LEN, "rx_frame_errors");
936 buff = buff + ETH_GSTRING_LEN;
937 snprintf(buff, ETH_GSTRING_LEN, "rx_fifo_errors");
938 buff = buff + ETH_GSTRING_LEN;
939 snprintf(buff, ETH_GSTRING_LEN, "rx_missed_errors");
940 buff = buff + ETH_GSTRING_LEN;
941 snprintf(buff, ETH_GSTRING_LEN, "tx_aborted_errors");
942 buff = buff + ETH_GSTRING_LEN;
943 snprintf(buff, ETH_GSTRING_LEN, "tx_carrier_errors");
944 buff = buff + ETH_GSTRING_LEN;
945 snprintf(buff, ETH_GSTRING_LEN, "tx_fifo_errors");
946 buff = buff + ETH_GSTRING_LEN;
947 snprintf(buff, ETH_GSTRING_LEN, "tx_heartbeat_errors");
948 buff = buff + ETH_GSTRING_LEN;
949 snprintf(buff, ETH_GSTRING_LEN, "rx_length_errors");
950 buff = buff + ETH_GSTRING_LEN;
951 snprintf(buff, ETH_GSTRING_LEN, "tx_window_errors");
952 buff = buff + ETH_GSTRING_LEN;
953 snprintf(buff, ETH_GSTRING_LEN, "rx_compressed");
954 buff = buff + ETH_GSTRING_LEN;
955 snprintf(buff, ETH_GSTRING_LEN, "tx_compressed");
956 buff = buff + ETH_GSTRING_LEN;
957 snprintf(buff, ETH_GSTRING_LEN, "netdev_rx_dropped");
958 buff = buff + ETH_GSTRING_LEN;
959 snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_dropped");
960 buff = buff + ETH_GSTRING_LEN;
961
962 snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_timeout");
963 buff = buff + ETH_GSTRING_LEN;
964
965 h->dev->ops->get_strings(h, stringset, (u8 *)buff);
966 }
967}
968
969/**
970 * nic_get_sset_count - get string set count witch returned by nic_get_strings.
971 * @dev: net device
972 * @stringset: string set index, 0: self test string; 1: statistics string.
973 *
974 * Return string set count.
975 */
336a443b 976static int hns_get_sset_count(struct net_device *netdev, int stringset)
b5996f11 977{
978 struct hns_nic_priv *priv = netdev_priv(netdev);
979 struct hnae_handle *h = priv->ae_handle;
980 struct hnae_ae_ops *ops = h->dev->ops;
981
982 if (!ops->get_sset_count) {
983 netdev_err(netdev, "get_sset_count is null!\n");
984 return -EOPNOTSUPP;
985 }
986 if (stringset == ETH_SS_TEST) {
987 u32 cnt = (sizeof(hns_nic_test_strs) / ETH_GSTRING_LEN);
988
989 if (priv->ae_handle->phy_if == PHY_INTERFACE_MODE_XGMII)
990 cnt--;
991
262b38cd 992 if ((!netdev->phydev) || (netdev->phydev->is_c45))
b5996f11 993 cnt--;
994
995 return cnt;
d61d263c 996 } else if (stringset == ETH_SS_STATS) {
b5996f11 997 return (HNS_NET_STATS_CNT + ops->get_sset_count(h, stringset));
d61d263c
MB
998 } else {
999 return -EOPNOTSUPP;
b5996f11 1000 }
1001}
1002
1003/**
1004 * hns_phy_led_set - set phy LED status.
1005 * @dev: net device
1006 * @value: LED state.
1007 *
1008 * Return 0 on success, negative on failure.
1009 */
336a443b 1010static int hns_phy_led_set(struct net_device *netdev, int value)
b5996f11 1011{
1012 int retval;
262b38cd 1013 struct phy_device *phy_dev = netdev->phydev;
b5996f11 1014
cd690e48 1015 retval = phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_LED);
055a9417
QX
1016 retval |= phy_write(phy_dev, HNS_LED_FC_REG, value);
1017 retval |= phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER);
b5996f11 1018 if (retval) {
1019 netdev_err(netdev, "mdiobus_write fail !\n");
1020 return retval;
1021 }
1022 return 0;
1023}
1024
1025/**
1026 * nic_set_phys_id - set phy identify LED.
1027 * @dev: net device
1028 * @state: LED state.
1029 *
1030 * Return 0 on success, negative on failure.
1031 */
336a443b
Y
1032static int
1033hns_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state)
b5996f11 1034{
1035 struct hns_nic_priv *priv = netdev_priv(netdev);
1036 struct hnae_handle *h = priv->ae_handle;
262b38cd 1037 struct phy_device *phy_dev = netdev->phydev;
b5996f11 1038 int ret;
1039
1040 if (phy_dev)
1041 switch (state) {
1042 case ETHTOOL_ID_ACTIVE:
cd690e48
AL
1043 ret = phy_write(phy_dev, HNS_PHY_PAGE_REG,
1044 HNS_PHY_PAGE_LED);
b5996f11 1045 if (ret)
1046 return ret;
1047
cd690e48 1048 priv->phy_led_val = phy_read(phy_dev, HNS_LED_FC_REG);
b5996f11 1049
cd690e48
AL
1050 ret = phy_write(phy_dev, HNS_PHY_PAGE_REG,
1051 HNS_PHY_PAGE_COPPER);
b5996f11 1052 if (ret)
1053 return ret;
1054 return 2;
1055 case ETHTOOL_ID_ON:
1056 ret = hns_phy_led_set(netdev, HNS_LED_FORCE_ON);
1057 if (ret)
1058 return ret;
1059 break;
1060 case ETHTOOL_ID_OFF:
1061 ret = hns_phy_led_set(netdev, HNS_LED_FORCE_OFF);
1062 if (ret)
1063 return ret;
1064 break;
1065 case ETHTOOL_ID_INACTIVE:
cd690e48
AL
1066 ret = phy_write(phy_dev, HNS_PHY_PAGE_REG,
1067 HNS_PHY_PAGE_LED);
b5996f11 1068 if (ret)
1069 return ret;
1070
cd690e48
AL
1071 ret = phy_write(phy_dev, HNS_LED_FC_REG,
1072 priv->phy_led_val);
b5996f11 1073 if (ret)
1074 return ret;
1075
cd690e48
AL
1076 ret = phy_write(phy_dev, HNS_PHY_PAGE_REG,
1077 HNS_PHY_PAGE_COPPER);
b5996f11 1078 if (ret)
1079 return ret;
1080 break;
1081 default:
1082 return -EINVAL;
1083 }
1084 else
1085 switch (state) {
1086 case ETHTOOL_ID_ACTIVE:
1087 return h->dev->ops->set_led_id(h, HNAE_LED_ACTIVE);
1088 case ETHTOOL_ID_ON:
1089 return h->dev->ops->set_led_id(h, HNAE_LED_ON);
1090 case ETHTOOL_ID_OFF:
1091 return h->dev->ops->set_led_id(h, HNAE_LED_OFF);
1092 case ETHTOOL_ID_INACTIVE:
1093 return h->dev->ops->set_led_id(h, HNAE_LED_INACTIVE);
1094 default:
1095 return -EINVAL;
1096 }
1097
1098 return 0;
1099}
1100
1101/**
1102 * hns_get_regs - get net device register
1103 * @dev: net device
1104 * @cmd: ethtool cmd
1105 * @date: register data
1106 */
336a443b
Y
1107static void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd,
1108 void *data)
b5996f11 1109{
1110 struct hns_nic_priv *priv = netdev_priv(net_dev);
1111 struct hnae_ae_ops *ops;
1112
b5996f11 1113 ops = priv->ae_handle->dev->ops;
1114
1115 cmd->version = HNS_CHIP_VERSION;
1116 if (!ops->get_regs) {
1117 netdev_err(net_dev, "ops->get_regs is null!\n");
1118 return;
1119 }
1120 ops->get_regs(priv->ae_handle, data);
1121}
1122
1123/**
1124 * nic_get_regs_len - get total register len.
1125 * @dev: net device
1126 *
1127 * Return total register len.
1128 */
1129static int hns_get_regs_len(struct net_device *net_dev)
1130{
1131 u32 reg_num;
1132 struct hns_nic_priv *priv = netdev_priv(net_dev);
1133 struct hnae_ae_ops *ops;
1134
b5996f11 1135 ops = priv->ae_handle->dev->ops;
1136 if (!ops->get_regs_len) {
1137 netdev_err(net_dev, "ops->get_regs_len is null!\n");
1138 return -EOPNOTSUPP;
1139 }
1140
1141 reg_num = ops->get_regs_len(priv->ae_handle);
1142 if (reg_num > 0)
1143 return reg_num * sizeof(u32);
1144 else
1145 return reg_num; /* error code */
1146}
1147
1148/**
1149 * hns_nic_nway_reset - nway reset
1150 * @dev: net device
1151 *
1152 * Return 0 on success, negative on failure
1153 */
1154static int hns_nic_nway_reset(struct net_device *netdev)
1155{
262b38cd 1156 struct phy_device *phy = netdev->phydev;
b5996f11 1157
ed29ca8b
YL
1158 if (!netif_running(netdev))
1159 return 0;
b5996f11 1160
ed29ca8b
YL
1161 if (!phy)
1162 return -EOPNOTSUPP;
1163
1164 if (phy->autoneg != AUTONEG_ENABLE)
1165 return -EINVAL;
1166
1167 return genphy_restart_aneg(phy);
b5996f11 1168}
1169
6bc0ce7d
S
1170static u32
1171hns_get_rss_key_size(struct net_device *netdev)
1172{
1173 struct hns_nic_priv *priv = netdev_priv(netdev);
1174 struct hnae_ae_ops *ops;
6bc0ce7d
S
1175
1176 if (AE_IS_VER1(priv->enet_ver)) {
1177 netdev_err(netdev,
1178 "RSS feature is not supported on this hardware\n");
beecfe9e 1179 return 0;
6bc0ce7d
S
1180 }
1181
1182 ops = priv->ae_handle->dev->ops;
beecfe9e 1183 return ops->get_rss_key_size(priv->ae_handle);
6bc0ce7d
S
1184}
1185
1186static u32
1187hns_get_rss_indir_size(struct net_device *netdev)
1188{
1189 struct hns_nic_priv *priv = netdev_priv(netdev);
1190 struct hnae_ae_ops *ops;
6bc0ce7d
S
1191
1192 if (AE_IS_VER1(priv->enet_ver)) {
1193 netdev_err(netdev,
1194 "RSS feature is not supported on this hardware\n");
beecfe9e 1195 return 0;
6bc0ce7d
S
1196 }
1197
1198 ops = priv->ae_handle->dev->ops;
beecfe9e 1199 return ops->get_rss_indir_size(priv->ae_handle);
6bc0ce7d
S
1200}
1201
1202static int
1203hns_get_rss(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc)
1204{
1205 struct hns_nic_priv *priv = netdev_priv(netdev);
1206 struct hnae_ae_ops *ops;
6bc0ce7d
S
1207
1208 if (AE_IS_VER1(priv->enet_ver)) {
1209 netdev_err(netdev,
1210 "RSS feature is not supported on this hardware\n");
1211 return -EOPNOTSUPP;
1212 }
1213
1214 ops = priv->ae_handle->dev->ops;
1215
1216 if (!indir)
1217 return 0;
1218
beecfe9e 1219 return ops->get_rss(priv->ae_handle, indir, key, hfunc);
6bc0ce7d
S
1220}
1221
1222static int
1223hns_set_rss(struct net_device *netdev, const u32 *indir, const u8 *key,
1224 const u8 hfunc)
1225{
1226 struct hns_nic_priv *priv = netdev_priv(netdev);
1227 struct hnae_ae_ops *ops;
6bc0ce7d
S
1228
1229 if (AE_IS_VER1(priv->enet_ver)) {
1230 netdev_err(netdev,
1231 "RSS feature is not supported on this hardware\n");
1232 return -EOPNOTSUPP;
1233 }
1234
1235 ops = priv->ae_handle->dev->ops;
1236
64ec10dc 1237 if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) {
1238 netdev_err(netdev, "Invalid hfunc!\n");
6bc0ce7d 1239 return -EOPNOTSUPP;
64ec10dc 1240 }
6bc0ce7d 1241
beecfe9e 1242 return ops->set_rss(priv->ae_handle, indir, key, hfunc);
6bc0ce7d
S
1243}
1244
717dd807
KY
1245static int hns_get_rxnfc(struct net_device *netdev,
1246 struct ethtool_rxnfc *cmd,
1247 u32 *rule_locs)
1248{
1249 struct hns_nic_priv *priv = netdev_priv(netdev);
1250
1251 switch (cmd->cmd) {
1252 case ETHTOOL_GRXRINGS:
1253 cmd->data = priv->ae_handle->q_num;
1254 break;
1255 default:
1256 return -EOPNOTSUPP;
1257 }
1258
1259 return 0;
1260}
1261
bc6f0136 1262static const struct ethtool_ops hns_ethtool_ops = {
b5996f11 1263 .get_drvinfo = hns_nic_get_drvinfo,
1264 .get_link = hns_nic_get_link,
b5996f11 1265 .get_ringparam = hns_get_ringparam,
1266 .get_pauseparam = hns_get_pauseparam,
1267 .set_pauseparam = hns_set_pauseparam,
1268 .get_coalesce = hns_get_coalesce,
1269 .set_coalesce = hns_set_coalesce,
1270 .get_channels = hns_get_channels,
1271 .self_test = hns_nic_self_test,
1272 .get_strings = hns_get_strings,
1273 .get_sset_count = hns_get_sset_count,
1274 .get_ethtool_stats = hns_get_ethtool_stats,
1275 .set_phys_id = hns_set_phys_id,
1276 .get_regs_len = hns_get_regs_len,
1277 .get_regs = hns_get_regs,
1278 .nway_reset = hns_nic_nway_reset,
6bc0ce7d
S
1279 .get_rxfh_key_size = hns_get_rss_key_size,
1280 .get_rxfh_indir_size = hns_get_rss_indir_size,
1281 .get_rxfh = hns_get_rss,
1282 .set_rxfh = hns_set_rss,
717dd807 1283 .get_rxnfc = hns_get_rxnfc,
d270f76c
PR
1284 .get_link_ksettings = hns_nic_get_link_ksettings,
1285 .set_link_ksettings = hns_nic_set_link_ksettings,
b5996f11 1286};
1287
1288void hns_ethtool_set_ops(struct net_device *ndev)
1289{
1290 ndev->ethtool_ops = &hns_ethtool_ops;
1291}