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, &param->autoneg,
7038c2ecf20Sopenharmony_ci					    &param->rx_pause, &param->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