18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014-2015 Hisilicon Limited. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 78c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 108c2ecf20Sopenharmony_ci#include "hns_enet.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define HNS_PHY_PAGE_MDIX 0 138c2ecf20Sopenharmony_ci#define HNS_PHY_PAGE_LED 3 148c2ecf20Sopenharmony_ci#define HNS_PHY_PAGE_COPPER 0 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define HNS_PHY_PAGE_REG 22 /* Page Selection Reg. */ 178c2ecf20Sopenharmony_ci#define HNS_PHY_CSC_REG 16 /* Copper Specific Control Register */ 188c2ecf20Sopenharmony_ci#define HNS_PHY_CSS_REG 17 /* Copper Specific Status Register */ 198c2ecf20Sopenharmony_ci#define HNS_LED_FC_REG 16 /* LED Function Control Reg. */ 208c2ecf20Sopenharmony_ci#define HNS_LED_PC_REG 17 /* LED Polarity Control Reg. */ 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define HNS_LED_FORCE_ON 9 238c2ecf20Sopenharmony_ci#define HNS_LED_FORCE_OFF 8 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define HNS_CHIP_VERSION 660 268c2ecf20Sopenharmony_ci#define HNS_NET_STATS_CNT 26 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define PHY_MDIX_CTRL_S (5) 298c2ecf20Sopenharmony_ci#define PHY_MDIX_CTRL_M (3 << PHY_MDIX_CTRL_S) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define PHY_MDIX_STATUS_B (6) 328c2ecf20Sopenharmony_ci#define PHY_SPEED_DUP_RESOLVE_B (11) 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/** 358c2ecf20Sopenharmony_ci *hns_nic_get_link - get current link status 368c2ecf20Sopenharmony_ci *@net_dev: net_device 378c2ecf20Sopenharmony_ci *retuen 0 - success , negative --fail 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_cistatic u32 hns_nic_get_link(struct net_device *net_dev) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 428c2ecf20Sopenharmony_ci u32 link_stat = priv->link; 438c2ecf20Sopenharmony_ci struct hnae_handle *h; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci h = priv->ae_handle; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (net_dev->phydev) { 488c2ecf20Sopenharmony_ci if (!genphy_read_status(net_dev->phydev)) 498c2ecf20Sopenharmony_ci link_stat = net_dev->phydev->link; 508c2ecf20Sopenharmony_ci else 518c2ecf20Sopenharmony_ci link_stat = 0; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (h->dev && h->dev->ops && h->dev->ops->get_status) 558c2ecf20Sopenharmony_ci link_stat = link_stat && h->dev->ops->get_status(h); 568c2ecf20Sopenharmony_ci else 578c2ecf20Sopenharmony_ci link_stat = 0; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci return link_stat; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic void hns_get_mdix_mode(struct net_device *net_dev, 638c2ecf20Sopenharmony_ci struct ethtool_link_ksettings *cmd) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci int mdix_ctrl, mdix, retval, is_resolved; 668c2ecf20Sopenharmony_ci struct phy_device *phy_dev = net_dev->phydev; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (!phy_dev || !phy_dev->mdio.bus) { 698c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID; 708c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; 718c2ecf20Sopenharmony_ci return; 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_MDIX); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci retval = phy_read(phy_dev, HNS_PHY_CSC_REG); 778c2ecf20Sopenharmony_ci mdix_ctrl = hnae_get_field(retval, PHY_MDIX_CTRL_M, PHY_MDIX_CTRL_S); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci retval = phy_read(phy_dev, HNS_PHY_CSS_REG); 808c2ecf20Sopenharmony_ci mdix = hnae_get_bit(retval, PHY_MDIX_STATUS_B); 818c2ecf20Sopenharmony_ci is_resolved = hnae_get_bit(retval, PHY_SPEED_DUP_RESOLVE_B); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci switch (mdix_ctrl) { 868c2ecf20Sopenharmony_ci case 0x0: 878c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI; 888c2ecf20Sopenharmony_ci break; 898c2ecf20Sopenharmony_ci case 0x1: 908c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_X; 918c2ecf20Sopenharmony_ci break; 928c2ecf20Sopenharmony_ci case 0x3: 938c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; 948c2ecf20Sopenharmony_ci break; 958c2ecf20Sopenharmony_ci default: 968c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID; 978c2ecf20Sopenharmony_ci break; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci if (!is_resolved) 1018c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; 1028c2ecf20Sopenharmony_ci else if (mdix) 1038c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix = ETH_TP_MDI_X; 1048c2ecf20Sopenharmony_ci else 1058c2ecf20Sopenharmony_ci cmd->base.eth_tp_mdix = ETH_TP_MDI; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/** 1098c2ecf20Sopenharmony_ci *hns_nic_get_link_ksettings - implement ethtool get link ksettings 1108c2ecf20Sopenharmony_ci *@net_dev: net_device 1118c2ecf20Sopenharmony_ci *@cmd: ethtool_link_ksettings 1128c2ecf20Sopenharmony_ci *retuen 0 - success , negative --fail 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_cistatic int hns_nic_get_link_ksettings(struct net_device *net_dev, 1158c2ecf20Sopenharmony_ci struct ethtool_link_ksettings *cmd) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 1188c2ecf20Sopenharmony_ci struct hnae_handle *h; 1198c2ecf20Sopenharmony_ci u32 link_stat; 1208c2ecf20Sopenharmony_ci int ret; 1218c2ecf20Sopenharmony_ci u8 duplex; 1228c2ecf20Sopenharmony_ci u16 speed; 1238c2ecf20Sopenharmony_ci u32 supported, advertising; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (!priv || !priv->ae_handle) 1268c2ecf20Sopenharmony_ci return -ESRCH; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci h = priv->ae_handle; 1298c2ecf20Sopenharmony_ci if (!h->dev || !h->dev->ops || !h->dev->ops->get_info) 1308c2ecf20Sopenharmony_ci return -ESRCH; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci ret = h->dev->ops->get_info(h, NULL, &speed, &duplex); 1338c2ecf20Sopenharmony_ci if (ret < 0) { 1348c2ecf20Sopenharmony_ci netdev_err(net_dev, "%s get_info error!\n", __func__); 1358c2ecf20Sopenharmony_ci return -EINVAL; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci ethtool_convert_link_mode_to_legacy_u32(&supported, 1398c2ecf20Sopenharmony_ci cmd->link_modes.supported); 1408c2ecf20Sopenharmony_ci ethtool_convert_link_mode_to_legacy_u32(&advertising, 1418c2ecf20Sopenharmony_ci cmd->link_modes.advertising); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci /* When there is no phy, autoneg is off. */ 1448c2ecf20Sopenharmony_ci cmd->base.autoneg = false; 1458c2ecf20Sopenharmony_ci cmd->base.speed = speed; 1468c2ecf20Sopenharmony_ci cmd->base.duplex = duplex; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (net_dev->phydev) 1498c2ecf20Sopenharmony_ci phy_ethtool_ksettings_get(net_dev->phydev, cmd); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci link_stat = hns_nic_get_link(net_dev); 1528c2ecf20Sopenharmony_ci if (!link_stat) { 1538c2ecf20Sopenharmony_ci cmd->base.speed = (u32)SPEED_UNKNOWN; 1548c2ecf20Sopenharmony_ci cmd->base.duplex = DUPLEX_UNKNOWN; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (cmd->base.autoneg) 1588c2ecf20Sopenharmony_ci advertising |= ADVERTISED_Autoneg; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci supported |= h->if_support; 1618c2ecf20Sopenharmony_ci if (h->phy_if == PHY_INTERFACE_MODE_SGMII) { 1628c2ecf20Sopenharmony_ci supported |= SUPPORTED_TP; 1638c2ecf20Sopenharmony_ci advertising |= ADVERTISED_1000baseT_Full; 1648c2ecf20Sopenharmony_ci } else if (h->phy_if == PHY_INTERFACE_MODE_XGMII) { 1658c2ecf20Sopenharmony_ci supported |= SUPPORTED_FIBRE; 1668c2ecf20Sopenharmony_ci advertising |= ADVERTISED_10000baseKR_Full; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci switch (h->media_type) { 1708c2ecf20Sopenharmony_ci case HNAE_MEDIA_TYPE_FIBER: 1718c2ecf20Sopenharmony_ci cmd->base.port = PORT_FIBRE; 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci case HNAE_MEDIA_TYPE_COPPER: 1748c2ecf20Sopenharmony_ci cmd->base.port = PORT_TP; 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci case HNAE_MEDIA_TYPE_UNKNOWN: 1778c2ecf20Sopenharmony_ci default: 1788c2ecf20Sopenharmony_ci break; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if (!(AE_IS_VER1(priv->enet_ver) && h->port_type == HNAE_PORT_DEBUG)) 1828c2ecf20Sopenharmony_ci supported |= SUPPORTED_Pause; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 1858c2ecf20Sopenharmony_ci supported); 1868c2ecf20Sopenharmony_ci ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 1878c2ecf20Sopenharmony_ci advertising); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C45 | ETH_MDIO_SUPPORTS_C22; 1908c2ecf20Sopenharmony_ci hns_get_mdix_mode(net_dev, cmd); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci return 0; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/** 1968c2ecf20Sopenharmony_ci *hns_nic_set_link_settings - implement ethtool set link ksettings 1978c2ecf20Sopenharmony_ci *@net_dev: net_device 1988c2ecf20Sopenharmony_ci *@cmd: ethtool_link_ksettings 1998c2ecf20Sopenharmony_ci *retuen 0 - success , negative --fail 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_cistatic int hns_nic_set_link_ksettings(struct net_device *net_dev, 2028c2ecf20Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 2058c2ecf20Sopenharmony_ci struct hnae_handle *h; 2068c2ecf20Sopenharmony_ci u32 speed; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci if (!netif_running(net_dev)) 2098c2ecf20Sopenharmony_ci return -ESRCH; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (!priv || !priv->ae_handle || !priv->ae_handle->dev || 2128c2ecf20Sopenharmony_ci !priv->ae_handle->dev->ops) 2138c2ecf20Sopenharmony_ci return -ENODEV; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci h = priv->ae_handle; 2168c2ecf20Sopenharmony_ci speed = cmd->base.speed; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci if (h->phy_if == PHY_INTERFACE_MODE_XGMII) { 2198c2ecf20Sopenharmony_ci if (cmd->base.autoneg == AUTONEG_ENABLE || 2208c2ecf20Sopenharmony_ci speed != SPEED_10000 || 2218c2ecf20Sopenharmony_ci cmd->base.duplex != DUPLEX_FULL) 2228c2ecf20Sopenharmony_ci return -EINVAL; 2238c2ecf20Sopenharmony_ci } else if (h->phy_if == PHY_INTERFACE_MODE_SGMII) { 2248c2ecf20Sopenharmony_ci if (!net_dev->phydev && cmd->base.autoneg == AUTONEG_ENABLE) 2258c2ecf20Sopenharmony_ci return -EINVAL; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF) 2288c2ecf20Sopenharmony_ci return -EINVAL; 2298c2ecf20Sopenharmony_ci if (net_dev->phydev) 2308c2ecf20Sopenharmony_ci return phy_ethtool_ksettings_set(net_dev->phydev, cmd); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if ((speed != SPEED_10 && speed != SPEED_100 && 2338c2ecf20Sopenharmony_ci speed != SPEED_1000) || (cmd->base.duplex != DUPLEX_HALF && 2348c2ecf20Sopenharmony_ci cmd->base.duplex != DUPLEX_FULL)) 2358c2ecf20Sopenharmony_ci return -EINVAL; 2368c2ecf20Sopenharmony_ci } else { 2378c2ecf20Sopenharmony_ci netdev_err(net_dev, "Not supported!"); 2388c2ecf20Sopenharmony_ci return -ENOTSUPP; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (h->dev->ops->adjust_link) { 2428c2ecf20Sopenharmony_ci netif_carrier_off(net_dev); 2438c2ecf20Sopenharmony_ci h->dev->ops->adjust_link(h, (int)speed, cmd->base.duplex); 2448c2ecf20Sopenharmony_ci netif_carrier_on(net_dev); 2458c2ecf20Sopenharmony_ci return 0; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci netdev_err(net_dev, "Not supported!"); 2498c2ecf20Sopenharmony_ci return -ENOTSUPP; 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic const char hns_nic_test_strs[][ETH_GSTRING_LEN] = { 2538c2ecf20Sopenharmony_ci "Mac Loopback test", 2548c2ecf20Sopenharmony_ci "Serdes Loopback test", 2558c2ecf20Sopenharmony_ci "Phy Loopback test" 2568c2ecf20Sopenharmony_ci}; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci int err; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (en) { 2638c2ecf20Sopenharmony_ci /* Doing phy loopback in offline state, phy resuming is 2648c2ecf20Sopenharmony_ci * needed to power up the device. 2658c2ecf20Sopenharmony_ci */ 2668c2ecf20Sopenharmony_ci err = phy_resume(phy_dev); 2678c2ecf20Sopenharmony_ci if (err) 2688c2ecf20Sopenharmony_ci goto out; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci err = phy_loopback(phy_dev, true); 2718c2ecf20Sopenharmony_ci } else { 2728c2ecf20Sopenharmony_ci err = phy_loopback(phy_dev, false); 2738c2ecf20Sopenharmony_ci if (err) 2748c2ecf20Sopenharmony_ci goto out; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci err = phy_suspend(phy_dev); 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ciout: 2808c2ecf20Sopenharmony_ci return err; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic int __lb_setup(struct net_device *ndev, 2848c2ecf20Sopenharmony_ci enum hnae_loop loop) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci int ret = 0; 2878c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(ndev); 2888c2ecf20Sopenharmony_ci struct phy_device *phy_dev = ndev->phydev; 2898c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci switch (loop) { 2928c2ecf20Sopenharmony_ci case MAC_INTERNALLOOP_PHY: 2938c2ecf20Sopenharmony_ci ret = hns_nic_config_phy_loopback(phy_dev, 0x1); 2948c2ecf20Sopenharmony_ci if (!ret) 2958c2ecf20Sopenharmony_ci ret = h->dev->ops->set_loopback(h, loop, 0x1); 2968c2ecf20Sopenharmony_ci break; 2978c2ecf20Sopenharmony_ci case MAC_INTERNALLOOP_MAC: 2988c2ecf20Sopenharmony_ci if ((h->dev->ops->set_loopback) && 2998c2ecf20Sopenharmony_ci (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)) 3008c2ecf20Sopenharmony_ci ret = h->dev->ops->set_loopback(h, loop, 0x1); 3018c2ecf20Sopenharmony_ci break; 3028c2ecf20Sopenharmony_ci case MAC_INTERNALLOOP_SERDES: 3038c2ecf20Sopenharmony_ci if (h->dev->ops->set_loopback) 3048c2ecf20Sopenharmony_ci ret = h->dev->ops->set_loopback(h, loop, 0x1); 3058c2ecf20Sopenharmony_ci break; 3068c2ecf20Sopenharmony_ci case MAC_LOOP_PHY_NONE: 3078c2ecf20Sopenharmony_ci ret = hns_nic_config_phy_loopback(phy_dev, 0x0); 3088c2ecf20Sopenharmony_ci fallthrough; 3098c2ecf20Sopenharmony_ci case MAC_LOOP_NONE: 3108c2ecf20Sopenharmony_ci if (!ret && h->dev->ops->set_loopback) { 3118c2ecf20Sopenharmony_ci if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) 3128c2ecf20Sopenharmony_ci ret = h->dev->ops->set_loopback(h, 3138c2ecf20Sopenharmony_ci MAC_INTERNALLOOP_MAC, 0x0); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (!ret) 3168c2ecf20Sopenharmony_ci ret = h->dev->ops->set_loopback(h, 3178c2ecf20Sopenharmony_ci MAC_INTERNALLOOP_SERDES, 0x0); 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci break; 3208c2ecf20Sopenharmony_ci default: 3218c2ecf20Sopenharmony_ci ret = -EINVAL; 3228c2ecf20Sopenharmony_ci break; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (!ret) { 3268c2ecf20Sopenharmony_ci if (loop == MAC_LOOP_NONE) 3278c2ecf20Sopenharmony_ci h->dev->ops->set_promisc_mode( 3288c2ecf20Sopenharmony_ci h, ndev->flags & IFF_PROMISC); 3298c2ecf20Sopenharmony_ci else 3308c2ecf20Sopenharmony_ci h->dev->ops->set_promisc_mode(h, 1); 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci return ret; 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic int __lb_up(struct net_device *ndev, 3368c2ecf20Sopenharmony_ci enum hnae_loop loop_mode) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci#define NIC_LB_TEST_WAIT_PHY_LINK_TIME 300 3398c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(ndev); 3408c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 3418c2ecf20Sopenharmony_ci int speed, duplex; 3428c2ecf20Sopenharmony_ci int ret; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci hns_nic_net_reset(ndev); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci ret = __lb_setup(ndev, loop_mode); 3478c2ecf20Sopenharmony_ci if (ret) 3488c2ecf20Sopenharmony_ci return ret; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci msleep(200); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci ret = h->dev->ops->start ? h->dev->ops->start(h) : 0; 3538c2ecf20Sopenharmony_ci if (ret) 3548c2ecf20Sopenharmony_ci return ret; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* link adjust duplex*/ 3578c2ecf20Sopenharmony_ci if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) 3588c2ecf20Sopenharmony_ci speed = 1000; 3598c2ecf20Sopenharmony_ci else 3608c2ecf20Sopenharmony_ci speed = 10000; 3618c2ecf20Sopenharmony_ci duplex = 1; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci h->dev->ops->adjust_link(h, speed, duplex); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /* wait adjust link done and phy ready */ 3668c2ecf20Sopenharmony_ci msleep(NIC_LB_TEST_WAIT_PHY_LINK_TIME); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci return 0; 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic void __lb_other_process(struct hns_nic_ring_data *ring_data, 3728c2ecf20Sopenharmony_ci struct sk_buff *skb) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci struct net_device *ndev; 3758c2ecf20Sopenharmony_ci struct hns_nic_priv *priv; 3768c2ecf20Sopenharmony_ci struct hnae_ring *ring; 3778c2ecf20Sopenharmony_ci struct netdev_queue *dev_queue; 3788c2ecf20Sopenharmony_ci struct sk_buff *new_skb; 3798c2ecf20Sopenharmony_ci unsigned int frame_size; 3808c2ecf20Sopenharmony_ci int check_ok; 3818c2ecf20Sopenharmony_ci u32 i; 3828c2ecf20Sopenharmony_ci char buff[33]; /* 32B data and the last character '\0' */ 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci if (!ring_data) { /* Just for doing create frame*/ 3858c2ecf20Sopenharmony_ci ndev = skb->dev; 3868c2ecf20Sopenharmony_ci priv = netdev_priv(ndev); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci frame_size = skb->len; 3898c2ecf20Sopenharmony_ci memset(skb->data, 0xFF, frame_size); 3908c2ecf20Sopenharmony_ci if ((!AE_IS_VER1(priv->enet_ver)) && 3918c2ecf20Sopenharmony_ci (priv->ae_handle->port_type == HNAE_PORT_SERVICE)) { 3928c2ecf20Sopenharmony_ci memcpy(skb->data, ndev->dev_addr, 6); 3938c2ecf20Sopenharmony_ci skb->data[5] += 0x1f; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci frame_size &= ~1ul; 3978c2ecf20Sopenharmony_ci memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); 3988c2ecf20Sopenharmony_ci memset(&skb->data[frame_size / 2 + 10], 0xBE, 3998c2ecf20Sopenharmony_ci frame_size / 2 - 11); 4008c2ecf20Sopenharmony_ci memset(&skb->data[frame_size / 2 + 12], 0xAF, 4018c2ecf20Sopenharmony_ci frame_size / 2 - 13); 4028c2ecf20Sopenharmony_ci return; 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci ring = ring_data->ring; 4068c2ecf20Sopenharmony_ci ndev = ring_data->napi.dev; 4078c2ecf20Sopenharmony_ci if (is_tx_ring(ring)) { /* for tx queue reset*/ 4088c2ecf20Sopenharmony_ci dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index); 4098c2ecf20Sopenharmony_ci netdev_tx_reset_queue(dev_queue); 4108c2ecf20Sopenharmony_ci return; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci frame_size = skb->len; 4148c2ecf20Sopenharmony_ci frame_size &= ~1ul; 4158c2ecf20Sopenharmony_ci /* for mutl buffer*/ 4168c2ecf20Sopenharmony_ci new_skb = skb_copy(skb, GFP_ATOMIC); 4178c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 4188c2ecf20Sopenharmony_ci if (!new_skb) { 4198c2ecf20Sopenharmony_ci netdev_err(ndev, "skb alloc failed\n"); 4208c2ecf20Sopenharmony_ci return; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci skb = new_skb; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci check_ok = 0; 4258c2ecf20Sopenharmony_ci if (*(skb->data + 10) == 0xFF) { /* for rx check frame*/ 4268c2ecf20Sopenharmony_ci if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && 4278c2ecf20Sopenharmony_ci (*(skb->data + frame_size / 2 + 12) == 0xAF)) 4288c2ecf20Sopenharmony_ci check_ok = 1; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci if (check_ok) { 4328c2ecf20Sopenharmony_ci ndev->stats.rx_packets++; 4338c2ecf20Sopenharmony_ci ndev->stats.rx_bytes += skb->len; 4348c2ecf20Sopenharmony_ci } else { 4358c2ecf20Sopenharmony_ci ndev->stats.rx_frame_errors++; 4368c2ecf20Sopenharmony_ci for (i = 0; i < skb->len; i++) { 4378c2ecf20Sopenharmony_ci snprintf(buff + i % 16 * 2, 3, /* tailing \0*/ 4388c2ecf20Sopenharmony_ci "%02x", *(skb->data + i)); 4398c2ecf20Sopenharmony_ci if ((i % 16 == 15) || (i == skb->len - 1)) 4408c2ecf20Sopenharmony_ci pr_info("%s\n", buff); 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci dev_kfree_skb_any(skb); 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic int __lb_clean_rings(struct hns_nic_priv *priv, 4478c2ecf20Sopenharmony_ci int ringid0, int ringid1, int budget) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci int i, ret; 4508c2ecf20Sopenharmony_ci struct hns_nic_ring_data *ring_data; 4518c2ecf20Sopenharmony_ci struct net_device *ndev = priv->netdev; 4528c2ecf20Sopenharmony_ci unsigned long rx_packets = ndev->stats.rx_packets; 4538c2ecf20Sopenharmony_ci unsigned long rx_bytes = ndev->stats.rx_bytes; 4548c2ecf20Sopenharmony_ci unsigned long rx_frame_errors = ndev->stats.rx_frame_errors; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci for (i = ringid0; i <= ringid1; i++) { 4578c2ecf20Sopenharmony_ci ring_data = &priv->ring_data[i]; 4588c2ecf20Sopenharmony_ci (void)ring_data->poll_one(ring_data, 4598c2ecf20Sopenharmony_ci budget, __lb_other_process); 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci ret = (int)(ndev->stats.rx_packets - rx_packets); 4628c2ecf20Sopenharmony_ci ndev->stats.rx_packets = rx_packets; 4638c2ecf20Sopenharmony_ci ndev->stats.rx_bytes = rx_bytes; 4648c2ecf20Sopenharmony_ci ndev->stats.rx_frame_errors = rx_frame_errors; 4658c2ecf20Sopenharmony_ci return ret; 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci/** 4698c2ecf20Sopenharmony_ci * __lb_run_test - run loopback test 4708c2ecf20Sopenharmony_ci * @ndev: net device 4718c2ecf20Sopenharmony_ci * @loop_mode: loopback mode 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_cistatic int __lb_run_test(struct net_device *ndev, 4748c2ecf20Sopenharmony_ci enum hnae_loop loop_mode) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci#define NIC_LB_TEST_PKT_NUM_PER_CYCLE 1 4778c2ecf20Sopenharmony_ci#define NIC_LB_TEST_RING_ID 0 4788c2ecf20Sopenharmony_ci#define NIC_LB_TEST_FRAME_SIZE 128 4798c2ecf20Sopenharmony_ci/* nic loopback test err */ 4808c2ecf20Sopenharmony_ci#define NIC_LB_TEST_NO_MEM_ERR 1 4818c2ecf20Sopenharmony_ci#define NIC_LB_TEST_TX_CNT_ERR 2 4828c2ecf20Sopenharmony_ci#define NIC_LB_TEST_RX_CNT_ERR 3 4838c2ecf20Sopenharmony_ci#define NIC_LB_TEST_RX_PKG_ERR 4 4848c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(ndev); 4858c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 4868c2ecf20Sopenharmony_ci int i, j, lc, good_cnt, ret_val = 0; 4878c2ecf20Sopenharmony_ci unsigned int size; 4888c2ecf20Sopenharmony_ci netdev_tx_t tx_ret_val; 4898c2ecf20Sopenharmony_ci struct sk_buff *skb; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci size = NIC_LB_TEST_FRAME_SIZE; 4928c2ecf20Sopenharmony_ci /* allocate test skb */ 4938c2ecf20Sopenharmony_ci skb = alloc_skb(size, GFP_KERNEL); 4948c2ecf20Sopenharmony_ci if (!skb) 4958c2ecf20Sopenharmony_ci return NIC_LB_TEST_NO_MEM_ERR; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci /* place data into test skb */ 4988c2ecf20Sopenharmony_ci (void)skb_put(skb, size); 4998c2ecf20Sopenharmony_ci skb->dev = ndev; 5008c2ecf20Sopenharmony_ci __lb_other_process(NULL, skb); 5018c2ecf20Sopenharmony_ci skb->queue_mapping = NIC_LB_TEST_RING_ID; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci lc = 1; 5048c2ecf20Sopenharmony_ci for (j = 0; j < lc; j++) { 5058c2ecf20Sopenharmony_ci /* reset count of good packets */ 5068c2ecf20Sopenharmony_ci good_cnt = 0; 5078c2ecf20Sopenharmony_ci /* place 64 packets on the transmit queue*/ 5088c2ecf20Sopenharmony_ci for (i = 0; i < NIC_LB_TEST_PKT_NUM_PER_CYCLE; i++) { 5098c2ecf20Sopenharmony_ci (void)skb_get(skb); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci tx_ret_val = (netdev_tx_t)hns_nic_net_xmit_hw( 5128c2ecf20Sopenharmony_ci ndev, skb, 5138c2ecf20Sopenharmony_ci &tx_ring_data(priv, skb->queue_mapping)); 5148c2ecf20Sopenharmony_ci if (tx_ret_val == NETDEV_TX_OK) 5158c2ecf20Sopenharmony_ci good_cnt++; 5168c2ecf20Sopenharmony_ci else 5178c2ecf20Sopenharmony_ci break; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) { 5208c2ecf20Sopenharmony_ci ret_val = NIC_LB_TEST_TX_CNT_ERR; 5218c2ecf20Sopenharmony_ci dev_err(priv->dev, "%s sent fail, cnt=0x%x, budget=0x%x\n", 5228c2ecf20Sopenharmony_ci hns_nic_test_strs[loop_mode], good_cnt, 5238c2ecf20Sopenharmony_ci NIC_LB_TEST_PKT_NUM_PER_CYCLE); 5248c2ecf20Sopenharmony_ci break; 5258c2ecf20Sopenharmony_ci } 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci /* allow 100 milliseconds for packets to go from Tx to Rx */ 5288c2ecf20Sopenharmony_ci msleep(100); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci good_cnt = __lb_clean_rings(priv, 5318c2ecf20Sopenharmony_ci h->q_num, h->q_num * 2 - 1, 5328c2ecf20Sopenharmony_ci NIC_LB_TEST_PKT_NUM_PER_CYCLE); 5338c2ecf20Sopenharmony_ci if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) { 5348c2ecf20Sopenharmony_ci ret_val = NIC_LB_TEST_RX_CNT_ERR; 5358c2ecf20Sopenharmony_ci dev_err(priv->dev, "%s recv fail, cnt=0x%x, budget=0x%x\n", 5368c2ecf20Sopenharmony_ci hns_nic_test_strs[loop_mode], good_cnt, 5378c2ecf20Sopenharmony_ci NIC_LB_TEST_PKT_NUM_PER_CYCLE); 5388c2ecf20Sopenharmony_ci break; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci (void)__lb_clean_rings(priv, 5418c2ecf20Sopenharmony_ci NIC_LB_TEST_RING_ID, NIC_LB_TEST_RING_ID, 5428c2ecf20Sopenharmony_ci NIC_LB_TEST_PKT_NUM_PER_CYCLE); 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci /* free the original skb */ 5468c2ecf20Sopenharmony_ci kfree_skb(skb); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci return ret_val; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic int __lb_down(struct net_device *ndev, enum hnae_loop loop) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(ndev); 5548c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 5558c2ecf20Sopenharmony_ci int ret; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci if (loop == MAC_INTERNALLOOP_PHY) 5588c2ecf20Sopenharmony_ci ret = __lb_setup(ndev, MAC_LOOP_PHY_NONE); 5598c2ecf20Sopenharmony_ci else 5608c2ecf20Sopenharmony_ci ret = __lb_setup(ndev, MAC_LOOP_NONE); 5618c2ecf20Sopenharmony_ci if (ret) 5628c2ecf20Sopenharmony_ci netdev_err(ndev, "%s: __lb_setup return error(%d)!\n", 5638c2ecf20Sopenharmony_ci __func__, 5648c2ecf20Sopenharmony_ci ret); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if (h->dev->ops->stop) 5678c2ecf20Sopenharmony_ci h->dev->ops->stop(h); 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci usleep_range(10000, 20000); 5708c2ecf20Sopenharmony_ci (void)__lb_clean_rings(priv, 0, h->q_num - 1, 256); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci hns_nic_net_reset(ndev); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci return 0; 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci/** 5788c2ecf20Sopenharmony_ci * hns_nic_self_test - self test 5798c2ecf20Sopenharmony_ci * @ndev: net device 5808c2ecf20Sopenharmony_ci * @eth_test: test cmd 5818c2ecf20Sopenharmony_ci * @data: test result 5828c2ecf20Sopenharmony_ci */ 5838c2ecf20Sopenharmony_cistatic void hns_nic_self_test(struct net_device *ndev, 5848c2ecf20Sopenharmony_ci struct ethtool_test *eth_test, u64 *data) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(ndev); 5878c2ecf20Sopenharmony_ci bool if_running = netif_running(ndev); 5888c2ecf20Sopenharmony_ci#define SELF_TEST_TPYE_NUM 3 5898c2ecf20Sopenharmony_ci int st_param[SELF_TEST_TPYE_NUM][2]; 5908c2ecf20Sopenharmony_ci int i; 5918c2ecf20Sopenharmony_ci int test_index = 0; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci st_param[0][0] = MAC_INTERNALLOOP_MAC; /* XGE not supported lb */ 5948c2ecf20Sopenharmony_ci st_param[0][1] = (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII); 5958c2ecf20Sopenharmony_ci st_param[1][0] = MAC_INTERNALLOOP_SERDES; 5968c2ecf20Sopenharmony_ci st_param[1][1] = 1; /*serdes must exist*/ 5978c2ecf20Sopenharmony_ci st_param[2][0] = MAC_INTERNALLOOP_PHY; /* only supporte phy node*/ 5988c2ecf20Sopenharmony_ci st_param[2][1] = ((!!(priv->ae_handle->phy_dev)) && 5998c2ecf20Sopenharmony_ci (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 6028c2ecf20Sopenharmony_ci set_bit(NIC_STATE_TESTING, &priv->state); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci if (if_running) 6058c2ecf20Sopenharmony_ci dev_close(ndev); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci for (i = 0; i < SELF_TEST_TPYE_NUM; i++) { 6088c2ecf20Sopenharmony_ci if (!st_param[i][1]) 6098c2ecf20Sopenharmony_ci continue; /* NEXT testing */ 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci data[test_index] = __lb_up(ndev, 6128c2ecf20Sopenharmony_ci (enum hnae_loop)st_param[i][0]); 6138c2ecf20Sopenharmony_ci if (!data[test_index]) { 6148c2ecf20Sopenharmony_ci data[test_index] = __lb_run_test( 6158c2ecf20Sopenharmony_ci ndev, (enum hnae_loop)st_param[i][0]); 6168c2ecf20Sopenharmony_ci (void)__lb_down(ndev, 6178c2ecf20Sopenharmony_ci (enum hnae_loop)st_param[i][0]); 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (data[test_index]) 6218c2ecf20Sopenharmony_ci eth_test->flags |= ETH_TEST_FL_FAILED; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci test_index++; 6248c2ecf20Sopenharmony_ci } 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci hns_nic_net_reset(priv->netdev); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci clear_bit(NIC_STATE_TESTING, &priv->state); 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci if (if_running) 6318c2ecf20Sopenharmony_ci (void)dev_open(ndev, NULL); 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci /* Online tests aren't run; pass by default */ 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci (void)msleep_interruptible(4 * 1000); 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci/** 6398c2ecf20Sopenharmony_ci * hns_nic_get_drvinfo - get net driver info 6408c2ecf20Sopenharmony_ci * @net_dev: net device 6418c2ecf20Sopenharmony_ci * @drvinfo: driver info 6428c2ecf20Sopenharmony_ci */ 6438c2ecf20Sopenharmony_cistatic void hns_nic_get_drvinfo(struct net_device *net_dev, 6448c2ecf20Sopenharmony_ci struct ethtool_drvinfo *drvinfo) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci strncpy(drvinfo->version, HNAE_DRIVER_VERSION, 6498c2ecf20Sopenharmony_ci sizeof(drvinfo->version)); 6508c2ecf20Sopenharmony_ci drvinfo->version[sizeof(drvinfo->version) - 1] = '\0'; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci strncpy(drvinfo->driver, HNAE_DRIVER_NAME, sizeof(drvinfo->driver)); 6538c2ecf20Sopenharmony_ci drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0'; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci strncpy(drvinfo->bus_info, priv->dev->bus->name, 6568c2ecf20Sopenharmony_ci sizeof(drvinfo->bus_info)); 6578c2ecf20Sopenharmony_ci drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0'; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci strncpy(drvinfo->fw_version, "N/A", ETHTOOL_FWVERS_LEN); 6608c2ecf20Sopenharmony_ci drvinfo->eedump_len = 0; 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci/** 6648c2ecf20Sopenharmony_ci * hns_get_ringparam - get ring parameter 6658c2ecf20Sopenharmony_ci * @net_dev: net device 6668c2ecf20Sopenharmony_ci * @param: ethtool parameter 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_cistatic void hns_get_ringparam(struct net_device *net_dev, 6698c2ecf20Sopenharmony_ci struct ethtool_ringparam *param) 6708c2ecf20Sopenharmony_ci{ 6718c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 6728c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 6738c2ecf20Sopenharmony_ci struct hnae_queue *queue; 6748c2ecf20Sopenharmony_ci u32 uplimit = 0; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci queue = priv->ae_handle->qs[0]; 6778c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci if (ops->get_ring_bdnum_limit) 6808c2ecf20Sopenharmony_ci ops->get_ring_bdnum_limit(queue, &uplimit); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci param->rx_max_pending = uplimit; 6838c2ecf20Sopenharmony_ci param->tx_max_pending = uplimit; 6848c2ecf20Sopenharmony_ci param->rx_pending = queue->rx_ring.desc_num; 6858c2ecf20Sopenharmony_ci param->tx_pending = queue->tx_ring.desc_num; 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci/** 6898c2ecf20Sopenharmony_ci * hns_get_pauseparam - get pause parameter 6908c2ecf20Sopenharmony_ci * @net_dev: net device 6918c2ecf20Sopenharmony_ci * @param: pause parameter 6928c2ecf20Sopenharmony_ci */ 6938c2ecf20Sopenharmony_cistatic void hns_get_pauseparam(struct net_device *net_dev, 6948c2ecf20Sopenharmony_ci struct ethtool_pauseparam *param) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 6978c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci if (ops->get_pauseparam) 7028c2ecf20Sopenharmony_ci ops->get_pauseparam(priv->ae_handle, ¶m->autoneg, 7038c2ecf20Sopenharmony_ci ¶m->rx_pause, ¶m->tx_pause); 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci/** 7078c2ecf20Sopenharmony_ci * hns_set_pauseparam - set pause parameter 7088c2ecf20Sopenharmony_ci * @net_dev: net device 7098c2ecf20Sopenharmony_ci * @param: pause parameter 7108c2ecf20Sopenharmony_ci * 7118c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_cistatic int hns_set_pauseparam(struct net_device *net_dev, 7148c2ecf20Sopenharmony_ci struct ethtool_pauseparam *param) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 7178c2ecf20Sopenharmony_ci struct hnae_handle *h; 7188c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci h = priv->ae_handle; 7218c2ecf20Sopenharmony_ci ops = h->dev->ops; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci if (!ops->set_pauseparam) 7248c2ecf20Sopenharmony_ci return -ESRCH; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci return ops->set_pauseparam(priv->ae_handle, param->autoneg, 7278c2ecf20Sopenharmony_ci param->rx_pause, param->tx_pause); 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci/** 7318c2ecf20Sopenharmony_ci * hns_get_coalesce - get coalesce info. 7328c2ecf20Sopenharmony_ci * @net_dev: net device 7338c2ecf20Sopenharmony_ci * @ec: coalesce info. 7348c2ecf20Sopenharmony_ci * 7358c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure. 7368c2ecf20Sopenharmony_ci */ 7378c2ecf20Sopenharmony_cistatic int hns_get_coalesce(struct net_device *net_dev, 7388c2ecf20Sopenharmony_ci struct ethtool_coalesce *ec) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 7418c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci ec->use_adaptive_rx_coalesce = priv->ae_handle->coal_adapt_en; 7468c2ecf20Sopenharmony_ci ec->use_adaptive_tx_coalesce = priv->ae_handle->coal_adapt_en; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if ((!ops->get_coalesce_usecs) || 7498c2ecf20Sopenharmony_ci (!ops->get_max_coalesced_frames)) 7508c2ecf20Sopenharmony_ci return -ESRCH; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci ops->get_coalesce_usecs(priv->ae_handle, 7538c2ecf20Sopenharmony_ci &ec->tx_coalesce_usecs, 7548c2ecf20Sopenharmony_ci &ec->rx_coalesce_usecs); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci ops->get_max_coalesced_frames( 7578c2ecf20Sopenharmony_ci priv->ae_handle, 7588c2ecf20Sopenharmony_ci &ec->tx_max_coalesced_frames, 7598c2ecf20Sopenharmony_ci &ec->rx_max_coalesced_frames); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci ops->get_coalesce_range(priv->ae_handle, 7628c2ecf20Sopenharmony_ci &ec->tx_max_coalesced_frames_low, 7638c2ecf20Sopenharmony_ci &ec->rx_max_coalesced_frames_low, 7648c2ecf20Sopenharmony_ci &ec->tx_max_coalesced_frames_high, 7658c2ecf20Sopenharmony_ci &ec->rx_max_coalesced_frames_high, 7668c2ecf20Sopenharmony_ci &ec->tx_coalesce_usecs_low, 7678c2ecf20Sopenharmony_ci &ec->rx_coalesce_usecs_low, 7688c2ecf20Sopenharmony_ci &ec->tx_coalesce_usecs_high, 7698c2ecf20Sopenharmony_ci &ec->rx_coalesce_usecs_high); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci return 0; 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci/** 7758c2ecf20Sopenharmony_ci * hns_set_coalesce - set coalesce info. 7768c2ecf20Sopenharmony_ci * @net_dev: net device 7778c2ecf20Sopenharmony_ci * @ec: coalesce info. 7788c2ecf20Sopenharmony_ci * 7798c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure. 7808c2ecf20Sopenharmony_ci */ 7818c2ecf20Sopenharmony_cistatic int hns_set_coalesce(struct net_device *net_dev, 7828c2ecf20Sopenharmony_ci struct ethtool_coalesce *ec) 7838c2ecf20Sopenharmony_ci{ 7848c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 7858c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 7868c2ecf20Sopenharmony_ci int rc1, rc2; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (ec->tx_coalesce_usecs != ec->rx_coalesce_usecs) 7918c2ecf20Sopenharmony_ci return -EINVAL; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci if ((!ops->set_coalesce_usecs) || 7948c2ecf20Sopenharmony_ci (!ops->set_coalesce_frames)) 7958c2ecf20Sopenharmony_ci return -ESRCH; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci if (ec->use_adaptive_rx_coalesce != priv->ae_handle->coal_adapt_en) 7988c2ecf20Sopenharmony_ci priv->ae_handle->coal_adapt_en = ec->use_adaptive_rx_coalesce; 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci rc1 = ops->set_coalesce_usecs(priv->ae_handle, 8018c2ecf20Sopenharmony_ci ec->rx_coalesce_usecs); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci rc2 = ops->set_coalesce_frames(priv->ae_handle, 8048c2ecf20Sopenharmony_ci ec->tx_max_coalesced_frames, 8058c2ecf20Sopenharmony_ci ec->rx_max_coalesced_frames); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (rc1 || rc2) 8088c2ecf20Sopenharmony_ci return -EINVAL; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci return 0; 8118c2ecf20Sopenharmony_ci} 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci/** 8148c2ecf20Sopenharmony_ci * hns_get_channels - get channel info. 8158c2ecf20Sopenharmony_ci * @net_dev: net device 8168c2ecf20Sopenharmony_ci * @ch: channel info. 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_cistatic void 8198c2ecf20Sopenharmony_cihns_get_channels(struct net_device *net_dev, struct ethtool_channels *ch) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci ch->max_rx = priv->ae_handle->q_num; 8248c2ecf20Sopenharmony_ci ch->max_tx = priv->ae_handle->q_num; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci ch->rx_count = priv->ae_handle->q_num; 8278c2ecf20Sopenharmony_ci ch->tx_count = priv->ae_handle->q_num; 8288c2ecf20Sopenharmony_ci} 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci/** 8318c2ecf20Sopenharmony_ci * get_ethtool_stats - get detail statistics. 8328c2ecf20Sopenharmony_ci * @netdev: net device 8338c2ecf20Sopenharmony_ci * @stats: statistics info. 8348c2ecf20Sopenharmony_ci * @data: statistics data. 8358c2ecf20Sopenharmony_ci */ 8368c2ecf20Sopenharmony_cistatic void hns_get_ethtool_stats(struct net_device *netdev, 8378c2ecf20Sopenharmony_ci struct ethtool_stats *stats, u64 *data) 8388c2ecf20Sopenharmony_ci{ 8398c2ecf20Sopenharmony_ci u64 *p = data; 8408c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 8418c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 8428c2ecf20Sopenharmony_ci const struct rtnl_link_stats64 *net_stats; 8438c2ecf20Sopenharmony_ci struct rtnl_link_stats64 temp; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci if (!h->dev->ops->get_stats || !h->dev->ops->update_stats) { 8468c2ecf20Sopenharmony_ci netdev_err(netdev, "get_stats or update_stats is null!\n"); 8478c2ecf20Sopenharmony_ci return; 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci h->dev->ops->update_stats(h, &netdev->stats); 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci net_stats = dev_get_stats(netdev, &temp); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci /* get netdev statistics */ 8558c2ecf20Sopenharmony_ci p[0] = net_stats->rx_packets; 8568c2ecf20Sopenharmony_ci p[1] = net_stats->tx_packets; 8578c2ecf20Sopenharmony_ci p[2] = net_stats->rx_bytes; 8588c2ecf20Sopenharmony_ci p[3] = net_stats->tx_bytes; 8598c2ecf20Sopenharmony_ci p[4] = net_stats->rx_errors; 8608c2ecf20Sopenharmony_ci p[5] = net_stats->tx_errors; 8618c2ecf20Sopenharmony_ci p[6] = net_stats->rx_dropped; 8628c2ecf20Sopenharmony_ci p[7] = net_stats->tx_dropped; 8638c2ecf20Sopenharmony_ci p[8] = net_stats->multicast; 8648c2ecf20Sopenharmony_ci p[9] = net_stats->collisions; 8658c2ecf20Sopenharmony_ci p[10] = net_stats->rx_over_errors; 8668c2ecf20Sopenharmony_ci p[11] = net_stats->rx_crc_errors; 8678c2ecf20Sopenharmony_ci p[12] = net_stats->rx_frame_errors; 8688c2ecf20Sopenharmony_ci p[13] = net_stats->rx_fifo_errors; 8698c2ecf20Sopenharmony_ci p[14] = net_stats->rx_missed_errors; 8708c2ecf20Sopenharmony_ci p[15] = net_stats->tx_aborted_errors; 8718c2ecf20Sopenharmony_ci p[16] = net_stats->tx_carrier_errors; 8728c2ecf20Sopenharmony_ci p[17] = net_stats->tx_fifo_errors; 8738c2ecf20Sopenharmony_ci p[18] = net_stats->tx_heartbeat_errors; 8748c2ecf20Sopenharmony_ci p[19] = net_stats->rx_length_errors; 8758c2ecf20Sopenharmony_ci p[20] = net_stats->tx_window_errors; 8768c2ecf20Sopenharmony_ci p[21] = net_stats->rx_compressed; 8778c2ecf20Sopenharmony_ci p[22] = net_stats->tx_compressed; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci p[23] = netdev->rx_dropped.counter; 8808c2ecf20Sopenharmony_ci p[24] = netdev->tx_dropped.counter; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci p[25] = priv->tx_timeout_count; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci /* get driver statistics */ 8858c2ecf20Sopenharmony_ci h->dev->ops->get_stats(h, &p[26]); 8868c2ecf20Sopenharmony_ci} 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci/** 8898c2ecf20Sopenharmony_ci * get_strings: Return a set of strings that describe the requested objects 8908c2ecf20Sopenharmony_ci * @netdev: net device 8918c2ecf20Sopenharmony_ci * @stringset: string set ID. 8928c2ecf20Sopenharmony_ci * @data: objects data. 8938c2ecf20Sopenharmony_ci */ 8948c2ecf20Sopenharmony_cistatic void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data) 8958c2ecf20Sopenharmony_ci{ 8968c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 8978c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 8988c2ecf20Sopenharmony_ci char *buff = (char *)data; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci if (!h->dev->ops->get_strings) { 9018c2ecf20Sopenharmony_ci netdev_err(netdev, "h->dev->ops->get_strings is null!\n"); 9028c2ecf20Sopenharmony_ci return; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci if (stringset == ETH_SS_TEST) { 9068c2ecf20Sopenharmony_ci if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) { 9078c2ecf20Sopenharmony_ci memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_MAC], 9088c2ecf20Sopenharmony_ci ETH_GSTRING_LEN); 9098c2ecf20Sopenharmony_ci buff += ETH_GSTRING_LEN; 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_SERDES], 9128c2ecf20Sopenharmony_ci ETH_GSTRING_LEN); 9138c2ecf20Sopenharmony_ci buff += ETH_GSTRING_LEN; 9148c2ecf20Sopenharmony_ci if ((netdev->phydev) && (!netdev->phydev->is_c45)) 9158c2ecf20Sopenharmony_ci memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_PHY], 9168c2ecf20Sopenharmony_ci ETH_GSTRING_LEN); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci } else { 9198c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_packets"); 9208c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9218c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_packets"); 9228c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9238c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_bytes"); 9248c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9258c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_bytes"); 9268c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9278c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_errors"); 9288c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9298c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_errors"); 9308c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9318c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_dropped"); 9328c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9338c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_dropped"); 9348c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9358c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "multicast"); 9368c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9378c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "collisions"); 9388c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9398c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_over_errors"); 9408c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9418c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_crc_errors"); 9428c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9438c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_frame_errors"); 9448c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9458c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_fifo_errors"); 9468c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9478c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_missed_errors"); 9488c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9498c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_aborted_errors"); 9508c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9518c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_carrier_errors"); 9528c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9538c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_fifo_errors"); 9548c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9558c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_heartbeat_errors"); 9568c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9578c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_length_errors"); 9588c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9598c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_window_errors"); 9608c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9618c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "rx_compressed"); 9628c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9638c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "tx_compressed"); 9648c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9658c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "netdev_rx_dropped"); 9668c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9678c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_dropped"); 9688c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_timeout"); 9718c2ecf20Sopenharmony_ci buff = buff + ETH_GSTRING_LEN; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci h->dev->ops->get_strings(h, stringset, (u8 *)buff); 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci/** 9788c2ecf20Sopenharmony_ci * hns_get_sset_count - get string set count returned by nic_get_strings 9798c2ecf20Sopenharmony_ci * @netdev: net device 9808c2ecf20Sopenharmony_ci * @stringset: string set index, 0: self test string; 1: statistics string. 9818c2ecf20Sopenharmony_ci * 9828c2ecf20Sopenharmony_ci * Return string set count. 9838c2ecf20Sopenharmony_ci */ 9848c2ecf20Sopenharmony_cistatic int hns_get_sset_count(struct net_device *netdev, int stringset) 9858c2ecf20Sopenharmony_ci{ 9868c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 9878c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 9888c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops = h->dev->ops; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci if (!ops->get_sset_count) { 9918c2ecf20Sopenharmony_ci netdev_err(netdev, "get_sset_count is null!\n"); 9928c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 9938c2ecf20Sopenharmony_ci } 9948c2ecf20Sopenharmony_ci if (stringset == ETH_SS_TEST) { 9958c2ecf20Sopenharmony_ci u32 cnt = (sizeof(hns_nic_test_strs) / ETH_GSTRING_LEN); 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci if (priv->ae_handle->phy_if == PHY_INTERFACE_MODE_XGMII) 9988c2ecf20Sopenharmony_ci cnt--; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci if ((!netdev->phydev) || (netdev->phydev->is_c45)) 10018c2ecf20Sopenharmony_ci cnt--; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci return cnt; 10048c2ecf20Sopenharmony_ci } else if (stringset == ETH_SS_STATS) { 10058c2ecf20Sopenharmony_ci return (HNS_NET_STATS_CNT + ops->get_sset_count(h, stringset)); 10068c2ecf20Sopenharmony_ci } else { 10078c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci} 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci/** 10128c2ecf20Sopenharmony_ci * hns_phy_led_set - set phy LED status. 10138c2ecf20Sopenharmony_ci * @netdev: net device 10148c2ecf20Sopenharmony_ci * @value: LED state. 10158c2ecf20Sopenharmony_ci * 10168c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure. 10178c2ecf20Sopenharmony_ci */ 10188c2ecf20Sopenharmony_cistatic int hns_phy_led_set(struct net_device *netdev, int value) 10198c2ecf20Sopenharmony_ci{ 10208c2ecf20Sopenharmony_ci int retval; 10218c2ecf20Sopenharmony_ci struct phy_device *phy_dev = netdev->phydev; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci retval = phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_LED); 10248c2ecf20Sopenharmony_ci retval |= phy_write(phy_dev, HNS_LED_FC_REG, value); 10258c2ecf20Sopenharmony_ci retval |= phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER); 10268c2ecf20Sopenharmony_ci if (retval) { 10278c2ecf20Sopenharmony_ci netdev_err(netdev, "mdiobus_write fail !\n"); 10288c2ecf20Sopenharmony_ci return retval; 10298c2ecf20Sopenharmony_ci } 10308c2ecf20Sopenharmony_ci return 0; 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci/** 10348c2ecf20Sopenharmony_ci * hns_set_phys_id - set phy identify LED. 10358c2ecf20Sopenharmony_ci * @netdev: net device 10368c2ecf20Sopenharmony_ci * @state: LED state. 10378c2ecf20Sopenharmony_ci * 10388c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure. 10398c2ecf20Sopenharmony_ci */ 10408c2ecf20Sopenharmony_cistatic int 10418c2ecf20Sopenharmony_cihns_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) 10428c2ecf20Sopenharmony_ci{ 10438c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 10448c2ecf20Sopenharmony_ci struct hnae_handle *h = priv->ae_handle; 10458c2ecf20Sopenharmony_ci struct phy_device *phy_dev = netdev->phydev; 10468c2ecf20Sopenharmony_ci int ret; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci if (phy_dev) 10498c2ecf20Sopenharmony_ci switch (state) { 10508c2ecf20Sopenharmony_ci case ETHTOOL_ID_ACTIVE: 10518c2ecf20Sopenharmony_ci ret = phy_write(phy_dev, HNS_PHY_PAGE_REG, 10528c2ecf20Sopenharmony_ci HNS_PHY_PAGE_LED); 10538c2ecf20Sopenharmony_ci if (ret) 10548c2ecf20Sopenharmony_ci return ret; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci priv->phy_led_val = phy_read(phy_dev, HNS_LED_FC_REG); 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci ret = phy_write(phy_dev, HNS_PHY_PAGE_REG, 10598c2ecf20Sopenharmony_ci HNS_PHY_PAGE_COPPER); 10608c2ecf20Sopenharmony_ci if (ret) 10618c2ecf20Sopenharmony_ci return ret; 10628c2ecf20Sopenharmony_ci return 2; 10638c2ecf20Sopenharmony_ci case ETHTOOL_ID_ON: 10648c2ecf20Sopenharmony_ci ret = hns_phy_led_set(netdev, HNS_LED_FORCE_ON); 10658c2ecf20Sopenharmony_ci if (ret) 10668c2ecf20Sopenharmony_ci return ret; 10678c2ecf20Sopenharmony_ci break; 10688c2ecf20Sopenharmony_ci case ETHTOOL_ID_OFF: 10698c2ecf20Sopenharmony_ci ret = hns_phy_led_set(netdev, HNS_LED_FORCE_OFF); 10708c2ecf20Sopenharmony_ci if (ret) 10718c2ecf20Sopenharmony_ci return ret; 10728c2ecf20Sopenharmony_ci break; 10738c2ecf20Sopenharmony_ci case ETHTOOL_ID_INACTIVE: 10748c2ecf20Sopenharmony_ci ret = phy_write(phy_dev, HNS_PHY_PAGE_REG, 10758c2ecf20Sopenharmony_ci HNS_PHY_PAGE_LED); 10768c2ecf20Sopenharmony_ci if (ret) 10778c2ecf20Sopenharmony_ci return ret; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci ret = phy_write(phy_dev, HNS_LED_FC_REG, 10808c2ecf20Sopenharmony_ci priv->phy_led_val); 10818c2ecf20Sopenharmony_ci if (ret) 10828c2ecf20Sopenharmony_ci return ret; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci ret = phy_write(phy_dev, HNS_PHY_PAGE_REG, 10858c2ecf20Sopenharmony_ci HNS_PHY_PAGE_COPPER); 10868c2ecf20Sopenharmony_ci if (ret) 10878c2ecf20Sopenharmony_ci return ret; 10888c2ecf20Sopenharmony_ci break; 10898c2ecf20Sopenharmony_ci default: 10908c2ecf20Sopenharmony_ci return -EINVAL; 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci else 10938c2ecf20Sopenharmony_ci switch (state) { 10948c2ecf20Sopenharmony_ci case ETHTOOL_ID_ACTIVE: 10958c2ecf20Sopenharmony_ci return h->dev->ops->set_led_id(h, HNAE_LED_ACTIVE); 10968c2ecf20Sopenharmony_ci case ETHTOOL_ID_ON: 10978c2ecf20Sopenharmony_ci return h->dev->ops->set_led_id(h, HNAE_LED_ON); 10988c2ecf20Sopenharmony_ci case ETHTOOL_ID_OFF: 10998c2ecf20Sopenharmony_ci return h->dev->ops->set_led_id(h, HNAE_LED_OFF); 11008c2ecf20Sopenharmony_ci case ETHTOOL_ID_INACTIVE: 11018c2ecf20Sopenharmony_ci return h->dev->ops->set_led_id(h, HNAE_LED_INACTIVE); 11028c2ecf20Sopenharmony_ci default: 11038c2ecf20Sopenharmony_ci return -EINVAL; 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci return 0; 11078c2ecf20Sopenharmony_ci} 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci/** 11108c2ecf20Sopenharmony_ci * hns_get_regs - get net device register 11118c2ecf20Sopenharmony_ci * @net_dev: net device 11128c2ecf20Sopenharmony_ci * @cmd: ethtool cmd 11138c2ecf20Sopenharmony_ci * @data: register data 11148c2ecf20Sopenharmony_ci */ 11158c2ecf20Sopenharmony_cistatic void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd, 11168c2ecf20Sopenharmony_ci void *data) 11178c2ecf20Sopenharmony_ci{ 11188c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 11198c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci cmd->version = HNS_CHIP_VERSION; 11248c2ecf20Sopenharmony_ci if (!ops->get_regs) { 11258c2ecf20Sopenharmony_ci netdev_err(net_dev, "ops->get_regs is null!\n"); 11268c2ecf20Sopenharmony_ci return; 11278c2ecf20Sopenharmony_ci } 11288c2ecf20Sopenharmony_ci ops->get_regs(priv->ae_handle, data); 11298c2ecf20Sopenharmony_ci} 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci/** 11328c2ecf20Sopenharmony_ci * hns_get_regs_len - get total register len. 11338c2ecf20Sopenharmony_ci * @net_dev: net device 11348c2ecf20Sopenharmony_ci * 11358c2ecf20Sopenharmony_ci * Return total register len. 11368c2ecf20Sopenharmony_ci */ 11378c2ecf20Sopenharmony_cistatic int hns_get_regs_len(struct net_device *net_dev) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci u32 reg_num; 11408c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(net_dev); 11418c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 11448c2ecf20Sopenharmony_ci if (!ops->get_regs_len) { 11458c2ecf20Sopenharmony_ci netdev_err(net_dev, "ops->get_regs_len is null!\n"); 11468c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 11478c2ecf20Sopenharmony_ci } 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci reg_num = ops->get_regs_len(priv->ae_handle); 11508c2ecf20Sopenharmony_ci if (reg_num > 0) 11518c2ecf20Sopenharmony_ci return reg_num * sizeof(u32); 11528c2ecf20Sopenharmony_ci else 11538c2ecf20Sopenharmony_ci return reg_num; /* error code */ 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci/** 11578c2ecf20Sopenharmony_ci * hns_nic_nway_reset - nway reset 11588c2ecf20Sopenharmony_ci * @netdev: net device 11598c2ecf20Sopenharmony_ci * 11608c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure 11618c2ecf20Sopenharmony_ci */ 11628c2ecf20Sopenharmony_cistatic int hns_nic_nway_reset(struct net_device *netdev) 11638c2ecf20Sopenharmony_ci{ 11648c2ecf20Sopenharmony_ci struct phy_device *phy = netdev->phydev; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (!netif_running(netdev)) 11678c2ecf20Sopenharmony_ci return 0; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci if (!phy) 11708c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci if (phy->autoneg != AUTONEG_ENABLE) 11738c2ecf20Sopenharmony_ci return -EINVAL; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci return genphy_restart_aneg(phy); 11768c2ecf20Sopenharmony_ci} 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_cistatic u32 11798c2ecf20Sopenharmony_cihns_get_rss_key_size(struct net_device *netdev) 11808c2ecf20Sopenharmony_ci{ 11818c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 11828c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci if (AE_IS_VER1(priv->enet_ver)) { 11858c2ecf20Sopenharmony_ci netdev_err(netdev, 11868c2ecf20Sopenharmony_ci "RSS feature is not supported on this hardware\n"); 11878c2ecf20Sopenharmony_ci return 0; 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 11918c2ecf20Sopenharmony_ci return ops->get_rss_key_size(priv->ae_handle); 11928c2ecf20Sopenharmony_ci} 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_cistatic u32 11958c2ecf20Sopenharmony_cihns_get_rss_indir_size(struct net_device *netdev) 11968c2ecf20Sopenharmony_ci{ 11978c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 11988c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci if (AE_IS_VER1(priv->enet_ver)) { 12018c2ecf20Sopenharmony_ci netdev_err(netdev, 12028c2ecf20Sopenharmony_ci "RSS feature is not supported on this hardware\n"); 12038c2ecf20Sopenharmony_ci return 0; 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 12078c2ecf20Sopenharmony_ci return ops->get_rss_indir_size(priv->ae_handle); 12088c2ecf20Sopenharmony_ci} 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_cistatic int 12118c2ecf20Sopenharmony_cihns_get_rss(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) 12128c2ecf20Sopenharmony_ci{ 12138c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 12148c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci if (AE_IS_VER1(priv->enet_ver)) { 12178c2ecf20Sopenharmony_ci netdev_err(netdev, 12188c2ecf20Sopenharmony_ci "RSS feature is not supported on this hardware\n"); 12198c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12208c2ecf20Sopenharmony_ci } 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci if (!indir) 12258c2ecf20Sopenharmony_ci return 0; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci return ops->get_rss(priv->ae_handle, indir, key, hfunc); 12288c2ecf20Sopenharmony_ci} 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_cistatic int 12318c2ecf20Sopenharmony_cihns_set_rss(struct net_device *netdev, const u32 *indir, const u8 *key, 12328c2ecf20Sopenharmony_ci const u8 hfunc) 12338c2ecf20Sopenharmony_ci{ 12348c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 12358c2ecf20Sopenharmony_ci struct hnae_ae_ops *ops; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci if (AE_IS_VER1(priv->enet_ver)) { 12388c2ecf20Sopenharmony_ci netdev_err(netdev, 12398c2ecf20Sopenharmony_ci "RSS feature is not supported on this hardware\n"); 12408c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci ops = priv->ae_handle->dev->ops; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) { 12468c2ecf20Sopenharmony_ci netdev_err(netdev, "Invalid hfunc!\n"); 12478c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12488c2ecf20Sopenharmony_ci } 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci return ops->set_rss(priv->ae_handle, indir, key, hfunc); 12518c2ecf20Sopenharmony_ci} 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_cistatic int hns_get_rxnfc(struct net_device *netdev, 12548c2ecf20Sopenharmony_ci struct ethtool_rxnfc *cmd, 12558c2ecf20Sopenharmony_ci u32 *rule_locs) 12568c2ecf20Sopenharmony_ci{ 12578c2ecf20Sopenharmony_ci struct hns_nic_priv *priv = netdev_priv(netdev); 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci switch (cmd->cmd) { 12608c2ecf20Sopenharmony_ci case ETHTOOL_GRXRINGS: 12618c2ecf20Sopenharmony_ci cmd->data = priv->ae_handle->q_num; 12628c2ecf20Sopenharmony_ci break; 12638c2ecf20Sopenharmony_ci default: 12648c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12658c2ecf20Sopenharmony_ci } 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci return 0; 12688c2ecf20Sopenharmony_ci} 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_cistatic const struct ethtool_ops hns_ethtool_ops = { 12718c2ecf20Sopenharmony_ci .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 12728c2ecf20Sopenharmony_ci ETHTOOL_COALESCE_MAX_FRAMES | 12738c2ecf20Sopenharmony_ci ETHTOOL_COALESCE_USE_ADAPTIVE | 12748c2ecf20Sopenharmony_ci ETHTOOL_COALESCE_USECS_LOW_HIGH | 12758c2ecf20Sopenharmony_ci ETHTOOL_COALESCE_MAX_FRAMES_LOW_HIGH, 12768c2ecf20Sopenharmony_ci .get_drvinfo = hns_nic_get_drvinfo, 12778c2ecf20Sopenharmony_ci .get_link = hns_nic_get_link, 12788c2ecf20Sopenharmony_ci .get_ringparam = hns_get_ringparam, 12798c2ecf20Sopenharmony_ci .get_pauseparam = hns_get_pauseparam, 12808c2ecf20Sopenharmony_ci .set_pauseparam = hns_set_pauseparam, 12818c2ecf20Sopenharmony_ci .get_coalesce = hns_get_coalesce, 12828c2ecf20Sopenharmony_ci .set_coalesce = hns_set_coalesce, 12838c2ecf20Sopenharmony_ci .get_channels = hns_get_channels, 12848c2ecf20Sopenharmony_ci .self_test = hns_nic_self_test, 12858c2ecf20Sopenharmony_ci .get_strings = hns_get_strings, 12868c2ecf20Sopenharmony_ci .get_sset_count = hns_get_sset_count, 12878c2ecf20Sopenharmony_ci .get_ethtool_stats = hns_get_ethtool_stats, 12888c2ecf20Sopenharmony_ci .set_phys_id = hns_set_phys_id, 12898c2ecf20Sopenharmony_ci .get_regs_len = hns_get_regs_len, 12908c2ecf20Sopenharmony_ci .get_regs = hns_get_regs, 12918c2ecf20Sopenharmony_ci .nway_reset = hns_nic_nway_reset, 12928c2ecf20Sopenharmony_ci .get_rxfh_key_size = hns_get_rss_key_size, 12938c2ecf20Sopenharmony_ci .get_rxfh_indir_size = hns_get_rss_indir_size, 12948c2ecf20Sopenharmony_ci .get_rxfh = hns_get_rss, 12958c2ecf20Sopenharmony_ci .set_rxfh = hns_set_rss, 12968c2ecf20Sopenharmony_ci .get_rxnfc = hns_get_rxnfc, 12978c2ecf20Sopenharmony_ci .get_link_ksettings = hns_nic_get_link_ksettings, 12988c2ecf20Sopenharmony_ci .set_link_ksettings = hns_nic_set_link_ksettings, 12998c2ecf20Sopenharmony_ci}; 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_civoid hns_ethtool_set_ops(struct net_device *ndev) 13028c2ecf20Sopenharmony_ci{ 13038c2ecf20Sopenharmony_ci ndev->ethtool_ops = &hns_ethtool_ops; 13048c2ecf20Sopenharmony_ci} 1305