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