brintos

brintos / linux-shallow public Read only

0
0
Text · 54.2 KiB · 74a1e9f Raw
1847 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright(c) 2013 - 2018 Intel Corporation. */3 4#include <linux/bitfield.h>5#include <linux/uaccess.h>6 7/* ethtool support for iavf */8#include "iavf.h"9 10/* ethtool statistics helpers */11 12/**13 * struct iavf_stats - definition for an ethtool statistic14 * @stat_string: statistic name to display in ethtool -S output15 * @sizeof_stat: the sizeof() the stat, must be no greater than sizeof(u64)16 * @stat_offset: offsetof() the stat from a base pointer17 *18 * This structure defines a statistic to be added to the ethtool stats buffer.19 * It defines a statistic as offset from a common base pointer. Stats should20 * be defined in constant arrays using the IAVF_STAT macro, with every element21 * of the array using the same _type for calculating the sizeof_stat and22 * stat_offset.23 *24 * The @sizeof_stat is expected to be sizeof(u8), sizeof(u16), sizeof(u32) or25 * sizeof(u64). Other sizes are not expected and will produce a WARN_ONCE from26 * the iavf_add_ethtool_stat() helper function.27 *28 * The @stat_string is interpreted as a format string, allowing formatted29 * values to be inserted while looping over multiple structures for a given30 * statistics array. Thus, every statistic string in an array should have the31 * same type and number of format specifiers, to be formatted by variadic32 * arguments to the iavf_add_stat_string() helper function.33 **/34struct iavf_stats {35	char stat_string[ETH_GSTRING_LEN];36	int sizeof_stat;37	int stat_offset;38};39 40/* Helper macro to define an iavf_stat structure with proper size and type.41 * Use this when defining constant statistics arrays. Note that @_type expects42 * only a type name and is used multiple times.43 */44#define IAVF_STAT(_type, _name, _stat) { \45	.stat_string = _name, \46	.sizeof_stat = sizeof_field(_type, _stat), \47	.stat_offset = offsetof(_type, _stat) \48}49 50/* Helper macro for defining some statistics related to queues */51#define IAVF_QUEUE_STAT(_name, _stat) \52	IAVF_STAT(struct iavf_ring, _name, _stat)53 54/* Stats associated with a Tx or Rx ring */55static const struct iavf_stats iavf_gstrings_queue_stats[] = {56	IAVF_QUEUE_STAT("%s-%u.packets", stats.packets),57	IAVF_QUEUE_STAT("%s-%u.bytes", stats.bytes),58};59 60/**61 * iavf_add_one_ethtool_stat - copy the stat into the supplied buffer62 * @data: location to store the stat value63 * @pointer: basis for where to copy from64 * @stat: the stat definition65 *66 * Copies the stat data defined by the pointer and stat structure pair into67 * the memory supplied as data. Used to implement iavf_add_ethtool_stats and68 * iavf_add_queue_stats. If the pointer is null, data will be zero'd.69 */70static void71iavf_add_one_ethtool_stat(u64 *data, void *pointer,72			  const struct iavf_stats *stat)73{74	char *p;75 76	if (!pointer) {77		/* ensure that the ethtool data buffer is zero'd for any stats78		 * which don't have a valid pointer.79		 */80		*data = 0;81		return;82	}83 84	p = (char *)pointer + stat->stat_offset;85	switch (stat->sizeof_stat) {86	case sizeof(u64):87		*data = *((u64 *)p);88		break;89	case sizeof(u32):90		*data = *((u32 *)p);91		break;92	case sizeof(u16):93		*data = *((u16 *)p);94		break;95	case sizeof(u8):96		*data = *((u8 *)p);97		break;98	default:99		WARN_ONCE(1, "unexpected stat size for %s",100			  stat->stat_string);101		*data = 0;102	}103}104 105/**106 * __iavf_add_ethtool_stats - copy stats into the ethtool supplied buffer107 * @data: ethtool stats buffer108 * @pointer: location to copy stats from109 * @stats: array of stats to copy110 * @size: the size of the stats definition111 *112 * Copy the stats defined by the stats array using the pointer as a base into113 * the data buffer supplied by ethtool. Updates the data pointer to point to114 * the next empty location for successive calls to __iavf_add_ethtool_stats.115 * If pointer is null, set the data values to zero and update the pointer to116 * skip these stats.117 **/118static void119__iavf_add_ethtool_stats(u64 **data, void *pointer,120			 const struct iavf_stats stats[],121			 const unsigned int size)122{123	unsigned int i;124 125	for (i = 0; i < size; i++)126		iavf_add_one_ethtool_stat((*data)++, pointer, &stats[i]);127}128 129/**130 * iavf_add_ethtool_stats - copy stats into ethtool supplied buffer131 * @data: ethtool stats buffer132 * @pointer: location where stats are stored133 * @stats: static const array of stat definitions134 *135 * Macro to ease the use of __iavf_add_ethtool_stats by taking a static136 * constant stats array and passing the ARRAY_SIZE(). This avoids typos by137 * ensuring that we pass the size associated with the given stats array.138 *139 * The parameter @stats is evaluated twice, so parameters with side effects140 * should be avoided.141 **/142#define iavf_add_ethtool_stats(data, pointer, stats) \143	__iavf_add_ethtool_stats(data, pointer, stats, ARRAY_SIZE(stats))144 145/**146 * iavf_add_queue_stats - copy queue statistics into supplied buffer147 * @data: ethtool stats buffer148 * @ring: the ring to copy149 *150 * Queue statistics must be copied while protected by151 * u64_stats_fetch_begin, so we can't directly use iavf_add_ethtool_stats.152 * Assumes that queue stats are defined in iavf_gstrings_queue_stats. If the153 * ring pointer is null, zero out the queue stat values and update the data154 * pointer. Otherwise safely copy the stats from the ring into the supplied155 * buffer and update the data pointer when finished.156 *157 * This function expects to be called while under rcu_read_lock().158 **/159static void160iavf_add_queue_stats(u64 **data, struct iavf_ring *ring)161{162	const unsigned int size = ARRAY_SIZE(iavf_gstrings_queue_stats);163	const struct iavf_stats *stats = iavf_gstrings_queue_stats;164	unsigned int start;165	unsigned int i;166 167	/* To avoid invalid statistics values, ensure that we keep retrying168	 * the copy until we get a consistent value according to169	 * u64_stats_fetch_retry. But first, make sure our ring is170	 * non-null before attempting to access its syncp.171	 */172	do {173		start = !ring ? 0 : u64_stats_fetch_begin(&ring->syncp);174		for (i = 0; i < size; i++)175			iavf_add_one_ethtool_stat(&(*data)[i], ring, &stats[i]);176	} while (ring && u64_stats_fetch_retry(&ring->syncp, start));177 178	/* Once we successfully copy the stats in, update the data pointer */179	*data += size;180}181 182/**183 * __iavf_add_stat_strings - copy stat strings into ethtool buffer184 * @p: ethtool supplied buffer185 * @stats: stat definitions array186 * @size: size of the stats array187 *188 * Format and copy the strings described by stats into the buffer pointed at189 * by p.190 **/191static void __iavf_add_stat_strings(u8 **p, const struct iavf_stats stats[],192				    const unsigned int size, ...)193{194	unsigned int i;195 196	for (i = 0; i < size; i++) {197		va_list args;198 199		va_start(args, size);200		vsnprintf(*p, ETH_GSTRING_LEN, stats[i].stat_string, args);201		*p += ETH_GSTRING_LEN;202		va_end(args);203	}204}205 206/**207 * iavf_add_stat_strings - copy stat strings into ethtool buffer208 * @p: ethtool supplied buffer209 * @stats: stat definitions array210 *211 * Format and copy the strings described by the const static stats value into212 * the buffer pointed at by p.213 *214 * The parameter @stats is evaluated twice, so parameters with side effects215 * should be avoided. Additionally, stats must be an array such that216 * ARRAY_SIZE can be called on it.217 **/218#define iavf_add_stat_strings(p, stats, ...) \219	__iavf_add_stat_strings(p, stats, ARRAY_SIZE(stats), ## __VA_ARGS__)220 221#define VF_STAT(_name, _stat) \222	IAVF_STAT(struct iavf_adapter, _name, _stat)223 224static const struct iavf_stats iavf_gstrings_stats[] = {225	VF_STAT("rx_bytes", current_stats.rx_bytes),226	VF_STAT("rx_unicast", current_stats.rx_unicast),227	VF_STAT("rx_multicast", current_stats.rx_multicast),228	VF_STAT("rx_broadcast", current_stats.rx_broadcast),229	VF_STAT("rx_discards", current_stats.rx_discards),230	VF_STAT("rx_unknown_protocol", current_stats.rx_unknown_protocol),231	VF_STAT("tx_bytes", current_stats.tx_bytes),232	VF_STAT("tx_unicast", current_stats.tx_unicast),233	VF_STAT("tx_multicast", current_stats.tx_multicast),234	VF_STAT("tx_broadcast", current_stats.tx_broadcast),235	VF_STAT("tx_discards", current_stats.tx_discards),236	VF_STAT("tx_errors", current_stats.tx_errors),237};238 239#define IAVF_STATS_LEN	ARRAY_SIZE(iavf_gstrings_stats)240 241#define IAVF_QUEUE_STATS_LEN	ARRAY_SIZE(iavf_gstrings_queue_stats)242 243/**244 * iavf_get_link_ksettings - Get Link Speed and Duplex settings245 * @netdev: network interface device structure246 * @cmd: ethtool command247 *248 * Reports speed/duplex settings. Because this is a VF, we don't know what249 * kind of link we really have, so we fake it.250 **/251static int iavf_get_link_ksettings(struct net_device *netdev,252				   struct ethtool_link_ksettings *cmd)253{254	struct iavf_adapter *adapter = netdev_priv(netdev);255 256	ethtool_link_ksettings_zero_link_mode(cmd, supported);257	cmd->base.autoneg = AUTONEG_DISABLE;258	cmd->base.port = PORT_NONE;259	cmd->base.duplex = DUPLEX_FULL;260 261	if (ADV_LINK_SUPPORT(adapter)) {262		if (adapter->link_speed_mbps &&263		    adapter->link_speed_mbps < U32_MAX)264			cmd->base.speed = adapter->link_speed_mbps;265		else266			cmd->base.speed = SPEED_UNKNOWN;267 268		return 0;269	}270 271	switch (adapter->link_speed) {272	case VIRTCHNL_LINK_SPEED_40GB:273		cmd->base.speed = SPEED_40000;274		break;275	case VIRTCHNL_LINK_SPEED_25GB:276		cmd->base.speed = SPEED_25000;277		break;278	case VIRTCHNL_LINK_SPEED_20GB:279		cmd->base.speed = SPEED_20000;280		break;281	case VIRTCHNL_LINK_SPEED_10GB:282		cmd->base.speed = SPEED_10000;283		break;284	case VIRTCHNL_LINK_SPEED_5GB:285		cmd->base.speed = SPEED_5000;286		break;287	case VIRTCHNL_LINK_SPEED_2_5GB:288		cmd->base.speed = SPEED_2500;289		break;290	case VIRTCHNL_LINK_SPEED_1GB:291		cmd->base.speed = SPEED_1000;292		break;293	case VIRTCHNL_LINK_SPEED_100MB:294		cmd->base.speed = SPEED_100;295		break;296	default:297		break;298	}299 300	return 0;301}302 303/**304 * iavf_get_sset_count - Get length of string set305 * @netdev: network interface device structure306 * @sset: id of string set307 *308 * Reports size of various string tables.309 **/310static int iavf_get_sset_count(struct net_device *netdev, int sset)311{312	/* Report the maximum number queues, even if not every queue is313	 * currently configured. Since allocation of queues is in pairs,314	 * use netdev->real_num_tx_queues * 2. The real_num_tx_queues is set315	 * at device creation and never changes.316	 */317 318	if (sset == ETH_SS_STATS)319		return IAVF_STATS_LEN +320			(IAVF_QUEUE_STATS_LEN * 2 *321			 netdev->real_num_tx_queues);322	else323		return -EINVAL;324}325 326/**327 * iavf_get_ethtool_stats - report device statistics328 * @netdev: network interface device structure329 * @stats: ethtool statistics structure330 * @data: pointer to data buffer331 *332 * All statistics are added to the data buffer as an array of u64.333 **/334static void iavf_get_ethtool_stats(struct net_device *netdev,335				   struct ethtool_stats *stats, u64 *data)336{337	struct iavf_adapter *adapter = netdev_priv(netdev);338	unsigned int i;339 340	/* Explicitly request stats refresh */341	iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_REQUEST_STATS);342 343	iavf_add_ethtool_stats(&data, adapter, iavf_gstrings_stats);344 345	rcu_read_lock();346	/* As num_active_queues describe both tx and rx queues, we can use347	 * it to iterate over rings' stats.348	 */349	for (i = 0; i < adapter->num_active_queues; i++) {350		struct iavf_ring *ring;351 352		/* Tx rings stats */353		ring = &adapter->tx_rings[i];354		iavf_add_queue_stats(&data, ring);355 356		/* Rx rings stats */357		ring = &adapter->rx_rings[i];358		iavf_add_queue_stats(&data, ring);359	}360	rcu_read_unlock();361}362 363/**364 * iavf_get_stat_strings - Get stat strings365 * @netdev: network interface device structure366 * @data: buffer for string data367 *368 * Builds the statistics string table369 **/370static void iavf_get_stat_strings(struct net_device *netdev, u8 *data)371{372	unsigned int i;373 374	iavf_add_stat_strings(&data, iavf_gstrings_stats);375 376	/* Queues are always allocated in pairs, so we just use377	 * real_num_tx_queues for both Tx and Rx queues.378	 */379	for (i = 0; i < netdev->real_num_tx_queues; i++) {380		iavf_add_stat_strings(&data, iavf_gstrings_queue_stats,381				      "tx", i);382		iavf_add_stat_strings(&data, iavf_gstrings_queue_stats,383				      "rx", i);384	}385}386 387/**388 * iavf_get_strings - Get string set389 * @netdev: network interface device structure390 * @sset: id of string set391 * @data: buffer for string data392 *393 * Builds string tables for various string sets394 **/395static void iavf_get_strings(struct net_device *netdev, u32 sset, u8 *data)396{397	switch (sset) {398	case ETH_SS_STATS:399		iavf_get_stat_strings(netdev, data);400		break;401	default:402		break;403	}404}405 406/**407 * iavf_get_msglevel - Get debug message level408 * @netdev: network interface device structure409 *410 * Returns current debug message level.411 **/412static u32 iavf_get_msglevel(struct net_device *netdev)413{414	struct iavf_adapter *adapter = netdev_priv(netdev);415 416	return adapter->msg_enable;417}418 419/**420 * iavf_set_msglevel - Set debug message level421 * @netdev: network interface device structure422 * @data: message level423 *424 * Set current debug message level. Higher values cause the driver to425 * be noisier.426 **/427static void iavf_set_msglevel(struct net_device *netdev, u32 data)428{429	struct iavf_adapter *adapter = netdev_priv(netdev);430 431	if (IAVF_DEBUG_USER & data)432		adapter->hw.debug_mask = data;433	adapter->msg_enable = data;434}435 436/**437 * iavf_get_drvinfo - Get driver info438 * @netdev: network interface device structure439 * @drvinfo: ethool driver info structure440 *441 * Returns information about the driver and device for display to the user.442 **/443static void iavf_get_drvinfo(struct net_device *netdev,444			     struct ethtool_drvinfo *drvinfo)445{446	struct iavf_adapter *adapter = netdev_priv(netdev);447 448	strscpy(drvinfo->driver, iavf_driver_name, 32);449	strscpy(drvinfo->fw_version, "N/A", 4);450	strscpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);451}452 453/**454 * iavf_get_ringparam - Get ring parameters455 * @netdev: network interface device structure456 * @ring: ethtool ringparam structure457 * @kernel_ring: ethtool extenal ringparam structure458 * @extack: netlink extended ACK report struct459 *460 * Returns current ring parameters. TX and RX rings are reported separately,461 * but the number of rings is not reported.462 **/463static void iavf_get_ringparam(struct net_device *netdev,464			       struct ethtool_ringparam *ring,465			       struct kernel_ethtool_ringparam *kernel_ring,466			       struct netlink_ext_ack *extack)467{468	struct iavf_adapter *adapter = netdev_priv(netdev);469 470	ring->rx_max_pending = IAVF_MAX_RXD;471	ring->tx_max_pending = IAVF_MAX_TXD;472	ring->rx_pending = adapter->rx_desc_count;473	ring->tx_pending = adapter->tx_desc_count;474}475 476/**477 * iavf_set_ringparam - Set ring parameters478 * @netdev: network interface device structure479 * @ring: ethtool ringparam structure480 * @kernel_ring: ethtool external ringparam structure481 * @extack: netlink extended ACK report struct482 *483 * Sets ring parameters. TX and RX rings are controlled separately, but the484 * number of rings is not specified, so all rings get the same settings.485 **/486static int iavf_set_ringparam(struct net_device *netdev,487			      struct ethtool_ringparam *ring,488			      struct kernel_ethtool_ringparam *kernel_ring,489			      struct netlink_ext_ack *extack)490{491	struct iavf_adapter *adapter = netdev_priv(netdev);492	u32 new_rx_count, new_tx_count;493	int ret = 0;494 495	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))496		return -EINVAL;497 498	if (ring->tx_pending > IAVF_MAX_TXD ||499	    ring->tx_pending < IAVF_MIN_TXD ||500	    ring->rx_pending > IAVF_MAX_RXD ||501	    ring->rx_pending < IAVF_MIN_RXD) {502		netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n",503			   ring->tx_pending, ring->rx_pending, IAVF_MIN_TXD,504			   IAVF_MAX_RXD, IAVF_REQ_DESCRIPTOR_MULTIPLE);505		return -EINVAL;506	}507 508	new_tx_count = ALIGN(ring->tx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE);509	if (new_tx_count != ring->tx_pending)510		netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n",511			    new_tx_count);512 513	new_rx_count = ALIGN(ring->rx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE);514	if (new_rx_count != ring->rx_pending)515		netdev_info(netdev, "Requested Rx descriptor count rounded up to %d\n",516			    new_rx_count);517 518	/* if nothing to do return success */519	if ((new_tx_count == adapter->tx_desc_count) &&520	    (new_rx_count == adapter->rx_desc_count)) {521		netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n");522		return 0;523	}524 525	if (new_tx_count != adapter->tx_desc_count) {526		netdev_dbg(netdev, "Changing Tx descriptor count from %d to %d\n",527			   adapter->tx_desc_count, new_tx_count);528		adapter->tx_desc_count = new_tx_count;529	}530 531	if (new_rx_count != adapter->rx_desc_count) {532		netdev_dbg(netdev, "Changing Rx descriptor count from %d to %d\n",533			   adapter->rx_desc_count, new_rx_count);534		adapter->rx_desc_count = new_rx_count;535	}536 537	if (netif_running(netdev)) {538		iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);539		ret = iavf_wait_for_reset(adapter);540		if (ret)541			netdev_warn(netdev, "Changing ring parameters timeout or interrupted waiting for reset");542	}543 544	return ret;545}546 547/**548 * __iavf_get_coalesce - get per-queue coalesce settings549 * @netdev: the netdev to check550 * @ec: ethtool coalesce data structure551 * @queue: which queue to pick552 *553 * Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs554 * are per queue. If queue is <0 then we default to queue 0 as the555 * representative value.556 **/557static int __iavf_get_coalesce(struct net_device *netdev,558			       struct ethtool_coalesce *ec, int queue)559{560	struct iavf_adapter *adapter = netdev_priv(netdev);561	struct iavf_ring *rx_ring, *tx_ring;562 563	/* Rx and Tx usecs per queue value. If user doesn't specify the564	 * queue, return queue 0's value to represent.565	 */566	if (queue < 0)567		queue = 0;568	else if (queue >= adapter->num_active_queues)569		return -EINVAL;570 571	rx_ring = &adapter->rx_rings[queue];572	tx_ring = &adapter->tx_rings[queue];573 574	if (ITR_IS_DYNAMIC(rx_ring->itr_setting))575		ec->use_adaptive_rx_coalesce = 1;576 577	if (ITR_IS_DYNAMIC(tx_ring->itr_setting))578		ec->use_adaptive_tx_coalesce = 1;579 580	ec->rx_coalesce_usecs = rx_ring->itr_setting & ~IAVF_ITR_DYNAMIC;581	ec->tx_coalesce_usecs = tx_ring->itr_setting & ~IAVF_ITR_DYNAMIC;582 583	return 0;584}585 586/**587 * iavf_get_coalesce - Get interrupt coalescing settings588 * @netdev: network interface device structure589 * @ec: ethtool coalesce structure590 * @kernel_coal: ethtool CQE mode setting structure591 * @extack: extack for reporting error messages592 *593 * Returns current coalescing settings. This is referred to elsewhere in the594 * driver as Interrupt Throttle Rate, as this is how the hardware describes595 * this functionality. Note that if per-queue settings have been modified this596 * only represents the settings of queue 0.597 **/598static int iavf_get_coalesce(struct net_device *netdev,599			     struct ethtool_coalesce *ec,600			     struct kernel_ethtool_coalesce *kernel_coal,601			     struct netlink_ext_ack *extack)602{603	return __iavf_get_coalesce(netdev, ec, -1);604}605 606/**607 * iavf_get_per_queue_coalesce - get coalesce values for specific queue608 * @netdev: netdev to read609 * @ec: coalesce settings from ethtool610 * @queue: the queue to read611 *612 * Read specific queue's coalesce settings.613 **/614static int iavf_get_per_queue_coalesce(struct net_device *netdev, u32 queue,615				       struct ethtool_coalesce *ec)616{617	return __iavf_get_coalesce(netdev, ec, queue);618}619 620/**621 * iavf_set_itr_per_queue - set ITR values for specific queue622 * @adapter: the VF adapter struct to set values for623 * @ec: coalesce settings from ethtool624 * @queue: the queue to modify625 *626 * Change the ITR settings for a specific queue.627 **/628static int iavf_set_itr_per_queue(struct iavf_adapter *adapter,629				  struct ethtool_coalesce *ec, int queue)630{631	struct iavf_ring *rx_ring = &adapter->rx_rings[queue];632	struct iavf_ring *tx_ring = &adapter->tx_rings[queue];633	struct iavf_q_vector *q_vector;634	u16 itr_setting;635 636	itr_setting = rx_ring->itr_setting & ~IAVF_ITR_DYNAMIC;637 638	if (ec->rx_coalesce_usecs != itr_setting &&639	    ec->use_adaptive_rx_coalesce) {640		netif_info(adapter, drv, adapter->netdev,641			   "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n");642		return -EINVAL;643	}644 645	itr_setting = tx_ring->itr_setting & ~IAVF_ITR_DYNAMIC;646 647	if (ec->tx_coalesce_usecs != itr_setting &&648	    ec->use_adaptive_tx_coalesce) {649		netif_info(adapter, drv, adapter->netdev,650			   "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n");651		return -EINVAL;652	}653 654	rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs);655	tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs);656 657	rx_ring->itr_setting |= IAVF_ITR_DYNAMIC;658	if (!ec->use_adaptive_rx_coalesce)659		rx_ring->itr_setting ^= IAVF_ITR_DYNAMIC;660 661	tx_ring->itr_setting |= IAVF_ITR_DYNAMIC;662	if (!ec->use_adaptive_tx_coalesce)663		tx_ring->itr_setting ^= IAVF_ITR_DYNAMIC;664 665	q_vector = rx_ring->q_vector;666	q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);667 668	q_vector = tx_ring->q_vector;669	q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);670 671	/* The interrupt handler itself will take care of programming672	 * the Tx and Rx ITR values based on the values we have entered673	 * into the q_vector, no need to write the values now.674	 */675	return 0;676}677 678/**679 * __iavf_set_coalesce - set coalesce settings for particular queue680 * @netdev: the netdev to change681 * @ec: ethtool coalesce settings682 * @queue: the queue to change683 *684 * Sets the coalesce settings for a particular queue.685 **/686static int __iavf_set_coalesce(struct net_device *netdev,687			       struct ethtool_coalesce *ec, int queue)688{689	struct iavf_adapter *adapter = netdev_priv(netdev);690	int i;691 692	if (ec->rx_coalesce_usecs > IAVF_MAX_ITR) {693		netif_info(adapter, drv, netdev, "Invalid value, rx-usecs range is 0-8160\n");694		return -EINVAL;695	} else if (ec->tx_coalesce_usecs > IAVF_MAX_ITR) {696		netif_info(adapter, drv, netdev, "Invalid value, tx-usecs range is 0-8160\n");697		return -EINVAL;698	}699 700	/* Rx and Tx usecs has per queue value. If user doesn't specify the701	 * queue, apply to all queues.702	 */703	if (queue < 0) {704		for (i = 0; i < adapter->num_active_queues; i++)705			if (iavf_set_itr_per_queue(adapter, ec, i))706				return -EINVAL;707	} else if (queue < adapter->num_active_queues) {708		if (iavf_set_itr_per_queue(adapter, ec, queue))709			return -EINVAL;710	} else {711		netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",712			   adapter->num_active_queues - 1);713		return -EINVAL;714	}715 716	return 0;717}718 719/**720 * iavf_set_coalesce - Set interrupt coalescing settings721 * @netdev: network interface device structure722 * @ec: ethtool coalesce structure723 * @kernel_coal: ethtool CQE mode setting structure724 * @extack: extack for reporting error messages725 *726 * Change current coalescing settings for every queue.727 **/728static int iavf_set_coalesce(struct net_device *netdev,729			     struct ethtool_coalesce *ec,730			     struct kernel_ethtool_coalesce *kernel_coal,731			     struct netlink_ext_ack *extack)732{733	return __iavf_set_coalesce(netdev, ec, -1);734}735 736/**737 * iavf_set_per_queue_coalesce - set specific queue's coalesce settings738 * @netdev: the netdev to change739 * @ec: ethtool's coalesce settings740 * @queue: the queue to modify741 *742 * Modifies a specific queue's coalesce settings.743 */744static int iavf_set_per_queue_coalesce(struct net_device *netdev, u32 queue,745				       struct ethtool_coalesce *ec)746{747	return __iavf_set_coalesce(netdev, ec, queue);748}749 750/**751 * iavf_fltr_to_ethtool_flow - convert filter type values to ethtool752 * flow type values753 * @flow: filter type to be converted754 *755 * Returns the corresponding ethtool flow type.756 */757static int iavf_fltr_to_ethtool_flow(enum iavf_fdir_flow_type flow)758{759	switch (flow) {760	case IAVF_FDIR_FLOW_IPV4_TCP:761		return TCP_V4_FLOW;762	case IAVF_FDIR_FLOW_IPV4_UDP:763		return UDP_V4_FLOW;764	case IAVF_FDIR_FLOW_IPV4_SCTP:765		return SCTP_V4_FLOW;766	case IAVF_FDIR_FLOW_IPV4_AH:767		return AH_V4_FLOW;768	case IAVF_FDIR_FLOW_IPV4_ESP:769		return ESP_V4_FLOW;770	case IAVF_FDIR_FLOW_IPV4_OTHER:771		return IPV4_USER_FLOW;772	case IAVF_FDIR_FLOW_IPV6_TCP:773		return TCP_V6_FLOW;774	case IAVF_FDIR_FLOW_IPV6_UDP:775		return UDP_V6_FLOW;776	case IAVF_FDIR_FLOW_IPV6_SCTP:777		return SCTP_V6_FLOW;778	case IAVF_FDIR_FLOW_IPV6_AH:779		return AH_V6_FLOW;780	case IAVF_FDIR_FLOW_IPV6_ESP:781		return ESP_V6_FLOW;782	case IAVF_FDIR_FLOW_IPV6_OTHER:783		return IPV6_USER_FLOW;784	case IAVF_FDIR_FLOW_NON_IP_L2:785		return ETHER_FLOW;786	default:787		/* 0 is undefined ethtool flow */788		return 0;789	}790}791 792/**793 * iavf_ethtool_flow_to_fltr - convert ethtool flow type to filter enum794 * @eth: Ethtool flow type to be converted795 *796 * Returns flow enum797 */798static enum iavf_fdir_flow_type iavf_ethtool_flow_to_fltr(int eth)799{800	switch (eth) {801	case TCP_V4_FLOW:802		return IAVF_FDIR_FLOW_IPV4_TCP;803	case UDP_V4_FLOW:804		return IAVF_FDIR_FLOW_IPV4_UDP;805	case SCTP_V4_FLOW:806		return IAVF_FDIR_FLOW_IPV4_SCTP;807	case AH_V4_FLOW:808		return IAVF_FDIR_FLOW_IPV4_AH;809	case ESP_V4_FLOW:810		return IAVF_FDIR_FLOW_IPV4_ESP;811	case IPV4_USER_FLOW:812		return IAVF_FDIR_FLOW_IPV4_OTHER;813	case TCP_V6_FLOW:814		return IAVF_FDIR_FLOW_IPV6_TCP;815	case UDP_V6_FLOW:816		return IAVF_FDIR_FLOW_IPV6_UDP;817	case SCTP_V6_FLOW:818		return IAVF_FDIR_FLOW_IPV6_SCTP;819	case AH_V6_FLOW:820		return IAVF_FDIR_FLOW_IPV6_AH;821	case ESP_V6_FLOW:822		return IAVF_FDIR_FLOW_IPV6_ESP;823	case IPV6_USER_FLOW:824		return IAVF_FDIR_FLOW_IPV6_OTHER;825	case ETHER_FLOW:826		return IAVF_FDIR_FLOW_NON_IP_L2;827	default:828		return IAVF_FDIR_FLOW_NONE;829	}830}831 832/**833 * iavf_is_mask_valid - check mask field set834 * @mask: full mask to check835 * @field: field for which mask should be valid836 *837 * If the mask is fully set return true. If it is not valid for field return838 * false.839 */840static bool iavf_is_mask_valid(u64 mask, u64 field)841{842	return (mask & field) == field;843}844 845/**846 * iavf_parse_rx_flow_user_data - deconstruct user-defined data847 * @fsp: pointer to ethtool Rx flow specification848 * @fltr: pointer to Flow Director filter for userdef data storage849 *850 * Returns 0 on success, negative error value on failure851 */852static int853iavf_parse_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp,854			     struct iavf_fdir_fltr *fltr)855{856	struct iavf_flex_word *flex;857	int i, cnt = 0;858 859	if (!(fsp->flow_type & FLOW_EXT))860		return 0;861 862	for (i = 0; i < IAVF_FLEX_WORD_NUM; i++) {863#define IAVF_USERDEF_FLEX_WORD_M	GENMASK(15, 0)864#define IAVF_USERDEF_FLEX_OFFS_S	16865#define IAVF_USERDEF_FLEX_OFFS_M	GENMASK(31, IAVF_USERDEF_FLEX_OFFS_S)866#define IAVF_USERDEF_FLEX_FLTR_M	GENMASK(31, 0)867		u32 value = be32_to_cpu(fsp->h_ext.data[i]);868		u32 mask = be32_to_cpu(fsp->m_ext.data[i]);869 870		if (!value || !mask)871			continue;872 873		if (!iavf_is_mask_valid(mask, IAVF_USERDEF_FLEX_FLTR_M))874			return -EINVAL;875 876		/* 504 is the maximum value for offsets, and offset is measured877		 * from the start of the MAC address.878		 */879#define IAVF_USERDEF_FLEX_MAX_OFFS_VAL 504880		flex = &fltr->flex_words[cnt++];881		flex->word = value & IAVF_USERDEF_FLEX_WORD_M;882		flex->offset = FIELD_GET(IAVF_USERDEF_FLEX_OFFS_M, value);883		if (flex->offset > IAVF_USERDEF_FLEX_MAX_OFFS_VAL)884			return -EINVAL;885	}886 887	fltr->flex_cnt = cnt;888 889	return 0;890}891 892/**893 * iavf_fill_rx_flow_ext_data - fill the additional data894 * @fsp: pointer to ethtool Rx flow specification895 * @fltr: pointer to Flow Director filter to get additional data896 */897static void898iavf_fill_rx_flow_ext_data(struct ethtool_rx_flow_spec *fsp,899			   struct iavf_fdir_fltr *fltr)900{901	if (!fltr->ext_mask.usr_def[0] && !fltr->ext_mask.usr_def[1])902		return;903 904	fsp->flow_type |= FLOW_EXT;905 906	memcpy(fsp->h_ext.data, fltr->ext_data.usr_def, sizeof(fsp->h_ext.data));907	memcpy(fsp->m_ext.data, fltr->ext_mask.usr_def, sizeof(fsp->m_ext.data));908}909 910/**911 * iavf_get_ethtool_fdir_entry - fill ethtool structure with Flow Director filter data912 * @adapter: the VF adapter structure that contains filter list913 * @cmd: ethtool command data structure to receive the filter data914 *915 * Returns 0 as expected for success by ethtool916 */917static int918iavf_get_ethtool_fdir_entry(struct iavf_adapter *adapter,919			    struct ethtool_rxnfc *cmd)920{921	struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;922	struct iavf_fdir_fltr *rule = NULL;923	int ret = 0;924 925	if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))926		return -EOPNOTSUPP;927 928	spin_lock_bh(&adapter->fdir_fltr_lock);929 930	rule = iavf_find_fdir_fltr(adapter, false, fsp->location);931	if (!rule) {932		ret = -EINVAL;933		goto release_lock;934	}935 936	fsp->flow_type = iavf_fltr_to_ethtool_flow(rule->flow_type);937 938	memset(&fsp->m_u, 0, sizeof(fsp->m_u));939	memset(&fsp->m_ext, 0, sizeof(fsp->m_ext));940 941	switch (fsp->flow_type) {942	case TCP_V4_FLOW:943	case UDP_V4_FLOW:944	case SCTP_V4_FLOW:945		fsp->h_u.tcp_ip4_spec.ip4src = rule->ip_data.v4_addrs.src_ip;946		fsp->h_u.tcp_ip4_spec.ip4dst = rule->ip_data.v4_addrs.dst_ip;947		fsp->h_u.tcp_ip4_spec.psrc = rule->ip_data.src_port;948		fsp->h_u.tcp_ip4_spec.pdst = rule->ip_data.dst_port;949		fsp->h_u.tcp_ip4_spec.tos = rule->ip_data.tos;950		fsp->m_u.tcp_ip4_spec.ip4src = rule->ip_mask.v4_addrs.src_ip;951		fsp->m_u.tcp_ip4_spec.ip4dst = rule->ip_mask.v4_addrs.dst_ip;952		fsp->m_u.tcp_ip4_spec.psrc = rule->ip_mask.src_port;953		fsp->m_u.tcp_ip4_spec.pdst = rule->ip_mask.dst_port;954		fsp->m_u.tcp_ip4_spec.tos = rule->ip_mask.tos;955		break;956	case AH_V4_FLOW:957	case ESP_V4_FLOW:958		fsp->h_u.ah_ip4_spec.ip4src = rule->ip_data.v4_addrs.src_ip;959		fsp->h_u.ah_ip4_spec.ip4dst = rule->ip_data.v4_addrs.dst_ip;960		fsp->h_u.ah_ip4_spec.spi = rule->ip_data.spi;961		fsp->h_u.ah_ip4_spec.tos = rule->ip_data.tos;962		fsp->m_u.ah_ip4_spec.ip4src = rule->ip_mask.v4_addrs.src_ip;963		fsp->m_u.ah_ip4_spec.ip4dst = rule->ip_mask.v4_addrs.dst_ip;964		fsp->m_u.ah_ip4_spec.spi = rule->ip_mask.spi;965		fsp->m_u.ah_ip4_spec.tos = rule->ip_mask.tos;966		break;967	case IPV4_USER_FLOW:968		fsp->h_u.usr_ip4_spec.ip4src = rule->ip_data.v4_addrs.src_ip;969		fsp->h_u.usr_ip4_spec.ip4dst = rule->ip_data.v4_addrs.dst_ip;970		fsp->h_u.usr_ip4_spec.l4_4_bytes = rule->ip_data.l4_header;971		fsp->h_u.usr_ip4_spec.tos = rule->ip_data.tos;972		fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;973		fsp->h_u.usr_ip4_spec.proto = rule->ip_data.proto;974		fsp->m_u.usr_ip4_spec.ip4src = rule->ip_mask.v4_addrs.src_ip;975		fsp->m_u.usr_ip4_spec.ip4dst = rule->ip_mask.v4_addrs.dst_ip;976		fsp->m_u.usr_ip4_spec.l4_4_bytes = rule->ip_mask.l4_header;977		fsp->m_u.usr_ip4_spec.tos = rule->ip_mask.tos;978		fsp->m_u.usr_ip4_spec.ip_ver = 0xFF;979		fsp->m_u.usr_ip4_spec.proto = rule->ip_mask.proto;980		break;981	case TCP_V6_FLOW:982	case UDP_V6_FLOW:983	case SCTP_V6_FLOW:984		memcpy(fsp->h_u.usr_ip6_spec.ip6src, &rule->ip_data.v6_addrs.src_ip,985		       sizeof(struct in6_addr));986		memcpy(fsp->h_u.usr_ip6_spec.ip6dst, &rule->ip_data.v6_addrs.dst_ip,987		       sizeof(struct in6_addr));988		fsp->h_u.tcp_ip6_spec.psrc = rule->ip_data.src_port;989		fsp->h_u.tcp_ip6_spec.pdst = rule->ip_data.dst_port;990		fsp->h_u.tcp_ip6_spec.tclass = rule->ip_data.tclass;991		memcpy(fsp->m_u.usr_ip6_spec.ip6src, &rule->ip_mask.v6_addrs.src_ip,992		       sizeof(struct in6_addr));993		memcpy(fsp->m_u.usr_ip6_spec.ip6dst, &rule->ip_mask.v6_addrs.dst_ip,994		       sizeof(struct in6_addr));995		fsp->m_u.tcp_ip6_spec.psrc = rule->ip_mask.src_port;996		fsp->m_u.tcp_ip6_spec.pdst = rule->ip_mask.dst_port;997		fsp->m_u.tcp_ip6_spec.tclass = rule->ip_mask.tclass;998		break;999	case AH_V6_FLOW:1000	case ESP_V6_FLOW:1001		memcpy(fsp->h_u.ah_ip6_spec.ip6src, &rule->ip_data.v6_addrs.src_ip,1002		       sizeof(struct in6_addr));1003		memcpy(fsp->h_u.ah_ip6_spec.ip6dst, &rule->ip_data.v6_addrs.dst_ip,1004		       sizeof(struct in6_addr));1005		fsp->h_u.ah_ip6_spec.spi = rule->ip_data.spi;1006		fsp->h_u.ah_ip6_spec.tclass = rule->ip_data.tclass;1007		memcpy(fsp->m_u.ah_ip6_spec.ip6src, &rule->ip_mask.v6_addrs.src_ip,1008		       sizeof(struct in6_addr));1009		memcpy(fsp->m_u.ah_ip6_spec.ip6dst, &rule->ip_mask.v6_addrs.dst_ip,1010		       sizeof(struct in6_addr));1011		fsp->m_u.ah_ip6_spec.spi = rule->ip_mask.spi;1012		fsp->m_u.ah_ip6_spec.tclass = rule->ip_mask.tclass;1013		break;1014	case IPV6_USER_FLOW:1015		memcpy(fsp->h_u.usr_ip6_spec.ip6src, &rule->ip_data.v6_addrs.src_ip,1016		       sizeof(struct in6_addr));1017		memcpy(fsp->h_u.usr_ip6_spec.ip6dst, &rule->ip_data.v6_addrs.dst_ip,1018		       sizeof(struct in6_addr));1019		fsp->h_u.usr_ip6_spec.l4_4_bytes = rule->ip_data.l4_header;1020		fsp->h_u.usr_ip6_spec.tclass = rule->ip_data.tclass;1021		fsp->h_u.usr_ip6_spec.l4_proto = rule->ip_data.proto;1022		memcpy(fsp->m_u.usr_ip6_spec.ip6src, &rule->ip_mask.v6_addrs.src_ip,1023		       sizeof(struct in6_addr));1024		memcpy(fsp->m_u.usr_ip6_spec.ip6dst, &rule->ip_mask.v6_addrs.dst_ip,1025		       sizeof(struct in6_addr));1026		fsp->m_u.usr_ip6_spec.l4_4_bytes = rule->ip_mask.l4_header;1027		fsp->m_u.usr_ip6_spec.tclass = rule->ip_mask.tclass;1028		fsp->m_u.usr_ip6_spec.l4_proto = rule->ip_mask.proto;1029		break;1030	case ETHER_FLOW:1031		fsp->h_u.ether_spec.h_proto = rule->eth_data.etype;1032		fsp->m_u.ether_spec.h_proto = rule->eth_mask.etype;1033		break;1034	default:1035		ret = -EINVAL;1036		break;1037	}1038 1039	iavf_fill_rx_flow_ext_data(fsp, rule);1040 1041	if (rule->action == VIRTCHNL_ACTION_DROP)1042		fsp->ring_cookie = RX_CLS_FLOW_DISC;1043	else1044		fsp->ring_cookie = rule->q_index;1045 1046release_lock:1047	spin_unlock_bh(&adapter->fdir_fltr_lock);1048	return ret;1049}1050 1051/**1052 * iavf_get_fdir_fltr_ids - fill buffer with filter IDs of active filters1053 * @adapter: the VF adapter structure containing the filter list1054 * @cmd: ethtool command data structure1055 * @rule_locs: ethtool array passed in from OS to receive filter IDs1056 *1057 * Returns 0 as expected for success by ethtool1058 */1059static int1060iavf_get_fdir_fltr_ids(struct iavf_adapter *adapter, struct ethtool_rxnfc *cmd,1061		       u32 *rule_locs)1062{1063	struct iavf_fdir_fltr *fltr;1064	unsigned int cnt = 0;1065	int val = 0;1066 1067	if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))1068		return -EOPNOTSUPP;1069 1070	cmd->data = IAVF_MAX_FDIR_FILTERS;1071 1072	spin_lock_bh(&adapter->fdir_fltr_lock);1073 1074	list_for_each_entry(fltr, &adapter->fdir_list_head, list) {1075		if (iavf_is_raw_fdir(fltr))1076			continue;1077 1078		if (cnt == cmd->rule_cnt) {1079			val = -EMSGSIZE;1080			goto release_lock;1081		}1082		rule_locs[cnt] = fltr->loc;1083		cnt++;1084	}1085 1086release_lock:1087	spin_unlock_bh(&adapter->fdir_fltr_lock);1088	if (!val)1089		cmd->rule_cnt = cnt;1090 1091	return val;1092}1093 1094/**1095 * iavf_add_fdir_fltr_info - Set the input set for Flow Director filter1096 * @adapter: pointer to the VF adapter structure1097 * @fsp: pointer to ethtool Rx flow specification1098 * @fltr: filter structure1099 */1100static int1101iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spec *fsp,1102			struct iavf_fdir_fltr *fltr)1103{1104	u32 flow_type, q_index = 0;1105	enum virtchnl_action act;1106	int err;1107 1108	if (fsp->ring_cookie == RX_CLS_FLOW_DISC) {1109		act = VIRTCHNL_ACTION_DROP;1110	} else {1111		q_index = fsp->ring_cookie;1112		if (q_index >= adapter->num_active_queues)1113			return -EINVAL;1114 1115		act = VIRTCHNL_ACTION_QUEUE;1116	}1117 1118	fltr->action = act;1119	fltr->loc = fsp->location;1120	fltr->q_index = q_index;1121 1122	if (fsp->flow_type & FLOW_EXT) {1123		memcpy(fltr->ext_data.usr_def, fsp->h_ext.data,1124		       sizeof(fltr->ext_data.usr_def));1125		memcpy(fltr->ext_mask.usr_def, fsp->m_ext.data,1126		       sizeof(fltr->ext_mask.usr_def));1127	}1128 1129	flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);1130	fltr->flow_type = iavf_ethtool_flow_to_fltr(flow_type);1131 1132	switch (flow_type) {1133	case TCP_V4_FLOW:1134	case UDP_V4_FLOW:1135	case SCTP_V4_FLOW:1136		fltr->ip_data.v4_addrs.src_ip = fsp->h_u.tcp_ip4_spec.ip4src;1137		fltr->ip_data.v4_addrs.dst_ip = fsp->h_u.tcp_ip4_spec.ip4dst;1138		fltr->ip_data.src_port = fsp->h_u.tcp_ip4_spec.psrc;1139		fltr->ip_data.dst_port = fsp->h_u.tcp_ip4_spec.pdst;1140		fltr->ip_data.tos = fsp->h_u.tcp_ip4_spec.tos;1141		fltr->ip_mask.v4_addrs.src_ip = fsp->m_u.tcp_ip4_spec.ip4src;1142		fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.tcp_ip4_spec.ip4dst;1143		fltr->ip_mask.src_port = fsp->m_u.tcp_ip4_spec.psrc;1144		fltr->ip_mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst;1145		fltr->ip_mask.tos = fsp->m_u.tcp_ip4_spec.tos;1146		fltr->ip_ver = 4;1147		break;1148	case AH_V4_FLOW:1149	case ESP_V4_FLOW:1150		fltr->ip_data.v4_addrs.src_ip = fsp->h_u.ah_ip4_spec.ip4src;1151		fltr->ip_data.v4_addrs.dst_ip = fsp->h_u.ah_ip4_spec.ip4dst;1152		fltr->ip_data.spi = fsp->h_u.ah_ip4_spec.spi;1153		fltr->ip_data.tos = fsp->h_u.ah_ip4_spec.tos;1154		fltr->ip_mask.v4_addrs.src_ip = fsp->m_u.ah_ip4_spec.ip4src;1155		fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.ah_ip4_spec.ip4dst;1156		fltr->ip_mask.spi = fsp->m_u.ah_ip4_spec.spi;1157		fltr->ip_mask.tos = fsp->m_u.ah_ip4_spec.tos;1158		fltr->ip_ver = 4;1159		break;1160	case IPV4_USER_FLOW:1161		fltr->ip_data.v4_addrs.src_ip = fsp->h_u.usr_ip4_spec.ip4src;1162		fltr->ip_data.v4_addrs.dst_ip = fsp->h_u.usr_ip4_spec.ip4dst;1163		fltr->ip_data.l4_header = fsp->h_u.usr_ip4_spec.l4_4_bytes;1164		fltr->ip_data.tos = fsp->h_u.usr_ip4_spec.tos;1165		fltr->ip_data.proto = fsp->h_u.usr_ip4_spec.proto;1166		fltr->ip_mask.v4_addrs.src_ip = fsp->m_u.usr_ip4_spec.ip4src;1167		fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.usr_ip4_spec.ip4dst;1168		fltr->ip_mask.l4_header = fsp->m_u.usr_ip4_spec.l4_4_bytes;1169		fltr->ip_mask.tos = fsp->m_u.usr_ip4_spec.tos;1170		fltr->ip_mask.proto = fsp->m_u.usr_ip4_spec.proto;1171		fltr->ip_ver = 4;1172		break;1173	case TCP_V6_FLOW:1174	case UDP_V6_FLOW:1175	case SCTP_V6_FLOW:1176		memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.usr_ip6_spec.ip6src,1177		       sizeof(struct in6_addr));1178		memcpy(&fltr->ip_data.v6_addrs.dst_ip, fsp->h_u.usr_ip6_spec.ip6dst,1179		       sizeof(struct in6_addr));1180		fltr->ip_data.src_port = fsp->h_u.tcp_ip6_spec.psrc;1181		fltr->ip_data.dst_port = fsp->h_u.tcp_ip6_spec.pdst;1182		fltr->ip_data.tclass = fsp->h_u.tcp_ip6_spec.tclass;1183		memcpy(&fltr->ip_mask.v6_addrs.src_ip, fsp->m_u.usr_ip6_spec.ip6src,1184		       sizeof(struct in6_addr));1185		memcpy(&fltr->ip_mask.v6_addrs.dst_ip, fsp->m_u.usr_ip6_spec.ip6dst,1186		       sizeof(struct in6_addr));1187		fltr->ip_mask.src_port = fsp->m_u.tcp_ip6_spec.psrc;1188		fltr->ip_mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst;1189		fltr->ip_mask.tclass = fsp->m_u.tcp_ip6_spec.tclass;1190		fltr->ip_ver = 6;1191		break;1192	case AH_V6_FLOW:1193	case ESP_V6_FLOW:1194		memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.ah_ip6_spec.ip6src,1195		       sizeof(struct in6_addr));1196		memcpy(&fltr->ip_data.v6_addrs.dst_ip, fsp->h_u.ah_ip6_spec.ip6dst,1197		       sizeof(struct in6_addr));1198		fltr->ip_data.spi = fsp->h_u.ah_ip6_spec.spi;1199		fltr->ip_data.tclass = fsp->h_u.ah_ip6_spec.tclass;1200		memcpy(&fltr->ip_mask.v6_addrs.src_ip, fsp->m_u.ah_ip6_spec.ip6src,1201		       sizeof(struct in6_addr));1202		memcpy(&fltr->ip_mask.v6_addrs.dst_ip, fsp->m_u.ah_ip6_spec.ip6dst,1203		       sizeof(struct in6_addr));1204		fltr->ip_mask.spi = fsp->m_u.ah_ip6_spec.spi;1205		fltr->ip_mask.tclass = fsp->m_u.ah_ip6_spec.tclass;1206		fltr->ip_ver = 6;1207		break;1208	case IPV6_USER_FLOW:1209		memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.usr_ip6_spec.ip6src,1210		       sizeof(struct in6_addr));1211		memcpy(&fltr->ip_data.v6_addrs.dst_ip, fsp->h_u.usr_ip6_spec.ip6dst,1212		       sizeof(struct in6_addr));1213		fltr->ip_data.l4_header = fsp->h_u.usr_ip6_spec.l4_4_bytes;1214		fltr->ip_data.tclass = fsp->h_u.usr_ip6_spec.tclass;1215		fltr->ip_data.proto = fsp->h_u.usr_ip6_spec.l4_proto;1216		memcpy(&fltr->ip_mask.v6_addrs.src_ip, fsp->m_u.usr_ip6_spec.ip6src,1217		       sizeof(struct in6_addr));1218		memcpy(&fltr->ip_mask.v6_addrs.dst_ip, fsp->m_u.usr_ip6_spec.ip6dst,1219		       sizeof(struct in6_addr));1220		fltr->ip_mask.l4_header = fsp->m_u.usr_ip6_spec.l4_4_bytes;1221		fltr->ip_mask.tclass = fsp->m_u.usr_ip6_spec.tclass;1222		fltr->ip_mask.proto = fsp->m_u.usr_ip6_spec.l4_proto;1223		fltr->ip_ver = 6;1224		break;1225	case ETHER_FLOW:1226		fltr->eth_data.etype = fsp->h_u.ether_spec.h_proto;1227		fltr->eth_mask.etype = fsp->m_u.ether_spec.h_proto;1228		break;1229	default:1230		/* not doing un-parsed flow types */1231		return -EINVAL;1232	}1233 1234	err = iavf_validate_fdir_fltr_masks(adapter, fltr);1235	if (err)1236		return err;1237 1238	if (iavf_fdir_is_dup_fltr(adapter, fltr))1239		return -EEXIST;1240 1241	err = iavf_parse_rx_flow_user_data(fsp, fltr);1242	if (err)1243		return err;1244 1245	return iavf_fill_fdir_add_msg(adapter, fltr);1246}1247 1248/**1249 * iavf_add_fdir_ethtool - add Flow Director filter1250 * @adapter: pointer to the VF adapter structure1251 * @cmd: command to add Flow Director filter1252 *1253 * Returns 0 on success and negative values for failure1254 */1255static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rxnfc *cmd)1256{1257	struct ethtool_rx_flow_spec *fsp = &cmd->fs;1258	struct iavf_fdir_fltr *fltr;1259	int count = 50;1260	int err;1261 1262	if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))1263		return -EOPNOTSUPP;1264 1265	if (fsp->flow_type & FLOW_MAC_EXT)1266		return -EINVAL;1267 1268	spin_lock_bh(&adapter->fdir_fltr_lock);1269	if (iavf_find_fdir_fltr(adapter, false, fsp->location)) {1270		dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n");1271		spin_unlock_bh(&adapter->fdir_fltr_lock);1272		return -EEXIST;1273	}1274	spin_unlock_bh(&adapter->fdir_fltr_lock);1275 1276	fltr = kzalloc(sizeof(*fltr), GFP_KERNEL);1277	if (!fltr)1278		return -ENOMEM;1279 1280	while (!mutex_trylock(&adapter->crit_lock)) {1281		if (--count == 0) {1282			kfree(fltr);1283			return -EINVAL;1284		}1285		udelay(1);1286	}1287 1288	err = iavf_add_fdir_fltr_info(adapter, fsp, fltr);1289	if (!err)1290		err = iavf_fdir_add_fltr(adapter, fltr);1291 1292	if (err)1293		kfree(fltr);1294 1295	mutex_unlock(&adapter->crit_lock);1296	return err;1297}1298 1299/**1300 * iavf_del_fdir_ethtool - delete Flow Director filter1301 * @adapter: pointer to the VF adapter structure1302 * @cmd: command to delete Flow Director filter1303 *1304 * Returns 0 on success and negative values for failure1305 */1306static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rxnfc *cmd)1307{1308	struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;1309 1310	if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))1311		return -EOPNOTSUPP;1312 1313	return iavf_fdir_del_fltr(adapter, false, fsp->location);1314}1315 1316/**1317 * iavf_adv_rss_parse_hdrs - parses headers from RSS hash input1318 * @cmd: ethtool rxnfc command1319 *1320 * This function parses the rxnfc command and returns intended1321 * header types for RSS configuration1322 */1323static u32 iavf_adv_rss_parse_hdrs(struct ethtool_rxnfc *cmd)1324{1325	u32 hdrs = IAVF_ADV_RSS_FLOW_SEG_HDR_NONE;1326 1327	switch (cmd->flow_type) {1328	case TCP_V4_FLOW:1329		hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_TCP |1330			IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;1331		break;1332	case UDP_V4_FLOW:1333		hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_UDP |1334			IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;1335		break;1336	case SCTP_V4_FLOW:1337		hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP |1338			IAVF_ADV_RSS_FLOW_SEG_HDR_IPV4;1339		break;1340	case TCP_V6_FLOW:1341		hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_TCP |1342			IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;1343		break;1344	case UDP_V6_FLOW:1345		hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_UDP |1346			IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;1347		break;1348	case SCTP_V6_FLOW:1349		hdrs |= IAVF_ADV_RSS_FLOW_SEG_HDR_SCTP |1350			IAVF_ADV_RSS_FLOW_SEG_HDR_IPV6;1351		break;1352	default:1353		break;1354	}1355 1356	return hdrs;1357}1358 1359/**1360 * iavf_adv_rss_parse_hash_flds - parses hash fields from RSS hash input1361 * @cmd: ethtool rxnfc command1362 * @symm: true if Symmetric Topelitz is set1363 *1364 * This function parses the rxnfc command and returns intended hash fields for1365 * RSS configuration1366 */1367static u64 iavf_adv_rss_parse_hash_flds(struct ethtool_rxnfc *cmd, bool symm)1368{1369	u64 hfld = IAVF_ADV_RSS_HASH_INVALID;1370 1371	if (cmd->data & RXH_IP_SRC || cmd->data & RXH_IP_DST) {1372		switch (cmd->flow_type) {1373		case TCP_V4_FLOW:1374		case UDP_V4_FLOW:1375		case SCTP_V4_FLOW:1376			if (cmd->data & RXH_IP_SRC)1377				hfld |= IAVF_ADV_RSS_HASH_FLD_IPV4_SA;1378			if (cmd->data & RXH_IP_DST)1379				hfld |= IAVF_ADV_RSS_HASH_FLD_IPV4_DA;1380			break;1381		case TCP_V6_FLOW:1382		case UDP_V6_FLOW:1383		case SCTP_V6_FLOW:1384			if (cmd->data & RXH_IP_SRC)1385				hfld |= IAVF_ADV_RSS_HASH_FLD_IPV6_SA;1386			if (cmd->data & RXH_IP_DST)1387				hfld |= IAVF_ADV_RSS_HASH_FLD_IPV6_DA;1388			break;1389		default:1390			break;1391		}1392	}1393 1394	if (cmd->data & RXH_L4_B_0_1 || cmd->data & RXH_L4_B_2_3) {1395		switch (cmd->flow_type) {1396		case TCP_V4_FLOW:1397		case TCP_V6_FLOW:1398			if (cmd->data & RXH_L4_B_0_1)1399				hfld |= IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT;1400			if (cmd->data & RXH_L4_B_2_3)1401				hfld |= IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT;1402			break;1403		case UDP_V4_FLOW:1404		case UDP_V6_FLOW:1405			if (cmd->data & RXH_L4_B_0_1)1406				hfld |= IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT;1407			if (cmd->data & RXH_L4_B_2_3)1408				hfld |= IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT;1409			break;1410		case SCTP_V4_FLOW:1411		case SCTP_V6_FLOW:1412			if (cmd->data & RXH_L4_B_0_1)1413				hfld |= IAVF_ADV_RSS_HASH_FLD_SCTP_SRC_PORT;1414			if (cmd->data & RXH_L4_B_2_3)1415				hfld |= IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT;1416			break;1417		default:1418			break;1419		}1420	}1421 1422	return hfld;1423}1424 1425/**1426 * iavf_set_adv_rss_hash_opt - Enable/Disable flow types for RSS hash1427 * @adapter: pointer to the VF adapter structure1428 * @cmd: ethtool rxnfc command1429 *1430 * Returns Success if the flow input set is supported.1431 */1432static int1433iavf_set_adv_rss_hash_opt(struct iavf_adapter *adapter,1434			  struct ethtool_rxnfc *cmd)1435{1436	struct iavf_adv_rss *rss_old, *rss_new;1437	bool rss_new_add = false;1438	int count = 50, err = 0;1439	bool symm = false;1440	u64 hash_flds;1441	u32 hdrs;1442 1443	if (!ADV_RSS_SUPPORT(adapter))1444		return -EOPNOTSUPP;1445 1446	symm = !!(adapter->hfunc == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC);1447 1448	hdrs = iavf_adv_rss_parse_hdrs(cmd);1449	if (hdrs == IAVF_ADV_RSS_FLOW_SEG_HDR_NONE)1450		return -EINVAL;1451 1452	hash_flds = iavf_adv_rss_parse_hash_flds(cmd, symm);1453	if (hash_flds == IAVF_ADV_RSS_HASH_INVALID)1454		return -EINVAL;1455 1456	rss_new = kzalloc(sizeof(*rss_new), GFP_KERNEL);1457	if (!rss_new)1458		return -ENOMEM;1459 1460	if (iavf_fill_adv_rss_cfg_msg(&rss_new->cfg_msg, hdrs, hash_flds,1461				      symm)) {1462		kfree(rss_new);1463		return -EINVAL;1464	}1465 1466	while (!mutex_trylock(&adapter->crit_lock)) {1467		if (--count == 0) {1468			kfree(rss_new);1469			return -EINVAL;1470		}1471 1472		udelay(1);1473	}1474 1475	spin_lock_bh(&adapter->adv_rss_lock);1476	rss_old = iavf_find_adv_rss_cfg_by_hdrs(adapter, hdrs);1477	if (rss_old) {1478		if (rss_old->state != IAVF_ADV_RSS_ACTIVE) {1479			err = -EBUSY;1480		} else if (rss_old->hash_flds != hash_flds ||1481			   rss_old->symm != symm) {1482			rss_old->state = IAVF_ADV_RSS_ADD_REQUEST;1483			rss_old->hash_flds = hash_flds;1484			rss_old->symm = symm;1485			memcpy(&rss_old->cfg_msg, &rss_new->cfg_msg,1486			       sizeof(rss_new->cfg_msg));1487		} else {1488			err = -EEXIST;1489		}1490	} else {1491		rss_new_add = true;1492		rss_new->state = IAVF_ADV_RSS_ADD_REQUEST;1493		rss_new->packet_hdrs = hdrs;1494		rss_new->hash_flds = hash_flds;1495		rss_new->symm = symm;1496		list_add_tail(&rss_new->list, &adapter->adv_rss_list_head);1497	}1498	spin_unlock_bh(&adapter->adv_rss_lock);1499 1500	if (!err)1501		iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_ADV_RSS_CFG);1502 1503	mutex_unlock(&adapter->crit_lock);1504 1505	if (!rss_new_add)1506		kfree(rss_new);1507 1508	return err;1509}1510 1511/**1512 * iavf_get_adv_rss_hash_opt - Retrieve hash fields for a given flow-type1513 * @adapter: pointer to the VF adapter structure1514 * @cmd: ethtool rxnfc command1515 *1516 * Returns Success if the flow input set is supported.1517 */1518static int1519iavf_get_adv_rss_hash_opt(struct iavf_adapter *adapter,1520			  struct ethtool_rxnfc *cmd)1521{1522	struct iavf_adv_rss *rss;1523	u64 hash_flds;1524	u32 hdrs;1525 1526	if (!ADV_RSS_SUPPORT(adapter))1527		return -EOPNOTSUPP;1528 1529	cmd->data = 0;1530 1531	hdrs = iavf_adv_rss_parse_hdrs(cmd);1532	if (hdrs == IAVF_ADV_RSS_FLOW_SEG_HDR_NONE)1533		return -EINVAL;1534 1535	spin_lock_bh(&adapter->adv_rss_lock);1536	rss = iavf_find_adv_rss_cfg_by_hdrs(adapter, hdrs);1537	if (rss)1538		hash_flds = rss->hash_flds;1539	else1540		hash_flds = IAVF_ADV_RSS_HASH_INVALID;1541	spin_unlock_bh(&adapter->adv_rss_lock);1542 1543	if (hash_flds == IAVF_ADV_RSS_HASH_INVALID)1544		return -EINVAL;1545 1546	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_SA |1547			 IAVF_ADV_RSS_HASH_FLD_IPV6_SA))1548		cmd->data |= (u64)RXH_IP_SRC;1549 1550	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_IPV4_DA |1551			 IAVF_ADV_RSS_HASH_FLD_IPV6_DA))1552		cmd->data |= (u64)RXH_IP_DST;1553 1554	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_SRC_PORT |1555			 IAVF_ADV_RSS_HASH_FLD_UDP_SRC_PORT |1556			 IAVF_ADV_RSS_HASH_FLD_SCTP_SRC_PORT))1557		cmd->data |= (u64)RXH_L4_B_0_1;1558 1559	if (hash_flds & (IAVF_ADV_RSS_HASH_FLD_TCP_DST_PORT |1560			 IAVF_ADV_RSS_HASH_FLD_UDP_DST_PORT |1561			 IAVF_ADV_RSS_HASH_FLD_SCTP_DST_PORT))1562		cmd->data |= (u64)RXH_L4_B_2_3;1563 1564	return 0;1565}1566 1567/**1568 * iavf_set_rxnfc - command to set Rx flow rules.1569 * @netdev: network interface device structure1570 * @cmd: ethtool rxnfc command1571 *1572 * Returns 0 for success and negative values for errors1573 */1574static int iavf_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)1575{1576	struct iavf_adapter *adapter = netdev_priv(netdev);1577	int ret = -EOPNOTSUPP;1578 1579	switch (cmd->cmd) {1580	case ETHTOOL_SRXCLSRLINS:1581		ret = iavf_add_fdir_ethtool(adapter, cmd);1582		break;1583	case ETHTOOL_SRXCLSRLDEL:1584		ret = iavf_del_fdir_ethtool(adapter, cmd);1585		break;1586	case ETHTOOL_SRXFH:1587		ret = iavf_set_adv_rss_hash_opt(adapter, cmd);1588		break;1589	default:1590		break;1591	}1592 1593	return ret;1594}1595 1596/**1597 * iavf_get_rxnfc - command to get RX flow classification rules1598 * @netdev: network interface device structure1599 * @cmd: ethtool rxnfc command1600 * @rule_locs: pointer to store rule locations1601 *1602 * Returns Success if the command is supported.1603 **/1604static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,1605			  u32 *rule_locs)1606{1607	struct iavf_adapter *adapter = netdev_priv(netdev);1608	int ret = -EOPNOTSUPP;1609 1610	switch (cmd->cmd) {1611	case ETHTOOL_GRXRINGS:1612		cmd->data = adapter->num_active_queues;1613		ret = 0;1614		break;1615	case ETHTOOL_GRXCLSRLCNT:1616		if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))1617			break;1618		spin_lock_bh(&adapter->fdir_fltr_lock);1619		cmd->rule_cnt = adapter->fdir_active_fltr;1620		spin_unlock_bh(&adapter->fdir_fltr_lock);1621		cmd->data = IAVF_MAX_FDIR_FILTERS;1622		ret = 0;1623		break;1624	case ETHTOOL_GRXCLSRULE:1625		ret = iavf_get_ethtool_fdir_entry(adapter, cmd);1626		break;1627	case ETHTOOL_GRXCLSRLALL:1628		ret = iavf_get_fdir_fltr_ids(adapter, cmd, (u32 *)rule_locs);1629		break;1630	case ETHTOOL_GRXFH:1631		ret = iavf_get_adv_rss_hash_opt(adapter, cmd);1632		break;1633	default:1634		break;1635	}1636 1637	return ret;1638}1639/**1640 * iavf_get_channels: get the number of channels supported by the device1641 * @netdev: network interface device structure1642 * @ch: channel information structure1643 *1644 * For the purposes of our device, we only use combined channels, i.e. a tx/rx1645 * queue pair. Report one extra channel to match our "other" MSI-X vector.1646 **/1647static void iavf_get_channels(struct net_device *netdev,1648			      struct ethtool_channels *ch)1649{1650	struct iavf_adapter *adapter = netdev_priv(netdev);1651 1652	/* Report maximum channels */1653	ch->max_combined = adapter->vsi_res->num_queue_pairs;1654 1655	ch->max_other = NONQ_VECS;1656	ch->other_count = NONQ_VECS;1657 1658	ch->combined_count = adapter->num_active_queues;1659}1660 1661/**1662 * iavf_set_channels: set the new channel count1663 * @netdev: network interface device structure1664 * @ch: channel information structure1665 *1666 * Negotiate a new number of channels with the PF then do a reset.  During1667 * reset we'll realloc queues and fix the RSS table.  Returns 0 on success,1668 * negative on failure.1669 **/1670static int iavf_set_channels(struct net_device *netdev,1671			     struct ethtool_channels *ch)1672{1673	struct iavf_adapter *adapter = netdev_priv(netdev);1674	u32 num_req = ch->combined_count;1675	int ret = 0;1676 1677	if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&1678	    adapter->num_tc) {1679		dev_info(&adapter->pdev->dev, "Cannot set channels since ADq is enabled.\n");1680		return -EINVAL;1681	}1682 1683	/* All of these should have already been checked by ethtool before this1684	 * even gets to us, but just to be sure.1685	 */1686	if (num_req == 0 || num_req > adapter->vsi_res->num_queue_pairs)1687		return -EINVAL;1688 1689	if (num_req == adapter->num_active_queues)1690		return 0;1691 1692	if (ch->rx_count || ch->tx_count || ch->other_count != NONQ_VECS)1693		return -EINVAL;1694 1695	adapter->num_req_queues = num_req;1696	adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;1697	iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);1698 1699	ret = iavf_wait_for_reset(adapter);1700	if (ret)1701		netdev_warn(netdev, "Changing channel count timeout or interrupted waiting for reset");1702 1703	return ret;1704}1705 1706/**1707 * iavf_get_rxfh_key_size - get the RSS hash key size1708 * @netdev: network interface device structure1709 *1710 * Returns the table size.1711 **/1712static u32 iavf_get_rxfh_key_size(struct net_device *netdev)1713{1714	struct iavf_adapter *adapter = netdev_priv(netdev);1715 1716	return adapter->rss_key_size;1717}1718 1719/**1720 * iavf_get_rxfh_indir_size - get the rx flow hash indirection table size1721 * @netdev: network interface device structure1722 *1723 * Returns the table size.1724 **/1725static u32 iavf_get_rxfh_indir_size(struct net_device *netdev)1726{1727	struct iavf_adapter *adapter = netdev_priv(netdev);1728 1729	return adapter->rss_lut_size;1730}1731 1732/**1733 * iavf_get_rxfh - get the rx flow hash indirection table1734 * @netdev: network interface device structure1735 * @rxfh: pointer to param struct (indir, key, hfunc)1736 *1737 * Reads the indirection table directly from the hardware. Always returns 0.1738 **/1739static int iavf_get_rxfh(struct net_device *netdev,1740			 struct ethtool_rxfh_param *rxfh)1741{1742	struct iavf_adapter *adapter = netdev_priv(netdev);1743	u16 i;1744 1745	rxfh->hfunc = ETH_RSS_HASH_TOP;1746	if (adapter->hfunc == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)1747		rxfh->input_xfrm |= RXH_XFRM_SYM_XOR;1748 1749	if (rxfh->key)1750		memcpy(rxfh->key, adapter->rss_key, adapter->rss_key_size);1751 1752	if (rxfh->indir)1753		/* Each 32 bits pointed by 'indir' is stored with a lut entry */1754		for (i = 0; i < adapter->rss_lut_size; i++)1755			rxfh->indir[i] = (u32)adapter->rss_lut[i];1756 1757	return 0;1758}1759 1760/**1761 * iavf_set_rxfh - set the rx flow hash indirection table1762 * @netdev: network interface device structure1763 * @rxfh: pointer to param struct (indir, key, hfunc)1764 * @extack: extended ACK from the Netlink message1765 *1766 * Returns -EINVAL if the table specifies an invalid queue id, otherwise1767 * returns 0 after programming the table.1768 **/1769static int iavf_set_rxfh(struct net_device *netdev,1770			 struct ethtool_rxfh_param *rxfh,1771			 struct netlink_ext_ack *extack)1772{1773	struct iavf_adapter *adapter = netdev_priv(netdev);1774	u16 i;1775 1776	/* Only support toeplitz hash function */1777	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&1778	    rxfh->hfunc != ETH_RSS_HASH_TOP)1779		return -EOPNOTSUPP;1780 1781	if ((rxfh->input_xfrm & RXH_XFRM_SYM_XOR) &&1782	    adapter->hfunc != VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC) {1783		if (!ADV_RSS_SUPPORT(adapter))1784			return -EOPNOTSUPP;1785		adapter->hfunc = VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;1786		adapter->aq_required |= IAVF_FLAG_AQ_SET_RSS_HFUNC;1787	} else if (!(rxfh->input_xfrm & RXH_XFRM_SYM_XOR) &&1788		    adapter->hfunc != VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC) {1789		adapter->hfunc = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;1790		adapter->aq_required |= IAVF_FLAG_AQ_SET_RSS_HFUNC;1791	}1792 1793	if (!rxfh->key && !rxfh->indir)1794		return 0;1795 1796	if (rxfh->key)1797		memcpy(adapter->rss_key, rxfh->key, adapter->rss_key_size);1798 1799	if (rxfh->indir) {1800		/* Each 32 bits pointed by 'indir' is stored with a lut entry */1801		for (i = 0; i < adapter->rss_lut_size; i++)1802			adapter->rss_lut[i] = (u8)(rxfh->indir[i]);1803	}1804 1805	return iavf_config_rss(adapter);1806}1807 1808static const struct ethtool_ops iavf_ethtool_ops = {1809	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |1810				     ETHTOOL_COALESCE_USE_ADAPTIVE,1811	.cap_rss_sym_xor_supported = true,1812	.get_drvinfo		= iavf_get_drvinfo,1813	.get_link		= ethtool_op_get_link,1814	.get_ringparam		= iavf_get_ringparam,1815	.set_ringparam		= iavf_set_ringparam,1816	.get_strings		= iavf_get_strings,1817	.get_ethtool_stats	= iavf_get_ethtool_stats,1818	.get_sset_count		= iavf_get_sset_count,1819	.get_msglevel		= iavf_get_msglevel,1820	.set_msglevel		= iavf_set_msglevel,1821	.get_coalesce		= iavf_get_coalesce,1822	.set_coalesce		= iavf_set_coalesce,1823	.get_per_queue_coalesce = iavf_get_per_queue_coalesce,1824	.set_per_queue_coalesce = iavf_set_per_queue_coalesce,1825	.set_rxnfc		= iavf_set_rxnfc,1826	.get_rxnfc		= iavf_get_rxnfc,1827	.get_rxfh_indir_size	= iavf_get_rxfh_indir_size,1828	.get_rxfh		= iavf_get_rxfh,1829	.set_rxfh		= iavf_set_rxfh,1830	.get_channels		= iavf_get_channels,1831	.set_channels		= iavf_set_channels,1832	.get_rxfh_key_size	= iavf_get_rxfh_key_size,1833	.get_link_ksettings	= iavf_get_link_ksettings,1834};1835 1836/**1837 * iavf_set_ethtool_ops - Initialize ethtool ops struct1838 * @netdev: network interface device structure1839 *1840 * Sets ethtool ops struct in our netdev so that ethtool can call1841 * our functions.1842 **/1843void iavf_set_ethtool_ops(struct net_device *netdev)1844{1845	netdev->ethtool_ops = &iavf_ethtool_ops;1846}1847