brintos

brintos / linux-shallow public Read only

0
0
Text · 49.3 KiB · c559dd4 Raw
1851 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Huawei HiNIC PCI Express Linux driver3 * Copyright(c) 2017 Huawei Technologies Co., Ltd4 *5 * This program is free software; you can redistribute it and/or modify it6 * under the terms and conditions of the GNU General Public License,7 * version 2, as published by the Free Software Foundation.8 *9 * This program is distributed in the hope it will be useful, but WITHOUT10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License12 * for more details.13 *14 */15 16#include <linux/kernel.h>17#include <linux/pci.h>18#include <linux/device.h>19#include <linux/module.h>20#include <linux/types.h>21#include <linux/errno.h>22#include <linux/interrupt.h>23#include <linux/etherdevice.h>24#include <linux/netdevice.h>25#include <linux/if_vlan.h>26#include <linux/ethtool.h>27#include <linux/vmalloc.h>28#include <linux/sfp.h>29 30#include "hinic_hw_qp.h"31#include "hinic_hw_dev.h"32#include "hinic_port.h"33#include "hinic_tx.h"34#include "hinic_rx.h"35#include "hinic_dev.h"36 37#define SET_LINK_STR_MAX_LEN	1638 39#define GET_SUPPORTED_MODE	040#define GET_ADVERTISED_MODE	141 42#define ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE(ecmd, mode)	\43		((ecmd)->supported |=	\44		(1UL << hw_to_ethtool_link_mode_table[mode].link_mode_bit))45#define ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE(ecmd, mode)	\46		((ecmd)->advertising |=	\47		(1UL << hw_to_ethtool_link_mode_table[mode].link_mode_bit))48#define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode)	\49				((ecmd)->supported |= SUPPORTED_##mode)50#define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode)	\51				((ecmd)->advertising |= ADVERTISED_##mode)52 53#define COALESCE_PENDING_LIMIT_UNIT	854#define	COALESCE_TIMER_CFG_UNIT		955#define COALESCE_ALL_QUEUE		0xFFFF56#define COALESCE_MAX_PENDING_LIMIT	(255 * COALESCE_PENDING_LIMIT_UNIT)57#define COALESCE_MAX_TIMER_CFG		(255 * COALESCE_TIMER_CFG_UNIT)58 59struct hw2ethtool_link_mode {60	enum ethtool_link_mode_bit_indices link_mode_bit;61	u32 speed;62	enum hinic_link_mode hw_link_mode;63};64 65struct cmd_link_settings {66	u64	supported;67	u64	advertising;68 69	u32	speed;70	u8	duplex;71	u8	port;72	u8	autoneg;73};74 75static u32 hw_to_ethtool_speed[LINK_SPEED_LEVELS] = {76	SPEED_10, SPEED_100,77	SPEED_1000, SPEED_10000,78	SPEED_25000, SPEED_40000,79	SPEED_10000080};81 82static struct hw2ethtool_link_mode83	hw_to_ethtool_link_mode_table[HINIC_LINK_MODE_NUMBERS] = {84	{85		.link_mode_bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,86		.speed = SPEED_10000,87		.hw_link_mode = HINIC_10GE_BASE_KR,88	},89	{90		.link_mode_bit = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,91		.speed = SPEED_40000,92		.hw_link_mode = HINIC_40GE_BASE_KR4,93	},94	{95		.link_mode_bit = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,96		.speed = SPEED_40000,97		.hw_link_mode = HINIC_40GE_BASE_CR4,98	},99	{100		.link_mode_bit = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,101		.speed = SPEED_100000,102		.hw_link_mode = HINIC_100GE_BASE_KR4,103	},104	{105		.link_mode_bit = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,106		.speed = SPEED_100000,107		.hw_link_mode = HINIC_100GE_BASE_CR4,108	},109	{110		.link_mode_bit = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,111		.speed = SPEED_25000,112		.hw_link_mode = HINIC_25GE_BASE_KR_S,113	},114	{115		.link_mode_bit = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,116		.speed = SPEED_25000,117		.hw_link_mode = HINIC_25GE_BASE_CR_S,118	},119	{120		.link_mode_bit = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,121		.speed = SPEED_25000,122		.hw_link_mode = HINIC_25GE_BASE_KR,123	},124	{125		.link_mode_bit = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,126		.speed = SPEED_25000,127		.hw_link_mode = HINIC_25GE_BASE_CR,128	},129	{130		.link_mode_bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,131		.speed = SPEED_1000,132		.hw_link_mode = HINIC_GE_BASE_KX,133	},134};135 136#define LP_DEFAULT_TIME                 5 /* seconds */137#define LP_PKT_LEN                      1514138 139#define PORT_DOWN_ERR_IDX		0140enum diag_test_index {141	INTERNAL_LP_TEST = 0,142	EXTERNAL_LP_TEST = 1,143	DIAG_TEST_MAX = 2,144};145 146static void set_link_speed(struct ethtool_link_ksettings *link_ksettings,147			   enum hinic_speed speed)148{149	switch (speed) {150	case HINIC_SPEED_10MB_LINK:151		link_ksettings->base.speed = SPEED_10;152		break;153 154	case HINIC_SPEED_100MB_LINK:155		link_ksettings->base.speed = SPEED_100;156		break;157 158	case HINIC_SPEED_1000MB_LINK:159		link_ksettings->base.speed = SPEED_1000;160		break;161 162	case HINIC_SPEED_10GB_LINK:163		link_ksettings->base.speed = SPEED_10000;164		break;165 166	case HINIC_SPEED_25GB_LINK:167		link_ksettings->base.speed = SPEED_25000;168		break;169 170	case HINIC_SPEED_40GB_LINK:171		link_ksettings->base.speed = SPEED_40000;172		break;173 174	case HINIC_SPEED_100GB_LINK:175		link_ksettings->base.speed = SPEED_100000;176		break;177 178	default:179		link_ksettings->base.speed = SPEED_UNKNOWN;180		break;181	}182}183 184static int hinic_get_link_mode_index(enum hinic_link_mode link_mode)185{186	int i = 0;187 188	for (i = 0; i < HINIC_LINK_MODE_NUMBERS; i++) {189		if (link_mode == hw_to_ethtool_link_mode_table[i].hw_link_mode)190			break;191	}192 193	return i;194}195 196static void hinic_add_ethtool_link_mode(struct cmd_link_settings *link_settings,197					enum hinic_link_mode hw_link_mode,198					u32 name)199{200	enum hinic_link_mode link_mode;201	int idx = 0;202 203	for (link_mode = 0; link_mode < HINIC_LINK_MODE_NUMBERS; link_mode++) {204		if (hw_link_mode & ((u32)1 << link_mode)) {205			idx = hinic_get_link_mode_index(link_mode);206			if (idx >= HINIC_LINK_MODE_NUMBERS)207				continue;208 209			if (name == GET_SUPPORTED_MODE)210				ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE211					(link_settings, idx);212			else213				ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE214					(link_settings, idx);215		}216	}217}218 219static void hinic_link_port_type(struct cmd_link_settings *link_settings,220				 enum hinic_port_type port_type)221{222	switch (port_type) {223	case HINIC_PORT_ELEC:224	case HINIC_PORT_TP:225		ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, TP);226		ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, TP);227		link_settings->port = PORT_TP;228		break;229 230	case HINIC_PORT_AOC:231	case HINIC_PORT_FIBRE:232		ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);233		ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);234		link_settings->port = PORT_FIBRE;235		break;236 237	case HINIC_PORT_COPPER:238		ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);239		ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);240		link_settings->port = PORT_DA;241		break;242 243	case HINIC_PORT_BACKPLANE:244		ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Backplane);245		ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Backplane);246		link_settings->port = PORT_NONE;247		break;248 249	default:250		link_settings->port = PORT_OTHER;251		break;252	}253}254 255static int hinic_get_link_ksettings(struct net_device *netdev,256				    struct ethtool_link_ksettings257				    *link_ksettings)258{259	struct hinic_dev *nic_dev = netdev_priv(netdev);260	struct hinic_link_mode_cmd link_mode = { 0 };261	struct hinic_pause_config pause_info = { 0 };262	struct cmd_link_settings settings = { 0 };263	enum hinic_port_link_state link_state;264	struct hinic_port_cap port_cap;265	int err;266 267	ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);268	ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);269 270	link_ksettings->base.speed = SPEED_UNKNOWN;271	link_ksettings->base.autoneg = AUTONEG_DISABLE;272	link_ksettings->base.duplex = DUPLEX_UNKNOWN;273 274	err = hinic_port_get_cap(nic_dev, &port_cap);275	if (err)276		return err;277 278	hinic_link_port_type(&settings, port_cap.port_type);279	link_ksettings->base.port = settings.port;280 281	err = hinic_port_link_state(nic_dev, &link_state);282	if (err)283		return err;284 285	if (link_state == HINIC_LINK_STATE_UP) {286		set_link_speed(link_ksettings, port_cap.speed);287		link_ksettings->base.duplex =288			(port_cap.duplex == HINIC_DUPLEX_FULL) ?289			DUPLEX_FULL : DUPLEX_HALF;290	}291 292	if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED))293		ethtool_link_ksettings_add_link_mode(link_ksettings,294						     advertising, Autoneg);295 296	if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE)297		link_ksettings->base.autoneg = AUTONEG_ENABLE;298 299	err = hinic_get_link_mode(nic_dev->hwdev, &link_mode);300	if (err || link_mode.supported == HINIC_SUPPORTED_UNKNOWN ||301	    link_mode.advertised == HINIC_SUPPORTED_UNKNOWN)302		return -EIO;303 304	hinic_add_ethtool_link_mode(&settings, link_mode.supported,305				    GET_SUPPORTED_MODE);306	hinic_add_ethtool_link_mode(&settings, link_mode.advertised,307				    GET_ADVERTISED_MODE);308 309	if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) {310		err = hinic_get_hw_pause_info(nic_dev->hwdev, &pause_info);311		if (err)312			return err;313		ETHTOOL_ADD_SUPPORTED_LINK_MODE(&settings, Pause);314		if (pause_info.rx_pause && pause_info.tx_pause) {315			ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Pause);316		} else if (pause_info.tx_pause) {317			ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Asym_Pause);318		} else if (pause_info.rx_pause) {319			ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Pause);320			ETHTOOL_ADD_ADVERTISED_LINK_MODE(&settings, Asym_Pause);321		}322	}323 324	linkmode_copy(link_ksettings->link_modes.supported,325		      (unsigned long *)&settings.supported);326	linkmode_copy(link_ksettings->link_modes.advertising,327		      (unsigned long *)&settings.advertising);328 329	return 0;330}331 332static int hinic_ethtool_to_hw_speed_level(u32 speed)333{334	int i;335 336	for (i = 0; i < LINK_SPEED_LEVELS; i++) {337		if (hw_to_ethtool_speed[i] == speed)338			break;339	}340 341	return i;342}343 344static bool hinic_is_support_speed(enum hinic_link_mode supported_link,345				   u32 speed)346{347	enum hinic_link_mode link_mode;348	int idx;349 350	for (link_mode = 0; link_mode < HINIC_LINK_MODE_NUMBERS; link_mode++) {351		if (!(supported_link & ((u32)1 << link_mode)))352			continue;353 354		idx = hinic_get_link_mode_index(link_mode);355		if (idx >= HINIC_LINK_MODE_NUMBERS)356			continue;357 358		if (hw_to_ethtool_link_mode_table[idx].speed == speed)359			return true;360	}361 362	return false;363}364 365static bool hinic_is_speed_legal(struct hinic_dev *nic_dev, u32 speed)366{367	struct hinic_link_mode_cmd link_mode = { 0 };368	struct net_device *netdev = nic_dev->netdev;369	enum nic_speed_level speed_level = 0;370	int err;371 372	err = hinic_get_link_mode(nic_dev->hwdev, &link_mode);373	if (err)374		return false;375 376	if (link_mode.supported == HINIC_SUPPORTED_UNKNOWN ||377	    link_mode.advertised == HINIC_SUPPORTED_UNKNOWN)378		return false;379 380	speed_level = hinic_ethtool_to_hw_speed_level(speed);381	if (speed_level >= LINK_SPEED_LEVELS ||382	    !hinic_is_support_speed(link_mode.supported, speed)) {383		netif_err(nic_dev, drv, netdev,384			  "Unsupported speed: %d\n", speed);385		return false;386	}387 388	return true;389}390 391static int get_link_settings_type(struct hinic_dev *nic_dev,392				  u8 autoneg, u32 speed, u32 *set_settings)393{394	struct hinic_port_cap port_cap = { 0 };395	int err;396 397	err = hinic_port_get_cap(nic_dev, &port_cap);398	if (err)399		return err;400 401	/* always set autonegotiation */402	if (port_cap.autoneg_cap)403		*set_settings |= HILINK_LINK_SET_AUTONEG;404 405	if (autoneg == AUTONEG_ENABLE) {406		if (!port_cap.autoneg_cap) {407			netif_err(nic_dev, drv, nic_dev->netdev, "Not support autoneg\n");408			return -EOPNOTSUPP;409		}410	} else if (speed != (u32)SPEED_UNKNOWN) {411		/* set speed only when autoneg is disabled */412		if (!hinic_is_speed_legal(nic_dev, speed))413			return -EINVAL;414		*set_settings |= HILINK_LINK_SET_SPEED;415	} else {416		netif_err(nic_dev, drv, nic_dev->netdev, "Need to set speed when autoneg is off\n");417		return -EOPNOTSUPP;418	}419 420	return 0;421}422 423static int set_link_settings_separate_cmd(struct hinic_dev *nic_dev,424					  u32 set_settings, u8 autoneg,425					  u32 speed)426{427	enum nic_speed_level speed_level = 0;428	int err = 0;429 430	if (set_settings & HILINK_LINK_SET_AUTONEG) {431		err = hinic_set_autoneg(nic_dev->hwdev,432					(autoneg == AUTONEG_ENABLE));433		if (err)434			netif_err(nic_dev, drv, nic_dev->netdev, "%s autoneg failed\n",435				  (autoneg == AUTONEG_ENABLE) ?436				  "Enable" : "Disable");437		else438			netif_info(nic_dev, drv, nic_dev->netdev, "%s autoneg successfully\n",439				   (autoneg == AUTONEG_ENABLE) ?440				   "Enable" : "Disable");441	}442 443	if (!err && (set_settings & HILINK_LINK_SET_SPEED)) {444		speed_level = hinic_ethtool_to_hw_speed_level(speed);445		err = hinic_set_speed(nic_dev->hwdev, speed_level);446		if (err)447			netif_err(nic_dev, drv, nic_dev->netdev, "Set speed %d failed\n",448				  speed);449		else450			netif_info(nic_dev, drv, nic_dev->netdev, "Set speed %d successfully\n",451				   speed);452	}453 454	return err;455}456 457static int hinic_set_settings_to_hw(struct hinic_dev *nic_dev,458				    u32 set_settings, u8 autoneg, u32 speed)459{460	struct hinic_link_ksettings_info settings = {0};461	char set_link_str[SET_LINK_STR_MAX_LEN] = {0};462	const char *autoneg_str;463	struct net_device *netdev = nic_dev->netdev;464	enum nic_speed_level speed_level = 0;465	int err;466 467	autoneg_str = (set_settings & HILINK_LINK_SET_AUTONEG) ?468		      (autoneg ? "autong enable " : "autong disable ") : "";469 470	if (set_settings & HILINK_LINK_SET_SPEED) {471		speed_level = hinic_ethtool_to_hw_speed_level(speed);472		err = snprintf(set_link_str, SET_LINK_STR_MAX_LEN,473			       "speed %d ", speed);474		if (err >= SET_LINK_STR_MAX_LEN) {475			netif_err(nic_dev, drv, netdev, "Failed to snprintf link speed, function return(%d) and dest_len(%d)\n",476				  err, SET_LINK_STR_MAX_LEN);477			return -EFAULT;478		}479	}480 481	settings.func_id = HINIC_HWIF_FUNC_IDX(nic_dev->hwdev->hwif);482	settings.valid_bitmap = set_settings;483	settings.autoneg = autoneg;484	settings.speed = speed_level;485 486	err = hinic_set_link_settings(nic_dev->hwdev, &settings);487	if (err != HINIC_MGMT_CMD_UNSUPPORTED) {488		if (err)489			netif_err(nic_dev, drv, netdev, "Set %s%sfailed\n",490				  autoneg_str, set_link_str);491		else492			netif_info(nic_dev, drv, netdev, "Set %s%ssuccessfully\n",493				   autoneg_str, set_link_str);494 495		return err;496	}497 498	return set_link_settings_separate_cmd(nic_dev, set_settings, autoneg,499					      speed);500}501 502static int set_link_settings(struct net_device *netdev, u8 autoneg, u32 speed)503{504	struct hinic_dev *nic_dev = netdev_priv(netdev);505	u32 set_settings = 0;506	int err;507 508	err = get_link_settings_type(nic_dev, autoneg, speed, &set_settings);509	if (err)510		return err;511 512	if (set_settings)513		err = hinic_set_settings_to_hw(nic_dev, set_settings,514					       autoneg, speed);515	else516		netif_info(nic_dev, drv, netdev, "Nothing changed, exit without setting anything\n");517 518	return err;519}520 521static int hinic_set_link_ksettings(struct net_device *netdev, const struct522				    ethtool_link_ksettings *link_settings)523{524	/* only support to set autoneg and speed */525	return set_link_settings(netdev, link_settings->base.autoneg,526				 link_settings->base.speed);527}528 529static void hinic_get_drvinfo(struct net_device *netdev,530			      struct ethtool_drvinfo *info)531{532	struct hinic_dev *nic_dev = netdev_priv(netdev);533	u8 mgmt_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0};534	struct hinic_hwdev *hwdev = nic_dev->hwdev;535	struct hinic_hwif *hwif = hwdev->hwif;536	int err;537 538	strscpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver));539	strscpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info));540 541	err = hinic_get_mgmt_version(nic_dev, mgmt_ver);542	if (err)543		return;544 545	snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver);546}547 548static void hinic_get_ringparam(struct net_device *netdev,549				struct ethtool_ringparam *ring,550				struct kernel_ethtool_ringparam *kernel_ring,551				struct netlink_ext_ack *extack)552{553	struct hinic_dev *nic_dev = netdev_priv(netdev);554 555	ring->rx_max_pending = HINIC_MAX_QUEUE_DEPTH;556	ring->tx_max_pending = HINIC_MAX_QUEUE_DEPTH;557	ring->rx_pending = nic_dev->rq_depth;558	ring->tx_pending = nic_dev->sq_depth;559}560 561static int check_ringparam_valid(struct hinic_dev *nic_dev,562				 struct ethtool_ringparam *ring)563{564	if (ring->rx_jumbo_pending || ring->rx_mini_pending) {565		netif_err(nic_dev, drv, nic_dev->netdev,566			  "Unsupported rx_jumbo_pending/rx_mini_pending\n");567		return -EINVAL;568	}569 570	if (ring->tx_pending > HINIC_MAX_QUEUE_DEPTH ||571	    ring->tx_pending < HINIC_MIN_QUEUE_DEPTH ||572	    ring->rx_pending > HINIC_MAX_QUEUE_DEPTH ||573	    ring->rx_pending < HINIC_MIN_QUEUE_DEPTH) {574		netif_err(nic_dev, drv, nic_dev->netdev,575			  "Queue depth out of range [%d-%d]\n",576			  HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH);577		return -EINVAL;578	}579 580	return 0;581}582 583static int hinic_set_ringparam(struct net_device *netdev,584			       struct ethtool_ringparam *ring,585			       struct kernel_ethtool_ringparam *kernel_ring,586			       struct netlink_ext_ack *extack)587{588	struct hinic_dev *nic_dev = netdev_priv(netdev);589	u16 new_sq_depth, new_rq_depth;590	int err;591 592	err = check_ringparam_valid(nic_dev, ring);593	if (err)594		return err;595 596	new_sq_depth = (u16)(1U << (u16)ilog2(ring->tx_pending));597	new_rq_depth = (u16)(1U << (u16)ilog2(ring->rx_pending));598 599	if (new_sq_depth == nic_dev->sq_depth &&600	    new_rq_depth == nic_dev->rq_depth)601		return 0;602 603	netif_info(nic_dev, drv, netdev,604		   "Change Tx/Rx ring depth from %d/%d to %d/%d\n",605		   nic_dev->sq_depth, nic_dev->rq_depth,606		   new_sq_depth, new_rq_depth);607 608	nic_dev->sq_depth = new_sq_depth;609	nic_dev->rq_depth = new_rq_depth;610 611	if (netif_running(netdev)) {612		netif_info(nic_dev, drv, netdev, "Restarting netdev\n");613		err = hinic_close(netdev);614		if (err) {615			netif_err(nic_dev, drv, netdev,616				  "Failed to close netdev\n");617			return -EFAULT;618		}619 620		err = hinic_open(netdev);621		if (err) {622			netif_err(nic_dev, drv, netdev,623				  "Failed to open netdev\n");624			return -EFAULT;625		}626	}627 628	return 0;629}630 631static int __hinic_get_coalesce(struct net_device *netdev,632				struct ethtool_coalesce *coal, u16 queue)633{634	struct hinic_dev *nic_dev = netdev_priv(netdev);635	struct hinic_intr_coal_info *rx_intr_coal_info;636	struct hinic_intr_coal_info *tx_intr_coal_info;637 638	if (queue == COALESCE_ALL_QUEUE) {639		/* get tx/rx irq0 as default parameters */640		rx_intr_coal_info = &nic_dev->rx_intr_coalesce[0];641		tx_intr_coal_info = &nic_dev->tx_intr_coalesce[0];642	} else {643		if (queue >= nic_dev->num_qps) {644			netif_err(nic_dev, drv, netdev,645				  "Invalid queue_id: %d\n", queue);646			return -EINVAL;647		}648		rx_intr_coal_info = &nic_dev->rx_intr_coalesce[queue];649		tx_intr_coal_info = &nic_dev->tx_intr_coalesce[queue];650	}651 652	/* coalesce_timer is in unit of 9us */653	coal->rx_coalesce_usecs = rx_intr_coal_info->coalesce_timer_cfg *654			COALESCE_TIMER_CFG_UNIT;655	/* coalesced_frames is in unit of 8 */656	coal->rx_max_coalesced_frames = rx_intr_coal_info->pending_limt *657			COALESCE_PENDING_LIMIT_UNIT;658	coal->tx_coalesce_usecs = tx_intr_coal_info->coalesce_timer_cfg *659			COALESCE_TIMER_CFG_UNIT;660	coal->tx_max_coalesced_frames = tx_intr_coal_info->pending_limt *661			COALESCE_PENDING_LIMIT_UNIT;662 663	return 0;664}665 666static int is_coalesce_exceed_limit(const struct ethtool_coalesce *coal)667{668	if (coal->rx_coalesce_usecs > COALESCE_MAX_TIMER_CFG ||669	    coal->rx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT ||670	    coal->tx_coalesce_usecs > COALESCE_MAX_TIMER_CFG ||671	    coal->tx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT)672		return -ERANGE;673 674	return 0;675}676 677static int set_queue_coalesce(struct hinic_dev *nic_dev, u16 q_id,678			      struct hinic_intr_coal_info *coal,679			      bool set_rx_coal)680{681	struct hinic_intr_coal_info *intr_coal = NULL;682	struct hinic_msix_config interrupt_info = {0};683	struct net_device *netdev = nic_dev->netdev;684	u16 msix_idx;685	int err;686 687	intr_coal = set_rx_coal ? &nic_dev->rx_intr_coalesce[q_id] :688		    &nic_dev->tx_intr_coalesce[q_id];689 690	intr_coal->coalesce_timer_cfg = coal->coalesce_timer_cfg;691	intr_coal->pending_limt = coal->pending_limt;692 693	/* netdev not running or qp not in using,694	 * don't need to set coalesce to hw695	 */696	if (!(nic_dev->flags & HINIC_INTF_UP) ||697	    q_id >= nic_dev->num_qps)698		return 0;699 700	msix_idx = set_rx_coal ? nic_dev->rxqs[q_id].rq->msix_entry :701		   nic_dev->txqs[q_id].sq->msix_entry;702	interrupt_info.msix_index = msix_idx;703	interrupt_info.coalesce_timer_cnt = intr_coal->coalesce_timer_cfg;704	interrupt_info.pending_cnt = intr_coal->pending_limt;705	interrupt_info.resend_timer_cnt = intr_coal->resend_timer_cfg;706 707	err = hinic_set_interrupt_cfg(nic_dev->hwdev, &interrupt_info);708	if (err)709		netif_warn(nic_dev, drv, netdev,710			   "Failed to set %s queue%d coalesce",711			   set_rx_coal ? "rx" : "tx", q_id);712 713	return err;714}715 716static int __set_hw_coal_param(struct hinic_dev *nic_dev,717			       struct hinic_intr_coal_info *intr_coal,718			       u16 queue, bool set_rx_coal)719{720	int err;721	u16 i;722 723	if (queue == COALESCE_ALL_QUEUE) {724		for (i = 0; i < nic_dev->max_qps; i++) {725			err = set_queue_coalesce(nic_dev, i, intr_coal,726						 set_rx_coal);727			if (err)728				return err;729		}730	} else {731		if (queue >= nic_dev->num_qps) {732			netif_err(nic_dev, drv, nic_dev->netdev,733				  "Invalid queue_id: %d\n", queue);734			return -EINVAL;735		}736		err = set_queue_coalesce(nic_dev, queue, intr_coal,737					 set_rx_coal);738		if (err)739			return err;740	}741 742	return 0;743}744 745static int __hinic_set_coalesce(struct net_device *netdev,746				struct ethtool_coalesce *coal, u16 queue)747{748	struct hinic_dev *nic_dev = netdev_priv(netdev);749	struct hinic_intr_coal_info rx_intr_coal = {0};750	struct hinic_intr_coal_info tx_intr_coal = {0};751	bool set_rx_coal = false;752	bool set_tx_coal = false;753	int err;754 755	err = is_coalesce_exceed_limit(coal);756	if (err)757		return err;758 759	if (coal->rx_coalesce_usecs || coal->rx_max_coalesced_frames) {760		rx_intr_coal.coalesce_timer_cfg =761		(u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);762		rx_intr_coal.pending_limt = (u8)(coal->rx_max_coalesced_frames /763				COALESCE_PENDING_LIMIT_UNIT);764		set_rx_coal = true;765	}766 767	if (coal->tx_coalesce_usecs || coal->tx_max_coalesced_frames) {768		tx_intr_coal.coalesce_timer_cfg =769		(u8)(coal->tx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);770		tx_intr_coal.pending_limt = (u8)(coal->tx_max_coalesced_frames /771		COALESCE_PENDING_LIMIT_UNIT);772		set_tx_coal = true;773	}774 775	/* setting coalesce timer or pending limit to zero will disable776	 * coalesce777	 */778	if (set_rx_coal && (!rx_intr_coal.coalesce_timer_cfg ||779			    !rx_intr_coal.pending_limt))780		netif_warn(nic_dev, drv, netdev, "RX coalesce will be disabled\n");781	if (set_tx_coal && (!tx_intr_coal.coalesce_timer_cfg ||782			    !tx_intr_coal.pending_limt))783		netif_warn(nic_dev, drv, netdev, "TX coalesce will be disabled\n");784 785	if (set_rx_coal) {786		err = __set_hw_coal_param(nic_dev, &rx_intr_coal, queue, true);787		if (err)788			return err;789	}790	if (set_tx_coal) {791		err = __set_hw_coal_param(nic_dev, &tx_intr_coal, queue, false);792		if (err)793			return err;794	}795	return 0;796}797 798static int hinic_get_coalesce(struct net_device *netdev,799			      struct ethtool_coalesce *coal,800			      struct kernel_ethtool_coalesce *kernel_coal,801			      struct netlink_ext_ack *extack)802{803	return __hinic_get_coalesce(netdev, coal, COALESCE_ALL_QUEUE);804}805 806static int hinic_set_coalesce(struct net_device *netdev,807			      struct ethtool_coalesce *coal,808			      struct kernel_ethtool_coalesce *kernel_coal,809			      struct netlink_ext_ack *extack)810{811	return __hinic_set_coalesce(netdev, coal, COALESCE_ALL_QUEUE);812}813 814static int hinic_get_per_queue_coalesce(struct net_device *netdev, u32 queue,815					struct ethtool_coalesce *coal)816{817	return __hinic_get_coalesce(netdev, coal, queue);818}819 820static int hinic_set_per_queue_coalesce(struct net_device *netdev, u32 queue,821					struct ethtool_coalesce *coal)822{823	return __hinic_set_coalesce(netdev, coal, queue);824}825 826static void hinic_get_pauseparam(struct net_device *netdev,827				 struct ethtool_pauseparam *pause)828{829	struct hinic_dev *nic_dev = netdev_priv(netdev);830	struct hinic_pause_config pause_info = {0};831	struct hinic_nic_cfg *nic_cfg;832	int err;833 834	nic_cfg = &nic_dev->hwdev->func_to_io.nic_cfg;835 836	err = hinic_get_hw_pause_info(nic_dev->hwdev, &pause_info);837	if (!err) {838		pause->autoneg = pause_info.auto_neg;839		if (nic_cfg->pause_set || !pause_info.auto_neg) {840			pause->rx_pause = nic_cfg->rx_pause;841			pause->tx_pause = nic_cfg->tx_pause;842		} else {843			pause->rx_pause = pause_info.rx_pause;844			pause->tx_pause = pause_info.tx_pause;845		}846	}847}848 849static int hinic_set_pauseparam(struct net_device *netdev,850				struct ethtool_pauseparam *pause)851{852	struct hinic_dev *nic_dev = netdev_priv(netdev);853	struct hinic_pause_config pause_info = {0};854	struct hinic_port_cap port_cap = {0};855	int err;856 857	err = hinic_port_get_cap(nic_dev, &port_cap);858	if (err)859		return -EIO;860 861	if (pause->autoneg != port_cap.autoneg_state)862		return -EOPNOTSUPP;863 864	pause_info.auto_neg = pause->autoneg;865	pause_info.rx_pause = pause->rx_pause;866	pause_info.tx_pause = pause->tx_pause;867 868	mutex_lock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);869	err = hinic_set_hw_pause_info(nic_dev->hwdev, &pause_info);870	if (err) {871		mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);872		return err;873	}874	nic_dev->hwdev->func_to_io.nic_cfg.pause_set = true;875	nic_dev->hwdev->func_to_io.nic_cfg.auto_neg = pause->autoneg;876	nic_dev->hwdev->func_to_io.nic_cfg.rx_pause = pause->rx_pause;877	nic_dev->hwdev->func_to_io.nic_cfg.tx_pause = pause->tx_pause;878	mutex_unlock(&nic_dev->hwdev->func_to_io.nic_cfg.cfg_mutex);879 880	return 0;881}882 883static void hinic_get_channels(struct net_device *netdev,884			       struct ethtool_channels *channels)885{886	struct hinic_dev *nic_dev = netdev_priv(netdev);887	struct hinic_hwdev *hwdev = nic_dev->hwdev;888 889	channels->max_combined = nic_dev->max_qps;890	channels->combined_count = hinic_hwdev_num_qps(hwdev);891}892 893static int hinic_set_channels(struct net_device *netdev,894			      struct ethtool_channels *channels)895{896	struct hinic_dev *nic_dev = netdev_priv(netdev);897	unsigned int count = channels->combined_count;898	int err;899 900	netif_info(nic_dev, drv, netdev, "Set max combined queue number from %d to %d\n",901		   hinic_hwdev_num_qps(nic_dev->hwdev), count);902 903	if (netif_running(netdev)) {904		netif_info(nic_dev, drv, netdev, "Restarting netdev\n");905		hinic_close(netdev);906 907		nic_dev->hwdev->nic_cap.num_qps = count;908 909		err = hinic_open(netdev);910		if (err) {911			netif_err(nic_dev, drv, netdev,912				  "Failed to open netdev\n");913			return -EFAULT;914		}915	} else {916		nic_dev->hwdev->nic_cap.num_qps = count;917	}918 919	return 0;920}921 922static int hinic_get_rss_hash_opts(struct hinic_dev *nic_dev,923				   struct ethtool_rxnfc *cmd)924{925	struct hinic_rss_type rss_type = { 0 };926	int err;927 928	cmd->data = 0;929 930	if (!(nic_dev->flags & HINIC_RSS_ENABLE))931		return 0;932 933	err = hinic_get_rss_type(nic_dev, nic_dev->rss_tmpl_idx,934				 &rss_type);935	if (err)936		return err;937 938	cmd->data = RXH_IP_SRC | RXH_IP_DST;939	switch (cmd->flow_type) {940	case TCP_V4_FLOW:941		if (rss_type.tcp_ipv4)942			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;943		break;944	case TCP_V6_FLOW:945		if (rss_type.tcp_ipv6)946			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;947		break;948	case UDP_V4_FLOW:949		if (rss_type.udp_ipv4)950			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;951		break;952	case UDP_V6_FLOW:953		if (rss_type.udp_ipv6)954			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;955		break;956	case IPV4_FLOW:957	case IPV6_FLOW:958		break;959	default:960		cmd->data = 0;961		return -EINVAL;962	}963 964	return 0;965}966 967static int set_l4_rss_hash_ops(struct ethtool_rxnfc *cmd,968			       struct hinic_rss_type *rss_type)969{970	u8 rss_l4_en = 0;971 972	switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {973	case 0:974		rss_l4_en = 0;975		break;976	case (RXH_L4_B_0_1 | RXH_L4_B_2_3):977		rss_l4_en = 1;978		break;979	default:980		return -EINVAL;981	}982 983	switch (cmd->flow_type) {984	case TCP_V4_FLOW:985		rss_type->tcp_ipv4 = rss_l4_en;986		break;987	case TCP_V6_FLOW:988		rss_type->tcp_ipv6 = rss_l4_en;989		break;990	case UDP_V4_FLOW:991		rss_type->udp_ipv4 = rss_l4_en;992		break;993	case UDP_V6_FLOW:994		rss_type->udp_ipv6 = rss_l4_en;995		break;996	default:997		return -EINVAL;998	}999 1000	return 0;1001}1002 1003static int hinic_set_rss_hash_opts(struct hinic_dev *nic_dev,1004				   struct ethtool_rxnfc *cmd)1005{1006	struct hinic_rss_type *rss_type = &nic_dev->rss_type;1007	int err;1008 1009	if (!(nic_dev->flags & HINIC_RSS_ENABLE)) {1010		cmd->data = 0;1011		return -EOPNOTSUPP;1012	}1013 1014	/* RSS does not support anything other than hashing1015	 * to queues on src and dst IPs and ports1016	 */1017	if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 |1018		RXH_L4_B_2_3))1019		return -EINVAL;1020 1021	/* We need at least the IP SRC and DEST fields for hashing */1022	if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST))1023		return -EINVAL;1024 1025	err = hinic_get_rss_type(nic_dev,1026				 nic_dev->rss_tmpl_idx, rss_type);1027	if (err)1028		return -EFAULT;1029 1030	switch (cmd->flow_type) {1031	case TCP_V4_FLOW:1032	case TCP_V6_FLOW:1033	case UDP_V4_FLOW:1034	case UDP_V6_FLOW:1035		err = set_l4_rss_hash_ops(cmd, rss_type);1036		if (err)1037			return err;1038		break;1039	case IPV4_FLOW:1040		rss_type->ipv4 = 1;1041		break;1042	case IPV6_FLOW:1043		rss_type->ipv6 = 1;1044		break;1045	default:1046		return -EINVAL;1047	}1048 1049	err = hinic_set_rss_type(nic_dev, nic_dev->rss_tmpl_idx,1050				 *rss_type);1051	if (err)1052		return -EFAULT;1053 1054	return 0;1055}1056 1057static int __set_rss_rxfh(struct net_device *netdev,1058			  const u32 *indir, const u8 *key)1059{1060	struct hinic_dev *nic_dev = netdev_priv(netdev);1061	int err;1062 1063	if (indir) {1064		if (!nic_dev->rss_indir_user) {1065			nic_dev->rss_indir_user =1066				kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE,1067					GFP_KERNEL);1068			if (!nic_dev->rss_indir_user)1069				return -ENOMEM;1070		}1071 1072		memcpy(nic_dev->rss_indir_user, indir,1073		       sizeof(u32) * HINIC_RSS_INDIR_SIZE);1074 1075		err = hinic_rss_set_indir_tbl(nic_dev,1076					      nic_dev->rss_tmpl_idx, indir);1077		if (err)1078			return -EFAULT;1079	}1080 1081	if (key) {1082		if (!nic_dev->rss_hkey_user) {1083			nic_dev->rss_hkey_user =1084				kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);1085 1086			if (!nic_dev->rss_hkey_user)1087				return -ENOMEM;1088		}1089 1090		memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE);1091 1092		err = hinic_rss_set_template_tbl(nic_dev,1093						 nic_dev->rss_tmpl_idx, key);1094		if (err)1095			return -EFAULT;1096	}1097 1098	return 0;1099}1100 1101static int hinic_get_rxnfc(struct net_device *netdev,1102			   struct ethtool_rxnfc *cmd, u32 *rule_locs)1103{1104	struct hinic_dev *nic_dev = netdev_priv(netdev);1105	int err = 0;1106 1107	switch (cmd->cmd) {1108	case ETHTOOL_GRXRINGS:1109		cmd->data = nic_dev->num_qps;1110		break;1111	case ETHTOOL_GRXFH:1112		err = hinic_get_rss_hash_opts(nic_dev, cmd);1113		break;1114	default:1115		err = -EOPNOTSUPP;1116		break;1117	}1118 1119	return err;1120}1121 1122static int hinic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)1123{1124	struct hinic_dev *nic_dev = netdev_priv(netdev);1125	int err = 0;1126 1127	switch (cmd->cmd) {1128	case ETHTOOL_SRXFH:1129		err = hinic_set_rss_hash_opts(nic_dev, cmd);1130		break;1131	default:1132		err = -EOPNOTSUPP;1133		break;1134	}1135 1136	return err;1137}1138 1139static int hinic_get_rxfh(struct net_device *netdev,1140			  struct ethtool_rxfh_param *rxfh)1141{1142	struct hinic_dev *nic_dev = netdev_priv(netdev);1143	u8 hash_engine_type = 0;1144	int err = 0;1145 1146	if (!(nic_dev->flags & HINIC_RSS_ENABLE))1147		return -EOPNOTSUPP;1148 1149	err = hinic_rss_get_hash_engine(nic_dev,1150					nic_dev->rss_tmpl_idx,1151					&hash_engine_type);1152	if (err)1153		return -EFAULT;1154 1155	rxfh->hfunc = hash_engine_type ? ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR;1156 1157	if (rxfh->indir) {1158		err = hinic_rss_get_indir_tbl(nic_dev,1159					      nic_dev->rss_tmpl_idx,1160					      rxfh->indir);1161		if (err)1162			return -EFAULT;1163	}1164 1165	if (rxfh->key)1166		err = hinic_rss_get_template_tbl(nic_dev,1167						 nic_dev->rss_tmpl_idx,1168						 rxfh->key);1169 1170	return err;1171}1172 1173static int hinic_set_rxfh(struct net_device *netdev,1174			  struct ethtool_rxfh_param *rxfh,1175			  struct netlink_ext_ack *extack)1176{1177	struct hinic_dev *nic_dev = netdev_priv(netdev);1178	int err = 0;1179 1180	if (!(nic_dev->flags & HINIC_RSS_ENABLE))1181		return -EOPNOTSUPP;1182 1183	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE) {1184		if (rxfh->hfunc != ETH_RSS_HASH_TOP &&1185		    rxfh->hfunc != ETH_RSS_HASH_XOR)1186			return -EOPNOTSUPP;1187 1188		nic_dev->rss_hash_engine = (rxfh->hfunc == ETH_RSS_HASH_XOR) ?1189			HINIC_RSS_HASH_ENGINE_TYPE_XOR :1190			HINIC_RSS_HASH_ENGINE_TYPE_TOEP;1191		err = hinic_rss_set_hash_engine1192			(nic_dev, nic_dev->rss_tmpl_idx,1193			nic_dev->rss_hash_engine);1194		if (err)1195			return -EFAULT;1196	}1197 1198	err = __set_rss_rxfh(netdev, rxfh->indir, rxfh->key);1199 1200	return err;1201}1202 1203static u32 hinic_get_rxfh_key_size(struct net_device *netdev)1204{1205	return HINIC_RSS_KEY_SIZE;1206}1207 1208static u32 hinic_get_rxfh_indir_size(struct net_device *netdev)1209{1210	return HINIC_RSS_INDIR_SIZE;1211}1212 1213#define HINIC_FUNC_STAT(_stat_item) {	\1214	.name = #_stat_item, \1215	.size = sizeof_field(struct hinic_vport_stats, _stat_item), \1216	.offset = offsetof(struct hinic_vport_stats, _stat_item) \1217}1218 1219static struct hinic_stats hinic_function_stats[] = {1220	HINIC_FUNC_STAT(tx_unicast_pkts_vport),1221	HINIC_FUNC_STAT(tx_unicast_bytes_vport),1222	HINIC_FUNC_STAT(tx_multicast_pkts_vport),1223	HINIC_FUNC_STAT(tx_multicast_bytes_vport),1224	HINIC_FUNC_STAT(tx_broadcast_pkts_vport),1225	HINIC_FUNC_STAT(tx_broadcast_bytes_vport),1226 1227	HINIC_FUNC_STAT(rx_unicast_pkts_vport),1228	HINIC_FUNC_STAT(rx_unicast_bytes_vport),1229	HINIC_FUNC_STAT(rx_multicast_pkts_vport),1230	HINIC_FUNC_STAT(rx_multicast_bytes_vport),1231	HINIC_FUNC_STAT(rx_broadcast_pkts_vport),1232	HINIC_FUNC_STAT(rx_broadcast_bytes_vport),1233 1234	HINIC_FUNC_STAT(tx_discard_vport),1235	HINIC_FUNC_STAT(rx_discard_vport),1236	HINIC_FUNC_STAT(tx_err_vport),1237	HINIC_FUNC_STAT(rx_err_vport),1238};1239 1240static char hinic_test_strings[][ETH_GSTRING_LEN] = {1241	"Internal lb test  (on/offline)",1242	"External lb test (external_lb)",1243};1244 1245#define HINIC_PORT_STAT(_stat_item) { \1246	.name = #_stat_item, \1247	.size = sizeof_field(struct hinic_phy_port_stats, _stat_item), \1248	.offset = offsetof(struct hinic_phy_port_stats, _stat_item) \1249}1250 1251static struct hinic_stats hinic_port_stats[] = {1252	HINIC_PORT_STAT(mac_rx_total_pkt_num),1253	HINIC_PORT_STAT(mac_rx_total_oct_num),1254	HINIC_PORT_STAT(mac_rx_bad_pkt_num),1255	HINIC_PORT_STAT(mac_rx_bad_oct_num),1256	HINIC_PORT_STAT(mac_rx_good_pkt_num),1257	HINIC_PORT_STAT(mac_rx_good_oct_num),1258	HINIC_PORT_STAT(mac_rx_uni_pkt_num),1259	HINIC_PORT_STAT(mac_rx_multi_pkt_num),1260	HINIC_PORT_STAT(mac_rx_broad_pkt_num),1261	HINIC_PORT_STAT(mac_tx_total_pkt_num),1262	HINIC_PORT_STAT(mac_tx_total_oct_num),1263	HINIC_PORT_STAT(mac_tx_bad_pkt_num),1264	HINIC_PORT_STAT(mac_tx_bad_oct_num),1265	HINIC_PORT_STAT(mac_tx_good_pkt_num),1266	HINIC_PORT_STAT(mac_tx_good_oct_num),1267	HINIC_PORT_STAT(mac_tx_uni_pkt_num),1268	HINIC_PORT_STAT(mac_tx_multi_pkt_num),1269	HINIC_PORT_STAT(mac_tx_broad_pkt_num),1270	HINIC_PORT_STAT(mac_rx_fragment_pkt_num),1271	HINIC_PORT_STAT(mac_rx_undersize_pkt_num),1272	HINIC_PORT_STAT(mac_rx_undermin_pkt_num),1273	HINIC_PORT_STAT(mac_rx_64_oct_pkt_num),1274	HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),1275	HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),1276	HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),1277	HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),1278	HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),1279	HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),1280	HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),1281	HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),1282	HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),1283	HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),1284	HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),1285	HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),1286	HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),1287	HINIC_PORT_STAT(mac_rx_oversize_pkt_num),1288	HINIC_PORT_STAT(mac_rx_jabber_pkt_num),1289	HINIC_PORT_STAT(mac_rx_pause_num),1290	HINIC_PORT_STAT(mac_rx_pfc_pkt_num),1291	HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),1292	HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),1293	HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),1294	HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),1295	HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),1296	HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),1297	HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),1298	HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),1299	HINIC_PORT_STAT(mac_rx_control_pkt_num),1300	HINIC_PORT_STAT(mac_rx_sym_err_pkt_num),1301	HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num),1302	HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num),1303	HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),1304	HINIC_PORT_STAT(mac_tx_fragment_pkt_num),1305	HINIC_PORT_STAT(mac_tx_undersize_pkt_num),1306	HINIC_PORT_STAT(mac_tx_undermin_pkt_num),1307	HINIC_PORT_STAT(mac_tx_64_oct_pkt_num),1308	HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),1309	HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),1310	HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),1311	HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),1312	HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),1313	HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),1314	HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),1315	HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),1316	HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),1317	HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),1318	HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),1319	HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),1320	HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),1321	HINIC_PORT_STAT(mac_tx_oversize_pkt_num),1322	HINIC_PORT_STAT(mac_tx_jabber_pkt_num),1323	HINIC_PORT_STAT(mac_tx_pause_num),1324	HINIC_PORT_STAT(mac_tx_pfc_pkt_num),1325	HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),1326	HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),1327	HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),1328	HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),1329	HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),1330	HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),1331	HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),1332	HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),1333	HINIC_PORT_STAT(mac_tx_control_pkt_num),1334	HINIC_PORT_STAT(mac_tx_err_all_pkt_num),1335	HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num),1336	HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),1337};1338 1339#define HINIC_TXQ_STAT(_stat_item) { \1340	.name = "txq%d_"#_stat_item, \1341	.size = sizeof_field(struct hinic_txq_stats, _stat_item), \1342	.offset = offsetof(struct hinic_txq_stats, _stat_item) \1343}1344 1345static struct hinic_stats hinic_tx_queue_stats[] = {1346	HINIC_TXQ_STAT(pkts),1347	HINIC_TXQ_STAT(bytes),1348	HINIC_TXQ_STAT(tx_busy),1349	HINIC_TXQ_STAT(tx_wake),1350	HINIC_TXQ_STAT(tx_dropped),1351	HINIC_TXQ_STAT(big_frags_pkts),1352};1353 1354#define HINIC_RXQ_STAT(_stat_item) { \1355	.name = "rxq%d_"#_stat_item, \1356	.size = sizeof_field(struct hinic_rxq_stats, _stat_item), \1357	.offset = offsetof(struct hinic_rxq_stats, _stat_item) \1358}1359 1360static struct hinic_stats hinic_rx_queue_stats[] = {1361	HINIC_RXQ_STAT(pkts),1362	HINIC_RXQ_STAT(bytes),1363	HINIC_RXQ_STAT(errors),1364	HINIC_RXQ_STAT(csum_errors),1365	HINIC_RXQ_STAT(other_errors),1366};1367 1368static void get_drv_queue_stats(struct hinic_dev *nic_dev, u64 *data)1369{1370	struct hinic_txq_stats txq_stats;1371	struct hinic_rxq_stats rxq_stats;1372	u16 i = 0, j = 0, qid = 0;1373	char *p;1374 1375	for (qid = 0; qid < nic_dev->num_qps; qid++) {1376		if (!nic_dev->txqs)1377			break;1378 1379		hinic_txq_get_stats(&nic_dev->txqs[qid], &txq_stats);1380		for (j = 0; j < ARRAY_SIZE(hinic_tx_queue_stats); j++, i++) {1381			p = (char *)&txq_stats +1382				hinic_tx_queue_stats[j].offset;1383			data[i] = (hinic_tx_queue_stats[j].size ==1384					sizeof(u64)) ? *(u64 *)p : *(u32 *)p;1385		}1386	}1387 1388	for (qid = 0; qid < nic_dev->num_qps; qid++) {1389		if (!nic_dev->rxqs)1390			break;1391 1392		hinic_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats);1393		for (j = 0; j < ARRAY_SIZE(hinic_rx_queue_stats); j++, i++) {1394			p = (char *)&rxq_stats +1395				hinic_rx_queue_stats[j].offset;1396			data[i] = (hinic_rx_queue_stats[j].size ==1397					sizeof(u64)) ? *(u64 *)p : *(u32 *)p;1398		}1399	}1400}1401 1402static void hinic_get_ethtool_stats(struct net_device *netdev,1403				    struct ethtool_stats *stats, u64 *data)1404{1405	struct hinic_dev *nic_dev = netdev_priv(netdev);1406	struct hinic_vport_stats vport_stats = {0};1407	struct hinic_phy_port_stats *port_stats;1408	u16 i = 0, j = 0;1409	char *p;1410	int err;1411 1412	err = hinic_get_vport_stats(nic_dev, &vport_stats);1413	if (err)1414		netif_err(nic_dev, drv, netdev,1415			  "Failed to get vport stats from firmware\n");1416 1417	for (j = 0; j < ARRAY_SIZE(hinic_function_stats); j++, i++) {1418		p = (char *)&vport_stats + hinic_function_stats[j].offset;1419		data[i] = (hinic_function_stats[j].size ==1420				sizeof(u64)) ? *(u64 *)p : *(u32 *)p;1421	}1422 1423	port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);1424	if (!port_stats) {1425		memset(&data[i], 0,1426		       ARRAY_SIZE(hinic_port_stats) * sizeof(*data));1427		i += ARRAY_SIZE(hinic_port_stats);1428		goto get_drv_stats;1429	}1430 1431	err = hinic_get_phy_port_stats(nic_dev, port_stats);1432	if (err)1433		netif_err(nic_dev, drv, netdev,1434			  "Failed to get port stats from firmware\n");1435 1436	for (j = 0; j < ARRAY_SIZE(hinic_port_stats); j++, i++) {1437		p = (char *)port_stats + hinic_port_stats[j].offset;1438		data[i] = (hinic_port_stats[j].size ==1439				sizeof(u64)) ? *(u64 *)p : *(u32 *)p;1440	}1441 1442	kfree(port_stats);1443 1444get_drv_stats:1445	get_drv_queue_stats(nic_dev, data + i);1446}1447 1448static int hinic_get_sset_count(struct net_device *netdev, int sset)1449{1450	struct hinic_dev *nic_dev = netdev_priv(netdev);1451	int count, q_num;1452 1453	switch (sset) {1454	case ETH_SS_TEST:1455		return ARRAY_SIZE(hinic_test_strings);1456	case ETH_SS_STATS:1457		q_num = nic_dev->num_qps;1458		count = ARRAY_SIZE(hinic_function_stats) +1459			(ARRAY_SIZE(hinic_tx_queue_stats) +1460			ARRAY_SIZE(hinic_rx_queue_stats)) * q_num;1461 1462		count += ARRAY_SIZE(hinic_port_stats);1463 1464		return count;1465	default:1466		return -EOPNOTSUPP;1467	}1468}1469 1470static void hinic_get_strings(struct net_device *netdev,1471			      u32 stringset, u8 *data)1472{1473	struct hinic_dev *nic_dev = netdev_priv(netdev);1474	u16 i, j;1475 1476	switch (stringset) {1477	case ETH_SS_TEST:1478		memcpy(data, *hinic_test_strings, sizeof(hinic_test_strings));1479		return;1480	case ETH_SS_STATS:1481		for (i = 0; i < ARRAY_SIZE(hinic_function_stats); i++)1482			ethtool_puts(&data, hinic_function_stats[i].name);1483 1484		for (i = 0; i < ARRAY_SIZE(hinic_port_stats); i++)1485			ethtool_puts(&data, hinic_port_stats[i].name);1486 1487		for (i = 0; i < nic_dev->num_qps; i++)1488			for (j = 0; j < ARRAY_SIZE(hinic_tx_queue_stats); j++)1489				ethtool_sprintf(&data, hinic_tx_queue_stats[j].name, i);1490 1491		for (i = 0; i < nic_dev->num_qps; i++)1492			for (j = 0; j < ARRAY_SIZE(hinic_rx_queue_stats); j++)1493				ethtool_sprintf(&data, hinic_rx_queue_stats[j].name, i);1494 1495		return;1496	default:1497		return;1498	}1499}1500 1501static int hinic_run_lp_test(struct hinic_dev *nic_dev, u32 test_time)1502{1503	u8 *lb_test_rx_buf = nic_dev->lb_test_rx_buf;1504	struct net_device *netdev = nic_dev->netdev;1505	struct sk_buff *skb_tmp = NULL;1506	struct sk_buff *skb = NULL;1507	u32 cnt = test_time * 5;1508	u8 *test_data = NULL;1509	u32 i;1510	u8 j;1511 1512	skb_tmp = alloc_skb(LP_PKT_LEN, GFP_ATOMIC);1513	if (!skb_tmp)1514		return -ENOMEM;1515 1516	test_data = __skb_put(skb_tmp, LP_PKT_LEN);1517 1518	memset(test_data, 0xFF, 2 * ETH_ALEN);1519	test_data[ETH_ALEN] = 0xFE;1520	test_data[2 * ETH_ALEN] = 0x08;1521	test_data[2 * ETH_ALEN + 1] = 0x0;1522 1523	for (i = ETH_HLEN; i < LP_PKT_LEN; i++)1524		test_data[i] = i & 0xFF;1525 1526	skb_tmp->queue_mapping = 0;1527	skb_tmp->ip_summed = CHECKSUM_COMPLETE;1528	skb_tmp->dev = netdev;1529 1530	for (i = 0; i < cnt; i++) {1531		nic_dev->lb_test_rx_idx = 0;1532		memset(lb_test_rx_buf, 0, LP_PKT_CNT * LP_PKT_LEN);1533 1534		for (j = 0; j < LP_PKT_CNT; j++) {1535			skb = pskb_copy(skb_tmp, GFP_ATOMIC);1536			if (!skb) {1537				dev_kfree_skb_any(skb_tmp);1538				netif_err(nic_dev, drv, netdev,1539					  "Copy skb failed for loopback test\n");1540				return -ENOMEM;1541			}1542 1543			/* mark index for every pkt */1544			skb->data[LP_PKT_LEN - 1] = j;1545 1546			if (hinic_lb_xmit_frame(skb, netdev)) {1547				dev_kfree_skb_any(skb);1548				dev_kfree_skb_any(skb_tmp);1549				netif_err(nic_dev, drv, netdev,1550					  "Xmit pkt failed for loopback test\n");1551				return -EBUSY;1552			}1553		}1554 1555		/* wait till all pkts received to RX buffer */1556		msleep(200);1557 1558		for (j = 0; j < LP_PKT_CNT; j++) {1559			if (memcmp(lb_test_rx_buf + j * LP_PKT_LEN,1560				   skb_tmp->data, LP_PKT_LEN - 1) ||1561			    (*(lb_test_rx_buf + j * LP_PKT_LEN +1562			     LP_PKT_LEN - 1) != j)) {1563				dev_kfree_skb_any(skb_tmp);1564				netif_err(nic_dev, drv, netdev,1565					  "Compare pkt failed in loopback test(index=0x%02x, data[%d]=0x%02x)\n",1566					  j + i * LP_PKT_CNT,1567					  LP_PKT_LEN - 1,1568					  *(lb_test_rx_buf + j * LP_PKT_LEN +1569					    LP_PKT_LEN - 1));1570				return -EIO;1571			}1572		}1573	}1574 1575	dev_kfree_skb_any(skb_tmp);1576	return 0;1577}1578 1579static int do_lp_test(struct hinic_dev *nic_dev, u32 flags, u32 test_time,1580		      enum diag_test_index *test_index)1581{1582	struct net_device *netdev = nic_dev->netdev;1583	u8 *lb_test_rx_buf = NULL;1584	int err = 0;1585 1586	if (!(flags & ETH_TEST_FL_EXTERNAL_LB)) {1587		*test_index = INTERNAL_LP_TEST;1588		if (hinic_set_loopback_mode(nic_dev->hwdev,1589					    HINIC_INTERNAL_LP_MODE, true)) {1590			netif_err(nic_dev, drv, netdev,1591				  "Failed to set port loopback mode before loopback test\n");1592			return -EIO;1593		}1594	} else {1595		*test_index = EXTERNAL_LP_TEST;1596	}1597 1598	lb_test_rx_buf = vmalloc(LP_PKT_CNT * LP_PKT_LEN);1599	if (!lb_test_rx_buf) {1600		err = -ENOMEM;1601	} else {1602		nic_dev->lb_test_rx_buf = lb_test_rx_buf;1603		nic_dev->lb_pkt_len = LP_PKT_LEN;1604		nic_dev->flags |= HINIC_LP_TEST;1605		err = hinic_run_lp_test(nic_dev, test_time);1606		nic_dev->flags &= ~HINIC_LP_TEST;1607		msleep(100);1608		vfree(lb_test_rx_buf);1609		nic_dev->lb_test_rx_buf = NULL;1610	}1611 1612	if (!(flags & ETH_TEST_FL_EXTERNAL_LB)) {1613		if (hinic_set_loopback_mode(nic_dev->hwdev,1614					    HINIC_INTERNAL_LP_MODE, false)) {1615			netif_err(nic_dev, drv, netdev,1616				  "Failed to cancel port loopback mode after loopback test\n");1617			err = -EIO;1618		}1619	}1620 1621	return err;1622}1623 1624static void hinic_diag_test(struct net_device *netdev,1625			    struct ethtool_test *eth_test, u64 *data)1626{1627	struct hinic_dev *nic_dev = netdev_priv(netdev);1628	enum hinic_port_link_state link_state;1629	enum diag_test_index test_index = 0;1630	int err = 0;1631 1632	memset(data, 0, DIAG_TEST_MAX * sizeof(u64));1633 1634	/* don't support loopback test when netdev is closed. */1635	if (!(nic_dev->flags & HINIC_INTF_UP)) {1636		netif_err(nic_dev, drv, netdev,1637			  "Do not support loopback test when netdev is closed\n");1638		eth_test->flags |= ETH_TEST_FL_FAILED;1639		data[PORT_DOWN_ERR_IDX] = 1;1640		return;1641	}1642 1643	netif_carrier_off(netdev);1644	netif_tx_disable(netdev);1645 1646	err = do_lp_test(nic_dev, eth_test->flags, LP_DEFAULT_TIME,1647			 &test_index);1648	if (err) {1649		eth_test->flags |= ETH_TEST_FL_FAILED;1650		data[test_index] = 1;1651	}1652 1653	netif_tx_wake_all_queues(netdev);1654 1655	err = hinic_port_link_state(nic_dev, &link_state);1656	if (!err && link_state == HINIC_LINK_STATE_UP)1657		netif_carrier_on(netdev);1658}1659 1660static int hinic_set_phys_id(struct net_device *netdev,1661			     enum ethtool_phys_id_state state)1662{1663	struct hinic_dev *nic_dev = netdev_priv(netdev);1664	int err = 0;1665	u8 port;1666 1667	port = nic_dev->hwdev->port_id;1668 1669	switch (state) {1670	case ETHTOOL_ID_ACTIVE:1671		err = hinic_set_led_status(nic_dev->hwdev, port,1672					   HINIC_LED_TYPE_LINK,1673					   HINIC_LED_MODE_FORCE_2HZ);1674		if (err)1675			netif_err(nic_dev, drv, netdev,1676				  "Set LED blinking in 2HZ failed\n");1677		break;1678 1679	case ETHTOOL_ID_INACTIVE:1680		err = hinic_reset_led_status(nic_dev->hwdev, port);1681		if (err)1682			netif_err(nic_dev, drv, netdev,1683				  "Reset LED to original status failed\n");1684		break;1685 1686	default:1687		return -EOPNOTSUPP;1688	}1689 1690	return err;1691}1692 1693static int hinic_get_module_info(struct net_device *netdev,1694				 struct ethtool_modinfo *modinfo)1695{1696	struct hinic_dev *nic_dev = netdev_priv(netdev);1697	u8 sfp_type_ext;1698	u8 sfp_type;1699	int err;1700 1701	err = hinic_get_sfp_type(nic_dev->hwdev, &sfp_type, &sfp_type_ext);1702	if (err)1703		return err;1704 1705	switch (sfp_type) {1706	case SFF8024_ID_SFP:1707		modinfo->type = ETH_MODULE_SFF_8472;1708		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;1709		break;1710	case SFF8024_ID_QSFP_8438:1711		modinfo->type = ETH_MODULE_SFF_8436;1712		modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;1713		break;1714	case SFF8024_ID_QSFP_8436_8636:1715		if (sfp_type_ext >= 0x3) {1716			modinfo->type = ETH_MODULE_SFF_8636;1717			modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;1718 1719		} else {1720			modinfo->type = ETH_MODULE_SFF_8436;1721			modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;1722		}1723		break;1724	case SFF8024_ID_QSFP28_8636:1725		modinfo->type = ETH_MODULE_SFF_8636;1726		modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;1727		break;1728	default:1729		netif_warn(nic_dev, drv, netdev,1730			   "Optical module unknown: 0x%x\n", sfp_type);1731		return -EINVAL;1732	}1733 1734	return 0;1735}1736 1737static int hinic_get_module_eeprom(struct net_device *netdev,1738				   struct ethtool_eeprom *ee, u8 *data)1739{1740	struct hinic_dev *nic_dev = netdev_priv(netdev);1741	u8 sfp_data[STD_SFP_INFO_MAX_SIZE];1742	u16 len;1743	int err;1744 1745	if (!ee->len || ((ee->len + ee->offset) > STD_SFP_INFO_MAX_SIZE))1746		return -EINVAL;1747 1748	memset(data, 0, ee->len);1749 1750	err = hinic_get_sfp_eeprom(nic_dev->hwdev, sfp_data, &len);1751	if (err)1752		return err;1753 1754	memcpy(data, sfp_data + ee->offset, ee->len);1755 1756	return 0;1757}1758 1759static int1760hinic_get_link_ext_state(struct net_device *netdev,1761			 struct ethtool_link_ext_state_info *link_ext_state_info)1762{1763	struct hinic_dev *nic_dev = netdev_priv(netdev);1764 1765	if (netif_carrier_ok(netdev))1766		return -ENODATA;1767 1768	if (nic_dev->cable_unplugged)1769		link_ext_state_info->link_ext_state =1770			ETHTOOL_LINK_EXT_STATE_NO_CABLE;1771	else if (nic_dev->module_unrecognized)1772		link_ext_state_info->link_ext_state =1773			ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH;1774 1775	return 0;1776}1777 1778static const struct ethtool_ops hinic_ethtool_ops = {1779	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |1780				     ETHTOOL_COALESCE_RX_MAX_FRAMES |1781				     ETHTOOL_COALESCE_TX_USECS |1782				     ETHTOOL_COALESCE_TX_MAX_FRAMES,1783 1784	.get_link_ksettings = hinic_get_link_ksettings,1785	.set_link_ksettings = hinic_set_link_ksettings,1786	.get_drvinfo = hinic_get_drvinfo,1787	.get_link = ethtool_op_get_link,1788	.get_link_ext_state = hinic_get_link_ext_state,1789	.get_ringparam = hinic_get_ringparam,1790	.set_ringparam = hinic_set_ringparam,1791	.get_coalesce = hinic_get_coalesce,1792	.set_coalesce = hinic_set_coalesce,1793	.get_per_queue_coalesce = hinic_get_per_queue_coalesce,1794	.set_per_queue_coalesce = hinic_set_per_queue_coalesce,1795	.get_pauseparam = hinic_get_pauseparam,1796	.set_pauseparam = hinic_set_pauseparam,1797	.get_channels = hinic_get_channels,1798	.set_channels = hinic_set_channels,1799	.get_rxnfc = hinic_get_rxnfc,1800	.set_rxnfc = hinic_set_rxnfc,1801	.get_rxfh_key_size = hinic_get_rxfh_key_size,1802	.get_rxfh_indir_size = hinic_get_rxfh_indir_size,1803	.get_rxfh = hinic_get_rxfh,1804	.set_rxfh = hinic_set_rxfh,1805	.get_sset_count = hinic_get_sset_count,1806	.get_ethtool_stats = hinic_get_ethtool_stats,1807	.get_strings = hinic_get_strings,1808	.self_test = hinic_diag_test,1809	.set_phys_id = hinic_set_phys_id,1810	.get_module_info = hinic_get_module_info,1811	.get_module_eeprom = hinic_get_module_eeprom,1812};1813 1814static const struct ethtool_ops hinicvf_ethtool_ops = {1815	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |1816				     ETHTOOL_COALESCE_RX_MAX_FRAMES |1817				     ETHTOOL_COALESCE_TX_USECS |1818				     ETHTOOL_COALESCE_TX_MAX_FRAMES,1819 1820	.get_link_ksettings = hinic_get_link_ksettings,1821	.get_drvinfo = hinic_get_drvinfo,1822	.get_link = ethtool_op_get_link,1823	.get_ringparam = hinic_get_ringparam,1824	.set_ringparam = hinic_set_ringparam,1825	.get_coalesce = hinic_get_coalesce,1826	.set_coalesce = hinic_set_coalesce,1827	.get_per_queue_coalesce = hinic_get_per_queue_coalesce,1828	.set_per_queue_coalesce = hinic_set_per_queue_coalesce,1829	.get_channels = hinic_get_channels,1830	.set_channels = hinic_set_channels,1831	.get_rxnfc = hinic_get_rxnfc,1832	.set_rxnfc = hinic_set_rxnfc,1833	.get_rxfh_key_size = hinic_get_rxfh_key_size,1834	.get_rxfh_indir_size = hinic_get_rxfh_indir_size,1835	.get_rxfh = hinic_get_rxfh,1836	.set_rxfh = hinic_set_rxfh,1837	.get_sset_count = hinic_get_sset_count,1838	.get_ethtool_stats = hinic_get_ethtool_stats,1839	.get_strings = hinic_get_strings,1840};1841 1842void hinic_set_ethtool_ops(struct net_device *netdev)1843{1844	struct hinic_dev *nic_dev = netdev_priv(netdev);1845 1846	if (!HINIC_IS_VF(nic_dev->hwdev->hwif))1847		netdev->ethtool_ops = &hinic_ethtool_ops;1848	else1849		netdev->ethtool_ops = &hinicvf_ethtool_ops;1850}1851