brintos

brintos / linux-shallow public Read only

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