182dd0f7eSAlexander Duyck /* Intel Ethernet Switch Host Interface Driver
297c71e3cSJeff Kirsher  * Copyright(c) 2013 - 2015 Intel Corporation.
382dd0f7eSAlexander Duyck  *
482dd0f7eSAlexander Duyck  * This program is free software; you can redistribute it and/or modify it
582dd0f7eSAlexander Duyck  * under the terms and conditions of the GNU General Public License,
682dd0f7eSAlexander Duyck  * version 2, as published by the Free Software Foundation.
782dd0f7eSAlexander Duyck  *
882dd0f7eSAlexander Duyck  * This program is distributed in the hope it will be useful, but WITHOUT
982dd0f7eSAlexander Duyck  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1082dd0f7eSAlexander Duyck  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
1182dd0f7eSAlexander Duyck  * more details.
1282dd0f7eSAlexander Duyck  *
1382dd0f7eSAlexander Duyck  * The full GNU General Public License is included in this distribution in
1482dd0f7eSAlexander Duyck  * the file called "COPYING".
1582dd0f7eSAlexander Duyck  *
1682dd0f7eSAlexander Duyck  * Contact Information:
1782dd0f7eSAlexander Duyck  * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
1882dd0f7eSAlexander Duyck  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
1982dd0f7eSAlexander Duyck  */
2082dd0f7eSAlexander Duyck 
21eb51bbafSStephen Rothwell #include <linux/vmalloc.h>
22eb51bbafSStephen Rothwell 
2382dd0f7eSAlexander Duyck #include "fm10k.h"
2482dd0f7eSAlexander Duyck 
2582dd0f7eSAlexander Duyck struct fm10k_stats {
2682dd0f7eSAlexander Duyck 	char stat_string[ETH_GSTRING_LEN];
2782dd0f7eSAlexander Duyck 	int sizeof_stat;
2882dd0f7eSAlexander Duyck 	int stat_offset;
2982dd0f7eSAlexander Duyck };
3082dd0f7eSAlexander Duyck 
3182dd0f7eSAlexander Duyck #define FM10K_NETDEV_STAT(_net_stat) { \
3282dd0f7eSAlexander Duyck 	.stat_string = #_net_stat, \
3382dd0f7eSAlexander Duyck 	.sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \
3482dd0f7eSAlexander Duyck 	.stat_offset = offsetof(struct net_device_stats, _net_stat) \
3582dd0f7eSAlexander Duyck }
3682dd0f7eSAlexander Duyck 
3782dd0f7eSAlexander Duyck static const struct fm10k_stats fm10k_gstrings_net_stats[] = {
3882dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(tx_packets),
3982dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(tx_bytes),
4082dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(tx_errors),
4182dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(rx_packets),
4282dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(rx_bytes),
4382dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(rx_errors),
4482dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(rx_dropped),
4582dd0f7eSAlexander Duyck 
4682dd0f7eSAlexander Duyck 	/* detailed Rx errors */
4782dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(rx_length_errors),
4882dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(rx_crc_errors),
4982dd0f7eSAlexander Duyck 	FM10K_NETDEV_STAT(rx_fifo_errors),
5082dd0f7eSAlexander Duyck };
5182dd0f7eSAlexander Duyck 
5282dd0f7eSAlexander Duyck #define FM10K_NETDEV_STATS_LEN	ARRAY_SIZE(fm10k_gstrings_net_stats)
5382dd0f7eSAlexander Duyck 
5482dd0f7eSAlexander Duyck #define FM10K_STAT(_name, _stat) { \
5582dd0f7eSAlexander Duyck 	.stat_string = _name, \
5682dd0f7eSAlexander Duyck 	.sizeof_stat = FIELD_SIZEOF(struct fm10k_intfc, _stat), \
5782dd0f7eSAlexander Duyck 	.stat_offset = offsetof(struct fm10k_intfc, _stat) \
5882dd0f7eSAlexander Duyck }
5982dd0f7eSAlexander Duyck 
60fbdb159fSJeff Kirsher static const struct fm10k_stats fm10k_gstrings_global_stats[] = {
6182dd0f7eSAlexander Duyck 	FM10K_STAT("tx_restart_queue", restart_queue),
6282dd0f7eSAlexander Duyck 	FM10K_STAT("tx_busy", tx_busy),
6382dd0f7eSAlexander Duyck 	FM10K_STAT("tx_csum_errors", tx_csum_errors),
6482dd0f7eSAlexander Duyck 	FM10K_STAT("rx_alloc_failed", alloc_failed),
6582dd0f7eSAlexander Duyck 	FM10K_STAT("rx_csum_errors", rx_csum_errors),
6682dd0f7eSAlexander Duyck 
6782dd0f7eSAlexander Duyck 	FM10K_STAT("tx_packets_nic", tx_packets_nic),
6882dd0f7eSAlexander Duyck 	FM10K_STAT("tx_bytes_nic", tx_bytes_nic),
6982dd0f7eSAlexander Duyck 	FM10K_STAT("rx_packets_nic", rx_packets_nic),
7082dd0f7eSAlexander Duyck 	FM10K_STAT("rx_bytes_nic", rx_bytes_nic),
7182dd0f7eSAlexander Duyck 	FM10K_STAT("rx_drops_nic", rx_drops_nic),
7282dd0f7eSAlexander Duyck 	FM10K_STAT("rx_overrun_pf", rx_overrun_pf),
7382dd0f7eSAlexander Duyck 	FM10K_STAT("rx_overrun_vf", rx_overrun_vf),
7482dd0f7eSAlexander Duyck 
7582dd0f7eSAlexander Duyck 	FM10K_STAT("swapi_status", hw.swapi.status),
7682dd0f7eSAlexander Duyck 	FM10K_STAT("mac_rules_used", hw.swapi.mac.used),
7782dd0f7eSAlexander Duyck 	FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail),
7882dd0f7eSAlexander Duyck 
79e05546ecSJeff Kirsher 	FM10K_STAT("tx_hang_count", tx_timeout_count),
80e05546ecSJeff Kirsher 
81a211e013SAlexander Duyck 	FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
8282dd0f7eSAlexander Duyck };
8382dd0f7eSAlexander Duyck 
8480043f3bSJacob Keller static const struct fm10k_stats fm10k_gstrings_debug_stats[] = {
8580043f3bSJacob Keller 	FM10K_STAT("hw_sm_mbx_full", hw_sm_mbx_full),
8680043f3bSJacob Keller 	FM10K_STAT("hw_csum_tx_good", hw_csum_tx_good),
8780043f3bSJacob Keller 	FM10K_STAT("hw_csum_rx_good", hw_csum_rx_good),
8880043f3bSJacob Keller 	FM10K_STAT("rx_switch_errors", rx_switch_errors),
8980043f3bSJacob Keller 	FM10K_STAT("rx_drops", rx_drops),
9080043f3bSJacob Keller 	FM10K_STAT("rx_pp_errors", rx_pp_errors),
9180043f3bSJacob Keller 	FM10K_STAT("rx_link_errors", rx_link_errors),
9280043f3bSJacob Keller 	FM10K_STAT("rx_length_errors", rx_length_errors),
9380043f3bSJacob Keller };
9480043f3bSJacob Keller 
95fbdb159fSJeff Kirsher static const struct fm10k_stats fm10k_gstrings_pf_stats[] = {
96fbdb159fSJeff Kirsher 	FM10K_STAT("timeout", stats.timeout.count),
97fbdb159fSJeff Kirsher 	FM10K_STAT("ur", stats.ur.count),
98fbdb159fSJeff Kirsher 	FM10K_STAT("ca", stats.ca.count),
99fbdb159fSJeff Kirsher 	FM10K_STAT("um", stats.um.count),
100fbdb159fSJeff Kirsher 	FM10K_STAT("xec", stats.xec.count),
101fbdb159fSJeff Kirsher 	FM10K_STAT("vlan_drop", stats.vlan_drop.count),
102fbdb159fSJeff Kirsher 	FM10K_STAT("loopback_drop", stats.loopback_drop.count),
103fbdb159fSJeff Kirsher 	FM10K_STAT("nodesc_drop", stats.nodesc_drop.count),
104fbdb159fSJeff Kirsher };
105fbdb159fSJeff Kirsher 
10680043f3bSJacob Keller #define FM10K_MBX_STAT(_name, _stat) { \
10780043f3bSJacob Keller 	.stat_string = _name, \
10880043f3bSJacob Keller 	.sizeof_stat = FIELD_SIZEOF(struct fm10k_mbx_info, _stat), \
10980043f3bSJacob Keller 	.stat_offset = offsetof(struct fm10k_mbx_info, _stat) \
11080043f3bSJacob Keller }
11180043f3bSJacob Keller 
11280043f3bSJacob Keller static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = {
11380043f3bSJacob Keller 	FM10K_MBX_STAT("mbx_tx_busy", tx_busy),
1145680ea69SJacob Keller 	FM10K_MBX_STAT("mbx_tx_dropped", tx_dropped),
11580043f3bSJacob Keller 	FM10K_MBX_STAT("mbx_tx_messages", tx_messages),
11680043f3bSJacob Keller 	FM10K_MBX_STAT("mbx_tx_dwords", tx_dwords),
11717d39facSJacob Keller 	FM10K_MBX_STAT("mbx_tx_mbmem_pulled", tx_mbmem_pulled),
11880043f3bSJacob Keller 	FM10K_MBX_STAT("mbx_rx_messages", rx_messages),
11980043f3bSJacob Keller 	FM10K_MBX_STAT("mbx_rx_dwords", rx_dwords),
12080043f3bSJacob Keller 	FM10K_MBX_STAT("mbx_rx_parse_err", rx_parse_err),
12117d39facSJacob Keller 	FM10K_MBX_STAT("mbx_rx_mbmem_pushed", rx_mbmem_pushed),
12280043f3bSJacob Keller };
12380043f3bSJacob Keller 
124fbdb159fSJeff Kirsher #define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats)
12580043f3bSJacob Keller #define FM10K_DEBUG_STATS_LEN ARRAY_SIZE(fm10k_gstrings_debug_stats)
126fbdb159fSJeff Kirsher #define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats)
12780043f3bSJacob Keller #define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats)
12882dd0f7eSAlexander Duyck 
129c0e61781SJeff Kirsher #define FM10K_QUEUE_STATS_LEN(_n) \
130c0e61781SJeff Kirsher 	((_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64)))
13182dd0f7eSAlexander Duyck 
132c0e61781SJeff Kirsher #define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \
13380043f3bSJacob Keller 				FM10K_NETDEV_STATS_LEN + \
13480043f3bSJacob Keller 				FM10K_MBX_STATS_LEN)
13582dd0f7eSAlexander Duyck 
1365cb8db4aSAlexander Duyck static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = {
1375cb8db4aSAlexander Duyck 	"Mailbox test (on/offline)"
1385cb8db4aSAlexander Duyck };
1395cb8db4aSAlexander Duyck 
1405cb8db4aSAlexander Duyck #define FM10K_TEST_LEN (sizeof(fm10k_gstrings_test) / ETH_GSTRING_LEN)
1415cb8db4aSAlexander Duyck 
1425cb8db4aSAlexander Duyck enum fm10k_self_test_types {
1435cb8db4aSAlexander Duyck 	FM10K_TEST_MBX,
1445cb8db4aSAlexander Duyck 	FM10K_TEST_MAX = FM10K_TEST_LEN
1455cb8db4aSAlexander Duyck };
1465cb8db4aSAlexander Duyck 
14780043f3bSJacob Keller enum {
14880043f3bSJacob Keller 	FM10K_PRV_FLAG_DEBUG_STATS,
14980043f3bSJacob Keller 	FM10K_PRV_FLAG_LEN,
15080043f3bSJacob Keller };
15180043f3bSJacob Keller 
15280043f3bSJacob Keller static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = {
15380043f3bSJacob Keller 	"debug-statistics",
15480043f3bSJacob Keller };
15580043f3bSJacob Keller 
156d2e0721bSJacob Keller static void fm10k_add_stat_strings(char **p, const char *prefix,
157d2e0721bSJacob Keller 				   const struct fm10k_stats stats[],
158d2e0721bSJacob Keller 				   const unsigned int size)
159d2e0721bSJacob Keller {
160d2e0721bSJacob Keller 	unsigned int i;
161d2e0721bSJacob Keller 
162d2e0721bSJacob Keller 	for (i = 0; i < size; i++) {
163d2e0721bSJacob Keller 		snprintf(*p, ETH_GSTRING_LEN, "%s%s",
164d2e0721bSJacob Keller 			 prefix, stats[i].stat_string);
165d2e0721bSJacob Keller 		*p += ETH_GSTRING_LEN;
166d2e0721bSJacob Keller 	}
167d2e0721bSJacob Keller }
168d2e0721bSJacob Keller 
16980043f3bSJacob Keller static void fm10k_get_stat_strings(struct net_device *dev, u8 *data)
17082dd0f7eSAlexander Duyck {
17129a928eeSJeff Kirsher 	struct fm10k_intfc *interface = netdev_priv(dev);
17280043f3bSJacob Keller 	struct fm10k_iov_data *iov_data = interface->iov_data;
17382dd0f7eSAlexander Duyck 	char *p = (char *)data;
174c0e58e93SJacob Keller 	unsigned int i;
17582dd0f7eSAlexander Duyck 
176d2e0721bSJacob Keller 	fm10k_add_stat_strings(&p, "", fm10k_gstrings_net_stats,
177d2e0721bSJacob Keller 			       FM10K_NETDEV_STATS_LEN);
17880043f3bSJacob Keller 
179d2e0721bSJacob Keller 	fm10k_add_stat_strings(&p, "", fm10k_gstrings_global_stats,
180d2e0721bSJacob Keller 			       FM10K_GLOBAL_STATS_LEN);
181fbdb159fSJeff Kirsher 
182d2e0721bSJacob Keller 	if (interface->flags & FM10K_FLAG_DEBUG_STATS)
183d2e0721bSJacob Keller 		fm10k_add_stat_strings(&p, "", fm10k_gstrings_debug_stats,
184d2e0721bSJacob Keller 				       FM10K_DEBUG_STATS_LEN);
18580043f3bSJacob Keller 
186d2e0721bSJacob Keller 	fm10k_add_stat_strings(&p, "", fm10k_gstrings_mbx_stats,
187d2e0721bSJacob Keller 			       FM10K_MBX_STATS_LEN);
18880043f3bSJacob Keller 
189d2e0721bSJacob Keller 	if (interface->hw.mac.type != fm10k_mac_vf)
190d2e0721bSJacob Keller 		fm10k_add_stat_strings(&p, "", fm10k_gstrings_pf_stats,
191d2e0721bSJacob Keller 				       FM10K_PF_STATS_LEN);
19282dd0f7eSAlexander Duyck 
19380043f3bSJacob Keller 	if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) {
19480043f3bSJacob Keller 		for (i = 0; i < iov_data->num_vfs; i++) {
195d2e0721bSJacob Keller 			char prefix[ETH_GSTRING_LEN];
196d2e0721bSJacob Keller 
197d2e0721bSJacob Keller 			snprintf(prefix, ETH_GSTRING_LEN, "vf_%u_", i);
198d2e0721bSJacob Keller 			fm10k_add_stat_strings(&p, prefix,
199d2e0721bSJacob Keller 					       fm10k_gstrings_mbx_stats,
200d2e0721bSJacob Keller 					       FM10K_MBX_STATS_LEN);
20180043f3bSJacob Keller 		}
20280043f3bSJacob Keller 	}
20380043f3bSJacob Keller 
20429a928eeSJeff Kirsher 	for (i = 0; i < interface->hw.mac.max_queues; i++) {
205f6f19f8bSJacob Keller 		snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_packets", i);
20682dd0f7eSAlexander Duyck 		p += ETH_GSTRING_LEN;
207f6f19f8bSJacob Keller 		snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i);
20882dd0f7eSAlexander Duyck 		p += ETH_GSTRING_LEN;
209f6f19f8bSJacob Keller 		snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_packets", i);
21082dd0f7eSAlexander Duyck 		p += ETH_GSTRING_LEN;
211f6f19f8bSJacob Keller 		snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i);
21282dd0f7eSAlexander Duyck 		p += ETH_GSTRING_LEN;
21382dd0f7eSAlexander Duyck 	}
21480043f3bSJacob Keller }
21580043f3bSJacob Keller 
21680043f3bSJacob Keller static void fm10k_get_strings(struct net_device *dev,
21780043f3bSJacob Keller 			      u32 stringset, u8 *data)
21880043f3bSJacob Keller {
21980043f3bSJacob Keller 	char *p = (char *)data;
22080043f3bSJacob Keller 
22180043f3bSJacob Keller 	switch (stringset) {
22280043f3bSJacob Keller 	case ETH_SS_TEST:
22380043f3bSJacob Keller 		memcpy(data, *fm10k_gstrings_test,
22480043f3bSJacob Keller 		       FM10K_TEST_LEN * ETH_GSTRING_LEN);
22580043f3bSJacob Keller 		break;
22680043f3bSJacob Keller 	case ETH_SS_STATS:
22780043f3bSJacob Keller 		fm10k_get_stat_strings(dev, data);
22880043f3bSJacob Keller 		break;
22980043f3bSJacob Keller 	case ETH_SS_PRIV_FLAGS:
23080043f3bSJacob Keller 		memcpy(p, fm10k_prv_flags,
23180043f3bSJacob Keller 		       FM10K_PRV_FLAG_LEN * ETH_GSTRING_LEN);
23282dd0f7eSAlexander Duyck 		break;
23382dd0f7eSAlexander Duyck 	}
23482dd0f7eSAlexander Duyck }
23582dd0f7eSAlexander Duyck 
23682dd0f7eSAlexander Duyck static int fm10k_get_sset_count(struct net_device *dev, int sset)
23782dd0f7eSAlexander Duyck {
238c0e61781SJeff Kirsher 	struct fm10k_intfc *interface = netdev_priv(dev);
23980043f3bSJacob Keller 	struct fm10k_iov_data *iov_data = interface->iov_data;
240c0e61781SJeff Kirsher 	struct fm10k_hw *hw = &interface->hw;
241c0e61781SJeff Kirsher 	int stats_len = FM10K_STATIC_STATS_LEN;
242c0e61781SJeff Kirsher 
24382dd0f7eSAlexander Duyck 	switch (sset) {
2445cb8db4aSAlexander Duyck 	case ETH_SS_TEST:
2455cb8db4aSAlexander Duyck 		return FM10K_TEST_LEN;
24682dd0f7eSAlexander Duyck 	case ETH_SS_STATS:
247c0e61781SJeff Kirsher 		stats_len += FM10K_QUEUE_STATS_LEN(hw->mac.max_queues);
248fbdb159fSJeff Kirsher 
249fbdb159fSJeff Kirsher 		if (hw->mac.type != fm10k_mac_vf)
250fbdb159fSJeff Kirsher 			stats_len += FM10K_PF_STATS_LEN;
251fbdb159fSJeff Kirsher 
25280043f3bSJacob Keller 		if (interface->flags & FM10K_FLAG_DEBUG_STATS) {
25380043f3bSJacob Keller 			stats_len += FM10K_DEBUG_STATS_LEN;
25480043f3bSJacob Keller 
25580043f3bSJacob Keller 			if (iov_data)
2563d02b3dfSBruce Allan 				stats_len += FM10K_MBX_STATS_LEN *
2573d02b3dfSBruce Allan 					iov_data->num_vfs;
25880043f3bSJacob Keller 		}
25980043f3bSJacob Keller 
260c0e61781SJeff Kirsher 		return stats_len;
26180043f3bSJacob Keller 	case ETH_SS_PRIV_FLAGS:
26280043f3bSJacob Keller 		return FM10K_PRV_FLAG_LEN;
26382dd0f7eSAlexander Duyck 	default:
26482dd0f7eSAlexander Duyck 		return -EOPNOTSUPP;
26582dd0f7eSAlexander Duyck 	}
26682dd0f7eSAlexander Duyck }
26782dd0f7eSAlexander Duyck 
268d2e0721bSJacob Keller static void fm10k_add_ethtool_stats(u64 **data, void *pointer,
269d2e0721bSJacob Keller 				    const struct fm10k_stats stats[],
270d2e0721bSJacob Keller 				    const unsigned int size)
271d2e0721bSJacob Keller {
272d2e0721bSJacob Keller 	unsigned int i;
273d2e0721bSJacob Keller 	char *p;
274d2e0721bSJacob Keller 
275d2e0721bSJacob Keller 	/* simply skip forward if we were not given a valid pointer */
276d2e0721bSJacob Keller 	if (!pointer) {
277d2e0721bSJacob Keller 		*data += size;
278d2e0721bSJacob Keller 		return;
279d2e0721bSJacob Keller 	}
280d2e0721bSJacob Keller 
281d2e0721bSJacob Keller 	for (i = 0; i < size; i++) {
282d2e0721bSJacob Keller 		p = (char *)pointer + stats[i].stat_offset;
283d2e0721bSJacob Keller 
284d2e0721bSJacob Keller 		switch (stats[i].sizeof_stat) {
285d2e0721bSJacob Keller 		case sizeof(u64):
286d2e0721bSJacob Keller 			*((*data)++) = *(u64 *)p;
287d2e0721bSJacob Keller 			break;
288d2e0721bSJacob Keller 		case sizeof(u32):
289d2e0721bSJacob Keller 			*((*data)++) = *(u32 *)p;
290d2e0721bSJacob Keller 			break;
291d2e0721bSJacob Keller 		case sizeof(u16):
292d2e0721bSJacob Keller 			*((*data)++) = *(u16 *)p;
293d2e0721bSJacob Keller 			break;
294d2e0721bSJacob Keller 		case sizeof(u8):
295d2e0721bSJacob Keller 			*((*data)++) = *(u8 *)p;
296d2e0721bSJacob Keller 			break;
297d2e0721bSJacob Keller 		default:
298d2e0721bSJacob Keller 			*((*data)++) = 0;
299d2e0721bSJacob Keller 		}
300d2e0721bSJacob Keller 	}
301d2e0721bSJacob Keller }
302d2e0721bSJacob Keller 
30382dd0f7eSAlexander Duyck static void fm10k_get_ethtool_stats(struct net_device *netdev,
304de445199SJeff Kirsher 				    struct ethtool_stats __always_unused *stats,
305de445199SJeff Kirsher 				    u64 *data)
30682dd0f7eSAlexander Duyck {
30782dd0f7eSAlexander Duyck 	const int stat_count = sizeof(struct fm10k_queue_stats) / sizeof(u64);
30882dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
30980043f3bSJacob Keller 	struct fm10k_iov_data *iov_data = interface->iov_data;
31082dd0f7eSAlexander Duyck 	struct net_device_stats *net_stats = &netdev->stats;
31182dd0f7eSAlexander Duyck 	int i, j;
31282dd0f7eSAlexander Duyck 
31382dd0f7eSAlexander Duyck 	fm10k_update_stats(interface);
31482dd0f7eSAlexander Duyck 
315d2e0721bSJacob Keller 	fm10k_add_ethtool_stats(&data, net_stats, fm10k_gstrings_net_stats,
316d2e0721bSJacob Keller 				FM10K_NETDEV_STATS_LEN);
31782dd0f7eSAlexander Duyck 
318d2e0721bSJacob Keller 	fm10k_add_ethtool_stats(&data, interface, fm10k_gstrings_global_stats,
319d2e0721bSJacob Keller 				FM10K_GLOBAL_STATS_LEN);
320fbdb159fSJeff Kirsher 
321d2e0721bSJacob Keller 	if (interface->flags & FM10K_FLAG_DEBUG_STATS)
322d2e0721bSJacob Keller 		fm10k_add_ethtool_stats(&data, interface,
323d2e0721bSJacob Keller 					fm10k_gstrings_debug_stats,
324d2e0721bSJacob Keller 					FM10K_DEBUG_STATS_LEN);
32580043f3bSJacob Keller 
326d2e0721bSJacob Keller 	fm10k_add_ethtool_stats(&data, &interface->hw.mbx,
327d2e0721bSJacob Keller 				fm10k_gstrings_mbx_stats,
328d2e0721bSJacob Keller 				FM10K_MBX_STATS_LEN);
32980043f3bSJacob Keller 
33080043f3bSJacob Keller 	if (interface->hw.mac.type != fm10k_mac_vf) {
331d2e0721bSJacob Keller 		fm10k_add_ethtool_stats(&data, interface,
332d2e0721bSJacob Keller 					fm10k_gstrings_pf_stats,
333d2e0721bSJacob Keller 					FM10K_PF_STATS_LEN);
33480043f3bSJacob Keller 	}
33580043f3bSJacob Keller 
33680043f3bSJacob Keller 	if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) {
33780043f3bSJacob Keller 		for (i = 0; i < iov_data->num_vfs; i++) {
33880043f3bSJacob Keller 			struct fm10k_vf_info *vf_info;
339a4fcad65SBruce Allan 
34080043f3bSJacob Keller 			vf_info = &iov_data->vf_info[i];
34180043f3bSJacob Keller 
342d2e0721bSJacob Keller 			fm10k_add_ethtool_stats(&data, &vf_info->mbx,
343d2e0721bSJacob Keller 						fm10k_gstrings_mbx_stats,
344d2e0721bSJacob Keller 						FM10K_MBX_STATS_LEN);
34580043f3bSJacob Keller 		}
34680043f3bSJacob Keller 	}
34782dd0f7eSAlexander Duyck 
34829a928eeSJeff Kirsher 	for (i = 0; i < interface->hw.mac.max_queues; i++) {
34982dd0f7eSAlexander Duyck 		struct fm10k_ring *ring;
35082dd0f7eSAlexander Duyck 		u64 *queue_stat;
35182dd0f7eSAlexander Duyck 
35282dd0f7eSAlexander Duyck 		ring = interface->tx_ring[i];
35382dd0f7eSAlexander Duyck 		if (ring)
35482dd0f7eSAlexander Duyck 			queue_stat = (u64 *)&ring->stats;
35582dd0f7eSAlexander Duyck 		for (j = 0; j < stat_count; j++)
35682dd0f7eSAlexander Duyck 			*(data++) = ring ? queue_stat[j] : 0;
35782dd0f7eSAlexander Duyck 
35882dd0f7eSAlexander Duyck 		ring = interface->rx_ring[i];
35982dd0f7eSAlexander Duyck 		if (ring)
36082dd0f7eSAlexander Duyck 			queue_stat = (u64 *)&ring->stats;
36182dd0f7eSAlexander Duyck 		for (j = 0; j < stat_count; j++)
36282dd0f7eSAlexander Duyck 			*(data++) = ring ? queue_stat[j] : 0;
36382dd0f7eSAlexander Duyck 	}
36482dd0f7eSAlexander Duyck }
36582dd0f7eSAlexander Duyck 
36682dd0f7eSAlexander Duyck /* If function below adds more registers this define needs to be updated */
36782dd0f7eSAlexander Duyck #define FM10K_REGS_LEN_Q 29
36882dd0f7eSAlexander Duyck 
36982dd0f7eSAlexander Duyck static void fm10k_get_reg_q(struct fm10k_hw *hw, u32 *buff, int i)
37082dd0f7eSAlexander Duyck {
37182dd0f7eSAlexander Duyck 	int idx = 0;
37282dd0f7eSAlexander Duyck 
37382dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RDBAL(i));
37482dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RDBAH(i));
37582dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RDLEN(i));
37682dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TPH_RXCTRL(i));
37782dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RDH(i));
37882dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RDT(i));
37982dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RXQCTL(i));
38082dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RXDCTL(i));
38182dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_RXINT(i));
38282dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_SRRCTL(i));
38382dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_QPRC(i));
38482dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_QPRDC(i));
38582dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_QBRC_L(i));
38682dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_QBRC_H(i));
38782dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TDBAL(i));
38882dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TDBAH(i));
38982dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TDLEN(i));
39082dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TPH_TXCTRL(i));
39182dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TDH(i));
39282dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TDT(i));
39382dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TXDCTL(i));
39482dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TXQCTL(i));
39582dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TXINT(i));
39682dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_QPTC(i));
39782dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_QBTC_L(i));
39882dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_QBTC_H(i));
39982dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TQDLOC(i));
40082dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_TX_SGLORT(i));
40182dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_PFVTCTL(i));
40282dd0f7eSAlexander Duyck 
40382dd0f7eSAlexander Duyck 	BUG_ON(idx != FM10K_REGS_LEN_Q);
40482dd0f7eSAlexander Duyck }
40582dd0f7eSAlexander Duyck 
40682dd0f7eSAlexander Duyck /* If function above adds more registers this define needs to be updated */
40782dd0f7eSAlexander Duyck #define FM10K_REGS_LEN_VSI 43
40882dd0f7eSAlexander Duyck 
40982dd0f7eSAlexander Duyck static void fm10k_get_reg_vsi(struct fm10k_hw *hw, u32 *buff, int i)
41082dd0f7eSAlexander Duyck {
41182dd0f7eSAlexander Duyck 	int idx = 0, j;
41282dd0f7eSAlexander Duyck 
41382dd0f7eSAlexander Duyck 	buff[idx++] = fm10k_read_reg(hw, FM10K_MRQC(i));
41482dd0f7eSAlexander Duyck 	for (j = 0; j < 10; j++)
41582dd0f7eSAlexander Duyck 		buff[idx++] = fm10k_read_reg(hw, FM10K_RSSRK(i, j));
41682dd0f7eSAlexander Duyck 	for (j = 0; j < 32; j++)
41782dd0f7eSAlexander Duyck 		buff[idx++] = fm10k_read_reg(hw, FM10K_RETA(i, j));
41882dd0f7eSAlexander Duyck 
41982dd0f7eSAlexander Duyck 	BUG_ON(idx != FM10K_REGS_LEN_VSI);
42082dd0f7eSAlexander Duyck }
42182dd0f7eSAlexander Duyck 
42282dd0f7eSAlexander Duyck static void fm10k_get_regs(struct net_device *netdev,
42382dd0f7eSAlexander Duyck 			   struct ethtool_regs *regs, void *p)
42482dd0f7eSAlexander Duyck {
42582dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
42682dd0f7eSAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
42782dd0f7eSAlexander Duyck 	u32 *buff = p;
42882dd0f7eSAlexander Duyck 	u16 i;
42982dd0f7eSAlexander Duyck 
430fcdb0a99SBruce Allan 	regs->version = BIT(24) | (hw->revision_id << 16) | hw->device_id;
43182dd0f7eSAlexander Duyck 
43282dd0f7eSAlexander Duyck 	switch (hw->mac.type) {
43382dd0f7eSAlexander Duyck 	case fm10k_mac_pf:
43482dd0f7eSAlexander Duyck 		/* General PF Registers */
43582dd0f7eSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_CTRL);
43682dd0f7eSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_CTRL_EXT);
43782dd0f7eSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_GCR);
43882dd0f7eSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_GCR_EXT);
43982dd0f7eSAlexander Duyck 
44082dd0f7eSAlexander Duyck 		for (i = 0; i < 8; i++) {
44182dd0f7eSAlexander Duyck 			*(buff++) = fm10k_read_reg(hw, FM10K_DGLORTMAP(i));
44282dd0f7eSAlexander Duyck 			*(buff++) = fm10k_read_reg(hw, FM10K_DGLORTDEC(i));
44382dd0f7eSAlexander Duyck 		}
44482dd0f7eSAlexander Duyck 
44582dd0f7eSAlexander Duyck 		for (i = 0; i < 65; i++) {
44682dd0f7eSAlexander Duyck 			fm10k_get_reg_vsi(hw, buff, i);
44782dd0f7eSAlexander Duyck 			buff += FM10K_REGS_LEN_VSI;
44882dd0f7eSAlexander Duyck 		}
44982dd0f7eSAlexander Duyck 
45082dd0f7eSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_DMA_CTRL);
45182dd0f7eSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_DMA_CTRL2);
45282dd0f7eSAlexander Duyck 
45382dd0f7eSAlexander Duyck 		for (i = 0; i < FM10K_MAX_QUEUES_PF; i++) {
45482dd0f7eSAlexander Duyck 			fm10k_get_reg_q(hw, buff, i);
45582dd0f7eSAlexander Duyck 			buff += FM10K_REGS_LEN_Q;
45682dd0f7eSAlexander Duyck 		}
45782dd0f7eSAlexander Duyck 
45882dd0f7eSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_TPH_CTRL);
45982dd0f7eSAlexander Duyck 
46082dd0f7eSAlexander Duyck 		for (i = 0; i < 8; i++)
46182dd0f7eSAlexander Duyck 			*(buff++) = fm10k_read_reg(hw, FM10K_INT_MAP(i));
46282dd0f7eSAlexander Duyck 
46382dd0f7eSAlexander Duyck 		/* Interrupt Throttling Registers */
46482dd0f7eSAlexander Duyck 		for (i = 0; i < 130; i++)
46582dd0f7eSAlexander Duyck 			*(buff++) = fm10k_read_reg(hw, FM10K_ITR(i));
46682dd0f7eSAlexander Duyck 
46782dd0f7eSAlexander Duyck 		break;
4685cb8db4aSAlexander Duyck 	case fm10k_mac_vf:
4695cb8db4aSAlexander Duyck 		/* General VF registers */
4705cb8db4aSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_VFCTRL);
4715cb8db4aSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_VFINT_MAP);
4725cb8db4aSAlexander Duyck 		*(buff++) = fm10k_read_reg(hw, FM10K_VFSYSTIME);
4735cb8db4aSAlexander Duyck 
4745cb8db4aSAlexander Duyck 		/* Interrupt Throttling Registers */
4755cb8db4aSAlexander Duyck 		for (i = 0; i < 8; i++)
4765cb8db4aSAlexander Duyck 			*(buff++) = fm10k_read_reg(hw, FM10K_VFITR(i));
4775cb8db4aSAlexander Duyck 
4785cb8db4aSAlexander Duyck 		fm10k_get_reg_vsi(hw, buff, 0);
4795cb8db4aSAlexander Duyck 		buff += FM10K_REGS_LEN_VSI;
4805cb8db4aSAlexander Duyck 
4815cb8db4aSAlexander Duyck 		for (i = 0; i < FM10K_MAX_QUEUES_POOL; i++) {
4825cb8db4aSAlexander Duyck 			if (i < hw->mac.max_queues)
4835cb8db4aSAlexander Duyck 				fm10k_get_reg_q(hw, buff, i);
4845cb8db4aSAlexander Duyck 			else
4855cb8db4aSAlexander Duyck 				memset(buff, 0, sizeof(u32) * FM10K_REGS_LEN_Q);
4865cb8db4aSAlexander Duyck 			buff += FM10K_REGS_LEN_Q;
4875cb8db4aSAlexander Duyck 		}
4885cb8db4aSAlexander Duyck 
4895cb8db4aSAlexander Duyck 		break;
49082dd0f7eSAlexander Duyck 	default:
49182dd0f7eSAlexander Duyck 		return;
49282dd0f7eSAlexander Duyck 	}
49382dd0f7eSAlexander Duyck }
49482dd0f7eSAlexander Duyck 
49582dd0f7eSAlexander Duyck /* If function above adds more registers these define need to be updated */
49682dd0f7eSAlexander Duyck #define FM10K_REGS_LEN_PF \
49782dd0f7eSAlexander Duyck (162 + (65 * FM10K_REGS_LEN_VSI) + (FM10K_MAX_QUEUES_PF * FM10K_REGS_LEN_Q))
4985cb8db4aSAlexander Duyck #define FM10K_REGS_LEN_VF \
4995cb8db4aSAlexander Duyck (11 + FM10K_REGS_LEN_VSI + (FM10K_MAX_QUEUES_POOL * FM10K_REGS_LEN_Q))
50082dd0f7eSAlexander Duyck 
50182dd0f7eSAlexander Duyck static int fm10k_get_regs_len(struct net_device *netdev)
50282dd0f7eSAlexander Duyck {
50382dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
50482dd0f7eSAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
50582dd0f7eSAlexander Duyck 
50682dd0f7eSAlexander Duyck 	switch (hw->mac.type) {
50782dd0f7eSAlexander Duyck 	case fm10k_mac_pf:
50882dd0f7eSAlexander Duyck 		return FM10K_REGS_LEN_PF * sizeof(u32);
5095cb8db4aSAlexander Duyck 	case fm10k_mac_vf:
5105cb8db4aSAlexander Duyck 		return FM10K_REGS_LEN_VF * sizeof(u32);
51182dd0f7eSAlexander Duyck 	default:
51282dd0f7eSAlexander Duyck 		return 0;
51382dd0f7eSAlexander Duyck 	}
51482dd0f7eSAlexander Duyck }
51582dd0f7eSAlexander Duyck 
51682dd0f7eSAlexander Duyck static void fm10k_get_drvinfo(struct net_device *dev,
51782dd0f7eSAlexander Duyck 			      struct ethtool_drvinfo *info)
51882dd0f7eSAlexander Duyck {
51982dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
52082dd0f7eSAlexander Duyck 
52182dd0f7eSAlexander Duyck 	strncpy(info->driver, fm10k_driver_name,
52282dd0f7eSAlexander Duyck 		sizeof(info->driver) - 1);
52382dd0f7eSAlexander Duyck 	strncpy(info->version, fm10k_driver_version,
52482dd0f7eSAlexander Duyck 		sizeof(info->version) - 1);
52582dd0f7eSAlexander Duyck 	strncpy(info->bus_info, pci_name(interface->pdev),
52682dd0f7eSAlexander Duyck 		sizeof(info->bus_info) - 1);
52782dd0f7eSAlexander Duyck }
52882dd0f7eSAlexander Duyck 
52982dd0f7eSAlexander Duyck static void fm10k_get_pauseparam(struct net_device *dev,
53082dd0f7eSAlexander Duyck 				 struct ethtool_pauseparam *pause)
53182dd0f7eSAlexander Duyck {
53282dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
53382dd0f7eSAlexander Duyck 
53482dd0f7eSAlexander Duyck 	/* record fixed values for autoneg and tx pause */
53582dd0f7eSAlexander Duyck 	pause->autoneg = 0;
53682dd0f7eSAlexander Duyck 	pause->tx_pause = 1;
53782dd0f7eSAlexander Duyck 
53882dd0f7eSAlexander Duyck 	pause->rx_pause = interface->rx_pause ? 1 : 0;
53982dd0f7eSAlexander Duyck }
54082dd0f7eSAlexander Duyck 
54182dd0f7eSAlexander Duyck static int fm10k_set_pauseparam(struct net_device *dev,
54282dd0f7eSAlexander Duyck 				struct ethtool_pauseparam *pause)
54382dd0f7eSAlexander Duyck {
54482dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
54582dd0f7eSAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
54682dd0f7eSAlexander Duyck 
54782dd0f7eSAlexander Duyck 	if (pause->autoneg || !pause->tx_pause)
54882dd0f7eSAlexander Duyck 		return -EINVAL;
54982dd0f7eSAlexander Duyck 
55082dd0f7eSAlexander Duyck 	/* we can only support pause on the PF to avoid head-of-line blocking */
55182dd0f7eSAlexander Duyck 	if (hw->mac.type == fm10k_mac_pf)
55282dd0f7eSAlexander Duyck 		interface->rx_pause = pause->rx_pause ? ~0 : 0;
55382dd0f7eSAlexander Duyck 	else if (pause->rx_pause)
55482dd0f7eSAlexander Duyck 		return -EINVAL;
55582dd0f7eSAlexander Duyck 
55682dd0f7eSAlexander Duyck 	if (netif_running(dev))
55782dd0f7eSAlexander Duyck 		fm10k_update_rx_drop_en(interface);
55882dd0f7eSAlexander Duyck 
55982dd0f7eSAlexander Duyck 	return 0;
56082dd0f7eSAlexander Duyck }
56182dd0f7eSAlexander Duyck 
56282dd0f7eSAlexander Duyck static u32 fm10k_get_msglevel(struct net_device *netdev)
56382dd0f7eSAlexander Duyck {
56482dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
56582dd0f7eSAlexander Duyck 
56682dd0f7eSAlexander Duyck 	return interface->msg_enable;
56782dd0f7eSAlexander Duyck }
56882dd0f7eSAlexander Duyck 
56982dd0f7eSAlexander Duyck static void fm10k_set_msglevel(struct net_device *netdev, u32 data)
57082dd0f7eSAlexander Duyck {
57182dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
57282dd0f7eSAlexander Duyck 
57382dd0f7eSAlexander Duyck 	interface->msg_enable = data;
57482dd0f7eSAlexander Duyck }
57582dd0f7eSAlexander Duyck 
57682dd0f7eSAlexander Duyck static void fm10k_get_ringparam(struct net_device *netdev,
57782dd0f7eSAlexander Duyck 				struct ethtool_ringparam *ring)
57882dd0f7eSAlexander Duyck {
57982dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
58082dd0f7eSAlexander Duyck 
58182dd0f7eSAlexander Duyck 	ring->rx_max_pending = FM10K_MAX_RXD;
58282dd0f7eSAlexander Duyck 	ring->tx_max_pending = FM10K_MAX_TXD;
58382dd0f7eSAlexander Duyck 	ring->rx_mini_max_pending = 0;
58482dd0f7eSAlexander Duyck 	ring->rx_jumbo_max_pending = 0;
58582dd0f7eSAlexander Duyck 	ring->rx_pending = interface->rx_ring_count;
58682dd0f7eSAlexander Duyck 	ring->tx_pending = interface->tx_ring_count;
58782dd0f7eSAlexander Duyck 	ring->rx_mini_pending = 0;
58882dd0f7eSAlexander Duyck 	ring->rx_jumbo_pending = 0;
58982dd0f7eSAlexander Duyck }
59082dd0f7eSAlexander Duyck 
59182dd0f7eSAlexander Duyck static int fm10k_set_ringparam(struct net_device *netdev,
59282dd0f7eSAlexander Duyck 			       struct ethtool_ringparam *ring)
59382dd0f7eSAlexander Duyck {
59482dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
59582dd0f7eSAlexander Duyck 	struct fm10k_ring *temp_ring;
59682dd0f7eSAlexander Duyck 	int i, err = 0;
59782dd0f7eSAlexander Duyck 	u32 new_rx_count, new_tx_count;
59882dd0f7eSAlexander Duyck 
59982dd0f7eSAlexander Duyck 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
60082dd0f7eSAlexander Duyck 		return -EINVAL;
60182dd0f7eSAlexander Duyck 
60282dd0f7eSAlexander Duyck 	new_tx_count = clamp_t(u32, ring->tx_pending,
60382dd0f7eSAlexander Duyck 			       FM10K_MIN_TXD, FM10K_MAX_TXD);
60482dd0f7eSAlexander Duyck 	new_tx_count = ALIGN(new_tx_count, FM10K_REQ_TX_DESCRIPTOR_MULTIPLE);
60582dd0f7eSAlexander Duyck 
60682dd0f7eSAlexander Duyck 	new_rx_count = clamp_t(u32, ring->rx_pending,
60782dd0f7eSAlexander Duyck 			       FM10K_MIN_RXD, FM10K_MAX_RXD);
60882dd0f7eSAlexander Duyck 	new_rx_count = ALIGN(new_rx_count, FM10K_REQ_RX_DESCRIPTOR_MULTIPLE);
60982dd0f7eSAlexander Duyck 
61082dd0f7eSAlexander Duyck 	if ((new_tx_count == interface->tx_ring_count) &&
61182dd0f7eSAlexander Duyck 	    (new_rx_count == interface->rx_ring_count)) {
61282dd0f7eSAlexander Duyck 		/* nothing to do */
61382dd0f7eSAlexander Duyck 		return 0;
61482dd0f7eSAlexander Duyck 	}
61582dd0f7eSAlexander Duyck 
61682dd0f7eSAlexander Duyck 	while (test_and_set_bit(__FM10K_RESETTING, &interface->state))
61782dd0f7eSAlexander Duyck 		usleep_range(1000, 2000);
61882dd0f7eSAlexander Duyck 
61982dd0f7eSAlexander Duyck 	if (!netif_running(interface->netdev)) {
62082dd0f7eSAlexander Duyck 		for (i = 0; i < interface->num_tx_queues; i++)
62182dd0f7eSAlexander Duyck 			interface->tx_ring[i]->count = new_tx_count;
62282dd0f7eSAlexander Duyck 		for (i = 0; i < interface->num_rx_queues; i++)
62382dd0f7eSAlexander Duyck 			interface->rx_ring[i]->count = new_rx_count;
62482dd0f7eSAlexander Duyck 		interface->tx_ring_count = new_tx_count;
62582dd0f7eSAlexander Duyck 		interface->rx_ring_count = new_rx_count;
62682dd0f7eSAlexander Duyck 		goto clear_reset;
62782dd0f7eSAlexander Duyck 	}
62882dd0f7eSAlexander Duyck 
62982dd0f7eSAlexander Duyck 	/* allocate temporary buffer to store rings in */
63082dd0f7eSAlexander Duyck 	i = max_t(int, interface->num_tx_queues, interface->num_rx_queues);
63182dd0f7eSAlexander Duyck 	temp_ring = vmalloc(i * sizeof(struct fm10k_ring));
63282dd0f7eSAlexander Duyck 
63382dd0f7eSAlexander Duyck 	if (!temp_ring) {
63482dd0f7eSAlexander Duyck 		err = -ENOMEM;
63582dd0f7eSAlexander Duyck 		goto clear_reset;
63682dd0f7eSAlexander Duyck 	}
63782dd0f7eSAlexander Duyck 
63882dd0f7eSAlexander Duyck 	fm10k_down(interface);
63982dd0f7eSAlexander Duyck 
64082dd0f7eSAlexander Duyck 	/* Setup new Tx resources and free the old Tx resources in that order.
64182dd0f7eSAlexander Duyck 	 * We can then assign the new resources to the rings via a memcpy.
64282dd0f7eSAlexander Duyck 	 * The advantage to this approach is that we are guaranteed to still
64382dd0f7eSAlexander Duyck 	 * have resources even in the case of an allocation failure.
64482dd0f7eSAlexander Duyck 	 */
64582dd0f7eSAlexander Duyck 	if (new_tx_count != interface->tx_ring_count) {
64682dd0f7eSAlexander Duyck 		for (i = 0; i < interface->num_tx_queues; i++) {
64782dd0f7eSAlexander Duyck 			memcpy(&temp_ring[i], interface->tx_ring[i],
64882dd0f7eSAlexander Duyck 			       sizeof(struct fm10k_ring));
64982dd0f7eSAlexander Duyck 
65082dd0f7eSAlexander Duyck 			temp_ring[i].count = new_tx_count;
65182dd0f7eSAlexander Duyck 			err = fm10k_setup_tx_resources(&temp_ring[i]);
65282dd0f7eSAlexander Duyck 			if (err) {
65382dd0f7eSAlexander Duyck 				while (i) {
65482dd0f7eSAlexander Duyck 					i--;
65582dd0f7eSAlexander Duyck 					fm10k_free_tx_resources(&temp_ring[i]);
65682dd0f7eSAlexander Duyck 				}
65782dd0f7eSAlexander Duyck 				goto err_setup;
65882dd0f7eSAlexander Duyck 			}
65982dd0f7eSAlexander Duyck 		}
66082dd0f7eSAlexander Duyck 
66182dd0f7eSAlexander Duyck 		for (i = 0; i < interface->num_tx_queues; i++) {
66282dd0f7eSAlexander Duyck 			fm10k_free_tx_resources(interface->tx_ring[i]);
66382dd0f7eSAlexander Duyck 
66482dd0f7eSAlexander Duyck 			memcpy(interface->tx_ring[i], &temp_ring[i],
66582dd0f7eSAlexander Duyck 			       sizeof(struct fm10k_ring));
66682dd0f7eSAlexander Duyck 		}
66782dd0f7eSAlexander Duyck 
66882dd0f7eSAlexander Duyck 		interface->tx_ring_count = new_tx_count;
66982dd0f7eSAlexander Duyck 	}
67082dd0f7eSAlexander Duyck 
67182dd0f7eSAlexander Duyck 	/* Repeat the process for the Rx rings if needed */
67282dd0f7eSAlexander Duyck 	if (new_rx_count != interface->rx_ring_count) {
67382dd0f7eSAlexander Duyck 		for (i = 0; i < interface->num_rx_queues; i++) {
67482dd0f7eSAlexander Duyck 			memcpy(&temp_ring[i], interface->rx_ring[i],
67582dd0f7eSAlexander Duyck 			       sizeof(struct fm10k_ring));
67682dd0f7eSAlexander Duyck 
67782dd0f7eSAlexander Duyck 			temp_ring[i].count = new_rx_count;
67882dd0f7eSAlexander Duyck 			err = fm10k_setup_rx_resources(&temp_ring[i]);
67982dd0f7eSAlexander Duyck 			if (err) {
68082dd0f7eSAlexander Duyck 				while (i) {
68182dd0f7eSAlexander Duyck 					i--;
68282dd0f7eSAlexander Duyck 					fm10k_free_rx_resources(&temp_ring[i]);
68382dd0f7eSAlexander Duyck 				}
68482dd0f7eSAlexander Duyck 				goto err_setup;
68582dd0f7eSAlexander Duyck 			}
68682dd0f7eSAlexander Duyck 		}
68782dd0f7eSAlexander Duyck 
68882dd0f7eSAlexander Duyck 		for (i = 0; i < interface->num_rx_queues; i++) {
68982dd0f7eSAlexander Duyck 			fm10k_free_rx_resources(interface->rx_ring[i]);
69082dd0f7eSAlexander Duyck 
69182dd0f7eSAlexander Duyck 			memcpy(interface->rx_ring[i], &temp_ring[i],
69282dd0f7eSAlexander Duyck 			       sizeof(struct fm10k_ring));
69382dd0f7eSAlexander Duyck 		}
69482dd0f7eSAlexander Duyck 
69582dd0f7eSAlexander Duyck 		interface->rx_ring_count = new_rx_count;
69682dd0f7eSAlexander Duyck 	}
69782dd0f7eSAlexander Duyck 
69882dd0f7eSAlexander Duyck err_setup:
69982dd0f7eSAlexander Duyck 	fm10k_up(interface);
70082dd0f7eSAlexander Duyck 	vfree(temp_ring);
70182dd0f7eSAlexander Duyck clear_reset:
70282dd0f7eSAlexander Duyck 	clear_bit(__FM10K_RESETTING, &interface->state);
70382dd0f7eSAlexander Duyck 	return err;
70482dd0f7eSAlexander Duyck }
70582dd0f7eSAlexander Duyck 
70682dd0f7eSAlexander Duyck static int fm10k_get_coalesce(struct net_device *dev,
70782dd0f7eSAlexander Duyck 			      struct ethtool_coalesce *ec)
70882dd0f7eSAlexander Duyck {
70982dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
71082dd0f7eSAlexander Duyck 
711584373f5SJacob Keller 	ec->use_adaptive_tx_coalesce = ITR_IS_ADAPTIVE(interface->tx_itr);
71282dd0f7eSAlexander Duyck 	ec->tx_coalesce_usecs = interface->tx_itr & ~FM10K_ITR_ADAPTIVE;
71382dd0f7eSAlexander Duyck 
714584373f5SJacob Keller 	ec->use_adaptive_rx_coalesce = ITR_IS_ADAPTIVE(interface->rx_itr);
71582dd0f7eSAlexander Duyck 	ec->rx_coalesce_usecs = interface->rx_itr & ~FM10K_ITR_ADAPTIVE;
71682dd0f7eSAlexander Duyck 
71782dd0f7eSAlexander Duyck 	return 0;
71882dd0f7eSAlexander Duyck }
71982dd0f7eSAlexander Duyck 
72082dd0f7eSAlexander Duyck static int fm10k_set_coalesce(struct net_device *dev,
72182dd0f7eSAlexander Duyck 			      struct ethtool_coalesce *ec)
72282dd0f7eSAlexander Duyck {
72382dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
72482dd0f7eSAlexander Duyck 	struct fm10k_q_vector *qv;
72582dd0f7eSAlexander Duyck 	u16 tx_itr, rx_itr;
72682dd0f7eSAlexander Duyck 	int i;
72782dd0f7eSAlexander Duyck 
72882dd0f7eSAlexander Duyck 	/* verify limits */
72982dd0f7eSAlexander Duyck 	if ((ec->rx_coalesce_usecs > FM10K_ITR_MAX) ||
73082dd0f7eSAlexander Duyck 	    (ec->tx_coalesce_usecs > FM10K_ITR_MAX))
73182dd0f7eSAlexander Duyck 		return -EINVAL;
73282dd0f7eSAlexander Duyck 
73382dd0f7eSAlexander Duyck 	/* record settings */
73482dd0f7eSAlexander Duyck 	tx_itr = ec->tx_coalesce_usecs;
73582dd0f7eSAlexander Duyck 	rx_itr = ec->rx_coalesce_usecs;
73682dd0f7eSAlexander Duyck 
73782dd0f7eSAlexander Duyck 	/* set initial values for adaptive ITR */
73882dd0f7eSAlexander Duyck 	if (ec->use_adaptive_tx_coalesce)
739436ea956SJacob Keller 		tx_itr = FM10K_ITR_ADAPTIVE | FM10K_TX_ITR_DEFAULT;
74082dd0f7eSAlexander Duyck 
74182dd0f7eSAlexander Duyck 	if (ec->use_adaptive_rx_coalesce)
742436ea956SJacob Keller 		rx_itr = FM10K_ITR_ADAPTIVE | FM10K_RX_ITR_DEFAULT;
74382dd0f7eSAlexander Duyck 
74482dd0f7eSAlexander Duyck 	/* update interface */
74582dd0f7eSAlexander Duyck 	interface->tx_itr = tx_itr;
74682dd0f7eSAlexander Duyck 	interface->rx_itr = rx_itr;
74782dd0f7eSAlexander Duyck 
74882dd0f7eSAlexander Duyck 	/* update q_vectors */
74982dd0f7eSAlexander Duyck 	for (i = 0; i < interface->num_q_vectors; i++) {
75082dd0f7eSAlexander Duyck 		qv = interface->q_vector[i];
75182dd0f7eSAlexander Duyck 		qv->tx.itr = tx_itr;
75282dd0f7eSAlexander Duyck 		qv->rx.itr = rx_itr;
75382dd0f7eSAlexander Duyck 	}
75482dd0f7eSAlexander Duyck 
75582dd0f7eSAlexander Duyck 	return 0;
75682dd0f7eSAlexander Duyck }
75782dd0f7eSAlexander Duyck 
75882dd0f7eSAlexander Duyck static int fm10k_get_rss_hash_opts(struct fm10k_intfc *interface,
75982dd0f7eSAlexander Duyck 				   struct ethtool_rxnfc *cmd)
76082dd0f7eSAlexander Duyck {
76182dd0f7eSAlexander Duyck 	cmd->data = 0;
76282dd0f7eSAlexander Duyck 
76382dd0f7eSAlexander Duyck 	/* Report default options for RSS on fm10k */
76482dd0f7eSAlexander Duyck 	switch (cmd->flow_type) {
76582dd0f7eSAlexander Duyck 	case TCP_V4_FLOW:
76682dd0f7eSAlexander Duyck 	case TCP_V6_FLOW:
76782dd0f7eSAlexander Duyck 		cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
76882dd0f7eSAlexander Duyck 		/* fall through */
76982dd0f7eSAlexander Duyck 	case UDP_V4_FLOW:
77082dd0f7eSAlexander Duyck 		if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV4_UDP)
77182dd0f7eSAlexander Duyck 			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
77282dd0f7eSAlexander Duyck 		/* fall through */
77382dd0f7eSAlexander Duyck 	case SCTP_V4_FLOW:
77482dd0f7eSAlexander Duyck 	case SCTP_V6_FLOW:
77582dd0f7eSAlexander Duyck 	case AH_ESP_V4_FLOW:
77682dd0f7eSAlexander Duyck 	case AH_ESP_V6_FLOW:
77782dd0f7eSAlexander Duyck 	case AH_V4_FLOW:
77882dd0f7eSAlexander Duyck 	case AH_V6_FLOW:
77982dd0f7eSAlexander Duyck 	case ESP_V4_FLOW:
78082dd0f7eSAlexander Duyck 	case ESP_V6_FLOW:
78182dd0f7eSAlexander Duyck 	case IPV4_FLOW:
78282dd0f7eSAlexander Duyck 	case IPV6_FLOW:
78382dd0f7eSAlexander Duyck 		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
78482dd0f7eSAlexander Duyck 		break;
78582dd0f7eSAlexander Duyck 	case UDP_V6_FLOW:
78682dd0f7eSAlexander Duyck 		if (interface->flags & FM10K_FLAG_RSS_FIELD_IPV6_UDP)
78782dd0f7eSAlexander Duyck 			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
78882dd0f7eSAlexander Duyck 		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
78982dd0f7eSAlexander Duyck 		break;
79082dd0f7eSAlexander Duyck 	default:
79182dd0f7eSAlexander Duyck 		return -EINVAL;
79282dd0f7eSAlexander Duyck 	}
79382dd0f7eSAlexander Duyck 
79482dd0f7eSAlexander Duyck 	return 0;
79582dd0f7eSAlexander Duyck }
79682dd0f7eSAlexander Duyck 
79782dd0f7eSAlexander Duyck static int fm10k_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
798de445199SJeff Kirsher 			   u32 __always_unused *rule_locs)
79982dd0f7eSAlexander Duyck {
80082dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
80182dd0f7eSAlexander Duyck 	int ret = -EOPNOTSUPP;
80282dd0f7eSAlexander Duyck 
80382dd0f7eSAlexander Duyck 	switch (cmd->cmd) {
80482dd0f7eSAlexander Duyck 	case ETHTOOL_GRXRINGS:
80582dd0f7eSAlexander Duyck 		cmd->data = interface->num_rx_queues;
80682dd0f7eSAlexander Duyck 		ret = 0;
80782dd0f7eSAlexander Duyck 		break;
80882dd0f7eSAlexander Duyck 	case ETHTOOL_GRXFH:
80982dd0f7eSAlexander Duyck 		ret = fm10k_get_rss_hash_opts(interface, cmd);
81082dd0f7eSAlexander Duyck 		break;
81182dd0f7eSAlexander Duyck 	default:
81282dd0f7eSAlexander Duyck 		break;
81382dd0f7eSAlexander Duyck 	}
81482dd0f7eSAlexander Duyck 
81582dd0f7eSAlexander Duyck 	return ret;
81682dd0f7eSAlexander Duyck }
81782dd0f7eSAlexander Duyck 
81882dd0f7eSAlexander Duyck #define UDP_RSS_FLAGS (FM10K_FLAG_RSS_FIELD_IPV4_UDP | \
81982dd0f7eSAlexander Duyck 		       FM10K_FLAG_RSS_FIELD_IPV6_UDP)
82082dd0f7eSAlexander Duyck static int fm10k_set_rss_hash_opt(struct fm10k_intfc *interface,
82182dd0f7eSAlexander Duyck 				  struct ethtool_rxnfc *nfc)
82282dd0f7eSAlexander Duyck {
82382dd0f7eSAlexander Duyck 	u32 flags = interface->flags;
82482dd0f7eSAlexander Duyck 
82582dd0f7eSAlexander Duyck 	/* RSS does not support anything other than hashing
82682dd0f7eSAlexander Duyck 	 * to queues on src and dst IPs and ports
82782dd0f7eSAlexander Duyck 	 */
82882dd0f7eSAlexander Duyck 	if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
82982dd0f7eSAlexander Duyck 			  RXH_L4_B_0_1 | RXH_L4_B_2_3))
83082dd0f7eSAlexander Duyck 		return -EINVAL;
83182dd0f7eSAlexander Duyck 
83282dd0f7eSAlexander Duyck 	switch (nfc->flow_type) {
83382dd0f7eSAlexander Duyck 	case TCP_V4_FLOW:
83482dd0f7eSAlexander Duyck 	case TCP_V6_FLOW:
83582dd0f7eSAlexander Duyck 		if (!(nfc->data & RXH_IP_SRC) ||
83682dd0f7eSAlexander Duyck 		    !(nfc->data & RXH_IP_DST) ||
83782dd0f7eSAlexander Duyck 		    !(nfc->data & RXH_L4_B_0_1) ||
83882dd0f7eSAlexander Duyck 		    !(nfc->data & RXH_L4_B_2_3))
83982dd0f7eSAlexander Duyck 			return -EINVAL;
84082dd0f7eSAlexander Duyck 		break;
84182dd0f7eSAlexander Duyck 	case UDP_V4_FLOW:
84282dd0f7eSAlexander Duyck 		if (!(nfc->data & RXH_IP_SRC) ||
84382dd0f7eSAlexander Duyck 		    !(nfc->data & RXH_IP_DST))
84482dd0f7eSAlexander Duyck 			return -EINVAL;
84582dd0f7eSAlexander Duyck 		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
84682dd0f7eSAlexander Duyck 		case 0:
84782dd0f7eSAlexander Duyck 			flags &= ~FM10K_FLAG_RSS_FIELD_IPV4_UDP;
84882dd0f7eSAlexander Duyck 			break;
84982dd0f7eSAlexander Duyck 		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
85082dd0f7eSAlexander Duyck 			flags |= FM10K_FLAG_RSS_FIELD_IPV4_UDP;
85182dd0f7eSAlexander Duyck 			break;
85282dd0f7eSAlexander Duyck 		default:
85382dd0f7eSAlexander Duyck 			return -EINVAL;
85482dd0f7eSAlexander Duyck 		}
85582dd0f7eSAlexander Duyck 		break;
85682dd0f7eSAlexander Duyck 	case UDP_V6_FLOW:
85782dd0f7eSAlexander Duyck 		if (!(nfc->data & RXH_IP_SRC) ||
85882dd0f7eSAlexander Duyck 		    !(nfc->data & RXH_IP_DST))
85982dd0f7eSAlexander Duyck 			return -EINVAL;
86082dd0f7eSAlexander Duyck 		switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
86182dd0f7eSAlexander Duyck 		case 0:
86282dd0f7eSAlexander Duyck 			flags &= ~FM10K_FLAG_RSS_FIELD_IPV6_UDP;
86382dd0f7eSAlexander Duyck 			break;
86482dd0f7eSAlexander Duyck 		case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
86582dd0f7eSAlexander Duyck 			flags |= FM10K_FLAG_RSS_FIELD_IPV6_UDP;
86682dd0f7eSAlexander Duyck 			break;
86782dd0f7eSAlexander Duyck 		default:
86882dd0f7eSAlexander Duyck 			return -EINVAL;
86982dd0f7eSAlexander Duyck 		}
87082dd0f7eSAlexander Duyck 		break;
87182dd0f7eSAlexander Duyck 	case AH_ESP_V4_FLOW:
87282dd0f7eSAlexander Duyck 	case AH_V4_FLOW:
87382dd0f7eSAlexander Duyck 	case ESP_V4_FLOW:
87482dd0f7eSAlexander Duyck 	case SCTP_V4_FLOW:
87582dd0f7eSAlexander Duyck 	case AH_ESP_V6_FLOW:
87682dd0f7eSAlexander Duyck 	case AH_V6_FLOW:
87782dd0f7eSAlexander Duyck 	case ESP_V6_FLOW:
87882dd0f7eSAlexander Duyck 	case SCTP_V6_FLOW:
87982dd0f7eSAlexander Duyck 		if (!(nfc->data & RXH_IP_SRC) ||
88082dd0f7eSAlexander Duyck 		    !(nfc->data & RXH_IP_DST) ||
88182dd0f7eSAlexander Duyck 		    (nfc->data & RXH_L4_B_0_1) ||
88282dd0f7eSAlexander Duyck 		    (nfc->data & RXH_L4_B_2_3))
88382dd0f7eSAlexander Duyck 			return -EINVAL;
88482dd0f7eSAlexander Duyck 		break;
88582dd0f7eSAlexander Duyck 	default:
88682dd0f7eSAlexander Duyck 		return -EINVAL;
88782dd0f7eSAlexander Duyck 	}
88882dd0f7eSAlexander Duyck 
88982dd0f7eSAlexander Duyck 	/* if we changed something we need to update flags */
89082dd0f7eSAlexander Duyck 	if (flags != interface->flags) {
89182dd0f7eSAlexander Duyck 		struct fm10k_hw *hw = &interface->hw;
89282dd0f7eSAlexander Duyck 		u32 mrqc;
89382dd0f7eSAlexander Duyck 
89482dd0f7eSAlexander Duyck 		if ((flags & UDP_RSS_FLAGS) &&
89582dd0f7eSAlexander Duyck 		    !(interface->flags & UDP_RSS_FLAGS))
89682dd0f7eSAlexander Duyck 			netif_warn(interface, drv, interface->netdev,
89782dd0f7eSAlexander Duyck 				   "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
89882dd0f7eSAlexander Duyck 
89982dd0f7eSAlexander Duyck 		interface->flags = flags;
90082dd0f7eSAlexander Duyck 
90182dd0f7eSAlexander Duyck 		/* Perform hash on these packet types */
90282dd0f7eSAlexander Duyck 		mrqc = FM10K_MRQC_IPV4 |
90382dd0f7eSAlexander Duyck 		       FM10K_MRQC_TCP_IPV4 |
90482dd0f7eSAlexander Duyck 		       FM10K_MRQC_IPV6 |
90582dd0f7eSAlexander Duyck 		       FM10K_MRQC_TCP_IPV6;
90682dd0f7eSAlexander Duyck 
90782dd0f7eSAlexander Duyck 		if (flags & FM10K_FLAG_RSS_FIELD_IPV4_UDP)
90882dd0f7eSAlexander Duyck 			mrqc |= FM10K_MRQC_UDP_IPV4;
90982dd0f7eSAlexander Duyck 		if (flags & FM10K_FLAG_RSS_FIELD_IPV6_UDP)
91082dd0f7eSAlexander Duyck 			mrqc |= FM10K_MRQC_UDP_IPV6;
91182dd0f7eSAlexander Duyck 
91282dd0f7eSAlexander Duyck 		fm10k_write_reg(hw, FM10K_MRQC(0), mrqc);
91382dd0f7eSAlexander Duyck 	}
91482dd0f7eSAlexander Duyck 
91582dd0f7eSAlexander Duyck 	return 0;
91682dd0f7eSAlexander Duyck }
91782dd0f7eSAlexander Duyck 
91882dd0f7eSAlexander Duyck static int fm10k_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
91982dd0f7eSAlexander Duyck {
92082dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
92182dd0f7eSAlexander Duyck 	int ret = -EOPNOTSUPP;
92282dd0f7eSAlexander Duyck 
92382dd0f7eSAlexander Duyck 	switch (cmd->cmd) {
92482dd0f7eSAlexander Duyck 	case ETHTOOL_SRXFH:
92582dd0f7eSAlexander Duyck 		ret = fm10k_set_rss_hash_opt(interface, cmd);
92682dd0f7eSAlexander Duyck 		break;
92782dd0f7eSAlexander Duyck 	default:
92882dd0f7eSAlexander Duyck 		break;
92982dd0f7eSAlexander Duyck 	}
93082dd0f7eSAlexander Duyck 
93182dd0f7eSAlexander Duyck 	return ret;
93282dd0f7eSAlexander Duyck }
93382dd0f7eSAlexander Duyck 
9345cb8db4aSAlexander Duyck static int fm10k_mbx_test(struct fm10k_intfc *interface, u64 *data)
9355cb8db4aSAlexander Duyck {
9365cb8db4aSAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
9375cb8db4aSAlexander Duyck 	struct fm10k_mbx_info *mbx = &hw->mbx;
9385cb8db4aSAlexander Duyck 	u32 attr_flag, test_msg[6];
9395cb8db4aSAlexander Duyck 	unsigned long timeout;
940c4114e3dSBruce Allan 	int err = -EINVAL;
9415cb8db4aSAlexander Duyck 
9425cb8db4aSAlexander Duyck 	/* For now this is a VF only feature */
9435cb8db4aSAlexander Duyck 	if (hw->mac.type != fm10k_mac_vf)
9445cb8db4aSAlexander Duyck 		return 0;
9455cb8db4aSAlexander Duyck 
9465cb8db4aSAlexander Duyck 	/* loop through both nested and unnested attribute types */
947fcdb0a99SBruce Allan 	for (attr_flag = BIT(FM10K_TEST_MSG_UNSET);
948fcdb0a99SBruce Allan 	     attr_flag < BIT(2 * FM10K_TEST_MSG_NESTED);
9495cb8db4aSAlexander Duyck 	     attr_flag += attr_flag) {
9505cb8db4aSAlexander Duyck 		/* generate message to be tested */
9515cb8db4aSAlexander Duyck 		fm10k_tlv_msg_test_create(test_msg, attr_flag);
9525cb8db4aSAlexander Duyck 
9535cb8db4aSAlexander Duyck 		fm10k_mbx_lock(interface);
9545cb8db4aSAlexander Duyck 		mbx->test_result = FM10K_NOT_IMPLEMENTED;
9555cb8db4aSAlexander Duyck 		err = mbx->ops.enqueue_tx(hw, mbx, test_msg);
9565cb8db4aSAlexander Duyck 		fm10k_mbx_unlock(interface);
9575cb8db4aSAlexander Duyck 
9585cb8db4aSAlexander Duyck 		/* wait up to 1 second for response */
9595cb8db4aSAlexander Duyck 		timeout = jiffies + HZ;
9605cb8db4aSAlexander Duyck 		do {
9615cb8db4aSAlexander Duyck 			if (err < 0)
9625cb8db4aSAlexander Duyck 				goto err_out;
9635cb8db4aSAlexander Duyck 
9645cb8db4aSAlexander Duyck 			usleep_range(500, 1000);
9655cb8db4aSAlexander Duyck 
9665cb8db4aSAlexander Duyck 			fm10k_mbx_lock(interface);
9675cb8db4aSAlexander Duyck 			mbx->ops.process(hw, mbx);
9685cb8db4aSAlexander Duyck 			fm10k_mbx_unlock(interface);
9695cb8db4aSAlexander Duyck 
9705cb8db4aSAlexander Duyck 			err = mbx->test_result;
9715cb8db4aSAlexander Duyck 			if (!err)
9725cb8db4aSAlexander Duyck 				break;
9735cb8db4aSAlexander Duyck 		} while (time_is_after_jiffies(timeout));
9745cb8db4aSAlexander Duyck 
9755cb8db4aSAlexander Duyck 		/* reporting errors */
9765cb8db4aSAlexander Duyck 		if (err)
9775cb8db4aSAlexander Duyck 			goto err_out;
9785cb8db4aSAlexander Duyck 	}
9795cb8db4aSAlexander Duyck 
9805cb8db4aSAlexander Duyck err_out:
9815cb8db4aSAlexander Duyck 	*data = err < 0 ? (attr_flag) : (err > 0);
9825cb8db4aSAlexander Duyck 	return err;
9835cb8db4aSAlexander Duyck }
9845cb8db4aSAlexander Duyck 
9855cb8db4aSAlexander Duyck static void fm10k_self_test(struct net_device *dev,
9865cb8db4aSAlexander Duyck 			    struct ethtool_test *eth_test, u64 *data)
9875cb8db4aSAlexander Duyck {
9885cb8db4aSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
9895cb8db4aSAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
9905cb8db4aSAlexander Duyck 
9915cb8db4aSAlexander Duyck 	memset(data, 0, sizeof(*data) * FM10K_TEST_LEN);
9925cb8db4aSAlexander Duyck 
9935cb8db4aSAlexander Duyck 	if (FM10K_REMOVED(hw)) {
9945cb8db4aSAlexander Duyck 		netif_err(interface, drv, dev,
9955cb8db4aSAlexander Duyck 			  "Interface removed - test blocked\n");
9965cb8db4aSAlexander Duyck 		eth_test->flags |= ETH_TEST_FL_FAILED;
9975cb8db4aSAlexander Duyck 		return;
9985cb8db4aSAlexander Duyck 	}
9995cb8db4aSAlexander Duyck 
10005cb8db4aSAlexander Duyck 	if (fm10k_mbx_test(interface, &data[FM10K_TEST_MBX]))
10015cb8db4aSAlexander Duyck 		eth_test->flags |= ETH_TEST_FL_FAILED;
10025cb8db4aSAlexander Duyck }
10035cb8db4aSAlexander Duyck 
100480043f3bSJacob Keller static u32 fm10k_get_priv_flags(struct net_device *netdev)
100580043f3bSJacob Keller {
100680043f3bSJacob Keller 	struct fm10k_intfc *interface = netdev_priv(netdev);
100780043f3bSJacob Keller 	u32 priv_flags = 0;
100880043f3bSJacob Keller 
100980043f3bSJacob Keller 	if (interface->flags & FM10K_FLAG_DEBUG_STATS)
1010fcdb0a99SBruce Allan 		priv_flags |= BIT(FM10K_PRV_FLAG_DEBUG_STATS);
101180043f3bSJacob Keller 
101280043f3bSJacob Keller 	return priv_flags;
101380043f3bSJacob Keller }
101480043f3bSJacob Keller 
101580043f3bSJacob Keller static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags)
101680043f3bSJacob Keller {
101780043f3bSJacob Keller 	struct fm10k_intfc *interface = netdev_priv(netdev);
101880043f3bSJacob Keller 
1019fcdb0a99SBruce Allan 	if (priv_flags >= BIT(FM10K_PRV_FLAG_LEN))
102080043f3bSJacob Keller 		return -EINVAL;
102180043f3bSJacob Keller 
1022fcdb0a99SBruce Allan 	if (priv_flags & BIT(FM10K_PRV_FLAG_DEBUG_STATS))
102380043f3bSJacob Keller 		interface->flags |= FM10K_FLAG_DEBUG_STATS;
102480043f3bSJacob Keller 	else
102580043f3bSJacob Keller 		interface->flags &= ~FM10K_FLAG_DEBUG_STATS;
102680043f3bSJacob Keller 
102780043f3bSJacob Keller 	return 0;
102880043f3bSJacob Keller }
102980043f3bSJacob Keller 
10300ea7fae4SJacob Keller u32 fm10k_get_reta_size(struct net_device __always_unused *netdev)
103182dd0f7eSAlexander Duyck {
103282dd0f7eSAlexander Duyck 	return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG;
103382dd0f7eSAlexander Duyck }
103482dd0f7eSAlexander Duyck 
10350ea7fae4SJacob Keller void fm10k_write_reta(struct fm10k_intfc *interface, const u32 *indir)
10360ea7fae4SJacob Keller {
10370ea7fae4SJacob Keller 	struct fm10k_hw *hw = &interface->hw;
10380ea7fae4SJacob Keller 	int i;
10390ea7fae4SJacob Keller 
10400ea7fae4SJacob Keller 	/* record entries to reta table */
10410ea7fae4SJacob Keller 	for (i = 0; i < FM10K_RETA_SIZE; i++, indir += 4) {
10420ea7fae4SJacob Keller 		u32 reta = indir[0] |
10430ea7fae4SJacob Keller 			   (indir[1] << 8) |
10440ea7fae4SJacob Keller 			   (indir[2] << 16) |
10450ea7fae4SJacob Keller 			   (indir[3] << 24);
10460ea7fae4SJacob Keller 
10470ea7fae4SJacob Keller 		if (interface->reta[i] == reta)
10480ea7fae4SJacob Keller 			continue;
10490ea7fae4SJacob Keller 
10500ea7fae4SJacob Keller 		interface->reta[i] = reta;
10510ea7fae4SJacob Keller 		fm10k_write_reg(hw, FM10K_RETA(0, i), reta);
10520ea7fae4SJacob Keller 	}
10530ea7fae4SJacob Keller }
10540ea7fae4SJacob Keller 
105582dd0f7eSAlexander Duyck static int fm10k_get_reta(struct net_device *netdev, u32 *indir)
105682dd0f7eSAlexander Duyck {
105782dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
105882dd0f7eSAlexander Duyck 	int i;
105982dd0f7eSAlexander Duyck 
106082dd0f7eSAlexander Duyck 	if (!indir)
106182dd0f7eSAlexander Duyck 		return 0;
106282dd0f7eSAlexander Duyck 
106382dd0f7eSAlexander Duyck 	for (i = 0; i < FM10K_RETA_SIZE; i++, indir += 4) {
106482dd0f7eSAlexander Duyck 		u32 reta = interface->reta[i];
106582dd0f7eSAlexander Duyck 
106682dd0f7eSAlexander Duyck 		indir[0] = (reta << 24) >> 24;
106782dd0f7eSAlexander Duyck 		indir[1] = (reta << 16) >> 24;
106882dd0f7eSAlexander Duyck 		indir[2] = (reta <<  8) >> 24;
106982dd0f7eSAlexander Duyck 		indir[3] = (reta) >> 24;
107082dd0f7eSAlexander Duyck 	}
107182dd0f7eSAlexander Duyck 
107282dd0f7eSAlexander Duyck 	return 0;
107382dd0f7eSAlexander Duyck }
107482dd0f7eSAlexander Duyck 
107582dd0f7eSAlexander Duyck static int fm10k_set_reta(struct net_device *netdev, const u32 *indir)
107682dd0f7eSAlexander Duyck {
107782dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
107882dd0f7eSAlexander Duyck 	int i;
107982dd0f7eSAlexander Duyck 	u16 rss_i;
108082dd0f7eSAlexander Duyck 
108182dd0f7eSAlexander Duyck 	if (!indir)
108282dd0f7eSAlexander Duyck 		return 0;
108382dd0f7eSAlexander Duyck 
108482dd0f7eSAlexander Duyck 	/* Verify user input. */
108582dd0f7eSAlexander Duyck 	rss_i = interface->ring_feature[RING_F_RSS].indices;
108682dd0f7eSAlexander Duyck 	for (i = fm10k_get_reta_size(netdev); i--;) {
108782dd0f7eSAlexander Duyck 		if (indir[i] < rss_i)
108882dd0f7eSAlexander Duyck 			continue;
108982dd0f7eSAlexander Duyck 		return -EINVAL;
109082dd0f7eSAlexander Duyck 	}
109182dd0f7eSAlexander Duyck 
10920ea7fae4SJacob Keller 	fm10k_write_reta(interface, indir);
109382dd0f7eSAlexander Duyck 
109482dd0f7eSAlexander Duyck 	return 0;
109582dd0f7eSAlexander Duyck }
109682dd0f7eSAlexander Duyck 
1097de445199SJeff Kirsher static u32 fm10k_get_rssrk_size(struct net_device __always_unused *netdev)
109882dd0f7eSAlexander Duyck {
109982dd0f7eSAlexander Duyck 	return FM10K_RSSRK_SIZE * FM10K_RSSRK_ENTRIES_PER_REG;
110082dd0f7eSAlexander Duyck }
110182dd0f7eSAlexander Duyck 
1102892311f6SEyal Perry static int fm10k_get_rssh(struct net_device *netdev, u32 *indir, u8 *key,
1103892311f6SEyal Perry 			  u8 *hfunc)
110482dd0f7eSAlexander Duyck {
110582dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
110682dd0f7eSAlexander Duyck 	int i, err;
110782dd0f7eSAlexander Duyck 
1108892311f6SEyal Perry 	if (hfunc)
1109892311f6SEyal Perry 		*hfunc = ETH_RSS_HASH_TOP;
1110892311f6SEyal Perry 
111182dd0f7eSAlexander Duyck 	err = fm10k_get_reta(netdev, indir);
111282dd0f7eSAlexander Duyck 	if (err || !key)
111382dd0f7eSAlexander Duyck 		return err;
111482dd0f7eSAlexander Duyck 
111582dd0f7eSAlexander Duyck 	for (i = 0; i < FM10K_RSSRK_SIZE; i++, key += 4)
111682dd0f7eSAlexander Duyck 		*(__le32 *)key = cpu_to_le32(interface->rssrk[i]);
111782dd0f7eSAlexander Duyck 
111882dd0f7eSAlexander Duyck 	return 0;
111982dd0f7eSAlexander Duyck }
112082dd0f7eSAlexander Duyck 
112182dd0f7eSAlexander Duyck static int fm10k_set_rssh(struct net_device *netdev, const u32 *indir,
1122892311f6SEyal Perry 			  const u8 *key, const u8 hfunc)
112382dd0f7eSAlexander Duyck {
112482dd0f7eSAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(netdev);
112582dd0f7eSAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
112682dd0f7eSAlexander Duyck 	int i, err;
112782dd0f7eSAlexander Duyck 
1128892311f6SEyal Perry 	/* We do not allow change in unsupported parameters */
1129892311f6SEyal Perry 	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
1130892311f6SEyal Perry 		return -EOPNOTSUPP;
1131892311f6SEyal Perry 
113282dd0f7eSAlexander Duyck 	err = fm10k_set_reta(netdev, indir);
113382dd0f7eSAlexander Duyck 	if (err || !key)
113482dd0f7eSAlexander Duyck 		return err;
113582dd0f7eSAlexander Duyck 
113682dd0f7eSAlexander Duyck 	for (i = 0; i < FM10K_RSSRK_SIZE; i++, key += 4) {
113782dd0f7eSAlexander Duyck 		u32 rssrk = le32_to_cpu(*(__le32 *)key);
113882dd0f7eSAlexander Duyck 
113982dd0f7eSAlexander Duyck 		if (interface->rssrk[i] == rssrk)
114082dd0f7eSAlexander Duyck 			continue;
114182dd0f7eSAlexander Duyck 
114282dd0f7eSAlexander Duyck 		interface->rssrk[i] = rssrk;
114382dd0f7eSAlexander Duyck 		fm10k_write_reg(hw, FM10K_RSSRK(0, i), rssrk);
114482dd0f7eSAlexander Duyck 	}
114582dd0f7eSAlexander Duyck 
114682dd0f7eSAlexander Duyck 	return 0;
114782dd0f7eSAlexander Duyck }
114882dd0f7eSAlexander Duyck 
1149aa3ac822SAlexander Duyck static unsigned int fm10k_max_channels(struct net_device *dev)
1150aa3ac822SAlexander Duyck {
1151aa3ac822SAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
1152aa3ac822SAlexander Duyck 	unsigned int max_combined = interface->hw.mac.max_queues;
1153aa3ac822SAlexander Duyck 	u8 tcs = netdev_get_num_tc(dev);
1154aa3ac822SAlexander Duyck 
1155aa3ac822SAlexander Duyck 	/* For QoS report channels per traffic class */
1156aa3ac822SAlexander Duyck 	if (tcs > 1)
1157fcdb0a99SBruce Allan 		max_combined = BIT((fls(max_combined / tcs) - 1));
1158aa3ac822SAlexander Duyck 
1159aa3ac822SAlexander Duyck 	return max_combined;
1160aa3ac822SAlexander Duyck }
1161aa3ac822SAlexander Duyck 
1162aa3ac822SAlexander Duyck static void fm10k_get_channels(struct net_device *dev,
1163aa3ac822SAlexander Duyck 			       struct ethtool_channels *ch)
1164aa3ac822SAlexander Duyck {
1165aa3ac822SAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
1166aa3ac822SAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
1167aa3ac822SAlexander Duyck 
1168aa3ac822SAlexander Duyck 	/* report maximum channels */
1169aa3ac822SAlexander Duyck 	ch->max_combined = fm10k_max_channels(dev);
1170aa3ac822SAlexander Duyck 
1171aa3ac822SAlexander Duyck 	/* report info for other vector */
1172aa3ac822SAlexander Duyck 	ch->max_other = NON_Q_VECTORS(hw);
1173aa3ac822SAlexander Duyck 	ch->other_count = ch->max_other;
1174aa3ac822SAlexander Duyck 
1175aa3ac822SAlexander Duyck 	/* record RSS queues */
1176aa3ac822SAlexander Duyck 	ch->combined_count = interface->ring_feature[RING_F_RSS].indices;
1177aa3ac822SAlexander Duyck }
1178aa3ac822SAlexander Duyck 
1179aa3ac822SAlexander Duyck static int fm10k_set_channels(struct net_device *dev,
1180aa3ac822SAlexander Duyck 			      struct ethtool_channels *ch)
1181aa3ac822SAlexander Duyck {
1182aa3ac822SAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
1183aa3ac822SAlexander Duyck 	unsigned int count = ch->combined_count;
1184aa3ac822SAlexander Duyck 	struct fm10k_hw *hw = &interface->hw;
1185aa3ac822SAlexander Duyck 
1186aa3ac822SAlexander Duyck 	/* verify they are not requesting separate vectors */
1187aa3ac822SAlexander Duyck 	if (!count || ch->rx_count || ch->tx_count)
1188aa3ac822SAlexander Duyck 		return -EINVAL;
1189aa3ac822SAlexander Duyck 
1190aa3ac822SAlexander Duyck 	/* verify other_count has not changed */
1191aa3ac822SAlexander Duyck 	if (ch->other_count != NON_Q_VECTORS(hw))
1192aa3ac822SAlexander Duyck 		return -EINVAL;
1193aa3ac822SAlexander Duyck 
1194aa3ac822SAlexander Duyck 	/* verify the number of channels does not exceed hardware limits */
1195aa3ac822SAlexander Duyck 	if (count > fm10k_max_channels(dev))
1196aa3ac822SAlexander Duyck 		return -EINVAL;
1197aa3ac822SAlexander Duyck 
1198aa3ac822SAlexander Duyck 	interface->ring_feature[RING_F_RSS].limit = count;
1199aa3ac822SAlexander Duyck 
1200aa3ac822SAlexander Duyck 	/* use setup TC to update any traffic class queue mapping */
1201aa3ac822SAlexander Duyck 	return fm10k_setup_tc(dev, netdev_get_num_tc(dev));
1202aa3ac822SAlexander Duyck }
1203aa3ac822SAlexander Duyck 
1204a211e013SAlexander Duyck static int fm10k_get_ts_info(struct net_device *dev,
1205a211e013SAlexander Duyck 			     struct ethtool_ts_info *info)
1206a211e013SAlexander Duyck {
1207a211e013SAlexander Duyck 	struct fm10k_intfc *interface = netdev_priv(dev);
1208a211e013SAlexander Duyck 
1209a211e013SAlexander Duyck 	info->so_timestamping =
1210a211e013SAlexander Duyck 		SOF_TIMESTAMPING_TX_SOFTWARE |
1211a211e013SAlexander Duyck 		SOF_TIMESTAMPING_RX_SOFTWARE |
1212a211e013SAlexander Duyck 		SOF_TIMESTAMPING_SOFTWARE |
1213a211e013SAlexander Duyck 		SOF_TIMESTAMPING_TX_HARDWARE |
1214a211e013SAlexander Duyck 		SOF_TIMESTAMPING_RX_HARDWARE |
1215a211e013SAlexander Duyck 		SOF_TIMESTAMPING_RAW_HARDWARE;
1216a211e013SAlexander Duyck 
1217a211e013SAlexander Duyck 	if (interface->ptp_clock)
1218a211e013SAlexander Duyck 		info->phc_index = ptp_clock_index(interface->ptp_clock);
1219a211e013SAlexander Duyck 	else
1220a211e013SAlexander Duyck 		info->phc_index = -1;
1221a211e013SAlexander Duyck 
1222fcdb0a99SBruce Allan 	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
1223a211e013SAlexander Duyck 
1224fcdb0a99SBruce Allan 	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
1225a211e013SAlexander Duyck 
1226a211e013SAlexander Duyck 	return 0;
1227a211e013SAlexander Duyck }
1228a211e013SAlexander Duyck 
122982dd0f7eSAlexander Duyck static const struct ethtool_ops fm10k_ethtool_ops = {
123082dd0f7eSAlexander Duyck 	.get_strings		= fm10k_get_strings,
123182dd0f7eSAlexander Duyck 	.get_sset_count		= fm10k_get_sset_count,
123282dd0f7eSAlexander Duyck 	.get_ethtool_stats      = fm10k_get_ethtool_stats,
123382dd0f7eSAlexander Duyck 	.get_drvinfo		= fm10k_get_drvinfo,
123482dd0f7eSAlexander Duyck 	.get_link		= ethtool_op_get_link,
123582dd0f7eSAlexander Duyck 	.get_pauseparam		= fm10k_get_pauseparam,
123682dd0f7eSAlexander Duyck 	.set_pauseparam		= fm10k_set_pauseparam,
123782dd0f7eSAlexander Duyck 	.get_msglevel		= fm10k_get_msglevel,
123882dd0f7eSAlexander Duyck 	.set_msglevel		= fm10k_set_msglevel,
123982dd0f7eSAlexander Duyck 	.get_ringparam		= fm10k_get_ringparam,
124082dd0f7eSAlexander Duyck 	.set_ringparam		= fm10k_set_ringparam,
124182dd0f7eSAlexander Duyck 	.get_coalesce		= fm10k_get_coalesce,
124282dd0f7eSAlexander Duyck 	.set_coalesce		= fm10k_set_coalesce,
124382dd0f7eSAlexander Duyck 	.get_rxnfc		= fm10k_get_rxnfc,
124482dd0f7eSAlexander Duyck 	.set_rxnfc		= fm10k_set_rxnfc,
124582dd0f7eSAlexander Duyck 	.get_regs               = fm10k_get_regs,
124682dd0f7eSAlexander Duyck 	.get_regs_len           = fm10k_get_regs_len,
12475cb8db4aSAlexander Duyck 	.self_test		= fm10k_self_test,
124880043f3bSJacob Keller 	.get_priv_flags		= fm10k_get_priv_flags,
124980043f3bSJacob Keller 	.set_priv_flags		= fm10k_set_priv_flags,
125082dd0f7eSAlexander Duyck 	.get_rxfh_indir_size	= fm10k_get_reta_size,
125182dd0f7eSAlexander Duyck 	.get_rxfh_key_size	= fm10k_get_rssrk_size,
125282dd0f7eSAlexander Duyck 	.get_rxfh		= fm10k_get_rssh,
125382dd0f7eSAlexander Duyck 	.set_rxfh		= fm10k_set_rssh,
1254aa3ac822SAlexander Duyck 	.get_channels		= fm10k_get_channels,
1255aa3ac822SAlexander Duyck 	.set_channels		= fm10k_set_channels,
1256a211e013SAlexander Duyck 	.get_ts_info            = fm10k_get_ts_info,
125782dd0f7eSAlexander Duyck };
125882dd0f7eSAlexander Duyck 
125982dd0f7eSAlexander Duyck void fm10k_set_ethtool_ops(struct net_device *dev)
126082dd0f7eSAlexander Duyck {
126182dd0f7eSAlexander Duyck 	dev->ethtool_ops = &fm10k_ethtool_ops;
126282dd0f7eSAlexander Duyck }
1263