1133fac0eSSudarsana Kalluru /* QLogic qede NIC Driver
2e8f1cb50SMintz, Yuval  * Copyright (c) 2015-2017  QLogic Corporation
3133fac0eSSudarsana Kalluru  *
4e8f1cb50SMintz, Yuval  * This software is available to you under a choice of one of two
5e8f1cb50SMintz, Yuval  * licenses.  You may choose to be licensed under the terms of the GNU
6e8f1cb50SMintz, Yuval  * General Public License (GPL) Version 2, available from the file
7e8f1cb50SMintz, Yuval  * COPYING in the main directory of this source tree, or the
8e8f1cb50SMintz, Yuval  * OpenIB.org BSD license below:
9e8f1cb50SMintz, Yuval  *
10e8f1cb50SMintz, Yuval  *     Redistribution and use in source and binary forms, with or
11e8f1cb50SMintz, Yuval  *     without modification, are permitted provided that the following
12e8f1cb50SMintz, Yuval  *     conditions are met:
13e8f1cb50SMintz, Yuval  *
14e8f1cb50SMintz, Yuval  *      - Redistributions of source code must retain the above
15e8f1cb50SMintz, Yuval  *        copyright notice, this list of conditions and the following
16e8f1cb50SMintz, Yuval  *        disclaimer.
17e8f1cb50SMintz, Yuval  *
18e8f1cb50SMintz, Yuval  *      - Redistributions in binary form must reproduce the above
19e8f1cb50SMintz, Yuval  *        copyright notice, this list of conditions and the following
20e8f1cb50SMintz, Yuval  *        disclaimer in the documentation and /or other materials
21e8f1cb50SMintz, Yuval  *        provided with the distribution.
22e8f1cb50SMintz, Yuval  *
23e8f1cb50SMintz, Yuval  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24e8f1cb50SMintz, Yuval  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25e8f1cb50SMintz, Yuval  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26e8f1cb50SMintz, Yuval  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27e8f1cb50SMintz, Yuval  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28e8f1cb50SMintz, Yuval  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29e8f1cb50SMintz, Yuval  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30e8f1cb50SMintz, Yuval  * SOFTWARE.
31133fac0eSSudarsana Kalluru  */
32133fac0eSSudarsana Kalluru #include <linux/version.h>
33133fac0eSSudarsana Kalluru #include <linux/types.h>
34133fac0eSSudarsana Kalluru #include <linux/netdevice.h>
3516f46bf0SSudarsana Reddy Kalluru #include <linux/etherdevice.h>
36133fac0eSSudarsana Kalluru #include <linux/ethtool.h>
37133fac0eSSudarsana Kalluru #include <linux/string.h>
38133fac0eSSudarsana Kalluru #include <linux/pci.h>
39133fac0eSSudarsana Kalluru #include <linux/capability.h>
40f29ffdb6SMintz, Yuval #include <linux/vmalloc.h>
41133fac0eSSudarsana Kalluru #include "qede.h"
424c55215cSSudarsana Reddy Kalluru #include "qede_ptp.h"
43133fac0eSSudarsana Kalluru 
44133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \
45133fac0eSSudarsana Kalluru 	 (offsetof(struct qede_rx_queue, stat_name))
46133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name)
47133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \
48133fac0eSSudarsana Kalluru 	 {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)}
4916f46bf0SSudarsana Reddy Kalluru 
5016f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100
5116f46bf0SSudarsana Reddy Kalluru 
52133fac0eSSudarsana Kalluru static const struct {
53133fac0eSSudarsana Kalluru 	u64 offset;
54133fac0eSSudarsana Kalluru 	char string[ETH_GSTRING_LEN];
55133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = {
5668db9ec2SSudarsana Reddy Kalluru 	QEDE_RQSTAT(rcv_pkts),
57133fac0eSSudarsana Kalluru 	QEDE_RQSTAT(rx_hw_errors),
58133fac0eSSudarsana Kalluru 	QEDE_RQSTAT(rx_alloc_errors),
59c72a6125SManish Chopra 	QEDE_RQSTAT(rx_ip_frags),
60496e0517SMintz, Yuval 	QEDE_RQSTAT(xdp_no_pass),
61133fac0eSSudarsana Kalluru };
62133fac0eSSudarsana Kalluru 
63133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr)
6468db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \
6568db9ec2SSudarsana Reddy Kalluru 	(offsetof(struct qede_tx_queue, stat_name))
6668db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name)
6768db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \
6868db9ec2SSudarsana Reddy Kalluru 	{QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)}
6968db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr)
7068db9ec2SSudarsana Reddy Kalluru static const struct {
7168db9ec2SSudarsana Reddy Kalluru 	u64 offset;
7268db9ec2SSudarsana Reddy Kalluru 	char string[ETH_GSTRING_LEN];
7368db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = {
7468db9ec2SSudarsana Reddy Kalluru 	QEDE_TQSTAT(xmit_pkts),
7568db9ec2SSudarsana Reddy Kalluru 	QEDE_TQSTAT(stopped_cnt),
7668db9ec2SSudarsana Reddy Kalluru };
7768db9ec2SSudarsana Reddy Kalluru 
789c79ddaaSMintz, Yuval #define QEDE_STAT_OFFSET(stat_name, type, base) \
799c79ddaaSMintz, Yuval 	(offsetof(type, stat_name) + (base))
804dbcd640SMintz, Yuval #define QEDE_STAT_STRING(stat_name)	(#stat_name)
819c79ddaaSMintz, Yuval #define _QEDE_STAT(stat_name, type, base, attr) \
829c79ddaaSMintz, Yuval 	{QEDE_STAT_OFFSET(stat_name, type, base), \
839c79ddaaSMintz, Yuval 	 QEDE_STAT_STRING(stat_name), \
849c79ddaaSMintz, Yuval 	 attr}
859c79ddaaSMintz, Yuval #define QEDE_STAT(stat_name) \
869c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_common, 0, 0x0)
879c79ddaaSMintz, Yuval #define QEDE_PF_STAT(stat_name) \
889c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_common, 0, \
899c79ddaaSMintz, Yuval 		   BIT(QEDE_STAT_PF_ONLY))
909c79ddaaSMintz, Yuval #define QEDE_PF_BB_STAT(stat_name) \
919c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_bb, \
929c79ddaaSMintz, Yuval 		   offsetof(struct qede_stats, bb), \
939c79ddaaSMintz, Yuval 		   BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_BB_ONLY))
949c79ddaaSMintz, Yuval #define QEDE_PF_AH_STAT(stat_name) \
959c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_ah, \
969c79ddaaSMintz, Yuval 		   offsetof(struct qede_stats, ah), \
979c79ddaaSMintz, Yuval 		   BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_AH_ONLY))
98133fac0eSSudarsana Kalluru static const struct {
99133fac0eSSudarsana Kalluru 	u64 offset;
100133fac0eSSudarsana Kalluru 	char string[ETH_GSTRING_LEN];
1019c79ddaaSMintz, Yuval 	unsigned long attr;
1029c79ddaaSMintz, Yuval #define QEDE_STAT_PF_ONLY	0
1039c79ddaaSMintz, Yuval #define QEDE_STAT_BB_ONLY	1
1049c79ddaaSMintz, Yuval #define QEDE_STAT_AH_ONLY	2
105133fac0eSSudarsana Kalluru } qede_stats_arr[] = {
106133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_ucast_bytes),
107133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_mcast_bytes),
108133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_bcast_bytes),
109133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_ucast_pkts),
110133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_mcast_pkts),
111133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_bcast_pkts),
112133fac0eSSudarsana Kalluru 
113133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_ucast_bytes),
114133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_mcast_bytes),
115133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_bcast_bytes),
116133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_ucast_pkts),
117133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_mcast_pkts),
118133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_bcast_pkts),
119133fac0eSSudarsana Kalluru 
120133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_64_byte_packets),
121d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_65_to_127_byte_packets),
122d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_128_to_255_byte_packets),
123d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_256_to_511_byte_packets),
124d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_512_to_1023_byte_packets),
125d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_1024_to_1518_byte_packets),
1269c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_1519_to_1522_byte_packets),
1279c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_1519_to_2047_byte_packets),
1289c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_2048_to_4095_byte_packets),
1299c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_4096_to_9216_byte_packets),
1309c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_9217_to_16383_byte_packets),
1319c79ddaaSMintz, Yuval 	QEDE_PF_AH_STAT(rx_1519_to_max_byte_packets),
132133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_64_byte_packets),
133133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_65_to_127_byte_packets),
134133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_128_to_255_byte_packets),
135133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_256_to_511_byte_packets),
136133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_512_to_1023_byte_packets),
137133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_1024_to_1518_byte_packets),
1389c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_1519_to_2047_byte_packets),
1399c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_2048_to_4095_byte_packets),
1409c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_4096_to_9216_byte_packets),
1419c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_9217_to_16383_byte_packets),
1429c79ddaaSMintz, Yuval 	QEDE_PF_AH_STAT(tx_1519_to_max_byte_packets),
143133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_mac_crtl_frames),
144133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_mac_ctrl_frames),
145133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_pause_frames),
146133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_pause_frames),
147133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_pfc_frames),
148133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_pfc_frames),
149133fac0eSSudarsana Kalluru 
150133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_crc_errors),
151133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_align_errors),
152133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_carrier_errors),
153133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_oversize_packets),
154133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_jabbers),
155133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_undersize_packets),
156133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_fragments),
1579c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_lpi_entry_count),
1589c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_total_collisions),
159133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(brb_truncates),
160133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(brb_discards),
161133fac0eSSudarsana Kalluru 	QEDE_STAT(no_buff_discards),
162133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(mftag_filter_discards),
163133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(mac_filter_discards),
164133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_err_drop_pkts),
1651a5a366fSSudarsana Reddy Kalluru 	QEDE_STAT(ttl0_discard),
1661a5a366fSSudarsana Reddy Kalluru 	QEDE_STAT(packet_too_big_discard),
167133fac0eSSudarsana Kalluru 
168133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_pkts),
169133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_events),
170133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_aborts_num),
171133fac0eSSudarsana Kalluru 	QEDE_STAT(non_coalesced_pkts),
172133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_bytes),
173133fac0eSSudarsana Kalluru };
174133fac0eSSudarsana Kalluru 
175133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS	ARRAY_SIZE(qede_stats_arr)
1769c79ddaaSMintz, Yuval #define QEDE_STAT_IS_PF_ONLY(i) \
1779c79ddaaSMintz, Yuval 	test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr)
1789c79ddaaSMintz, Yuval #define QEDE_STAT_IS_BB_ONLY(i) \
1799c79ddaaSMintz, Yuval 	test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr)
1809c79ddaaSMintz, Yuval #define QEDE_STAT_IS_AH_ONLY(i) \
1819c79ddaaSMintz, Yuval 	test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr)
182133fac0eSSudarsana Kalluru 
183f3e72109SYuval Mintz enum {
184f3e72109SYuval Mintz 	QEDE_PRI_FLAG_CMT,
185f3e72109SYuval Mintz 	QEDE_PRI_FLAG_LEN,
186f3e72109SYuval Mintz };
187f3e72109SYuval Mintz 
188f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = {
189f3e72109SYuval Mintz 	"Coupled-Function",
190f3e72109SYuval Mintz };
191f3e72109SYuval Mintz 
1923044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests {
19316f46bf0SSudarsana Reddy Kalluru 	QEDE_ETHTOOL_INT_LOOPBACK,
1943044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_INTERRUPT_TEST,
1953044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_MEMORY_TEST,
1963044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_REGISTER_TEST,
1973044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_CLOCK_TEST,
1987a4b21b7SMintz, Yuval 	QEDE_ETHTOOL_NVRAM_TEST,
1993044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_TEST_MAX
2003044a02eSSudarsana Reddy Kalluru };
2013044a02eSSudarsana Reddy Kalluru 
2023044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = {
20316f46bf0SSudarsana Reddy Kalluru 	"Internal loopback (offline)",
2043044a02eSSudarsana Reddy Kalluru 	"Interrupt (online)\t",
2053044a02eSSudarsana Reddy Kalluru 	"Memory (online)\t\t",
2063044a02eSSudarsana Reddy Kalluru 	"Register (online)\t",
2073044a02eSSudarsana Reddy Kalluru 	"Clock (online)\t\t",
2087a4b21b7SMintz, Yuval 	"Nvram (online)\t\t",
2093044a02eSSudarsana Reddy Kalluru };
2103044a02eSSudarsana Reddy Kalluru 
2114dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev,
2124dbcd640SMintz, Yuval 				       struct qede_tx_queue *txq, u8 **buf)
2134dbcd640SMintz, Yuval {
2144dbcd640SMintz, Yuval 	int i;
2154dbcd640SMintz, Yuval 
2164dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
217cb6aeb07SMintz, Yuval 		if (txq->is_xdp)
218cb6aeb07SMintz, Yuval 			sprintf(*buf, "%d [XDP]: %s",
219cb6aeb07SMintz, Yuval 				QEDE_TXQ_XDP_TO_IDX(edev, txq),
220cb6aeb07SMintz, Yuval 				qede_tqstats_arr[i].string);
221cb6aeb07SMintz, Yuval 		else
2224dbcd640SMintz, Yuval 			sprintf(*buf, "%d: %s", txq->index,
2234dbcd640SMintz, Yuval 				qede_tqstats_arr[i].string);
2244dbcd640SMintz, Yuval 		*buf += ETH_GSTRING_LEN;
2254dbcd640SMintz, Yuval 	}
2264dbcd640SMintz, Yuval }
2274dbcd640SMintz, Yuval 
2284dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev,
2294dbcd640SMintz, Yuval 				       struct qede_rx_queue *rxq, u8 **buf)
2304dbcd640SMintz, Yuval {
2314dbcd640SMintz, Yuval 	int i;
2324dbcd640SMintz, Yuval 
2334dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
2344dbcd640SMintz, Yuval 		sprintf(*buf, "%d: %s", rxq->rxq_id,
2354dbcd640SMintz, Yuval 			qede_rqstats_arr[i].string);
2364dbcd640SMintz, Yuval 		*buf += ETH_GSTRING_LEN;
2374dbcd640SMintz, Yuval 	}
2384dbcd640SMintz, Yuval }
2394dbcd640SMintz, Yuval 
2409c79ddaaSMintz, Yuval static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index)
2419c79ddaaSMintz, Yuval {
2429c79ddaaSMintz, Yuval 	return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) ||
2439c79ddaaSMintz, Yuval 	       (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) ||
2449c79ddaaSMintz, Yuval 	       (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index));
2459c79ddaaSMintz, Yuval }
2469c79ddaaSMintz, Yuval 
247133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
248133fac0eSSudarsana Kalluru {
2494dbcd640SMintz, Yuval 	struct qede_fastpath *fp;
2504dbcd640SMintz, Yuval 	int i;
251133fac0eSSudarsana Kalluru 
2524dbcd640SMintz, Yuval 	/* Account for queue statistics */
2534dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
2544dbcd640SMintz, Yuval 		fp = &edev->fp_array[i];
25568db9ec2SSudarsana Reddy Kalluru 
2564dbcd640SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_RX)
2574dbcd640SMintz, Yuval 			qede_get_strings_stats_rxq(edev, fp->rxq, &buf);
2584dbcd640SMintz, Yuval 
259cb6aeb07SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_XDP)
260cb6aeb07SMintz, Yuval 			qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf);
261cb6aeb07SMintz, Yuval 
2624dbcd640SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_TX)
2634dbcd640SMintz, Yuval 			qede_get_strings_stats_txq(edev, fp->txq, &buf);
264cbbf049aSMintz, Yuval 	}
265cbbf049aSMintz, Yuval 
2664dbcd640SMintz, Yuval 	/* Account for non-queue statistics */
2674dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_STATS; i++) {
2689c79ddaaSMintz, Yuval 		if (qede_is_irrelevant_stat(edev, i))
269fefb0202SYuval Mintz 			continue;
2704dbcd640SMintz, Yuval 		strcpy(buf, qede_stats_arr[i].string);
2714dbcd640SMintz, Yuval 		buf += ETH_GSTRING_LEN;
272133fac0eSSudarsana Kalluru 	}
273133fac0eSSudarsana Kalluru }
274133fac0eSSudarsana Kalluru 
275133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
276133fac0eSSudarsana Kalluru {
277133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
278133fac0eSSudarsana Kalluru 
279133fac0eSSudarsana Kalluru 	switch (stringset) {
280133fac0eSSudarsana Kalluru 	case ETH_SS_STATS:
281133fac0eSSudarsana Kalluru 		qede_get_strings_stats(edev, buf);
282133fac0eSSudarsana Kalluru 		break;
283f3e72109SYuval Mintz 	case ETH_SS_PRIV_FLAGS:
284f3e72109SYuval Mintz 		memcpy(buf, qede_private_arr,
285f3e72109SYuval Mintz 		       ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN);
286f3e72109SYuval Mintz 		break;
2873044a02eSSudarsana Reddy Kalluru 	case ETH_SS_TEST:
2883044a02eSSudarsana Reddy Kalluru 		memcpy(buf, qede_tests_str_arr,
2893044a02eSSudarsana Reddy Kalluru 		       ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX);
2903044a02eSSudarsana Reddy Kalluru 		break;
291133fac0eSSudarsana Kalluru 	default:
292133fac0eSSudarsana Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
293133fac0eSSudarsana Kalluru 			   "Unsupported stringset 0x%08x\n", stringset);
294133fac0eSSudarsana Kalluru 	}
295133fac0eSSudarsana Kalluru }
296133fac0eSSudarsana Kalluru 
2974dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf)
2984dbcd640SMintz, Yuval {
2994dbcd640SMintz, Yuval 	int i;
3004dbcd640SMintz, Yuval 
3014dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
3024dbcd640SMintz, Yuval 		**buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset));
3034dbcd640SMintz, Yuval 		(*buf)++;
3044dbcd640SMintz, Yuval 	}
3054dbcd640SMintz, Yuval }
3064dbcd640SMintz, Yuval 
3074dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf)
3084dbcd640SMintz, Yuval {
3094dbcd640SMintz, Yuval 	int i;
3104dbcd640SMintz, Yuval 
3114dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
3124dbcd640SMintz, Yuval 		**buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset));
3134dbcd640SMintz, Yuval 		(*buf)++;
3144dbcd640SMintz, Yuval 	}
3154dbcd640SMintz, Yuval }
3164dbcd640SMintz, Yuval 
317133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev,
318133fac0eSSudarsana Kalluru 				   struct ethtool_stats *stats, u64 *buf)
319133fac0eSSudarsana Kalluru {
320133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
3214dbcd640SMintz, Yuval 	struct qede_fastpath *fp;
3224dbcd640SMintz, Yuval 	int i;
323133fac0eSSudarsana Kalluru 
324133fac0eSSudarsana Kalluru 	qede_fill_by_demand_stats(edev);
325133fac0eSSudarsana Kalluru 
326567b3c12SMintz, Yuval 	/* Need to protect the access to the fastpath array */
327567b3c12SMintz, Yuval 	__qede_lock(edev);
328567b3c12SMintz, Yuval 
3294dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
3304dbcd640SMintz, Yuval 		fp = &edev->fp_array[i];
331133fac0eSSudarsana Kalluru 
3324dbcd640SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_RX)
3334dbcd640SMintz, Yuval 			qede_get_ethtool_stats_rxq(fp->rxq, &buf);
33468db9ec2SSudarsana Reddy Kalluru 
335cb6aeb07SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_XDP)
336cb6aeb07SMintz, Yuval 			qede_get_ethtool_stats_txq(fp->xdp_tx, &buf);
337cb6aeb07SMintz, Yuval 
3384dbcd640SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_TX)
3394dbcd640SMintz, Yuval 			qede_get_ethtool_stats_txq(fp->txq, &buf);
34068db9ec2SSudarsana Reddy Kalluru 	}
34168db9ec2SSudarsana Reddy Kalluru 
3424dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_STATS; i++) {
3439c79ddaaSMintz, Yuval 		if (qede_is_irrelevant_stat(edev, i))
344fefb0202SYuval Mintz 			continue;
3454dbcd640SMintz, Yuval 		*buf = *((u64 *)(((void *)&edev->stats) +
3464dbcd640SMintz, Yuval 				 qede_stats_arr[i].offset));
3474dbcd640SMintz, Yuval 
3484dbcd640SMintz, Yuval 		buf++;
349fefb0202SYuval Mintz 	}
350133fac0eSSudarsana Kalluru 
351567b3c12SMintz, Yuval 	__qede_unlock(edev);
352133fac0eSSudarsana Kalluru }
353133fac0eSSudarsana Kalluru 
354133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset)
355133fac0eSSudarsana Kalluru {
356133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
3579c79ddaaSMintz, Yuval 	int num_stats = QEDE_NUM_STATS, i;
358133fac0eSSudarsana Kalluru 
359133fac0eSSudarsana Kalluru 	switch (stringset) {
360133fac0eSSudarsana Kalluru 	case ETH_SS_STATS:
361fefb0202SYuval Mintz 		for (i = 0; i < QEDE_NUM_STATS; i++)
3629c79ddaaSMintz, Yuval 			if (qede_is_irrelevant_stat(edev, i))
363fefb0202SYuval Mintz 				num_stats--;
3644dbcd640SMintz, Yuval 
3654dbcd640SMintz, Yuval 		/* Account for the Regular Tx statistics */
3664dbcd640SMintz, Yuval 		num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS;
3674dbcd640SMintz, Yuval 
3684dbcd640SMintz, Yuval 		/* Account for the Regular Rx statistics */
3694dbcd640SMintz, Yuval 		num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS;
3704dbcd640SMintz, Yuval 
371cb6aeb07SMintz, Yuval 		/* Account for XDP statistics [if needed] */
372cb6aeb07SMintz, Yuval 		if (edev->xdp_prog)
373cb6aeb07SMintz, Yuval 			num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS;
3744dbcd640SMintz, Yuval 		return num_stats;
3754dbcd640SMintz, Yuval 
376f3e72109SYuval Mintz 	case ETH_SS_PRIV_FLAGS:
377f3e72109SYuval Mintz 		return QEDE_PRI_FLAG_LEN;
3783044a02eSSudarsana Reddy Kalluru 	case ETH_SS_TEST:
3796ecb0a0cSYuval Mintz 		if (!IS_VF(edev))
3803044a02eSSudarsana Reddy Kalluru 			return QEDE_ETHTOOL_TEST_MAX;
3816ecb0a0cSYuval Mintz 		else
3826ecb0a0cSYuval Mintz 			return 0;
383133fac0eSSudarsana Kalluru 	default:
384133fac0eSSudarsana Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
385133fac0eSSudarsana Kalluru 			   "Unsupported stringset 0x%08x\n", stringset);
386133fac0eSSudarsana Kalluru 		return -EINVAL;
387133fac0eSSudarsana Kalluru 	}
388133fac0eSSudarsana Kalluru }
389133fac0eSSudarsana Kalluru 
390f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev)
391f3e72109SYuval Mintz {
392f3e72109SYuval Mintz 	struct qede_dev *edev = netdev_priv(dev);
393f3e72109SYuval Mintz 
394f3e72109SYuval Mintz 	return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT;
395f3e72109SYuval Mintz }
396f3e72109SYuval Mintz 
397054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping {
398054c67d1SSudarsana Reddy Kalluru 	u32 qed_link_mode;
399054c67d1SSudarsana Reddy Kalluru 	u32 ethtool_link_mode;
400054c67d1SSudarsana Reddy Kalluru };
401054c67d1SSudarsana Reddy Kalluru 
402054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = {
403054c67d1SSudarsana Reddy Kalluru 	{QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT},
404054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT},
405054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT},
406054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT},
407054c67d1SSudarsana Reddy Kalluru 	{QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT},
408054c67d1SSudarsana Reddy Kalluru 	{QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
409054c67d1SSudarsana Reddy Kalluru 	{QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
410054c67d1SSudarsana Reddy Kalluru 	{QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT},
411054c67d1SSudarsana Reddy Kalluru 	{QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT},
412054c67d1SSudarsana Reddy Kalluru 	{QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT},
413054c67d1SSudarsana Reddy Kalluru 	{QED_LM_100000baseKR4_Full_BIT,
414054c67d1SSudarsana Reddy Kalluru 	 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT},
415054c67d1SSudarsana Reddy Kalluru };
416054c67d1SSudarsana Reddy Kalluru 
417054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name)	\
418054c67d1SSudarsana Reddy Kalluru {								\
419054c67d1SSudarsana Reddy Kalluru 	int i;							\
420054c67d1SSudarsana Reddy Kalluru 								\
421d7455f6eSMintz, Yuval 	for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) {		\
422054c67d1SSudarsana Reddy Kalluru 		if ((caps) & (qed_lm_map[i].qed_link_mode))	\
423054c67d1SSudarsana Reddy Kalluru 			__set_bit(qed_lm_map[i].ethtool_link_mode,\
424054c67d1SSudarsana Reddy Kalluru 				  lk_ksettings->link_modes.name); \
425054c67d1SSudarsana Reddy Kalluru 	}							\
426054c67d1SSudarsana Reddy Kalluru }
427054c67d1SSudarsana Reddy Kalluru 
428054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name)	\
429054c67d1SSudarsana Reddy Kalluru {								\
430054c67d1SSudarsana Reddy Kalluru 	int i;							\
431054c67d1SSudarsana Reddy Kalluru 								\
432d7455f6eSMintz, Yuval 	for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) {		\
433054c67d1SSudarsana Reddy Kalluru 		if (test_bit(qed_lm_map[i].ethtool_link_mode,	\
434054c67d1SSudarsana Reddy Kalluru 			     lk_ksettings->link_modes.name))	\
435054c67d1SSudarsana Reddy Kalluru 			caps |= qed_lm_map[i].qed_link_mode;	\
436054c67d1SSudarsana Reddy Kalluru 	}							\
437054c67d1SSudarsana Reddy Kalluru }
438054c67d1SSudarsana Reddy Kalluru 
439054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev,
440054c67d1SSudarsana Reddy Kalluru 				   struct ethtool_link_ksettings *cmd)
441133fac0eSSudarsana Kalluru {
442054c67d1SSudarsana Reddy Kalluru 	struct ethtool_link_settings *base = &cmd->base;
443133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
444133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
445133fac0eSSudarsana Kalluru 
446567b3c12SMintz, Yuval 	__qede_lock(edev);
447567b3c12SMintz, Yuval 
448133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
449133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
450133fac0eSSudarsana Kalluru 
451054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
452054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported)
453054c67d1SSudarsana Reddy Kalluru 
454054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, advertising);
455054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising)
456054c67d1SSudarsana Reddy Kalluru 
457054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
458054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising)
459054c67d1SSudarsana Reddy Kalluru 
460133fac0eSSudarsana Kalluru 	if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) {
461054c67d1SSudarsana Reddy Kalluru 		base->speed = current_link.speed;
462054c67d1SSudarsana Reddy Kalluru 		base->duplex = current_link.duplex;
463133fac0eSSudarsana Kalluru 	} else {
464054c67d1SSudarsana Reddy Kalluru 		base->speed = SPEED_UNKNOWN;
465054c67d1SSudarsana Reddy Kalluru 		base->duplex = DUPLEX_UNKNOWN;
466133fac0eSSudarsana Kalluru 	}
467567b3c12SMintz, Yuval 
468567b3c12SMintz, Yuval 	__qede_unlock(edev);
469567b3c12SMintz, Yuval 
470054c67d1SSudarsana Reddy Kalluru 	base->port = current_link.port;
471054c67d1SSudarsana Reddy Kalluru 	base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE :
472133fac0eSSudarsana Kalluru 			AUTONEG_DISABLE;
473133fac0eSSudarsana Kalluru 
474133fac0eSSudarsana Kalluru 	return 0;
475133fac0eSSudarsana Kalluru }
476133fac0eSSudarsana Kalluru 
477054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev,
478054c67d1SSudarsana Reddy Kalluru 				   const struct ethtool_link_ksettings *cmd)
479133fac0eSSudarsana Kalluru {
480054c67d1SSudarsana Reddy Kalluru 	const struct ethtool_link_settings *base = &cmd->base;
481133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
482133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
483133fac0eSSudarsana Kalluru 	struct qed_link_params params;
484133fac0eSSudarsana Kalluru 
485fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
486054c67d1SSudarsana Reddy Kalluru 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
487133fac0eSSudarsana Kalluru 		return -EOPNOTSUPP;
488133fac0eSSudarsana Kalluru 	}
489133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
490133fac0eSSudarsana Kalluru 	memset(&params, 0, sizeof(params));
491133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
492133fac0eSSudarsana Kalluru 
493133fac0eSSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS;
494133fac0eSSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG;
495054c67d1SSudarsana Reddy Kalluru 	if (base->autoneg == AUTONEG_ENABLE) {
496161adb04Ssudarsana.kalluru@cavium.com 		if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) {
497161adb04Ssudarsana.kalluru@cavium.com 			DP_INFO(edev, "Auto negotiation is not supported\n");
498161adb04Ssudarsana.kalluru@cavium.com 			return -EOPNOTSUPP;
499161adb04Ssudarsana.kalluru@cavium.com 		}
500161adb04Ssudarsana.kalluru@cavium.com 
501133fac0eSSudarsana Kalluru 		params.autoneg = true;
502133fac0eSSudarsana Kalluru 		params.forced_speed = 0;
503054c67d1SSudarsana Reddy Kalluru 		QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising)
504133fac0eSSudarsana Kalluru 	} else {		/* forced speed */
505133fac0eSSudarsana Kalluru 		params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED;
506133fac0eSSudarsana Kalluru 		params.autoneg = false;
507054c67d1SSudarsana Reddy Kalluru 		params.forced_speed = base->speed;
508054c67d1SSudarsana Reddy Kalluru 		switch (base->speed) {
5099ac4c546SSudarsana Reddy Kalluru 		case SPEED_1000:
5109ac4c546SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
5119ac4c546SSudarsana Reddy Kalluru 			      QED_LM_1000baseT_Full_BIT)) {
5129ac4c546SSudarsana Reddy Kalluru 				DP_INFO(edev, "1G speed not supported\n");
5139ac4c546SSudarsana Reddy Kalluru 				return -EINVAL;
5149ac4c546SSudarsana Reddy Kalluru 			}
5159ac4c546SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_1000baseT_Full_BIT;
5169ac4c546SSudarsana Reddy Kalluru 			break;
517133fac0eSSudarsana Kalluru 		case SPEED_10000:
518133fac0eSSudarsana Kalluru 			if (!(current_link.supported_caps &
519054c67d1SSudarsana Reddy Kalluru 			      QED_LM_10000baseKR_Full_BIT)) {
520133fac0eSSudarsana Kalluru 				DP_INFO(edev, "10G speed not supported\n");
521133fac0eSSudarsana Kalluru 				return -EINVAL;
522133fac0eSSudarsana Kalluru 			}
523054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_10000baseKR_Full_BIT;
524054c67d1SSudarsana Reddy Kalluru 			break;
525054c67d1SSudarsana Reddy Kalluru 		case SPEED_25000:
526054c67d1SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
527054c67d1SSudarsana Reddy Kalluru 			      QED_LM_25000baseKR_Full_BIT)) {
528054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "25G speed not supported\n");
529054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
530054c67d1SSudarsana Reddy Kalluru 			}
531054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_25000baseKR_Full_BIT;
532133fac0eSSudarsana Kalluru 			break;
533133fac0eSSudarsana Kalluru 		case SPEED_40000:
534133fac0eSSudarsana Kalluru 			if (!(current_link.supported_caps &
535054c67d1SSudarsana Reddy Kalluru 			      QED_LM_40000baseLR4_Full_BIT)) {
536133fac0eSSudarsana Kalluru 				DP_INFO(edev, "40G speed not supported\n");
537133fac0eSSudarsana Kalluru 				return -EINVAL;
538133fac0eSSudarsana Kalluru 			}
539054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_40000baseLR4_Full_BIT;
540054c67d1SSudarsana Reddy Kalluru 			break;
54116d5946aSYuval Mintz 		case SPEED_50000:
542054c67d1SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
543054c67d1SSudarsana Reddy Kalluru 			      QED_LM_50000baseKR2_Full_BIT)) {
544054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "50G speed not supported\n");
545054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
546054c67d1SSudarsana Reddy Kalluru 			}
547054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_50000baseKR2_Full_BIT;
548054c67d1SSudarsana Reddy Kalluru 			break;
54916d5946aSYuval Mintz 		case SPEED_100000:
550054c67d1SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
551054c67d1SSudarsana Reddy Kalluru 			      QED_LM_100000baseKR4_Full_BIT)) {
552054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "100G speed not supported\n");
553054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
554054c67d1SSudarsana Reddy Kalluru 			}
555054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_100000baseKR4_Full_BIT;
556133fac0eSSudarsana Kalluru 			break;
557133fac0eSSudarsana Kalluru 		default:
558054c67d1SSudarsana Reddy Kalluru 			DP_INFO(edev, "Unsupported speed %u\n", base->speed);
559133fac0eSSudarsana Kalluru 			return -EINVAL;
560133fac0eSSudarsana Kalluru 		}
561133fac0eSSudarsana Kalluru 	}
562133fac0eSSudarsana Kalluru 
563133fac0eSSudarsana Kalluru 	params.link_up = true;
564133fac0eSSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
565133fac0eSSudarsana Kalluru 
566133fac0eSSudarsana Kalluru 	return 0;
567133fac0eSSudarsana Kalluru }
568133fac0eSSudarsana Kalluru 
569133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev,
570133fac0eSSudarsana Kalluru 			     struct ethtool_drvinfo *info)
571133fac0eSSudarsana Kalluru {
572133fac0eSSudarsana Kalluru 	char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN];
573133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
574133fac0eSSudarsana Kalluru 
575133fac0eSSudarsana Kalluru 	strlcpy(info->driver, "qede", sizeof(info->driver));
576133fac0eSSudarsana Kalluru 	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
577133fac0eSSudarsana Kalluru 
578133fac0eSSudarsana Kalluru 	snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
579133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_major,
580133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_minor,
581133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_rev,
582133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_eng);
583133fac0eSSudarsana Kalluru 
584133fac0eSSudarsana Kalluru 	snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
585133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 24) & 0xFF,
586133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 16) & 0xFF,
587133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 8) & 0xFF,
588133fac0eSSudarsana Kalluru 		 edev->dev_info.common.mfw_rev & 0xFF);
589133fac0eSSudarsana Kalluru 
590133fac0eSSudarsana Kalluru 	if ((strlen(storm) + strlen(mfw) + strlen("mfw storm  ")) <
591133fac0eSSudarsana Kalluru 	    sizeof(info->fw_version)) {
592133fac0eSSudarsana Kalluru 		snprintf(info->fw_version, sizeof(info->fw_version),
593133fac0eSSudarsana Kalluru 			 "mfw %s storm %s", mfw, storm);
594133fac0eSSudarsana Kalluru 	} else {
595133fac0eSSudarsana Kalluru 		snprintf(info->fw_version, sizeof(info->fw_version),
596133fac0eSSudarsana Kalluru 			 "%s %s", mfw, storm);
597133fac0eSSudarsana Kalluru 	}
598133fac0eSSudarsana Kalluru 
599133fac0eSSudarsana Kalluru 	strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
600133fac0eSSudarsana Kalluru }
601133fac0eSSudarsana Kalluru 
60214d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
60314d39648SMintz, Yuval {
60414d39648SMintz, Yuval 	struct qede_dev *edev = netdev_priv(ndev);
60514d39648SMintz, Yuval 
60614d39648SMintz, Yuval 	if (edev->dev_info.common.wol_support) {
60714d39648SMintz, Yuval 		wol->supported = WAKE_MAGIC;
60814d39648SMintz, Yuval 		wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0;
60914d39648SMintz, Yuval 	}
61014d39648SMintz, Yuval }
61114d39648SMintz, Yuval 
61214d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
61314d39648SMintz, Yuval {
61414d39648SMintz, Yuval 	struct qede_dev *edev = netdev_priv(ndev);
61514d39648SMintz, Yuval 	bool wol_requested;
61614d39648SMintz, Yuval 	int rc;
61714d39648SMintz, Yuval 
61814d39648SMintz, Yuval 	if (wol->wolopts & ~WAKE_MAGIC) {
61914d39648SMintz, Yuval 		DP_INFO(edev,
62014d39648SMintz, Yuval 			"Can't support WoL options other than magic-packet\n");
62114d39648SMintz, Yuval 		return -EINVAL;
62214d39648SMintz, Yuval 	}
62314d39648SMintz, Yuval 
62414d39648SMintz, Yuval 	wol_requested = !!(wol->wolopts & WAKE_MAGIC);
62514d39648SMintz, Yuval 	if (wol_requested == edev->wol_enabled)
62614d39648SMintz, Yuval 		return 0;
62714d39648SMintz, Yuval 
62814d39648SMintz, Yuval 	/* Need to actually change configuration */
62914d39648SMintz, Yuval 	if (!edev->dev_info.common.wol_support) {
63014d39648SMintz, Yuval 		DP_INFO(edev, "Device doesn't support WoL\n");
63114d39648SMintz, Yuval 		return -EINVAL;
63214d39648SMintz, Yuval 	}
63314d39648SMintz, Yuval 
63414d39648SMintz, Yuval 	rc = edev->ops->common->update_wol(edev->cdev, wol_requested);
63514d39648SMintz, Yuval 	if (!rc)
63614d39648SMintz, Yuval 		edev->wol_enabled = wol_requested;
63714d39648SMintz, Yuval 
63814d39648SMintz, Yuval 	return rc;
63914d39648SMintz, Yuval }
64014d39648SMintz, Yuval 
641133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev)
642133fac0eSSudarsana Kalluru {
643133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
644133fac0eSSudarsana Kalluru 
6451a635e48SYuval Mintz 	return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module;
646133fac0eSSudarsana Kalluru }
647133fac0eSSudarsana Kalluru 
648133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level)
649133fac0eSSudarsana Kalluru {
650133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
651133fac0eSSudarsana Kalluru 	u32 dp_module = 0;
652133fac0eSSudarsana Kalluru 	u8 dp_level = 0;
653133fac0eSSudarsana Kalluru 
654133fac0eSSudarsana Kalluru 	qede_config_debug(level, &dp_module, &dp_level);
655133fac0eSSudarsana Kalluru 
656133fac0eSSudarsana Kalluru 	edev->dp_level = dp_level;
657133fac0eSSudarsana Kalluru 	edev->dp_module = dp_module;
658133fac0eSSudarsana Kalluru 	edev->ops->common->update_msglvl(edev->cdev,
659133fac0eSSudarsana Kalluru 					 dp_module, dp_level);
660133fac0eSSudarsana Kalluru }
661133fac0eSSudarsana Kalluru 
66232a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev)
66332a7a570SSudarsana Kalluru {
66432a7a570SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
66532a7a570SSudarsana Kalluru 	struct qed_link_output current_link;
66632a7a570SSudarsana Kalluru 	struct qed_link_params link_params;
66732a7a570SSudarsana Kalluru 
668fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
6691a635e48SYuval Mintz 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
670fe7cd2bfSYuval Mintz 		return -EOPNOTSUPP;
671fe7cd2bfSYuval Mintz 	}
672fe7cd2bfSYuval Mintz 
67332a7a570SSudarsana Kalluru 	if (!netif_running(dev))
67432a7a570SSudarsana Kalluru 		return 0;
67532a7a570SSudarsana Kalluru 
67632a7a570SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
67732a7a570SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
67832a7a570SSudarsana Kalluru 	if (!current_link.link_up)
67932a7a570SSudarsana Kalluru 		return 0;
68032a7a570SSudarsana Kalluru 
68132a7a570SSudarsana Kalluru 	/* Toggle the link */
68232a7a570SSudarsana Kalluru 	memset(&link_params, 0, sizeof(link_params));
68332a7a570SSudarsana Kalluru 	link_params.link_up = false;
68432a7a570SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
68532a7a570SSudarsana Kalluru 	link_params.link_up = true;
68632a7a570SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
68732a7a570SSudarsana Kalluru 
68832a7a570SSudarsana Kalluru 	return 0;
68932a7a570SSudarsana Kalluru }
69032a7a570SSudarsana Kalluru 
691133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev)
692133fac0eSSudarsana Kalluru {
693133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
694133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
695133fac0eSSudarsana Kalluru 
696133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
697133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
698133fac0eSSudarsana Kalluru 
699133fac0eSSudarsana Kalluru 	return current_link.link_up;
700133fac0eSSudarsana Kalluru }
701133fac0eSSudarsana Kalluru 
702d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev,
703d552fa84SSudarsana Reddy Kalluru 			     struct ethtool_coalesce *coal)
704d552fa84SSudarsana Reddy Kalluru {
705d552fa84SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
706d2890deaSSudarsana Reddy Kalluru 	u16 rxc, txc;
707d552fa84SSudarsana Reddy Kalluru 
708d552fa84SSudarsana Reddy Kalluru 	memset(coal, 0, sizeof(struct ethtool_coalesce));
709d2890deaSSudarsana Reddy Kalluru 	edev->ops->common->get_coalesce(edev->cdev, &rxc, &txc);
710d2890deaSSudarsana Reddy Kalluru 
711d2890deaSSudarsana Reddy Kalluru 	coal->rx_coalesce_usecs = rxc;
712d2890deaSSudarsana Reddy Kalluru 	coal->tx_coalesce_usecs = txc;
713d552fa84SSudarsana Reddy Kalluru 
714d552fa84SSudarsana Reddy Kalluru 	return 0;
715d552fa84SSudarsana Reddy Kalluru }
716d552fa84SSudarsana Reddy Kalluru 
717d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev,
718d552fa84SSudarsana Reddy Kalluru 			     struct ethtool_coalesce *coal)
719d552fa84SSudarsana Reddy Kalluru {
720d552fa84SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
721477f2d14SRahul Verma 	struct qede_fastpath *fp;
722d552fa84SSudarsana Reddy Kalluru 	int i, rc = 0;
723477f2d14SRahul Verma 	u16 rxc, txc;
724d552fa84SSudarsana Reddy Kalluru 
725d552fa84SSudarsana Reddy Kalluru 	if (!netif_running(dev)) {
726d552fa84SSudarsana Reddy Kalluru 		DP_INFO(edev, "Interface is down\n");
727d552fa84SSudarsana Reddy Kalluru 		return -EINVAL;
728d552fa84SSudarsana Reddy Kalluru 	}
729d552fa84SSudarsana Reddy Kalluru 
730d552fa84SSudarsana Reddy Kalluru 	if (coal->rx_coalesce_usecs > QED_COALESCE_MAX ||
731d552fa84SSudarsana Reddy Kalluru 	    coal->tx_coalesce_usecs > QED_COALESCE_MAX) {
732d552fa84SSudarsana Reddy Kalluru 		DP_INFO(edev,
733d552fa84SSudarsana Reddy Kalluru 			"Can't support requested %s coalesce value [max supported value %d]\n",
734477f2d14SRahul Verma 			coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" :
735477f2d14SRahul Verma 			"tx", QED_COALESCE_MAX);
736d552fa84SSudarsana Reddy Kalluru 		return -EINVAL;
737d552fa84SSudarsana Reddy Kalluru 	}
738d552fa84SSudarsana Reddy Kalluru 
739d552fa84SSudarsana Reddy Kalluru 	rxc = (u16)coal->rx_coalesce_usecs;
740d552fa84SSudarsana Reddy Kalluru 	txc = (u16)coal->tx_coalesce_usecs;
7419a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
742477f2d14SRahul Verma 		fp = &edev->fp_array[i];
743477f2d14SRahul Verma 
744477f2d14SRahul Verma 		if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
745477f2d14SRahul Verma 			rc = edev->ops->common->set_coalesce(edev->cdev,
746477f2d14SRahul Verma 							     rxc, 0,
747477f2d14SRahul Verma 							     fp->rxq->handle);
748d552fa84SSudarsana Reddy Kalluru 			if (rc) {
749477f2d14SRahul Verma 				DP_INFO(edev,
750477f2d14SRahul Verma 					"Set RX coalesce error, rc = %d\n", rc);
751d552fa84SSudarsana Reddy Kalluru 				return rc;
752d552fa84SSudarsana Reddy Kalluru 			}
753d552fa84SSudarsana Reddy Kalluru 		}
754d552fa84SSudarsana Reddy Kalluru 
755477f2d14SRahul Verma 		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
756477f2d14SRahul Verma 			rc = edev->ops->common->set_coalesce(edev->cdev,
757477f2d14SRahul Verma 							     0, txc,
758477f2d14SRahul Verma 							     fp->txq->handle);
759477f2d14SRahul Verma 			if (rc) {
760477f2d14SRahul Verma 				DP_INFO(edev,
761477f2d14SRahul Verma 					"Set TX coalesce error, rc = %d\n", rc);
762477f2d14SRahul Verma 				return rc;
763477f2d14SRahul Verma 			}
764477f2d14SRahul Verma 		}
765477f2d14SRahul Verma 	}
766477f2d14SRahul Verma 
767d552fa84SSudarsana Reddy Kalluru 	return rc;
768d552fa84SSudarsana Reddy Kalluru }
769d552fa84SSudarsana Reddy Kalluru 
77001ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev,
77101ef7e05SSudarsana Kalluru 			       struct ethtool_ringparam *ering)
77201ef7e05SSudarsana Kalluru {
77301ef7e05SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
77401ef7e05SSudarsana Kalluru 
77501ef7e05SSudarsana Kalluru 	ering->rx_max_pending = NUM_RX_BDS_MAX;
77601ef7e05SSudarsana Kalluru 	ering->rx_pending = edev->q_num_rx_buffers;
77701ef7e05SSudarsana Kalluru 	ering->tx_max_pending = NUM_TX_BDS_MAX;
77801ef7e05SSudarsana Kalluru 	ering->tx_pending = edev->q_num_tx_buffers;
77901ef7e05SSudarsana Kalluru }
78001ef7e05SSudarsana Kalluru 
78101ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev,
78201ef7e05SSudarsana Kalluru 			      struct ethtool_ringparam *ering)
78301ef7e05SSudarsana Kalluru {
78401ef7e05SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
78501ef7e05SSudarsana Kalluru 
78601ef7e05SSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
78701ef7e05SSudarsana Kalluru 		   "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n",
78801ef7e05SSudarsana Kalluru 		   ering->rx_pending, ering->tx_pending);
78901ef7e05SSudarsana Kalluru 
79001ef7e05SSudarsana Kalluru 	/* Validate legality of configuration */
79101ef7e05SSudarsana Kalluru 	if (ering->rx_pending > NUM_RX_BDS_MAX ||
79201ef7e05SSudarsana Kalluru 	    ering->rx_pending < NUM_RX_BDS_MIN ||
79301ef7e05SSudarsana Kalluru 	    ering->tx_pending > NUM_TX_BDS_MAX ||
79401ef7e05SSudarsana Kalluru 	    ering->tx_pending < NUM_TX_BDS_MIN) {
79501ef7e05SSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
79601ef7e05SSudarsana Kalluru 			   "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n",
79701ef7e05SSudarsana Kalluru 			   NUM_RX_BDS_MIN, NUM_RX_BDS_MAX,
79801ef7e05SSudarsana Kalluru 			   NUM_TX_BDS_MIN, NUM_TX_BDS_MAX);
79901ef7e05SSudarsana Kalluru 		return -EINVAL;
80001ef7e05SSudarsana Kalluru 	}
80101ef7e05SSudarsana Kalluru 
80201ef7e05SSudarsana Kalluru 	/* Change ring size and re-load */
80301ef7e05SSudarsana Kalluru 	edev->q_num_rx_buffers = ering->rx_pending;
80401ef7e05SSudarsana Kalluru 	edev->q_num_tx_buffers = ering->tx_pending;
80501ef7e05SSudarsana Kalluru 
806567b3c12SMintz, Yuval 	qede_reload(edev, NULL, false);
80701ef7e05SSudarsana Kalluru 
80801ef7e05SSudarsana Kalluru 	return 0;
80901ef7e05SSudarsana Kalluru }
81001ef7e05SSudarsana Kalluru 
8110f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev,
8120f7db144SSudarsana Kalluru 				struct ethtool_pauseparam *epause)
8130f7db144SSudarsana Kalluru {
8140f7db144SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
8150f7db144SSudarsana Kalluru 	struct qed_link_output current_link;
8160f7db144SSudarsana Kalluru 
8170f7db144SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
8180f7db144SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
8190f7db144SSudarsana Kalluru 
8200f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE)
8210f7db144SSudarsana Kalluru 		epause->autoneg = true;
8220f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE)
8230f7db144SSudarsana Kalluru 		epause->rx_pause = true;
8240f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE)
8250f7db144SSudarsana Kalluru 		epause->tx_pause = true;
8260f7db144SSudarsana Kalluru 
8270f7db144SSudarsana Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
8280f7db144SSudarsana Kalluru 		   "ethtool_pauseparam: cmd %d  autoneg %d  rx_pause %d  tx_pause %d\n",
8290f7db144SSudarsana Kalluru 		   epause->cmd, epause->autoneg, epause->rx_pause,
8300f7db144SSudarsana Kalluru 		   epause->tx_pause);
8310f7db144SSudarsana Kalluru }
8320f7db144SSudarsana Kalluru 
8330f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev,
8340f7db144SSudarsana Kalluru 			       struct ethtool_pauseparam *epause)
8350f7db144SSudarsana Kalluru {
8360f7db144SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
8370f7db144SSudarsana Kalluru 	struct qed_link_params params;
8380f7db144SSudarsana Kalluru 	struct qed_link_output current_link;
8390f7db144SSudarsana Kalluru 
840fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
8410f7db144SSudarsana Kalluru 		DP_INFO(edev,
842fe7cd2bfSYuval Mintz 			"Pause settings are not allowed to be changed\n");
8430f7db144SSudarsana Kalluru 		return -EOPNOTSUPP;
8440f7db144SSudarsana Kalluru 	}
8450f7db144SSudarsana Kalluru 
8460f7db144SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
8470f7db144SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
8480f7db144SSudarsana Kalluru 
8490f7db144SSudarsana Kalluru 	memset(&params, 0, sizeof(params));
8500f7db144SSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG;
8510f7db144SSudarsana Kalluru 	if (epause->autoneg) {
852d194fd26SYuval Mintz 		if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) {
8530f7db144SSudarsana Kalluru 			DP_INFO(edev, "autoneg not supported\n");
8540f7db144SSudarsana Kalluru 			return -EINVAL;
8550f7db144SSudarsana Kalluru 		}
8560f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
8570f7db144SSudarsana Kalluru 	}
8580f7db144SSudarsana Kalluru 	if (epause->rx_pause)
8590f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_RX_ENABLE;
8600f7db144SSudarsana Kalluru 	if (epause->tx_pause)
8610f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_TX_ENABLE;
8620f7db144SSudarsana Kalluru 
8630f7db144SSudarsana Kalluru 	params.link_up = true;
8640f7db144SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
8650f7db144SSudarsana Kalluru 
8660f7db144SSudarsana Kalluru 	return 0;
8670f7db144SSudarsana Kalluru }
8680f7db144SSudarsana Kalluru 
869e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev,
870e0971c83STomer Tayar 			  struct ethtool_regs *regs, void *buffer)
871e0971c83STomer Tayar {
872e0971c83STomer Tayar 	struct qede_dev *edev = netdev_priv(ndev);
873e0971c83STomer Tayar 
874e0971c83STomer Tayar 	regs->version = 0;
875e0971c83STomer Tayar 	memset(buffer, 0, regs->len);
876e0971c83STomer Tayar 
877e0971c83STomer Tayar 	if (edev->ops && edev->ops->common)
878e0971c83STomer Tayar 		edev->ops->common->dbg_all_data(edev->cdev, buffer);
879e0971c83STomer Tayar }
880e0971c83STomer Tayar 
881e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev)
882e0971c83STomer Tayar {
883e0971c83STomer Tayar 	struct qede_dev *edev = netdev_priv(ndev);
884e0971c83STomer Tayar 
885e0971c83STomer Tayar 	if (edev->ops && edev->ops->common)
886e0971c83STomer Tayar 		return edev->ops->common->dbg_all_data_size(edev->cdev);
887e0971c83STomer Tayar 	else
888e0971c83STomer Tayar 		return -EINVAL;
889e0971c83STomer Tayar }
890e0971c83STomer Tayar 
891567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev,
892567b3c12SMintz, Yuval 			    struct qede_reload_args *args)
893133fac0eSSudarsana Kalluru {
894567b3c12SMintz, Yuval 	edev->ndev->mtu = args->u.mtu;
895133fac0eSSudarsana Kalluru }
896133fac0eSSudarsana Kalluru 
897133fac0eSSudarsana Kalluru /* Netdevice NDOs */
898133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu)
899133fac0eSSudarsana Kalluru {
900133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
901567b3c12SMintz, Yuval 	struct qede_reload_args args;
902133fac0eSSudarsana Kalluru 
903133fac0eSSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
904133fac0eSSudarsana Kalluru 		   "Configuring MTU size of %d\n", new_mtu);
905133fac0eSSudarsana Kalluru 
906133fac0eSSudarsana Kalluru 	/* Set the mtu field and re-start the interface if needed */
907567b3c12SMintz, Yuval 	args.u.mtu = new_mtu;
908567b3c12SMintz, Yuval 	args.func = &qede_update_mtu;
909567b3c12SMintz, Yuval 	qede_reload(edev, &args, false);
910133fac0eSSudarsana Kalluru 
911567b3c12SMintz, Yuval 	edev->ops->common->update_mtu(edev->cdev, new_mtu);
9120fefbfbaSSudarsana Kalluru 
913133fac0eSSudarsana Kalluru 	return 0;
914133fac0eSSudarsana Kalluru }
915133fac0eSSudarsana Kalluru 
9168edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev,
9178edf049dSSudarsana Kalluru 			      struct ethtool_channels *channels)
9188edf049dSSudarsana Kalluru {
9198edf049dSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
9208edf049dSSudarsana Kalluru 
9218edf049dSSudarsana Kalluru 	channels->max_combined = QEDE_MAX_RSS_CNT(edev);
922bdc8cbd3SSudarsana Reddy Kalluru 	channels->max_rx = QEDE_MAX_RSS_CNT(edev);
923bdc8cbd3SSudarsana Reddy Kalluru 	channels->max_tx = QEDE_MAX_RSS_CNT(edev);
9249a4d7e86SSudarsana Reddy Kalluru 	channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx -
9259a4d7e86SSudarsana Reddy Kalluru 					edev->fp_num_rx;
9269a4d7e86SSudarsana Reddy Kalluru 	channels->tx_count = edev->fp_num_tx;
9279a4d7e86SSudarsana Reddy Kalluru 	channels->rx_count = edev->fp_num_rx;
9288edf049dSSudarsana Kalluru }
9298edf049dSSudarsana Kalluru 
9308edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev,
9318edf049dSSudarsana Kalluru 			     struct ethtool_channels *channels)
9328edf049dSSudarsana Kalluru {
9338edf049dSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
9349a4d7e86SSudarsana Reddy Kalluru 	u32 count;
9358edf049dSSudarsana Kalluru 
9368edf049dSSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
9378edf049dSSudarsana Kalluru 		   "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n",
9388edf049dSSudarsana Kalluru 		   channels->rx_count, channels->tx_count,
9398edf049dSSudarsana Kalluru 		   channels->other_count, channels->combined_count);
9408edf049dSSudarsana Kalluru 
9419a4d7e86SSudarsana Reddy Kalluru 	count = channels->rx_count + channels->tx_count +
9429a4d7e86SSudarsana Reddy Kalluru 			channels->combined_count;
9439a4d7e86SSudarsana Reddy Kalluru 
9449a4d7e86SSudarsana Reddy Kalluru 	/* We don't support `other' channels */
9459a4d7e86SSudarsana Reddy Kalluru 	if (channels->other_count) {
9468edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
9478edf049dSSudarsana Kalluru 			   "command parameters not supported\n");
9488edf049dSSudarsana Kalluru 		return -EINVAL;
9498edf049dSSudarsana Kalluru 	}
9508edf049dSSudarsana Kalluru 
9519a4d7e86SSudarsana Reddy Kalluru 	if (!(channels->combined_count || (channels->rx_count &&
9529a4d7e86SSudarsana Reddy Kalluru 					   channels->tx_count))) {
9539a4d7e86SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
9549a4d7e86SSudarsana Reddy Kalluru 			   "need to request at least one transmit and one receive channel\n");
9559a4d7e86SSudarsana Reddy Kalluru 		return -EINVAL;
9569a4d7e86SSudarsana Reddy Kalluru 	}
9579a4d7e86SSudarsana Reddy Kalluru 
9589a4d7e86SSudarsana Reddy Kalluru 	if (count > QEDE_MAX_RSS_CNT(edev)) {
9599a4d7e86SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
9609a4d7e86SSudarsana Reddy Kalluru 			   "requested channels = %d max supported channels = %d\n",
9619a4d7e86SSudarsana Reddy Kalluru 			   count, QEDE_MAX_RSS_CNT(edev));
9629a4d7e86SSudarsana Reddy Kalluru 		return -EINVAL;
9639a4d7e86SSudarsana Reddy Kalluru 	}
9649a4d7e86SSudarsana Reddy Kalluru 
9658edf049dSSudarsana Kalluru 	/* Check if there was a change in the active parameters */
9669a4d7e86SSudarsana Reddy Kalluru 	if ((count == QEDE_QUEUE_CNT(edev)) &&
9679a4d7e86SSudarsana Reddy Kalluru 	    (channels->tx_count == edev->fp_num_tx) &&
9689a4d7e86SSudarsana Reddy Kalluru 	    (channels->rx_count == edev->fp_num_rx)) {
9698edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
9708edf049dSSudarsana Kalluru 			   "No change in active parameters\n");
9718edf049dSSudarsana Kalluru 		return 0;
9728edf049dSSudarsana Kalluru 	}
9738edf049dSSudarsana Kalluru 
9748edf049dSSudarsana Kalluru 	/* We need the number of queues to be divisible between the hwfns */
9759a4d7e86SSudarsana Reddy Kalluru 	if ((count % edev->dev_info.common.num_hwfns) ||
9769a4d7e86SSudarsana Reddy Kalluru 	    (channels->tx_count % edev->dev_info.common.num_hwfns) ||
9779a4d7e86SSudarsana Reddy Kalluru 	    (channels->rx_count % edev->dev_info.common.num_hwfns)) {
9788edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
9799a4d7e86SSudarsana Reddy Kalluru 			   "Number of channels must be divisible by %04x\n",
9808edf049dSSudarsana Kalluru 			   edev->dev_info.common.num_hwfns);
9818edf049dSSudarsana Kalluru 		return -EINVAL;
9828edf049dSSudarsana Kalluru 	}
9838edf049dSSudarsana Kalluru 
9848edf049dSSudarsana Kalluru 	/* Set number of queues and reload if necessary */
9859a4d7e86SSudarsana Reddy Kalluru 	edev->req_queues = count;
9869a4d7e86SSudarsana Reddy Kalluru 	edev->req_num_tx = channels->tx_count;
9879a4d7e86SSudarsana Reddy Kalluru 	edev->req_num_rx = channels->rx_count;
988ed0dd915SSudarsana Reddy Kalluru 	/* Reset the indirection table if rx queue count is updated */
989ed0dd915SSudarsana Reddy Kalluru 	if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) {
990ed0dd915SSudarsana Reddy Kalluru 		edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED;
991f29ffdb6SMintz, Yuval 		memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table));
992ed0dd915SSudarsana Reddy Kalluru 	}
993ed0dd915SSudarsana Reddy Kalluru 
994567b3c12SMintz, Yuval 	qede_reload(edev, NULL, false);
9958edf049dSSudarsana Kalluru 
9968edf049dSSudarsana Kalluru 	return 0;
9978edf049dSSudarsana Kalluru }
9988edf049dSSudarsana Kalluru 
9994c55215cSSudarsana Reddy Kalluru static int qede_get_ts_info(struct net_device *dev,
10004c55215cSSudarsana Reddy Kalluru 			    struct ethtool_ts_info *info)
10014c55215cSSudarsana Reddy Kalluru {
10024c55215cSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
10034c55215cSSudarsana Reddy Kalluru 
10044c55215cSSudarsana Reddy Kalluru 	return qede_ptp_get_ts_info(edev, info);
10054c55215cSSudarsana Reddy Kalluru }
10064c55215cSSudarsana Reddy Kalluru 
10073d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev,
10083d971cbdSSudarsana Kalluru 			    enum ethtool_phys_id_state state)
10093d971cbdSSudarsana Kalluru {
10103d971cbdSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
10113d971cbdSSudarsana Kalluru 	u8 led_state = 0;
10123d971cbdSSudarsana Kalluru 
10133d971cbdSSudarsana Kalluru 	switch (state) {
10143d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ACTIVE:
10153d971cbdSSudarsana Kalluru 		return 1;	/* cycle on/off once per second */
10163d971cbdSSudarsana Kalluru 
10173d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ON:
10183d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_ON;
10193d971cbdSSudarsana Kalluru 		break;
10203d971cbdSSudarsana Kalluru 
10213d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_OFF:
10223d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_OFF;
10233d971cbdSSudarsana Kalluru 		break;
10243d971cbdSSudarsana Kalluru 
10253d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_INACTIVE:
10263d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_RESTORE;
10273d971cbdSSudarsana Kalluru 		break;
10283d971cbdSSudarsana Kalluru 	}
10293d971cbdSSudarsana Kalluru 
10303d971cbdSSudarsana Kalluru 	edev->ops->common->set_led(edev->cdev, led_state);
10313d971cbdSSudarsana Kalluru 
10323d971cbdSSudarsana Kalluru 	return 0;
10333d971cbdSSudarsana Kalluru }
10343d971cbdSSudarsana Kalluru 
1035961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
1036961acdeaSSudarsana Reddy Kalluru {
1037961acdeaSSudarsana Reddy Kalluru 	info->data = RXH_IP_SRC | RXH_IP_DST;
1038961acdeaSSudarsana Reddy Kalluru 
1039961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
1040961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
1041961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
1042961acdeaSSudarsana Reddy Kalluru 		info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1043961acdeaSSudarsana Reddy Kalluru 		break;
1044961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
1045f29ffdb6SMintz, Yuval 		if (edev->rss_caps & QED_RSS_IPV4_UDP)
1046961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1047961acdeaSSudarsana Reddy Kalluru 		break;
1048961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
1049f29ffdb6SMintz, Yuval 		if (edev->rss_caps & QED_RSS_IPV6_UDP)
1050961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1051961acdeaSSudarsana Reddy Kalluru 		break;
1052961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
1053961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
1054961acdeaSSudarsana Reddy Kalluru 		break;
1055961acdeaSSudarsana Reddy Kalluru 	default:
1056961acdeaSSudarsana Reddy Kalluru 		info->data = 0;
1057961acdeaSSudarsana Reddy Kalluru 		break;
1058961acdeaSSudarsana Reddy Kalluru 	}
1059961acdeaSSudarsana Reddy Kalluru 
1060961acdeaSSudarsana Reddy Kalluru 	return 0;
1061961acdeaSSudarsana Reddy Kalluru }
1062961acdeaSSudarsana Reddy Kalluru 
1063961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
1064ec9b8dbdSChopra, Manish 			  u32 *rule_locs)
1065961acdeaSSudarsana Reddy Kalluru {
1066961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1067ec9b8dbdSChopra, Manish 	int rc = 0;
1068961acdeaSSudarsana Reddy Kalluru 
1069961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
1070961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXRINGS:
10719a4d7e86SSudarsana Reddy Kalluru 		info->data = QEDE_RSS_COUNT(edev);
1072ec9b8dbdSChopra, Manish 		break;
1073961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXFH:
1074ec9b8dbdSChopra, Manish 		rc = qede_get_rss_flags(edev, info);
1075ec9b8dbdSChopra, Manish 		break;
1076ec9b8dbdSChopra, Manish 	case ETHTOOL_GRXCLSRLCNT:
1077ec9b8dbdSChopra, Manish 		info->rule_cnt = qede_get_arfs_filter_count(edev);
1078ec9b8dbdSChopra, Manish 		info->data = QEDE_RFS_MAX_FLTR;
1079ec9b8dbdSChopra, Manish 		break;
1080ec9b8dbdSChopra, Manish 	case ETHTOOL_GRXCLSRULE:
1081ec9b8dbdSChopra, Manish 		rc = qede_get_cls_rule_entry(edev, info);
1082ec9b8dbdSChopra, Manish 		break;
1083ec9b8dbdSChopra, Manish 	case ETHTOOL_GRXCLSRLALL:
1084ec9b8dbdSChopra, Manish 		rc = qede_get_cls_rule_all(edev, info, rule_locs);
1085ec9b8dbdSChopra, Manish 		break;
1086961acdeaSSudarsana Reddy Kalluru 	default:
1087961acdeaSSudarsana Reddy Kalluru 		DP_ERR(edev, "Command parameters not supported\n");
1088ec9b8dbdSChopra, Manish 		rc = -EOPNOTSUPP;
1089961acdeaSSudarsana Reddy Kalluru 	}
1090ec9b8dbdSChopra, Manish 
1091ec9b8dbdSChopra, Manish 	return rc;
1092961acdeaSSudarsana Reddy Kalluru }
1093961acdeaSSudarsana Reddy Kalluru 
1094961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
1095961acdeaSSudarsana Reddy Kalluru {
1096f29ffdb6SMintz, Yuval 	struct qed_update_vport_params *vport_update_params;
1097961acdeaSSudarsana Reddy Kalluru 	u8 set_caps = 0, clr_caps = 0;
1098f29ffdb6SMintz, Yuval 	int rc = 0;
1099961acdeaSSudarsana Reddy Kalluru 
1100961acdeaSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
1101961acdeaSSudarsana Reddy Kalluru 		   "Set rss flags command parameters: flow type = %d, data = %llu\n",
1102961acdeaSSudarsana Reddy Kalluru 		   info->flow_type, info->data);
1103961acdeaSSudarsana Reddy Kalluru 
1104961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
1105961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
1106961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
1107961acdeaSSudarsana Reddy Kalluru 		/* For TCP only 4-tuple hash is supported */
1108961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST |
1109961acdeaSSudarsana Reddy Kalluru 				  RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1110961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
1111961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1112961acdeaSSudarsana Reddy Kalluru 		}
1113961acdeaSSudarsana Reddy Kalluru 		return 0;
1114961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
1115961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
1116961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
1117961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1118961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV4_UDP;
1119961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1120961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
1121961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
1122961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV4_UDP;
1123961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1124961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
1125961acdeaSSudarsana Reddy Kalluru 		} else {
1126961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1127961acdeaSSudarsana Reddy Kalluru 		}
1128961acdeaSSudarsana Reddy Kalluru 		break;
1129961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
1130961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
1131961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
1132961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1133961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV6_UDP;
1134961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1135961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
1136961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
1137961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV6_UDP;
1138961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1139961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
1140961acdeaSSudarsana Reddy Kalluru 		} else {
1141961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1142961acdeaSSudarsana Reddy Kalluru 		}
1143961acdeaSSudarsana Reddy Kalluru 		break;
1144961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
1145961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
1146961acdeaSSudarsana Reddy Kalluru 		/* For IP only 2-tuple hash is supported */
1147961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) {
1148961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
1149961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1150961acdeaSSudarsana Reddy Kalluru 		}
1151961acdeaSSudarsana Reddy Kalluru 		return 0;
1152961acdeaSSudarsana Reddy Kalluru 	case SCTP_V4_FLOW:
1153961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V4_FLOW:
1154961acdeaSSudarsana Reddy Kalluru 	case AH_V4_FLOW:
1155961acdeaSSudarsana Reddy Kalluru 	case ESP_V4_FLOW:
1156961acdeaSSudarsana Reddy Kalluru 	case SCTP_V6_FLOW:
1157961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V6_FLOW:
1158961acdeaSSudarsana Reddy Kalluru 	case AH_V6_FLOW:
1159961acdeaSSudarsana Reddy Kalluru 	case ESP_V6_FLOW:
1160961acdeaSSudarsana Reddy Kalluru 	case IP_USER_FLOW:
1161961acdeaSSudarsana Reddy Kalluru 	case ETHER_FLOW:
1162961acdeaSSudarsana Reddy Kalluru 		/* RSS is not supported for these protocols */
1163961acdeaSSudarsana Reddy Kalluru 		if (info->data) {
1164961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
1165961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1166961acdeaSSudarsana Reddy Kalluru 		}
1167961acdeaSSudarsana Reddy Kalluru 		return 0;
1168961acdeaSSudarsana Reddy Kalluru 	default:
1169961acdeaSSudarsana Reddy Kalluru 		return -EINVAL;
1170961acdeaSSudarsana Reddy Kalluru 	}
1171961acdeaSSudarsana Reddy Kalluru 
1172961acdeaSSudarsana Reddy Kalluru 	/* No action is needed if there is no change in the rss capability */
1173f29ffdb6SMintz, Yuval 	if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps))
1174961acdeaSSudarsana Reddy Kalluru 		return 0;
1175961acdeaSSudarsana Reddy Kalluru 
1176961acdeaSSudarsana Reddy Kalluru 	/* Update internal configuration */
1177f29ffdb6SMintz, Yuval 	edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps);
1178961acdeaSSudarsana Reddy Kalluru 	edev->rss_params_inited |= QEDE_RSS_CAPS_INITED;
1179961acdeaSSudarsana Reddy Kalluru 
1180961acdeaSSudarsana Reddy Kalluru 	/* Re-configure if possible */
1181f29ffdb6SMintz, Yuval 	__qede_lock(edev);
1182f29ffdb6SMintz, Yuval 	if (edev->state == QEDE_STATE_OPEN) {
1183f29ffdb6SMintz, Yuval 		vport_update_params = vzalloc(sizeof(*vport_update_params));
1184f29ffdb6SMintz, Yuval 		if (!vport_update_params) {
1185f29ffdb6SMintz, Yuval 			__qede_unlock(edev);
1186f29ffdb6SMintz, Yuval 			return -ENOMEM;
1187961acdeaSSudarsana Reddy Kalluru 		}
1188f29ffdb6SMintz, Yuval 		qede_fill_rss_params(edev, &vport_update_params->rss_params,
1189f29ffdb6SMintz, Yuval 				     &vport_update_params->update_rss_flg);
1190f29ffdb6SMintz, Yuval 		rc = edev->ops->vport_update(edev->cdev, vport_update_params);
1191f29ffdb6SMintz, Yuval 		vfree(vport_update_params);
1192f29ffdb6SMintz, Yuval 	}
1193f29ffdb6SMintz, Yuval 	__qede_unlock(edev);
1194961acdeaSSudarsana Reddy Kalluru 
1195f29ffdb6SMintz, Yuval 	return rc;
1196961acdeaSSudarsana Reddy Kalluru }
1197961acdeaSSudarsana Reddy Kalluru 
1198961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
1199961acdeaSSudarsana Reddy Kalluru {
1200961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
12013f2a2b8bSChopra, Manish 	int rc;
1202961acdeaSSudarsana Reddy Kalluru 
1203961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
1204961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_SRXFH:
12053f2a2b8bSChopra, Manish 		rc = qede_set_rss_flags(edev, info);
12063f2a2b8bSChopra, Manish 		break;
12073f2a2b8bSChopra, Manish 	case ETHTOOL_SRXCLSRLINS:
12083f2a2b8bSChopra, Manish 		rc = qede_add_cls_rule(edev, info);
12093f2a2b8bSChopra, Manish 		break;
12103f2a2b8bSChopra, Manish 	case ETHTOOL_SRXCLSRLDEL:
12113f2a2b8bSChopra, Manish 		rc = qede_del_cls_rule(edev, info);
12123f2a2b8bSChopra, Manish 		break;
1213961acdeaSSudarsana Reddy Kalluru 	default:
1214961acdeaSSudarsana Reddy Kalluru 		DP_INFO(edev, "Command parameters not supported\n");
12153f2a2b8bSChopra, Manish 		rc = -EOPNOTSUPP;
1216961acdeaSSudarsana Reddy Kalluru 	}
12173f2a2b8bSChopra, Manish 
12183f2a2b8bSChopra, Manish 	return rc;
1219961acdeaSSudarsana Reddy Kalluru }
1220961acdeaSSudarsana Reddy Kalluru 
1221961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev)
1222961acdeaSSudarsana Reddy Kalluru {
1223961acdeaSSudarsana Reddy Kalluru 	return QED_RSS_IND_TABLE_SIZE;
1224961acdeaSSudarsana Reddy Kalluru }
1225961acdeaSSudarsana Reddy Kalluru 
1226961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev)
1227961acdeaSSudarsana Reddy Kalluru {
1228961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1229961acdeaSSudarsana Reddy Kalluru 
1230f29ffdb6SMintz, Yuval 	return sizeof(edev->rss_key);
1231961acdeaSSudarsana Reddy Kalluru }
1232961acdeaSSudarsana Reddy Kalluru 
1233961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc)
1234961acdeaSSudarsana Reddy Kalluru {
1235961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1236961acdeaSSudarsana Reddy Kalluru 	int i;
1237961acdeaSSudarsana Reddy Kalluru 
1238961acdeaSSudarsana Reddy Kalluru 	if (hfunc)
1239961acdeaSSudarsana Reddy Kalluru 		*hfunc = ETH_RSS_HASH_TOP;
1240961acdeaSSudarsana Reddy Kalluru 
1241961acdeaSSudarsana Reddy Kalluru 	if (!indir)
1242961acdeaSSudarsana Reddy Kalluru 		return 0;
1243961acdeaSSudarsana Reddy Kalluru 
1244961acdeaSSudarsana Reddy Kalluru 	for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1245f29ffdb6SMintz, Yuval 		indir[i] = edev->rss_ind_table[i];
1246961acdeaSSudarsana Reddy Kalluru 
1247961acdeaSSudarsana Reddy Kalluru 	if (key)
1248f29ffdb6SMintz, Yuval 		memcpy(key, edev->rss_key, qede_get_rxfh_key_size(dev));
1249961acdeaSSudarsana Reddy Kalluru 
1250961acdeaSSudarsana Reddy Kalluru 	return 0;
1251961acdeaSSudarsana Reddy Kalluru }
1252961acdeaSSudarsana Reddy Kalluru 
1253961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir,
1254961acdeaSSudarsana Reddy Kalluru 			 const u8 *key, const u8 hfunc)
1255961acdeaSSudarsana Reddy Kalluru {
1256f29ffdb6SMintz, Yuval 	struct qed_update_vport_params *vport_update_params;
1257961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1258f29ffdb6SMintz, Yuval 	int i, rc = 0;
1259961acdeaSSudarsana Reddy Kalluru 
1260ba300ce3SSudarsana Reddy Kalluru 	if (edev->dev_info.common.num_hwfns > 1) {
1261ba300ce3SSudarsana Reddy Kalluru 		DP_INFO(edev,
1262ba300ce3SSudarsana Reddy Kalluru 			"RSS configuration is not supported for 100G devices\n");
1263ba300ce3SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1264ba300ce3SSudarsana Reddy Kalluru 	}
1265ba300ce3SSudarsana Reddy Kalluru 
1266961acdeaSSudarsana Reddy Kalluru 	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
1267961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1268961acdeaSSudarsana Reddy Kalluru 
1269961acdeaSSudarsana Reddy Kalluru 	if (!indir && !key)
1270961acdeaSSudarsana Reddy Kalluru 		return 0;
1271961acdeaSSudarsana Reddy Kalluru 
1272961acdeaSSudarsana Reddy Kalluru 	if (indir) {
1273961acdeaSSudarsana Reddy Kalluru 		for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1274f29ffdb6SMintz, Yuval 			edev->rss_ind_table[i] = indir[i];
1275961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_INDIR_INITED;
1276961acdeaSSudarsana Reddy Kalluru 	}
1277961acdeaSSudarsana Reddy Kalluru 
1278961acdeaSSudarsana Reddy Kalluru 	if (key) {
1279f29ffdb6SMintz, Yuval 		memcpy(&edev->rss_key, key, qede_get_rxfh_key_size(dev));
1280961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_KEY_INITED;
1281961acdeaSSudarsana Reddy Kalluru 	}
1282961acdeaSSudarsana Reddy Kalluru 
1283f29ffdb6SMintz, Yuval 	__qede_lock(edev);
1284f29ffdb6SMintz, Yuval 	if (edev->state == QEDE_STATE_OPEN) {
1285f29ffdb6SMintz, Yuval 		vport_update_params = vzalloc(sizeof(*vport_update_params));
1286f29ffdb6SMintz, Yuval 		if (!vport_update_params) {
1287f29ffdb6SMintz, Yuval 			__qede_unlock(edev);
1288f29ffdb6SMintz, Yuval 			return -ENOMEM;
1289961acdeaSSudarsana Reddy Kalluru 		}
1290f29ffdb6SMintz, Yuval 		qede_fill_rss_params(edev, &vport_update_params->rss_params,
1291f29ffdb6SMintz, Yuval 				     &vport_update_params->update_rss_flg);
1292f29ffdb6SMintz, Yuval 		rc = edev->ops->vport_update(edev->cdev, vport_update_params);
1293f29ffdb6SMintz, Yuval 		vfree(vport_update_params);
1294f29ffdb6SMintz, Yuval 	}
1295f29ffdb6SMintz, Yuval 	__qede_unlock(edev);
1296961acdeaSSudarsana Reddy Kalluru 
1297f29ffdb6SMintz, Yuval 	return rc;
1298961acdeaSSudarsana Reddy Kalluru }
1299961acdeaSSudarsana Reddy Kalluru 
130016f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */
130116f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev)
130216f46bf0SSudarsana Reddy Kalluru {
130316f46bf0SSudarsana Reddy Kalluru 	int i;
130416f46bf0SSudarsana Reddy Kalluru 
130516f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev))
130616f46bf0SSudarsana Reddy Kalluru 		return;
130716f46bf0SSudarsana Reddy Kalluru 
13089a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
130916f46bf0SSudarsana Reddy Kalluru 		/* Update and reenable interrupts */
131016f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1);
131116f46bf0SSudarsana Reddy Kalluru 		napi_enable(&edev->fp_array[i].napi);
131216f46bf0SSudarsana Reddy Kalluru 	}
131316f46bf0SSudarsana Reddy Kalluru }
131416f46bf0SSudarsana Reddy Kalluru 
131516f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */
131616f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev)
131716f46bf0SSudarsana Reddy Kalluru {
131816f46bf0SSudarsana Reddy Kalluru 	int i;
131916f46bf0SSudarsana Reddy Kalluru 
13209a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
132116f46bf0SSudarsana Reddy Kalluru 		napi_disable(&edev->fp_array[i].napi);
132216f46bf0SSudarsana Reddy Kalluru 		/* Disable interrupts */
132316f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0);
132416f46bf0SSudarsana Reddy Kalluru 	}
132516f46bf0SSudarsana Reddy Kalluru }
132616f46bf0SSudarsana Reddy Kalluru 
132716f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev,
132816f46bf0SSudarsana Reddy Kalluru 					  struct sk_buff *skb)
132916f46bf0SSudarsana Reddy Kalluru {
13309a4d7e86SSudarsana Reddy Kalluru 	struct qede_tx_queue *txq = NULL;
133116f46bf0SSudarsana Reddy Kalluru 	struct eth_tx_1st_bd *first_bd;
133216f46bf0SSudarsana Reddy Kalluru 	dma_addr_t mapping;
133348848a06SManish Chopra 	int i, idx;
133448848a06SManish Chopra 	u16 val;
133516f46bf0SSudarsana Reddy Kalluru 
13369a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
13379a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
133880439a17SMintz, Yuval 			txq = edev->fp_array[i].txq;
13399a4d7e86SSudarsana Reddy Kalluru 			break;
13409a4d7e86SSudarsana Reddy Kalluru 		}
13419a4d7e86SSudarsana Reddy Kalluru 	}
13429a4d7e86SSudarsana Reddy Kalluru 
13439a4d7e86SSudarsana Reddy Kalluru 	if (!txq) {
13449a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx path is not available\n");
13459a4d7e86SSudarsana Reddy Kalluru 		return -1;
13469a4d7e86SSudarsana Reddy Kalluru 	}
13479a4d7e86SSudarsana Reddy Kalluru 
134816f46bf0SSudarsana Reddy Kalluru 	/* Fill the entry in the SW ring and the BDs in the FW ring */
13495a052d62SSudarsana Reddy Kalluru 	idx = txq->sw_tx_prod;
1350cb6aeb07SMintz, Yuval 	txq->sw_tx_ring.skbs[idx].skb = skb;
135116f46bf0SSudarsana Reddy Kalluru 	first_bd = qed_chain_produce(&txq->tx_pbl);
135216f46bf0SSudarsana Reddy Kalluru 	memset(first_bd, 0, sizeof(*first_bd));
135316f46bf0SSudarsana Reddy Kalluru 	val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
135416f46bf0SSudarsana Reddy Kalluru 	first_bd->data.bd_flags.bitfields = val;
1355351a4dedSYuval Mintz 	val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK;
135648848a06SManish Chopra 	val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT;
135748848a06SManish Chopra 	first_bd->data.bitfields |= cpu_to_le16(val);
135816f46bf0SSudarsana Reddy Kalluru 
135916f46bf0SSudarsana Reddy Kalluru 	/* Map skb linear data for DMA and set in the first BD */
136016f46bf0SSudarsana Reddy Kalluru 	mapping = dma_map_single(&edev->pdev->dev, skb->data,
136116f46bf0SSudarsana Reddy Kalluru 				 skb_headlen(skb), DMA_TO_DEVICE);
136216f46bf0SSudarsana Reddy Kalluru 	if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
136316f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "SKB mapping failed\n");
136416f46bf0SSudarsana Reddy Kalluru 		return -ENOMEM;
136516f46bf0SSudarsana Reddy Kalluru 	}
136616f46bf0SSudarsana Reddy Kalluru 	BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb));
136716f46bf0SSudarsana Reddy Kalluru 
136816f46bf0SSudarsana Reddy Kalluru 	/* update the first BD with the actual num BDs */
136916f46bf0SSudarsana Reddy Kalluru 	first_bd->data.nbds = 1;
13705a052d62SSudarsana Reddy Kalluru 	txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers;
137116f46bf0SSudarsana Reddy Kalluru 	/* 'next page' entries are counted in the producer value */
137248848a06SManish Chopra 	val = qed_chain_get_prod_idx(&txq->tx_pbl);
137348848a06SManish Chopra 	txq->tx_db.data.bd_prod = cpu_to_le16(val);
137416f46bf0SSudarsana Reddy Kalluru 
137516f46bf0SSudarsana Reddy Kalluru 	/* wmb makes sure that the BDs data is updated before updating the
137616f46bf0SSudarsana Reddy Kalluru 	 * producer, otherwise FW may read old data from the BDs.
137716f46bf0SSudarsana Reddy Kalluru 	 */
137816f46bf0SSudarsana Reddy Kalluru 	wmb();
137916f46bf0SSudarsana Reddy Kalluru 	barrier();
138016f46bf0SSudarsana Reddy Kalluru 	writel(txq->tx_db.raw, txq->doorbell_addr);
138116f46bf0SSudarsana Reddy Kalluru 
138216f46bf0SSudarsana Reddy Kalluru 	/* mmiowb is needed to synchronize doorbell writes from more than one
138316f46bf0SSudarsana Reddy Kalluru 	 * processor. It guarantees that the write arrives to the device before
138416f46bf0SSudarsana Reddy Kalluru 	 * the queue lock is released and another start_xmit is called (possibly
138516f46bf0SSudarsana Reddy Kalluru 	 * on another CPU). Without this barrier, the next doorbell can bypass
138616f46bf0SSudarsana Reddy Kalluru 	 * this doorbell. This is applicable to IA64/Altix systems.
138716f46bf0SSudarsana Reddy Kalluru 	 */
138816f46bf0SSudarsana Reddy Kalluru 	mmiowb();
138916f46bf0SSudarsana Reddy Kalluru 
139016f46bf0SSudarsana Reddy Kalluru 	for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
139116f46bf0SSudarsana Reddy Kalluru 		if (qede_txq_has_work(txq))
139216f46bf0SSudarsana Reddy Kalluru 			break;
139316f46bf0SSudarsana Reddy Kalluru 		usleep_range(100, 200);
139416f46bf0SSudarsana Reddy Kalluru 	}
139516f46bf0SSudarsana Reddy Kalluru 
139616f46bf0SSudarsana Reddy Kalluru 	if (!qede_txq_has_work(txq)) {
139716f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx completion didn't happen\n");
139816f46bf0SSudarsana Reddy Kalluru 		return -1;
139916f46bf0SSudarsana Reddy Kalluru 	}
140016f46bf0SSudarsana Reddy Kalluru 
140116f46bf0SSudarsana Reddy Kalluru 	first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
1402fabd545cSManish Chopra 	dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
140316f46bf0SSudarsana Reddy Kalluru 			 BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
14045a052d62SSudarsana Reddy Kalluru 	txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers;
1405cb6aeb07SMintz, Yuval 	txq->sw_tx_ring.skbs[idx].skb = NULL;
140616f46bf0SSudarsana Reddy Kalluru 
140716f46bf0SSudarsana Reddy Kalluru 	return 0;
140816f46bf0SSudarsana Reddy Kalluru }
140916f46bf0SSudarsana Reddy Kalluru 
141016f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev)
141116f46bf0SSudarsana Reddy Kalluru {
141216f46bf0SSudarsana Reddy Kalluru 	u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len;
141316f46bf0SSudarsana Reddy Kalluru 	struct eth_fast_path_rx_reg_cqe *fp_cqe;
14149a4d7e86SSudarsana Reddy Kalluru 	struct qede_rx_queue *rxq = NULL;
141516f46bf0SSudarsana Reddy Kalluru 	struct sw_rx_data *sw_rx_data;
141616f46bf0SSudarsana Reddy Kalluru 	union eth_rx_cqe *cqe;
1417afe981d6SSudarsana Reddy Kalluru 	int i, iter, rc = 0;
141816f46bf0SSudarsana Reddy Kalluru 	u8 *data_ptr;
141916f46bf0SSudarsana Reddy Kalluru 
14209a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
14219a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
14229a4d7e86SSudarsana Reddy Kalluru 			rxq = edev->fp_array[i].rxq;
14239a4d7e86SSudarsana Reddy Kalluru 			break;
14249a4d7e86SSudarsana Reddy Kalluru 		}
14259a4d7e86SSudarsana Reddy Kalluru 	}
14269a4d7e86SSudarsana Reddy Kalluru 
14279a4d7e86SSudarsana Reddy Kalluru 	if (!rxq) {
14289a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Rx path is not available\n");
14299a4d7e86SSudarsana Reddy Kalluru 		return -1;
14309a4d7e86SSudarsana Reddy Kalluru 	}
14319a4d7e86SSudarsana Reddy Kalluru 
143216f46bf0SSudarsana Reddy Kalluru 	/* The packet is expected to receive on rx-queue 0 even though RSS is
143316f46bf0SSudarsana Reddy Kalluru 	 * enabled. This is because the queue 0 is configured as the default
143416f46bf0SSudarsana Reddy Kalluru 	 * queue and that the loopback traffic is not IP.
143516f46bf0SSudarsana Reddy Kalluru 	 */
1436afe981d6SSudarsana Reddy Kalluru 	for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) {
143716f46bf0SSudarsana Reddy Kalluru 		if (!qede_has_rx_work(rxq)) {
1438837d4eb6SSudarsana Reddy Kalluru 			usleep_range(100, 200);
1439837d4eb6SSudarsana Reddy Kalluru 			continue;
144016f46bf0SSudarsana Reddy Kalluru 		}
144116f46bf0SSudarsana Reddy Kalluru 
144216f46bf0SSudarsana Reddy Kalluru 		hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
144316f46bf0SSudarsana Reddy Kalluru 		sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
144416f46bf0SSudarsana Reddy Kalluru 
1445837d4eb6SSudarsana Reddy Kalluru 		/* Memory barrier to prevent the CPU from doing speculative
1446837d4eb6SSudarsana Reddy Kalluru 		 * reads of CQE/BD before reading hw_comp_cons. If the CQE is
1447837d4eb6SSudarsana Reddy Kalluru 		 * read before it is written by FW, then FW writes CQE and SB,
1448837d4eb6SSudarsana Reddy Kalluru 		 * and then the CPU reads the hw_comp_cons, it will use an old
1449837d4eb6SSudarsana Reddy Kalluru 		 * CQE.
145016f46bf0SSudarsana Reddy Kalluru 		 */
145116f46bf0SSudarsana Reddy Kalluru 		rmb();
145216f46bf0SSudarsana Reddy Kalluru 
145316f46bf0SSudarsana Reddy Kalluru 		/* Get the CQE from the completion ring */
145416f46bf0SSudarsana Reddy Kalluru 		cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring);
145516f46bf0SSudarsana Reddy Kalluru 
145616f46bf0SSudarsana Reddy Kalluru 		/* Get the data from the SW ring */
145716f46bf0SSudarsana Reddy Kalluru 		sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
145816f46bf0SSudarsana Reddy Kalluru 		sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
145916f46bf0SSudarsana Reddy Kalluru 		fp_cqe = &cqe->fast_path_regular;
146016f46bf0SSudarsana Reddy Kalluru 		len =  le16_to_cpu(fp_cqe->len_on_first_bd);
146116f46bf0SSudarsana Reddy Kalluru 		data_ptr = (u8 *)(page_address(sw_rx_data->data) +
1462837d4eb6SSudarsana Reddy Kalluru 				  fp_cqe->placement_offset +
1463837d4eb6SSudarsana Reddy Kalluru 				  sw_rx_data->page_offset);
1464837d4eb6SSudarsana Reddy Kalluru 		if (ether_addr_equal(data_ptr,  edev->ndev->dev_addr) &&
1465837d4eb6SSudarsana Reddy Kalluru 		    ether_addr_equal(data_ptr + ETH_ALEN,
1466837d4eb6SSudarsana Reddy Kalluru 				     edev->ndev->dev_addr)) {
146716f46bf0SSudarsana Reddy Kalluru 			for (i = ETH_HLEN; i < len; i++)
146816f46bf0SSudarsana Reddy Kalluru 				if (data_ptr[i] != (unsigned char)(i & 0xff)) {
1469837d4eb6SSudarsana Reddy Kalluru 					rc = -1;
1470837d4eb6SSudarsana Reddy Kalluru 					break;
147116f46bf0SSudarsana Reddy Kalluru 				}
147216f46bf0SSudarsana Reddy Kalluru 
14739eb22357SMintz, Yuval 			qede_recycle_rx_bd_ring(rxq, 1);
1474837d4eb6SSudarsana Reddy Kalluru 			qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1475837d4eb6SSudarsana Reddy Kalluru 			break;
1476837d4eb6SSudarsana Reddy Kalluru 		}
147716f46bf0SSudarsana Reddy Kalluru 
1478837d4eb6SSudarsana Reddy Kalluru 		DP_INFO(edev, "Not the transmitted packet\n");
14799eb22357SMintz, Yuval 		qede_recycle_rx_bd_ring(rxq, 1);
1480837d4eb6SSudarsana Reddy Kalluru 		qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1481837d4eb6SSudarsana Reddy Kalluru 	}
1482837d4eb6SSudarsana Reddy Kalluru 
1483afe981d6SSudarsana Reddy Kalluru 	if (iter == QEDE_SELFTEST_POLL_COUNT) {
1484837d4eb6SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Failed to receive the traffic\n");
1485837d4eb6SSudarsana Reddy Kalluru 		return -1;
1486837d4eb6SSudarsana Reddy Kalluru 	}
1487837d4eb6SSudarsana Reddy Kalluru 
1488837d4eb6SSudarsana Reddy Kalluru 	qede_update_rx_prod(edev, rxq);
1489837d4eb6SSudarsana Reddy Kalluru 
1490837d4eb6SSudarsana Reddy Kalluru 	return rc;
149116f46bf0SSudarsana Reddy Kalluru }
149216f46bf0SSudarsana Reddy Kalluru 
149316f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode)
149416f46bf0SSudarsana Reddy Kalluru {
149516f46bf0SSudarsana Reddy Kalluru 	struct qed_link_params link_params;
149616f46bf0SSudarsana Reddy Kalluru 	struct sk_buff *skb = NULL;
149716f46bf0SSudarsana Reddy Kalluru 	int rc = 0, i;
149816f46bf0SSudarsana Reddy Kalluru 	u32 pkt_size;
149916f46bf0SSudarsana Reddy Kalluru 	u8 *packet;
150016f46bf0SSudarsana Reddy Kalluru 
150116f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev)) {
150216f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Interface is down\n");
150316f46bf0SSudarsana Reddy Kalluru 		return -EINVAL;
150416f46bf0SSudarsana Reddy Kalluru 	}
150516f46bf0SSudarsana Reddy Kalluru 
150616f46bf0SSudarsana Reddy Kalluru 	qede_netif_stop(edev);
150716f46bf0SSudarsana Reddy Kalluru 
150816f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Loopback mode */
150916f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
151016f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
151116f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
151216f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = loopback_mode;
151316f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
151416f46bf0SSudarsana Reddy Kalluru 
151516f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
151616f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
151716f46bf0SSudarsana Reddy Kalluru 
151816f46bf0SSudarsana Reddy Kalluru 	/* prepare the loopback packet */
151916f46bf0SSudarsana Reddy Kalluru 	pkt_size = edev->ndev->mtu + ETH_HLEN;
152016f46bf0SSudarsana Reddy Kalluru 
152116f46bf0SSudarsana Reddy Kalluru 	skb = netdev_alloc_skb(edev->ndev, pkt_size);
152216f46bf0SSudarsana Reddy Kalluru 	if (!skb) {
152316f46bf0SSudarsana Reddy Kalluru 		DP_INFO(edev, "Can't allocate skb\n");
152416f46bf0SSudarsana Reddy Kalluru 		rc = -ENOMEM;
152516f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
152616f46bf0SSudarsana Reddy Kalluru 	}
152716f46bf0SSudarsana Reddy Kalluru 	packet = skb_put(skb, pkt_size);
152816f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet, edev->ndev->dev_addr);
152916f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr);
153016f46bf0SSudarsana Reddy Kalluru 	memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN)));
153116f46bf0SSudarsana Reddy Kalluru 	for (i = ETH_HLEN; i < pkt_size; i++)
153216f46bf0SSudarsana Reddy Kalluru 		packet[i] = (unsigned char)(i & 0xff);
153316f46bf0SSudarsana Reddy Kalluru 
153416f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_transmit_traffic(edev, skb);
153516f46bf0SSudarsana Reddy Kalluru 	if (rc)
153616f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
153716f46bf0SSudarsana Reddy Kalluru 
153816f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_receive_traffic(edev);
153916f46bf0SSudarsana Reddy Kalluru 	if (rc)
154016f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
154116f46bf0SSudarsana Reddy Kalluru 
154216f46bf0SSudarsana Reddy Kalluru 	DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n");
154316f46bf0SSudarsana Reddy Kalluru 
154416f46bf0SSudarsana Reddy Kalluru test_loopback_exit:
154516f46bf0SSudarsana Reddy Kalluru 	dev_kfree_skb(skb);
154616f46bf0SSudarsana Reddy Kalluru 
154716f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Normal mode */
154816f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
154916f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
155016f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
155116f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = QED_LINK_LOOPBACK_NONE;
155216f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
155316f46bf0SSudarsana Reddy Kalluru 
155416f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
155516f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
155616f46bf0SSudarsana Reddy Kalluru 
155716f46bf0SSudarsana Reddy Kalluru 	qede_netif_start(edev);
155816f46bf0SSudarsana Reddy Kalluru 
155916f46bf0SSudarsana Reddy Kalluru 	return rc;
156016f46bf0SSudarsana Reddy Kalluru }
156116f46bf0SSudarsana Reddy Kalluru 
15623044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev,
15633044a02eSSudarsana Reddy Kalluru 			   struct ethtool_test *etest, u64 *buf)
15643044a02eSSudarsana Reddy Kalluru {
15653044a02eSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
15663044a02eSSudarsana Reddy Kalluru 
15673044a02eSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
15683044a02eSSudarsana Reddy Kalluru 		   "Self-test command parameters: offline = %d, external_lb = %d\n",
15693044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_OFFLINE),
15703044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2);
15713044a02eSSudarsana Reddy Kalluru 
15723044a02eSSudarsana Reddy Kalluru 	memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX);
15733044a02eSSudarsana Reddy Kalluru 
157416f46bf0SSudarsana Reddy Kalluru 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
157516f46bf0SSudarsana Reddy Kalluru 		if (qede_selftest_run_loopback(edev,
157616f46bf0SSudarsana Reddy Kalluru 					       QED_LINK_LOOPBACK_INT_PHY)) {
157716f46bf0SSudarsana Reddy Kalluru 			buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1;
157816f46bf0SSudarsana Reddy Kalluru 			etest->flags |= ETH_TEST_FL_FAILED;
157916f46bf0SSudarsana Reddy Kalluru 		}
158016f46bf0SSudarsana Reddy Kalluru 	}
158116f46bf0SSudarsana Reddy Kalluru 
15823044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) {
15833044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1;
15843044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
15853044a02eSSudarsana Reddy Kalluru 	}
15863044a02eSSudarsana Reddy Kalluru 
15873044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_memory(edev->cdev)) {
15883044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_MEMORY_TEST] = 1;
15893044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
15903044a02eSSudarsana Reddy Kalluru 	}
15913044a02eSSudarsana Reddy Kalluru 
15923044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_register(edev->cdev)) {
15933044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_REGISTER_TEST] = 1;
15943044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
15953044a02eSSudarsana Reddy Kalluru 	}
15963044a02eSSudarsana Reddy Kalluru 
15973044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_clock(edev->cdev)) {
15983044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_CLOCK_TEST] = 1;
15993044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
16003044a02eSSudarsana Reddy Kalluru 	}
16017a4b21b7SMintz, Yuval 
16027a4b21b7SMintz, Yuval 	if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) {
16037a4b21b7SMintz, Yuval 		buf[QEDE_ETHTOOL_NVRAM_TEST] = 1;
16047a4b21b7SMintz, Yuval 		etest->flags |= ETH_TEST_FL_FAILED;
16057a4b21b7SMintz, Yuval 	}
16063044a02eSSudarsana Reddy Kalluru }
16073044a02eSSudarsana Reddy Kalluru 
16083d789994SManish Chopra static int qede_set_tunable(struct net_device *dev,
16093d789994SManish Chopra 			    const struct ethtool_tunable *tuna,
16103d789994SManish Chopra 			    const void *data)
16113d789994SManish Chopra {
16123d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
16133d789994SManish Chopra 	u32 val;
16143d789994SManish Chopra 
16153d789994SManish Chopra 	switch (tuna->id) {
16163d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
16173d789994SManish Chopra 		val = *(u32 *)data;
16183d789994SManish Chopra 		if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) {
16193d789994SManish Chopra 			DP_VERBOSE(edev, QED_MSG_DEBUG,
16203d789994SManish Chopra 				   "Invalid rx copy break value, range is [%u, %u]",
16213d789994SManish Chopra 				   QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE);
16223d789994SManish Chopra 			return -EINVAL;
16233d789994SManish Chopra 		}
16243d789994SManish Chopra 
16253d789994SManish Chopra 		edev->rx_copybreak = *(u32 *)data;
16263d789994SManish Chopra 		break;
16273d789994SManish Chopra 	default:
16283d789994SManish Chopra 		return -EOPNOTSUPP;
16293d789994SManish Chopra 	}
16303d789994SManish Chopra 
16313d789994SManish Chopra 	return 0;
16323d789994SManish Chopra }
16333d789994SManish Chopra 
16343d789994SManish Chopra static int qede_get_tunable(struct net_device *dev,
16353d789994SManish Chopra 			    const struct ethtool_tunable *tuna, void *data)
16363d789994SManish Chopra {
16373d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
16383d789994SManish Chopra 
16393d789994SManish Chopra 	switch (tuna->id) {
16403d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
16413d789994SManish Chopra 		*(u32 *)data = edev->rx_copybreak;
16423d789994SManish Chopra 		break;
16433d789994SManish Chopra 	default:
16443d789994SManish Chopra 		return -EOPNOTSUPP;
16453d789994SManish Chopra 	}
16463d789994SManish Chopra 
16473d789994SManish Chopra 	return 0;
16483d789994SManish Chopra }
16493d789994SManish Chopra 
1650c3dc48f7SSudarsana Reddy Kalluru static int qede_get_eee(struct net_device *dev, struct ethtool_eee *edata)
1651c3dc48f7SSudarsana Reddy Kalluru {
1652c3dc48f7SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1653c3dc48f7SSudarsana Reddy Kalluru 	struct qed_link_output current_link;
1654c3dc48f7SSudarsana Reddy Kalluru 
1655c3dc48f7SSudarsana Reddy Kalluru 	memset(&current_link, 0, sizeof(current_link));
1656c3dc48f7SSudarsana Reddy Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
1657c3dc48f7SSudarsana Reddy Kalluru 
1658c3dc48f7SSudarsana Reddy Kalluru 	if (!current_link.eee_supported) {
1659c3dc48f7SSudarsana Reddy Kalluru 		DP_INFO(edev, "EEE is not supported\n");
1660c3dc48f7SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1661c3dc48f7SSudarsana Reddy Kalluru 	}
1662c3dc48f7SSudarsana Reddy Kalluru 
1663c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.adv_caps & QED_EEE_1G_ADV)
1664c3dc48f7SSudarsana Reddy Kalluru 		edata->advertised = ADVERTISED_1000baseT_Full;
1665c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.adv_caps & QED_EEE_10G_ADV)
1666c3dc48f7SSudarsana Reddy Kalluru 		edata->advertised |= ADVERTISED_10000baseT_Full;
1667c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.sup_caps & QED_EEE_1G_ADV)
1668c3dc48f7SSudarsana Reddy Kalluru 		edata->supported = ADVERTISED_1000baseT_Full;
1669c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.sup_caps & QED_EEE_10G_ADV)
1670c3dc48f7SSudarsana Reddy Kalluru 		edata->supported |= ADVERTISED_10000baseT_Full;
1671c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.lp_adv_caps & QED_EEE_1G_ADV)
1672c3dc48f7SSudarsana Reddy Kalluru 		edata->lp_advertised = ADVERTISED_1000baseT_Full;
1673c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.lp_adv_caps & QED_EEE_10G_ADV)
1674c3dc48f7SSudarsana Reddy Kalluru 		edata->lp_advertised |= ADVERTISED_10000baseT_Full;
1675c3dc48f7SSudarsana Reddy Kalluru 
1676c3dc48f7SSudarsana Reddy Kalluru 	edata->tx_lpi_timer = current_link.eee.tx_lpi_timer;
1677c3dc48f7SSudarsana Reddy Kalluru 	edata->eee_enabled = current_link.eee.enable;
1678c3dc48f7SSudarsana Reddy Kalluru 	edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable;
1679c3dc48f7SSudarsana Reddy Kalluru 	edata->eee_active = current_link.eee_active;
1680c3dc48f7SSudarsana Reddy Kalluru 
1681c3dc48f7SSudarsana Reddy Kalluru 	return 0;
1682c3dc48f7SSudarsana Reddy Kalluru }
1683c3dc48f7SSudarsana Reddy Kalluru 
1684c3dc48f7SSudarsana Reddy Kalluru static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
1685c3dc48f7SSudarsana Reddy Kalluru {
1686c3dc48f7SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1687c3dc48f7SSudarsana Reddy Kalluru 	struct qed_link_output current_link;
1688c3dc48f7SSudarsana Reddy Kalluru 	struct qed_link_params params;
1689c3dc48f7SSudarsana Reddy Kalluru 
1690c3dc48f7SSudarsana Reddy Kalluru 	if (!edev->ops->common->can_link_change(edev->cdev)) {
1691c3dc48f7SSudarsana Reddy Kalluru 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
1692c3dc48f7SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1693c3dc48f7SSudarsana Reddy Kalluru 	}
1694c3dc48f7SSudarsana Reddy Kalluru 
1695c3dc48f7SSudarsana Reddy Kalluru 	memset(&current_link, 0, sizeof(current_link));
1696c3dc48f7SSudarsana Reddy Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
1697c3dc48f7SSudarsana Reddy Kalluru 
1698c3dc48f7SSudarsana Reddy Kalluru 	if (!current_link.eee_supported) {
1699c3dc48f7SSudarsana Reddy Kalluru 		DP_INFO(edev, "EEE is not supported\n");
1700c3dc48f7SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1701c3dc48f7SSudarsana Reddy Kalluru 	}
1702c3dc48f7SSudarsana Reddy Kalluru 
1703c3dc48f7SSudarsana Reddy Kalluru 	memset(&params, 0, sizeof(params));
1704c3dc48f7SSudarsana Reddy Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG;
1705c3dc48f7SSudarsana Reddy Kalluru 
1706c3dc48f7SSudarsana Reddy Kalluru 	if (!(edata->advertised & (ADVERTISED_1000baseT_Full |
1707c3dc48f7SSudarsana Reddy Kalluru 				   ADVERTISED_10000baseT_Full)) ||
1708c3dc48f7SSudarsana Reddy Kalluru 	    ((edata->advertised & (ADVERTISED_1000baseT_Full |
1709c3dc48f7SSudarsana Reddy Kalluru 				   ADVERTISED_10000baseT_Full)) !=
1710c3dc48f7SSudarsana Reddy Kalluru 	     edata->advertised)) {
1711c3dc48f7SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
1712c3dc48f7SSudarsana Reddy Kalluru 			   "Invalid advertised capabilities %d\n",
1713c3dc48f7SSudarsana Reddy Kalluru 			   edata->advertised);
1714c3dc48f7SSudarsana Reddy Kalluru 		return -EINVAL;
1715c3dc48f7SSudarsana Reddy Kalluru 	}
1716c3dc48f7SSudarsana Reddy Kalluru 
1717c3dc48f7SSudarsana Reddy Kalluru 	if (edata->advertised & ADVERTISED_1000baseT_Full)
1718c3dc48f7SSudarsana Reddy Kalluru 		params.eee.adv_caps = QED_EEE_1G_ADV;
1719c3dc48f7SSudarsana Reddy Kalluru 	if (edata->advertised & ADVERTISED_10000baseT_Full)
1720c3dc48f7SSudarsana Reddy Kalluru 		params.eee.adv_caps |= QED_EEE_10G_ADV;
1721c3dc48f7SSudarsana Reddy Kalluru 	params.eee.enable = edata->eee_enabled;
1722c3dc48f7SSudarsana Reddy Kalluru 	params.eee.tx_lpi_enable = edata->tx_lpi_enabled;
1723c3dc48f7SSudarsana Reddy Kalluru 	params.eee.tx_lpi_timer = edata->tx_lpi_timer;
1724c3dc48f7SSudarsana Reddy Kalluru 
1725c3dc48f7SSudarsana Reddy Kalluru 	params.link_up = true;
1726c3dc48f7SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
1727c3dc48f7SSudarsana Reddy Kalluru 
1728c3dc48f7SSudarsana Reddy Kalluru 	return 0;
1729c3dc48f7SSudarsana Reddy Kalluru }
1730c3dc48f7SSudarsana Reddy Kalluru 
1731133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = {
1732054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
1733054c67d1SSudarsana Reddy Kalluru 	.set_link_ksettings = qede_set_link_ksettings,
1734133fac0eSSudarsana Kalluru 	.get_drvinfo = qede_get_drvinfo,
1735e0971c83STomer Tayar 	.get_regs_len = qede_get_regs_len,
1736e0971c83STomer Tayar 	.get_regs = qede_get_regs,
173714d39648SMintz, Yuval 	.get_wol = qede_get_wol,
173814d39648SMintz, Yuval 	.set_wol = qede_set_wol,
1739133fac0eSSudarsana Kalluru 	.get_msglevel = qede_get_msglevel,
1740133fac0eSSudarsana Kalluru 	.set_msglevel = qede_set_msglevel,
174132a7a570SSudarsana Kalluru 	.nway_reset = qede_nway_reset,
1742133fac0eSSudarsana Kalluru 	.get_link = qede_get_link,
1743d552fa84SSudarsana Reddy Kalluru 	.get_coalesce = qede_get_coalesce,
1744d552fa84SSudarsana Reddy Kalluru 	.set_coalesce = qede_set_coalesce,
174501ef7e05SSudarsana Kalluru 	.get_ringparam = qede_get_ringparam,
174601ef7e05SSudarsana Kalluru 	.set_ringparam = qede_set_ringparam,
17470f7db144SSudarsana Kalluru 	.get_pauseparam = qede_get_pauseparam,
17480f7db144SSudarsana Kalluru 	.set_pauseparam = qede_set_pauseparam,
1749133fac0eSSudarsana Kalluru 	.get_strings = qede_get_strings,
17503d971cbdSSudarsana Kalluru 	.set_phys_id = qede_set_phys_id,
1751133fac0eSSudarsana Kalluru 	.get_ethtool_stats = qede_get_ethtool_stats,
1752f3e72109SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
1753133fac0eSSudarsana Kalluru 	.get_sset_count = qede_get_sset_count,
1754961acdeaSSudarsana Reddy Kalluru 	.get_rxnfc = qede_get_rxnfc,
1755961acdeaSSudarsana Reddy Kalluru 	.set_rxnfc = qede_set_rxnfc,
1756961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
1757961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_key_size = qede_get_rxfh_key_size,
1758961acdeaSSudarsana Reddy Kalluru 	.get_rxfh = qede_get_rxfh,
1759961acdeaSSudarsana Reddy Kalluru 	.set_rxfh = qede_set_rxfh,
17604c55215cSSudarsana Reddy Kalluru 	.get_ts_info = qede_get_ts_info,
17618edf049dSSudarsana Kalluru 	.get_channels = qede_get_channels,
17628edf049dSSudarsana Kalluru 	.set_channels = qede_set_channels,
17633044a02eSSudarsana Reddy Kalluru 	.self_test = qede_self_test,
1764c3dc48f7SSudarsana Reddy Kalluru 	.get_eee = qede_get_eee,
1765c3dc48f7SSudarsana Reddy Kalluru 	.set_eee = qede_set_eee,
1766c3dc48f7SSudarsana Reddy Kalluru 
17673d789994SManish Chopra 	.get_tunable = qede_get_tunable,
17683d789994SManish Chopra 	.set_tunable = qede_set_tunable,
1769133fac0eSSudarsana Kalluru };
1770133fac0eSSudarsana Kalluru 
1771fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = {
1772054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
1773fefb0202SYuval Mintz 	.get_drvinfo = qede_get_drvinfo,
1774fefb0202SYuval Mintz 	.get_msglevel = qede_get_msglevel,
1775fefb0202SYuval Mintz 	.set_msglevel = qede_set_msglevel,
1776fefb0202SYuval Mintz 	.get_link = qede_get_link,
1777477f2d14SRahul Verma 	.get_coalesce = qede_get_coalesce,
1778477f2d14SRahul Verma 	.set_coalesce = qede_set_coalesce,
1779fefb0202SYuval Mintz 	.get_ringparam = qede_get_ringparam,
1780fefb0202SYuval Mintz 	.set_ringparam = qede_set_ringparam,
1781fefb0202SYuval Mintz 	.get_strings = qede_get_strings,
1782fefb0202SYuval Mintz 	.get_ethtool_stats = qede_get_ethtool_stats,
1783fefb0202SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
1784fefb0202SYuval Mintz 	.get_sset_count = qede_get_sset_count,
1785fefb0202SYuval Mintz 	.get_rxnfc = qede_get_rxnfc,
1786fefb0202SYuval Mintz 	.set_rxnfc = qede_set_rxnfc,
1787fefb0202SYuval Mintz 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
1788fefb0202SYuval Mintz 	.get_rxfh_key_size = qede_get_rxfh_key_size,
1789fefb0202SYuval Mintz 	.get_rxfh = qede_get_rxfh,
1790fefb0202SYuval Mintz 	.set_rxfh = qede_set_rxfh,
1791fefb0202SYuval Mintz 	.get_channels = qede_get_channels,
1792fefb0202SYuval Mintz 	.set_channels = qede_set_channels,
17933d789994SManish Chopra 	.get_tunable = qede_get_tunable,
17943d789994SManish Chopra 	.set_tunable = qede_set_tunable,
1795fefb0202SYuval Mintz };
1796fefb0202SYuval Mintz 
1797133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev)
1798133fac0eSSudarsana Kalluru {
1799fefb0202SYuval Mintz 	struct qede_dev *edev = netdev_priv(dev);
1800fefb0202SYuval Mintz 
1801fefb0202SYuval Mintz 	if (IS_VF(edev))
1802fefb0202SYuval Mintz 		dev->ethtool_ops = &qede_vf_ethtool_ops;
1803fefb0202SYuval Mintz 	else
1804133fac0eSSudarsana Kalluru 		dev->ethtool_ops = &qede_ethtool_ops;
1805133fac0eSSudarsana Kalluru }
1806