175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ce6a690cSNikita Danilov /* Atlantic Network Driver
3ce6a690cSNikita Danilov  *
4ce6a690cSNikita Danilov  * Copyright (C) 2014-2019 aQuantia Corporation
5ce6a690cSNikita Danilov  * Copyright (C) 2019-2020 Marvell International Ltd.
6c5760d03SDavid VomLehn  */
7c5760d03SDavid VomLehn 
8c5760d03SDavid VomLehn /* File aq_ethtool.c: Definition of ethertool related functions. */
9c5760d03SDavid VomLehn 
10c5760d03SDavid VomLehn #include "aq_ethtool.h"
11c5760d03SDavid VomLehn #include "aq_nic.h"
12c1af5427SAnton Mikaev #include "aq_vec.h"
1384989af0SEgor Pomozov #include "aq_ptp.h"
148d0bcb01SDmitry Bogdanov #include "aq_filters.h"
15aec0f1aaSDmitry Bogdanov #include "aq_macsec.h"
16*2a838911SIzabela Bakollari #include "aq_main.h"
17c5760d03SDavid VomLehn 
1884989af0SEgor Pomozov #include <linux/ptp_clock_kernel.h>
1984989af0SEgor Pomozov 
aq_ethtool_get_regs(struct net_device * ndev,struct ethtool_regs * regs,void * p)20c5760d03SDavid VomLehn static void aq_ethtool_get_regs(struct net_device *ndev,
21c5760d03SDavid VomLehn 				struct ethtool_regs *regs, void *p)
22c5760d03SDavid VomLehn {
23c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
247b0c342fSNikita Danilov 	u32 regs_count;
257b0c342fSNikita Danilov 
267b0c342fSNikita Danilov 	regs_count = aq_nic_get_regs_count(aq_nic);
27c5760d03SDavid VomLehn 
28c5760d03SDavid VomLehn 	memset(p, 0, regs_count * sizeof(u32));
29c5760d03SDavid VomLehn 	aq_nic_get_regs(aq_nic, regs, p);
30c5760d03SDavid VomLehn }
31c5760d03SDavid VomLehn 
aq_ethtool_get_regs_len(struct net_device * ndev)32c5760d03SDavid VomLehn static int aq_ethtool_get_regs_len(struct net_device *ndev)
33c5760d03SDavid VomLehn {
34c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
357b0c342fSNikita Danilov 	u32 regs_count;
367b0c342fSNikita Danilov 
377b0c342fSNikita Danilov 	regs_count = aq_nic_get_regs_count(aq_nic);
38c5760d03SDavid VomLehn 
39c5760d03SDavid VomLehn 	return regs_count * sizeof(u32);
40c5760d03SDavid VomLehn }
41c5760d03SDavid VomLehn 
aq_ethtool_get_link(struct net_device * ndev)42c5760d03SDavid VomLehn static u32 aq_ethtool_get_link(struct net_device *ndev)
43c5760d03SDavid VomLehn {
44c5760d03SDavid VomLehn 	return ethtool_op_get_link(ndev);
45c5760d03SDavid VomLehn }
46c5760d03SDavid VomLehn 
aq_ethtool_get_link_ksettings(struct net_device * ndev,struct ethtool_link_ksettings * cmd)47f8244ab5SPhilippe Reynes static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
48f8244ab5SPhilippe Reynes 					 struct ethtool_link_ksettings *cmd)
49c5760d03SDavid VomLehn {
50c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
51c5760d03SDavid VomLehn 
52f8244ab5SPhilippe Reynes 	aq_nic_get_link_ksettings(aq_nic, cmd);
53f8244ab5SPhilippe Reynes 	cmd->base.speed = netif_carrier_ok(ndev) ?
54f8244ab5SPhilippe Reynes 				aq_nic_get_link_speed(aq_nic) : 0U;
55c5760d03SDavid VomLehn 
56c5760d03SDavid VomLehn 	return 0;
57c5760d03SDavid VomLehn }
58c5760d03SDavid VomLehn 
59f8244ab5SPhilippe Reynes static int
aq_ethtool_set_link_ksettings(struct net_device * ndev,const struct ethtool_link_ksettings * cmd)60f8244ab5SPhilippe Reynes aq_ethtool_set_link_ksettings(struct net_device *ndev,
61f8244ab5SPhilippe Reynes 			      const struct ethtool_link_ksettings *cmd)
62c5760d03SDavid VomLehn {
63c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
64c5760d03SDavid VomLehn 
65f8244ab5SPhilippe Reynes 	return aq_nic_set_link_ksettings(aq_nic, cmd);
66c5760d03SDavid VomLehn }
67c5760d03SDavid VomLehn 
68c5760d03SDavid VomLehn static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
69c5760d03SDavid VomLehn 	"InPackets",
70c5760d03SDavid VomLehn 	"InUCast",
71c5760d03SDavid VomLehn 	"InMCast",
72c5760d03SDavid VomLehn 	"InBCast",
73c5760d03SDavid VomLehn 	"InErrors",
74c5760d03SDavid VomLehn 	"OutPackets",
75c5760d03SDavid VomLehn 	"OutUCast",
76c5760d03SDavid VomLehn 	"OutMCast",
77c5760d03SDavid VomLehn 	"OutBCast",
7898bc036dSIgor Russkikh 	"InUCastOctets",
7998bc036dSIgor Russkikh 	"OutUCastOctets",
8098bc036dSIgor Russkikh 	"InMCastOctets",
8198bc036dSIgor Russkikh 	"OutMCastOctets",
8298bc036dSIgor Russkikh 	"InBCastOctets",
8398bc036dSIgor Russkikh 	"OutBCastOctets",
8498bc036dSIgor Russkikh 	"InOctets",
8598bc036dSIgor Russkikh 	"OutOctets",
86c5760d03SDavid VomLehn 	"InPacketsDma",
87c5760d03SDavid VomLehn 	"OutPacketsDma",
88c5760d03SDavid VomLehn 	"InOctetsDma",
89c5760d03SDavid VomLehn 	"OutOctetsDma",
90c5760d03SDavid VomLehn 	"InDroppedDma",
915d8d84e9SIgor Russkikh };
925d8d84e9SIgor Russkikh 
93508f2e3dSMark Starovoytov static const char * const aq_ethtool_queue_rx_stat_names[] = {
944272ba8bSMark Starovoytov 	"%sQueue[%d] InPackets",
954272ba8bSMark Starovoytov 	"%sQueue[%d] InJumboPackets",
964272ba8bSMark Starovoytov 	"%sQueue[%d] InLroPackets",
974272ba8bSMark Starovoytov 	"%sQueue[%d] InErrors",
98aa7e17a3SDmitry Bogdanov 	"%sQueue[%d] AllocFails",
99aa7e17a3SDmitry Bogdanov 	"%sQueue[%d] SkbAllocFails",
100aa7e17a3SDmitry Bogdanov 	"%sQueue[%d] Polls",
10126efaef7STaehee Yoo 	"%sQueue[%d] PageFlips",
10226efaef7STaehee Yoo 	"%sQueue[%d] PageReuses",
10326efaef7STaehee Yoo 	"%sQueue[%d] PageFrees",
10426efaef7STaehee Yoo 	"%sQueue[%d] XdpAbort",
10526efaef7STaehee Yoo 	"%sQueue[%d] XdpDrop",
10626efaef7STaehee Yoo 	"%sQueue[%d] XdpPass",
10726efaef7STaehee Yoo 	"%sQueue[%d] XdpTx",
10826efaef7STaehee Yoo 	"%sQueue[%d] XdpInvalid",
10926efaef7STaehee Yoo 	"%sQueue[%d] XdpRedirect",
110c5760d03SDavid VomLehn };
111c5760d03SDavid VomLehn 
112508f2e3dSMark Starovoytov static const char * const aq_ethtool_queue_tx_stat_names[] = {
113508f2e3dSMark Starovoytov 	"%sQueue[%d] OutPackets",
114508f2e3dSMark Starovoytov 	"%sQueue[%d] Restarts",
115508f2e3dSMark Starovoytov };
116508f2e3dSMark Starovoytov 
117aec0f1aaSDmitry Bogdanov #if IS_ENABLED(CONFIG_MACSEC)
118aec0f1aaSDmitry Bogdanov static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
119aec0f1aaSDmitry Bogdanov 	"MACSec InCtlPackets",
120aec0f1aaSDmitry Bogdanov 	"MACSec InTaggedMissPackets",
121aec0f1aaSDmitry Bogdanov 	"MACSec InUntaggedMissPackets",
122aec0f1aaSDmitry Bogdanov 	"MACSec InNotagPackets",
123aec0f1aaSDmitry Bogdanov 	"MACSec InUntaggedPackets",
124aec0f1aaSDmitry Bogdanov 	"MACSec InBadTagPackets",
125aec0f1aaSDmitry Bogdanov 	"MACSec InNoSciPackets",
126aec0f1aaSDmitry Bogdanov 	"MACSec InUnknownSciPackets",
127aec0f1aaSDmitry Bogdanov 	"MACSec InCtrlPortPassPackets",
128aec0f1aaSDmitry Bogdanov 	"MACSec InUnctrlPortPassPackets",
129aec0f1aaSDmitry Bogdanov 	"MACSec InCtrlPortFailPackets",
130aec0f1aaSDmitry Bogdanov 	"MACSec InUnctrlPortFailPackets",
131aec0f1aaSDmitry Bogdanov 	"MACSec InTooLongPackets",
132aec0f1aaSDmitry Bogdanov 	"MACSec InIgpocCtlPackets",
133aec0f1aaSDmitry Bogdanov 	"MACSec InEccErrorPackets",
134aec0f1aaSDmitry Bogdanov 	"MACSec InUnctrlHitDropRedir",
135aec0f1aaSDmitry Bogdanov 	"MACSec OutCtlPackets",
136aec0f1aaSDmitry Bogdanov 	"MACSec OutUnknownSaPackets",
137aec0f1aaSDmitry Bogdanov 	"MACSec OutUntaggedPackets",
138aec0f1aaSDmitry Bogdanov 	"MACSec OutTooLong",
139aec0f1aaSDmitry Bogdanov 	"MACSec OutEccErrorPackets",
140aec0f1aaSDmitry Bogdanov 	"MACSec OutUnctrlHitDropRedir",
141aec0f1aaSDmitry Bogdanov };
142aec0f1aaSDmitry Bogdanov 
1433a8b4454SMark Starovoytov static const char * const aq_macsec_txsc_stat_names[] = {
144aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%d ProtectedPkts",
145aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%d EncryptedPkts",
146aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%d ProtectedOctets",
147aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%d EncryptedOctets",
148aec0f1aaSDmitry Bogdanov };
149aec0f1aaSDmitry Bogdanov 
1503a8b4454SMark Starovoytov static const char * const aq_macsec_txsa_stat_names[] = {
151aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%dSA%d HitDropRedirect",
152aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%dSA%d Protected2Pkts",
153aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%dSA%d ProtectedPkts",
154aec0f1aaSDmitry Bogdanov 	"MACSecTXSC%dSA%d EncryptedPkts",
155aec0f1aaSDmitry Bogdanov };
156aec0f1aaSDmitry Bogdanov 
1573a8b4454SMark Starovoytov static const char * const aq_macsec_rxsa_stat_names[] = {
158aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d UntaggedHitPkts",
159aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d CtrlHitDrpRedir",
160aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d NotUsingSa",
161aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d UnusedSa",
162aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d NotValidPkts",
163aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d InvalidPkts",
164aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d OkPkts",
165aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d LatePkts",
166aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d DelayedPkts",
167aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d UncheckedPkts",
168aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d ValidatedOctets",
169aec0f1aaSDmitry Bogdanov 	"MACSecRXSC%dSA%d DecryptedOctets",
170aec0f1aaSDmitry Bogdanov };
171aec0f1aaSDmitry Bogdanov #endif
172aec0f1aaSDmitry Bogdanov 
173ea4b4d7fSIgor Russkikh static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
174ea4b4d7fSIgor Russkikh 	"DMASystemLoopback",
175ea4b4d7fSIgor Russkikh 	"PKTSystemLoopback",
176ea4b4d7fSIgor Russkikh 	"DMANetworkLoopback",
177ea4b4d7fSIgor Russkikh 	"PHYInternalLoopback",
178ea4b4d7fSIgor Russkikh 	"PHYExternalLoopback",
179ea4b4d7fSIgor Russkikh };
180ea4b4d7fSIgor Russkikh 
aq_ethtool_n_stats(struct net_device * ndev)181aec0f1aaSDmitry Bogdanov static u32 aq_ethtool_n_stats(struct net_device *ndev)
182aec0f1aaSDmitry Bogdanov {
183508f2e3dSMark Starovoytov 	const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
184508f2e3dSMark Starovoytov 	const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
185aec0f1aaSDmitry Bogdanov 	struct aq_nic_s *nic = netdev_priv(ndev);
186aec0f1aaSDmitry Bogdanov 	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
187aec0f1aaSDmitry Bogdanov 	u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
188508f2e3dSMark Starovoytov 		      (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs;
189aec0f1aaSDmitry Bogdanov 
19014b539a3SPavel Belous #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
19114b539a3SPavel Belous 	n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) +
19214b539a3SPavel Belous 		   tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
19314b539a3SPavel Belous #endif
19414b539a3SPavel Belous 
195aec0f1aaSDmitry Bogdanov #if IS_ENABLED(CONFIG_MACSEC)
196aec0f1aaSDmitry Bogdanov 	if (nic->macsec_cfg) {
197aec0f1aaSDmitry Bogdanov 		n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
198aec0f1aaSDmitry Bogdanov 			   ARRAY_SIZE(aq_macsec_txsc_stat_names) *
199aec0f1aaSDmitry Bogdanov 				   aq_macsec_tx_sc_cnt(nic) +
200aec0f1aaSDmitry Bogdanov 			   ARRAY_SIZE(aq_macsec_txsa_stat_names) *
201aec0f1aaSDmitry Bogdanov 				   aq_macsec_tx_sa_cnt(nic) +
202aec0f1aaSDmitry Bogdanov 			   ARRAY_SIZE(aq_macsec_rxsa_stat_names) *
203aec0f1aaSDmitry Bogdanov 				   aq_macsec_rx_sa_cnt(nic);
204aec0f1aaSDmitry Bogdanov 	}
205aec0f1aaSDmitry Bogdanov #endif
206aec0f1aaSDmitry Bogdanov 
207aec0f1aaSDmitry Bogdanov 	return n_stats;
208aec0f1aaSDmitry Bogdanov }
209aec0f1aaSDmitry Bogdanov 
aq_ethtool_stats(struct net_device * ndev,struct ethtool_stats * stats,u64 * data)210c5760d03SDavid VomLehn static void aq_ethtool_stats(struct net_device *ndev,
211c5760d03SDavid VomLehn 			     struct ethtool_stats *stats, u64 *data)
212c5760d03SDavid VomLehn {
213c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
2147b0c342fSNikita Danilov 
215aec0f1aaSDmitry Bogdanov 	memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
216aec0f1aaSDmitry Bogdanov 	data = aq_nic_get_stats(aq_nic, data);
21714b539a3SPavel Belous #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
21814b539a3SPavel Belous 	data = aq_ptp_get_stats(aq_nic, data);
21914b539a3SPavel Belous #endif
220aec0f1aaSDmitry Bogdanov #if IS_ENABLED(CONFIG_MACSEC)
221aec0f1aaSDmitry Bogdanov 	data = aq_macsec_get_stats(aq_nic, data);
222aec0f1aaSDmitry Bogdanov #endif
223c5760d03SDavid VomLehn }
224c5760d03SDavid VomLehn 
aq_ethtool_get_drvinfo(struct net_device * ndev,struct ethtool_drvinfo * drvinfo)225c5760d03SDavid VomLehn static void aq_ethtool_get_drvinfo(struct net_device *ndev,
226c5760d03SDavid VomLehn 				   struct ethtool_drvinfo *drvinfo)
227c5760d03SDavid VomLehn {
228c5760d03SDavid VomLehn 	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
2297b0c342fSNikita Danilov 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
2307b0c342fSNikita Danilov 	u32 firmware_version;
2317b0c342fSNikita Danilov 	u32 regs_count;
2327b0c342fSNikita Danilov 
2337b0c342fSNikita Danilov 	firmware_version = aq_nic_get_fw_version(aq_nic);
2347b0c342fSNikita Danilov 	regs_count = aq_nic_get_regs_count(aq_nic);
235c5760d03SDavid VomLehn 
236c5760d03SDavid VomLehn 	strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
237c5760d03SDavid VomLehn 
238c5760d03SDavid VomLehn 	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
239c5760d03SDavid VomLehn 		 "%u.%u.%u", firmware_version >> 24,
240c5760d03SDavid VomLehn 		 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
241c5760d03SDavid VomLehn 
242f029c781SWolfram Sang 	strscpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
243c5760d03SDavid VomLehn 		sizeof(drvinfo->bus_info));
244aec0f1aaSDmitry Bogdanov 	drvinfo->n_stats = aq_ethtool_n_stats(ndev);
245c5760d03SDavid VomLehn 	drvinfo->testinfo_len = 0;
246c5760d03SDavid VomLehn 	drvinfo->regdump_len = regs_count;
247c5760d03SDavid VomLehn 	drvinfo->eedump_len = 0;
248c5760d03SDavid VomLehn }
249c5760d03SDavid VomLehn 
aq_ethtool_get_strings(struct net_device * ndev,u32 stringset,u8 * data)250c5760d03SDavid VomLehn static void aq_ethtool_get_strings(struct net_device *ndev,
251c5760d03SDavid VomLehn 				   u32 stringset, u8 *data)
252c5760d03SDavid VomLehn {
2534272ba8bSMark Starovoytov 	struct aq_nic_s *nic = netdev_priv(ndev);
2547b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
2555d8d84e9SIgor Russkikh 	u8 *p = data;
2567b0c342fSNikita Danilov 	int i, si;
257aec0f1aaSDmitry Bogdanov #if IS_ENABLED(CONFIG_MACSEC)
258aec0f1aaSDmitry Bogdanov 	int sa;
259aec0f1aaSDmitry Bogdanov #endif
2607b0c342fSNikita Danilov 
2614272ba8bSMark Starovoytov 	cfg = aq_nic_get_cfg(nic);
262c5760d03SDavid VomLehn 
263ea4b4d7fSIgor Russkikh 	switch (stringset) {
2644272ba8bSMark Starovoytov 	case ETH_SS_STATS: {
265508f2e3dSMark Starovoytov 		const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
266508f2e3dSMark Starovoytov 		const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
2674272ba8bSMark Starovoytov 		char tc_string[8];
2684272ba8bSMark Starovoytov 		int tc;
2694272ba8bSMark Starovoytov 
2704272ba8bSMark Starovoytov 		memset(tc_string, 0, sizeof(tc_string));
271ff83dbf2SNikita Danilov 		memcpy(p, aq_ethtool_stat_names,
2725d8d84e9SIgor Russkikh 		       sizeof(aq_ethtool_stat_names));
2735d8d84e9SIgor Russkikh 		p = p + sizeof(aq_ethtool_stat_names);
2744272ba8bSMark Starovoytov 
2754272ba8bSMark Starovoytov 		for (tc = 0; tc < cfg->tcs; tc++) {
2764272ba8bSMark Starovoytov 			if (cfg->is_qos)
2774272ba8bSMark Starovoytov 				snprintf(tc_string, 8, "TC%d ", tc);
2784272ba8bSMark Starovoytov 
2795d8d84e9SIgor Russkikh 			for (i = 0; i < cfg->vecs; i++) {
280508f2e3dSMark Starovoytov 				for (si = 0; si < rx_stat_cnt; si++) {
2815d8d84e9SIgor Russkikh 					snprintf(p, ETH_GSTRING_LEN,
282508f2e3dSMark Starovoytov 					     aq_ethtool_queue_rx_stat_names[si],
283508f2e3dSMark Starovoytov 					     tc_string,
284508f2e3dSMark Starovoytov 					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
285508f2e3dSMark Starovoytov 					p += ETH_GSTRING_LEN;
286508f2e3dSMark Starovoytov 				}
287508f2e3dSMark Starovoytov 				for (si = 0; si < tx_stat_cnt; si++) {
288508f2e3dSMark Starovoytov 					snprintf(p, ETH_GSTRING_LEN,
289508f2e3dSMark Starovoytov 					     aq_ethtool_queue_tx_stat_names[si],
2904272ba8bSMark Starovoytov 					     tc_string,
291b9e98926SMark Starovoytov 					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
2925d8d84e9SIgor Russkikh 					p += ETH_GSTRING_LEN;
2935d8d84e9SIgor Russkikh 				}
2945d8d84e9SIgor Russkikh 			}
2954272ba8bSMark Starovoytov 		}
29614b539a3SPavel Belous #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
29714b539a3SPavel Belous 		if (nic->aq_ptp) {
29814b539a3SPavel Belous 			const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX);
29914b539a3SPavel Belous 			const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
30014b539a3SPavel Belous 			unsigned int ptp_ring_idx =
30114b539a3SPavel Belous 				aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode);
30214b539a3SPavel Belous 
30314b539a3SPavel Belous 			snprintf(tc_string, 8, "PTP ");
30414b539a3SPavel Belous 
30514b539a3SPavel Belous 			for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) {
30614b539a3SPavel Belous 				for (si = 0; si < rx_stat_cnt; si++) {
30714b539a3SPavel Belous 					snprintf(p, ETH_GSTRING_LEN,
30814b539a3SPavel Belous 						 aq_ethtool_queue_rx_stat_names[si],
30914b539a3SPavel Belous 						 tc_string,
31014b539a3SPavel Belous 						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
31114b539a3SPavel Belous 					p += ETH_GSTRING_LEN;
31214b539a3SPavel Belous 				}
31314b539a3SPavel Belous 				if (i >= tx_ring_cnt)
31414b539a3SPavel Belous 					continue;
31514b539a3SPavel Belous 				for (si = 0; si < tx_stat_cnt; si++) {
31614b539a3SPavel Belous 					snprintf(p, ETH_GSTRING_LEN,
31714b539a3SPavel Belous 						 aq_ethtool_queue_tx_stat_names[si],
31814b539a3SPavel Belous 						 tc_string,
31914b539a3SPavel Belous 						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
32014b539a3SPavel Belous 					p += ETH_GSTRING_LEN;
32114b539a3SPavel Belous 				}
32214b539a3SPavel Belous 			}
32314b539a3SPavel Belous 		}
32414b539a3SPavel Belous #endif
325aec0f1aaSDmitry Bogdanov #if IS_ENABLED(CONFIG_MACSEC)
3264272ba8bSMark Starovoytov 		if (!nic->macsec_cfg)
327aec0f1aaSDmitry Bogdanov 			break;
328aec0f1aaSDmitry Bogdanov 
329aec0f1aaSDmitry Bogdanov 		memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
330aec0f1aaSDmitry Bogdanov 		p = p + sizeof(aq_macsec_stat_names);
331aec0f1aaSDmitry Bogdanov 		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
332aec0f1aaSDmitry Bogdanov 			struct aq_macsec_txsc *aq_txsc;
333aec0f1aaSDmitry Bogdanov 
3344272ba8bSMark Starovoytov 			if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
335aec0f1aaSDmitry Bogdanov 				continue;
336aec0f1aaSDmitry Bogdanov 
337aec0f1aaSDmitry Bogdanov 			for (si = 0;
338aec0f1aaSDmitry Bogdanov 				si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
339aec0f1aaSDmitry Bogdanov 				si++) {
340aec0f1aaSDmitry Bogdanov 				snprintf(p, ETH_GSTRING_LEN,
341aec0f1aaSDmitry Bogdanov 					 aq_macsec_txsc_stat_names[si], i);
342aec0f1aaSDmitry Bogdanov 				p += ETH_GSTRING_LEN;
343aec0f1aaSDmitry Bogdanov 			}
3444272ba8bSMark Starovoytov 			aq_txsc = &nic->macsec_cfg->aq_txsc[i];
345aec0f1aaSDmitry Bogdanov 			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
346aec0f1aaSDmitry Bogdanov 				if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
347aec0f1aaSDmitry Bogdanov 					continue;
348aec0f1aaSDmitry Bogdanov 				for (si = 0;
349aec0f1aaSDmitry Bogdanov 				     si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
350aec0f1aaSDmitry Bogdanov 				     si++) {
351aec0f1aaSDmitry Bogdanov 					snprintf(p, ETH_GSTRING_LEN,
352aec0f1aaSDmitry Bogdanov 						 aq_macsec_txsa_stat_names[si],
353aec0f1aaSDmitry Bogdanov 						 i, sa);
354aec0f1aaSDmitry Bogdanov 					p += ETH_GSTRING_LEN;
355aec0f1aaSDmitry Bogdanov 				}
356aec0f1aaSDmitry Bogdanov 			}
357aec0f1aaSDmitry Bogdanov 		}
358aec0f1aaSDmitry Bogdanov 		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
359aec0f1aaSDmitry Bogdanov 			struct aq_macsec_rxsc *aq_rxsc;
360aec0f1aaSDmitry Bogdanov 
3614272ba8bSMark Starovoytov 			if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
362aec0f1aaSDmitry Bogdanov 				continue;
363aec0f1aaSDmitry Bogdanov 
3644272ba8bSMark Starovoytov 			aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
365aec0f1aaSDmitry Bogdanov 			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
366aec0f1aaSDmitry Bogdanov 				if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
367aec0f1aaSDmitry Bogdanov 					continue;
368aec0f1aaSDmitry Bogdanov 				for (si = 0;
369aec0f1aaSDmitry Bogdanov 				     si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
370aec0f1aaSDmitry Bogdanov 				     si++) {
371aec0f1aaSDmitry Bogdanov 					snprintf(p, ETH_GSTRING_LEN,
372aec0f1aaSDmitry Bogdanov 						 aq_macsec_rxsa_stat_names[si],
373aec0f1aaSDmitry Bogdanov 						 i, sa);
374aec0f1aaSDmitry Bogdanov 					p += ETH_GSTRING_LEN;
375aec0f1aaSDmitry Bogdanov 				}
376aec0f1aaSDmitry Bogdanov 			}
377aec0f1aaSDmitry Bogdanov 		}
378aec0f1aaSDmitry Bogdanov #endif
379ea4b4d7fSIgor Russkikh 		break;
3804272ba8bSMark Starovoytov 	}
381ea4b4d7fSIgor Russkikh 	case ETH_SS_PRIV_FLAGS:
382ea4b4d7fSIgor Russkikh 		memcpy(p, aq_ethtool_priv_flag_names,
383ea4b4d7fSIgor Russkikh 		       sizeof(aq_ethtool_priv_flag_names));
384ea4b4d7fSIgor Russkikh 		break;
3855d8d84e9SIgor Russkikh 	}
386c5760d03SDavid VomLehn }
387c5760d03SDavid VomLehn 
aq_ethtool_set_phys_id(struct net_device * ndev,enum ethtool_phys_id_state state)388d1287ce4SNikita Danilov static int aq_ethtool_set_phys_id(struct net_device *ndev,
389d1287ce4SNikita Danilov 				  enum ethtool_phys_id_state state)
390d1287ce4SNikita Danilov {
391d1287ce4SNikita Danilov 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
392d1287ce4SNikita Danilov 	struct aq_hw_s *hw = aq_nic->aq_hw;
393d1287ce4SNikita Danilov 	int ret = 0;
394d1287ce4SNikita Danilov 
395d1287ce4SNikita Danilov 	if (!aq_nic->aq_fw_ops->led_control)
396d1287ce4SNikita Danilov 		return -EOPNOTSUPP;
397d1287ce4SNikita Danilov 
398d1287ce4SNikita Danilov 	mutex_lock(&aq_nic->fwreq_mutex);
399d1287ce4SNikita Danilov 
400d1287ce4SNikita Danilov 	switch (state) {
401d1287ce4SNikita Danilov 	case ETHTOOL_ID_ACTIVE:
402d1287ce4SNikita Danilov 		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK |
403d1287ce4SNikita Danilov 				 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4);
404d1287ce4SNikita Danilov 		break;
405d1287ce4SNikita Danilov 	case ETHTOOL_ID_INACTIVE:
406d1287ce4SNikita Danilov 		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT);
407d1287ce4SNikita Danilov 		break;
408d1287ce4SNikita Danilov 	default:
409d1287ce4SNikita Danilov 		break;
410d1287ce4SNikita Danilov 	}
411d1287ce4SNikita Danilov 
412d1287ce4SNikita Danilov 	mutex_unlock(&aq_nic->fwreq_mutex);
413d1287ce4SNikita Danilov 
414d1287ce4SNikita Danilov 	return ret;
415d1287ce4SNikita Danilov }
416d1287ce4SNikita Danilov 
aq_ethtool_get_sset_count(struct net_device * ndev,int stringset)417c5760d03SDavid VomLehn static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
418c5760d03SDavid VomLehn {
4197b0c342fSNikita Danilov 	int ret = 0;
4207b0c342fSNikita Danilov 
421c5760d03SDavid VomLehn 	switch (stringset) {
422c5760d03SDavid VomLehn 	case ETH_SS_STATS:
423aec0f1aaSDmitry Bogdanov 		ret = aq_ethtool_n_stats(ndev);
424c5760d03SDavid VomLehn 		break;
425ea4b4d7fSIgor Russkikh 	case ETH_SS_PRIV_FLAGS:
426ea4b4d7fSIgor Russkikh 		ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
427ea4b4d7fSIgor Russkikh 		break;
428c5760d03SDavid VomLehn 	default:
429c5760d03SDavid VomLehn 		ret = -EOPNOTSUPP;
430c5760d03SDavid VomLehn 	}
4317b0c342fSNikita Danilov 
432c5760d03SDavid VomLehn 	return ret;
433c5760d03SDavid VomLehn }
434c5760d03SDavid VomLehn 
aq_ethtool_get_rss_indir_size(struct net_device * ndev)435c5760d03SDavid VomLehn static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
436c5760d03SDavid VomLehn {
437c5760d03SDavid VomLehn 	return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
438c5760d03SDavid VomLehn }
439c5760d03SDavid VomLehn 
aq_ethtool_get_rss_key_size(struct net_device * ndev)440c5760d03SDavid VomLehn static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
441c5760d03SDavid VomLehn {
442c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
4437b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
4447b0c342fSNikita Danilov 
4457b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
446c5760d03SDavid VomLehn 
447c5760d03SDavid VomLehn 	return sizeof(cfg->aq_rss.hash_secret_key);
448c5760d03SDavid VomLehn }
449c5760d03SDavid VomLehn 
aq_ethtool_get_rss(struct net_device * ndev,u32 * indir,u8 * key,u8 * hfunc)450c5760d03SDavid VomLehn static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
451c5760d03SDavid VomLehn 			      u8 *hfunc)
452c5760d03SDavid VomLehn {
453c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
4547b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
455c5760d03SDavid VomLehn 	unsigned int i = 0U;
456c5760d03SDavid VomLehn 
4577b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
4587b0c342fSNikita Danilov 
459c5760d03SDavid VomLehn 	if (hfunc)
460c5760d03SDavid VomLehn 		*hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
461c5760d03SDavid VomLehn 	if (indir) {
462c5760d03SDavid VomLehn 		for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
463c5760d03SDavid VomLehn 			indir[i] = cfg->aq_rss.indirection_table[i];
464c5760d03SDavid VomLehn 	}
465c5760d03SDavid VomLehn 	if (key)
466c5760d03SDavid VomLehn 		memcpy(key, cfg->aq_rss.hash_secret_key,
467c5760d03SDavid VomLehn 		       sizeof(cfg->aq_rss.hash_secret_key));
4687b0c342fSNikita Danilov 
469c5760d03SDavid VomLehn 	return 0;
470c5760d03SDavid VomLehn }
471c5760d03SDavid VomLehn 
aq_ethtool_set_rss(struct net_device * netdev,const u32 * indir,const u8 * key,const u8 hfunc)47239163767SDmitry Bogdanov static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
47339163767SDmitry Bogdanov 			      const u8 *key, const u8 hfunc)
47439163767SDmitry Bogdanov {
47539163767SDmitry Bogdanov 	struct aq_nic_s *aq_nic = netdev_priv(netdev);
47639163767SDmitry Bogdanov 	struct aq_nic_cfg_s *cfg;
47739163767SDmitry Bogdanov 	unsigned int i = 0U;
47839163767SDmitry Bogdanov 	u32 rss_entries;
47939163767SDmitry Bogdanov 	int err = 0;
48039163767SDmitry Bogdanov 
48139163767SDmitry Bogdanov 	cfg = aq_nic_get_cfg(aq_nic);
48239163767SDmitry Bogdanov 	rss_entries = cfg->aq_rss.indirection_table_size;
48339163767SDmitry Bogdanov 
48439163767SDmitry Bogdanov 	/* We do not allow change in unsupported parameters */
48539163767SDmitry Bogdanov 	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
48639163767SDmitry Bogdanov 		return -EOPNOTSUPP;
48739163767SDmitry Bogdanov 	/* Fill out the redirection table */
48839163767SDmitry Bogdanov 	if (indir)
48939163767SDmitry Bogdanov 		for (i = 0; i < rss_entries; i++)
49039163767SDmitry Bogdanov 			cfg->aq_rss.indirection_table[i] = indir[i];
49139163767SDmitry Bogdanov 
49239163767SDmitry Bogdanov 	/* Fill out the rss hash key */
49339163767SDmitry Bogdanov 	if (key) {
49439163767SDmitry Bogdanov 		memcpy(cfg->aq_rss.hash_secret_key, key,
49539163767SDmitry Bogdanov 		       sizeof(cfg->aq_rss.hash_secret_key));
49639163767SDmitry Bogdanov 		err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
49739163767SDmitry Bogdanov 			&cfg->aq_rss);
49839163767SDmitry Bogdanov 		if (err)
49939163767SDmitry Bogdanov 			return err;
50039163767SDmitry Bogdanov 	}
50139163767SDmitry Bogdanov 
50239163767SDmitry Bogdanov 	err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
50339163767SDmitry Bogdanov 
50439163767SDmitry Bogdanov 	return err;
50539163767SDmitry Bogdanov }
50639163767SDmitry Bogdanov 
aq_ethtool_get_rxnfc(struct net_device * ndev,struct ethtool_rxnfc * cmd,u32 * rule_locs)507c5760d03SDavid VomLehn static int aq_ethtool_get_rxnfc(struct net_device *ndev,
508c5760d03SDavid VomLehn 				struct ethtool_rxnfc *cmd,
509c5760d03SDavid VomLehn 				u32 *rule_locs)
510c5760d03SDavid VomLehn {
511c5760d03SDavid VomLehn 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5127b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
513c5760d03SDavid VomLehn 	int err = 0;
514c5760d03SDavid VomLehn 
5157b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
5167b0c342fSNikita Danilov 
517c5760d03SDavid VomLehn 	switch (cmd->cmd) {
518c5760d03SDavid VomLehn 	case ETHTOOL_GRXRINGS:
519c5760d03SDavid VomLehn 		cmd->data = cfg->vecs;
520c5760d03SDavid VomLehn 		break;
5218d0bcb01SDmitry Bogdanov 	case ETHTOOL_GRXCLSRLCNT:
5228d0bcb01SDmitry Bogdanov 		cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
5238d0bcb01SDmitry Bogdanov 		break;
5248d0bcb01SDmitry Bogdanov 	case ETHTOOL_GRXCLSRULE:
5258d0bcb01SDmitry Bogdanov 		err = aq_get_rxnfc_rule(aq_nic, cmd);
5268d0bcb01SDmitry Bogdanov 		break;
5278d0bcb01SDmitry Bogdanov 	case ETHTOOL_GRXCLSRLALL:
5288d0bcb01SDmitry Bogdanov 		err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
5298d0bcb01SDmitry Bogdanov 		break;
5308d0bcb01SDmitry Bogdanov 	default:
5318d0bcb01SDmitry Bogdanov 		err = -EOPNOTSUPP;
5328d0bcb01SDmitry Bogdanov 		break;
5338d0bcb01SDmitry Bogdanov 	}
534c5760d03SDavid VomLehn 
5358d0bcb01SDmitry Bogdanov 	return err;
5368d0bcb01SDmitry Bogdanov }
5378d0bcb01SDmitry Bogdanov 
aq_ethtool_set_rxnfc(struct net_device * ndev,struct ethtool_rxnfc * cmd)5388d0bcb01SDmitry Bogdanov static int aq_ethtool_set_rxnfc(struct net_device *ndev,
5398d0bcb01SDmitry Bogdanov 				struct ethtool_rxnfc *cmd)
5408d0bcb01SDmitry Bogdanov {
5418d0bcb01SDmitry Bogdanov 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5427b0c342fSNikita Danilov 	int err = 0;
5438d0bcb01SDmitry Bogdanov 
5448d0bcb01SDmitry Bogdanov 	switch (cmd->cmd) {
5458d0bcb01SDmitry Bogdanov 	case ETHTOOL_SRXCLSRLINS:
5468d0bcb01SDmitry Bogdanov 		err = aq_add_rxnfc_rule(aq_nic, cmd);
5478d0bcb01SDmitry Bogdanov 		break;
5488d0bcb01SDmitry Bogdanov 	case ETHTOOL_SRXCLSRLDEL:
5498d0bcb01SDmitry Bogdanov 		err = aq_del_rxnfc_rule(aq_nic, cmd);
5508d0bcb01SDmitry Bogdanov 		break;
551c5760d03SDavid VomLehn 	default:
552c5760d03SDavid VomLehn 		err = -EOPNOTSUPP;
553c5760d03SDavid VomLehn 		break;
554c5760d03SDavid VomLehn 	}
555c5760d03SDavid VomLehn 
556c5760d03SDavid VomLehn 	return err;
557c5760d03SDavid VomLehn }
558c5760d03SDavid VomLehn 
aq_ethtool_get_coalesce(struct net_device * ndev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)5592660d226SWei Yongjun static int aq_ethtool_get_coalesce(struct net_device *ndev,
560f3ccfda1SYufeng Mo 				   struct ethtool_coalesce *coal,
561f3ccfda1SYufeng Mo 				   struct kernel_ethtool_coalesce *kernel_coal,
562f3ccfda1SYufeng Mo 				   struct netlink_ext_ack *extack)
563b82ee71aSIgor Russkikh {
564b82ee71aSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5657b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
5667b0c342fSNikita Danilov 
5677b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
568b82ee71aSIgor Russkikh 
569b82ee71aSIgor Russkikh 	if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
570b82ee71aSIgor Russkikh 	    cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
571b82ee71aSIgor Russkikh 		coal->rx_coalesce_usecs = cfg->rx_itr;
572b82ee71aSIgor Russkikh 		coal->tx_coalesce_usecs = cfg->tx_itr;
573b82ee71aSIgor Russkikh 		coal->rx_max_coalesced_frames = 0;
574b82ee71aSIgor Russkikh 		coal->tx_max_coalesced_frames = 0;
575b82ee71aSIgor Russkikh 	} else {
576b82ee71aSIgor Russkikh 		coal->rx_coalesce_usecs = 0;
577b82ee71aSIgor Russkikh 		coal->tx_coalesce_usecs = 0;
578b82ee71aSIgor Russkikh 		coal->rx_max_coalesced_frames = 1;
579b82ee71aSIgor Russkikh 		coal->tx_max_coalesced_frames = 1;
580b82ee71aSIgor Russkikh 	}
5817b0c342fSNikita Danilov 
582b82ee71aSIgor Russkikh 	return 0;
583b82ee71aSIgor Russkikh }
584b82ee71aSIgor Russkikh 
aq_ethtool_set_coalesce(struct net_device * ndev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)5852660d226SWei Yongjun static int aq_ethtool_set_coalesce(struct net_device *ndev,
586f3ccfda1SYufeng Mo 				   struct ethtool_coalesce *coal,
587f3ccfda1SYufeng Mo 				   struct kernel_ethtool_coalesce *kernel_coal,
588f3ccfda1SYufeng Mo 				   struct netlink_ext_ack *extack)
589b82ee71aSIgor Russkikh {
590b82ee71aSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
5917b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
5927b0c342fSNikita Danilov 
5937b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
594b82ee71aSIgor Russkikh 
595b82ee71aSIgor Russkikh 	/* Atlantic only supports timing based coalescing
596b82ee71aSIgor Russkikh 	 */
597b82ee71aSIgor Russkikh 	if (coal->rx_max_coalesced_frames > 1 ||
598fcca747fSJakub Kicinski 	    coal->tx_max_coalesced_frames > 1)
599b82ee71aSIgor Russkikh 		return -EOPNOTSUPP;
600b82ee71aSIgor Russkikh 
601b82ee71aSIgor Russkikh 	/* We do not support frame counting. Check this
602b82ee71aSIgor Russkikh 	 */
603b82ee71aSIgor Russkikh 	if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
604b82ee71aSIgor Russkikh 		return -EOPNOTSUPP;
605b82ee71aSIgor Russkikh 	if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
606b82ee71aSIgor Russkikh 		return -EOPNOTSUPP;
607b82ee71aSIgor Russkikh 
608b82ee71aSIgor Russkikh 	if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
609b82ee71aSIgor Russkikh 	    coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
610b82ee71aSIgor Russkikh 		return -EINVAL;
611b82ee71aSIgor Russkikh 
612b82ee71aSIgor Russkikh 	cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
613b82ee71aSIgor Russkikh 
614b82ee71aSIgor Russkikh 	cfg->rx_itr = coal->rx_coalesce_usecs;
615b82ee71aSIgor Russkikh 	cfg->tx_itr = coal->tx_coalesce_usecs;
616b82ee71aSIgor Russkikh 
617b82ee71aSIgor Russkikh 	return aq_nic_update_interrupt_moderation_settings(aq_nic);
618b82ee71aSIgor Russkikh }
619b82ee71aSIgor Russkikh 
aq_ethtool_get_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)620a0da96c0SYana Esina static void aq_ethtool_get_wol(struct net_device *ndev,
621a0da96c0SYana Esina 			       struct ethtool_wolinfo *wol)
622a0da96c0SYana Esina {
623a0da96c0SYana Esina 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
6247b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
6257b0c342fSNikita Danilov 
6267b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
627a0da96c0SYana Esina 
628837c6378SNikita Danilov 	wol->supported = AQ_NIC_WOL_MODES;
629837c6378SNikita Danilov 	wol->wolopts = cfg->wol;
630a0da96c0SYana Esina }
631a0da96c0SYana Esina 
aq_ethtool_set_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)632a0da96c0SYana Esina static int aq_ethtool_set_wol(struct net_device *ndev,
633a0da96c0SYana Esina 			      struct ethtool_wolinfo *wol)
634a0da96c0SYana Esina {
635a0da96c0SYana Esina 	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
636a0da96c0SYana Esina 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
6377b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
638a0da96c0SYana Esina 	int err = 0;
639a0da96c0SYana Esina 
6407b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
6417b0c342fSNikita Danilov 
642837c6378SNikita Danilov 	if (wol->wolopts & ~AQ_NIC_WOL_MODES)
643837c6378SNikita Danilov 		return -EOPNOTSUPP;
644837c6378SNikita Danilov 
645837c6378SNikita Danilov 	cfg->wol = wol->wolopts;
646837c6378SNikita Danilov 
647837c6378SNikita Danilov 	err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);
648a0da96c0SYana Esina 
649a0da96c0SYana Esina 	return err;
650a0da96c0SYana Esina }
651a0da96c0SYana Esina 
aq_ethtool_get_ts_info(struct net_device * ndev,struct ethtool_ts_info * info)65284989af0SEgor Pomozov static int aq_ethtool_get_ts_info(struct net_device *ndev,
65384989af0SEgor Pomozov 				  struct ethtool_ts_info *info)
65484989af0SEgor Pomozov {
65584989af0SEgor Pomozov 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
65684989af0SEgor Pomozov 
65784989af0SEgor Pomozov 	ethtool_op_get_ts_info(ndev, info);
65884989af0SEgor Pomozov 
65984989af0SEgor Pomozov 	if (!aq_nic->aq_ptp)
66084989af0SEgor Pomozov 		return 0;
66184989af0SEgor Pomozov 
66284989af0SEgor Pomozov 	info->so_timestamping |=
66384989af0SEgor Pomozov 		SOF_TIMESTAMPING_TX_HARDWARE |
66484989af0SEgor Pomozov 		SOF_TIMESTAMPING_RX_HARDWARE |
66584989af0SEgor Pomozov 		SOF_TIMESTAMPING_RAW_HARDWARE;
66684989af0SEgor Pomozov 
66784989af0SEgor Pomozov 	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
66884989af0SEgor Pomozov 			 BIT(HWTSTAMP_TX_ON);
66984989af0SEgor Pomozov 
67084989af0SEgor Pomozov 	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
67184989af0SEgor Pomozov 
67284989af0SEgor Pomozov 	info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
67384989af0SEgor Pomozov 			    BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
67484989af0SEgor Pomozov 			    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
67584989af0SEgor Pomozov 
6764378b882SIgor Russkikh #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
67784989af0SEgor Pomozov 	info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
6784378b882SIgor Russkikh #endif
67984989af0SEgor Pomozov 
68084989af0SEgor Pomozov 	return 0;
68184989af0SEgor Pomozov }
68284989af0SEgor Pomozov 
eee_mask_to_ethtool_mask(u32 speed)683ce6a690cSNikita Danilov static u32 eee_mask_to_ethtool_mask(u32 speed)
68492ab6407SYana Esina {
68592ab6407SYana Esina 	u32 rate = 0;
68692ab6407SYana Esina 
68792ab6407SYana Esina 	if (speed & AQ_NIC_RATE_EEE_10G)
68892ab6407SYana Esina 		rate |= SUPPORTED_10000baseT_Full;
68992ab6407SYana Esina 
69092ab6407SYana Esina 	if (speed & AQ_NIC_RATE_EEE_1G)
69192ab6407SYana Esina 		rate |= SUPPORTED_1000baseT_Full;
69292ab6407SYana Esina 
6933d464aadSIgor Russkikh 	if (speed & AQ_NIC_RATE_EEE_100M)
6943d464aadSIgor Russkikh 		rate |= SUPPORTED_100baseT_Full;
6953d464aadSIgor Russkikh 
69692ab6407SYana Esina 	return rate;
69792ab6407SYana Esina }
69892ab6407SYana Esina 
aq_ethtool_get_eee(struct net_device * ndev,struct ethtool_eee * eee)69992ab6407SYana Esina static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
70092ab6407SYana Esina {
70192ab6407SYana Esina 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
70292ab6407SYana Esina 	u32 rate, supported_rates;
70392ab6407SYana Esina 	int err = 0;
70492ab6407SYana Esina 
70592ab6407SYana Esina 	if (!aq_nic->aq_fw_ops->get_eee_rate)
70692ab6407SYana Esina 		return -EOPNOTSUPP;
70792ab6407SYana Esina 
708f5dce08aSNikita Danilov 	mutex_lock(&aq_nic->fwreq_mutex);
70992ab6407SYana Esina 	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
71092ab6407SYana Esina 					      &supported_rates);
711f5dce08aSNikita Danilov 	mutex_unlock(&aq_nic->fwreq_mutex);
71292ab6407SYana Esina 	if (err < 0)
71392ab6407SYana Esina 		return err;
71492ab6407SYana Esina 
71592ab6407SYana Esina 	eee->supported = eee_mask_to_ethtool_mask(supported_rates);
71692ab6407SYana Esina 
71792ab6407SYana Esina 	if (aq_nic->aq_nic_cfg.eee_speeds)
71892ab6407SYana Esina 		eee->advertised = eee->supported;
71992ab6407SYana Esina 
72092ab6407SYana Esina 	eee->lp_advertised = eee_mask_to_ethtool_mask(rate);
72192ab6407SYana Esina 
72292ab6407SYana Esina 	eee->eee_enabled = !!eee->advertised;
72392ab6407SYana Esina 
72492ab6407SYana Esina 	eee->tx_lpi_enabled = eee->eee_enabled;
725ce6a690cSNikita Danilov 	if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK)
72692ab6407SYana Esina 		eee->eee_active = true;
72792ab6407SYana Esina 
72892ab6407SYana Esina 	return 0;
72992ab6407SYana Esina }
73092ab6407SYana Esina 
aq_ethtool_set_eee(struct net_device * ndev,struct ethtool_eee * eee)73192ab6407SYana Esina static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
73292ab6407SYana Esina {
73392ab6407SYana Esina 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
73492ab6407SYana Esina 	u32 rate, supported_rates;
73592ab6407SYana Esina 	struct aq_nic_cfg_s *cfg;
73692ab6407SYana Esina 	int err = 0;
73792ab6407SYana Esina 
73892ab6407SYana Esina 	cfg = aq_nic_get_cfg(aq_nic);
73992ab6407SYana Esina 
74092ab6407SYana Esina 	if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
74192ab6407SYana Esina 		     !aq_nic->aq_fw_ops->set_eee_rate))
74292ab6407SYana Esina 		return -EOPNOTSUPP;
74392ab6407SYana Esina 
744f5dce08aSNikita Danilov 	mutex_lock(&aq_nic->fwreq_mutex);
74592ab6407SYana Esina 	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
74692ab6407SYana Esina 					      &supported_rates);
747f5dce08aSNikita Danilov 	mutex_unlock(&aq_nic->fwreq_mutex);
74892ab6407SYana Esina 	if (err < 0)
74992ab6407SYana Esina 		return err;
75092ab6407SYana Esina 
75192ab6407SYana Esina 	if (eee->eee_enabled) {
75292ab6407SYana Esina 		rate = supported_rates;
75392ab6407SYana Esina 		cfg->eee_speeds = rate;
75492ab6407SYana Esina 	} else {
75592ab6407SYana Esina 		rate = 0;
75692ab6407SYana Esina 		cfg->eee_speeds = 0;
75792ab6407SYana Esina 	}
75892ab6407SYana Esina 
759f5dce08aSNikita Danilov 	mutex_lock(&aq_nic->fwreq_mutex);
760f5dce08aSNikita Danilov 	err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
761f5dce08aSNikita Danilov 	mutex_unlock(&aq_nic->fwreq_mutex);
762f5dce08aSNikita Danilov 
763f5dce08aSNikita Danilov 	return err;
76492ab6407SYana Esina }
76592ab6407SYana Esina 
aq_ethtool_nway_reset(struct net_device * ndev)766b8d68b62SAnton Mikaev static int aq_ethtool_nway_reset(struct net_device *ndev)
767b8d68b62SAnton Mikaev {
768b8d68b62SAnton Mikaev 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
769f5dce08aSNikita Danilov 	int err = 0;
770b8d68b62SAnton Mikaev 
771b8d68b62SAnton Mikaev 	if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
772b8d68b62SAnton Mikaev 		return -EOPNOTSUPP;
773b8d68b62SAnton Mikaev 
774f5dce08aSNikita Danilov 	if (netif_running(ndev)) {
775f5dce08aSNikita Danilov 		mutex_lock(&aq_nic->fwreq_mutex);
776f5dce08aSNikita Danilov 		err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
777f5dce08aSNikita Danilov 		mutex_unlock(&aq_nic->fwreq_mutex);
778f5dce08aSNikita Danilov 	}
779b8d68b62SAnton Mikaev 
780f5dce08aSNikita Danilov 	return err;
781b8d68b62SAnton Mikaev }
782b8d68b62SAnton Mikaev 
aq_ethtool_get_pauseparam(struct net_device * ndev,struct ethtool_pauseparam * pause)783288551deSIgor Russkikh static void aq_ethtool_get_pauseparam(struct net_device *ndev,
784288551deSIgor Russkikh 				      struct ethtool_pauseparam *pause)
785288551deSIgor Russkikh {
786288551deSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
787e39b8ffeSNikita Danilov 	int fc = aq_nic->aq_nic_cfg.fc.req;
788288551deSIgor Russkikh 
789288551deSIgor Russkikh 	pause->autoneg = 0;
790288551deSIgor Russkikh 
79135e8e8b4SIgor Russkikh 	pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
79235e8e8b4SIgor Russkikh 	pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
793288551deSIgor Russkikh }
794288551deSIgor Russkikh 
aq_ethtool_set_pauseparam(struct net_device * ndev,struct ethtool_pauseparam * pause)795288551deSIgor Russkikh static int aq_ethtool_set_pauseparam(struct net_device *ndev,
796288551deSIgor Russkikh 				     struct ethtool_pauseparam *pause)
797288551deSIgor Russkikh {
798288551deSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
799288551deSIgor Russkikh 	int err = 0;
800288551deSIgor Russkikh 
801288551deSIgor Russkikh 	if (!aq_nic->aq_fw_ops->set_flow_control)
802288551deSIgor Russkikh 		return -EOPNOTSUPP;
803288551deSIgor Russkikh 
804288551deSIgor Russkikh 	if (pause->autoneg == AUTONEG_ENABLE)
805288551deSIgor Russkikh 		return -EOPNOTSUPP;
806288551deSIgor Russkikh 
807288551deSIgor Russkikh 	if (pause->rx_pause)
8088009bb19SNikita Danilov 		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
809288551deSIgor Russkikh 	else
8108009bb19SNikita Danilov 		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
811288551deSIgor Russkikh 
812288551deSIgor Russkikh 	if (pause->tx_pause)
8138009bb19SNikita Danilov 		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
814288551deSIgor Russkikh 	else
8158009bb19SNikita Danilov 		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
816288551deSIgor Russkikh 
817f5dce08aSNikita Danilov 	mutex_lock(&aq_nic->fwreq_mutex);
818288551deSIgor Russkikh 	err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
819f5dce08aSNikita Danilov 	mutex_unlock(&aq_nic->fwreq_mutex);
820288551deSIgor Russkikh 
821288551deSIgor Russkikh 	return err;
822288551deSIgor Russkikh }
823288551deSIgor Russkikh 
aq_get_ringparam(struct net_device * ndev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)824c1af5427SAnton Mikaev static void aq_get_ringparam(struct net_device *ndev,
82574624944SHao Chen 			     struct ethtool_ringparam *ring,
82674624944SHao Chen 			     struct kernel_ethtool_ringparam *kernel_ring,
82774624944SHao Chen 			     struct netlink_ext_ack *extack)
828c1af5427SAnton Mikaev {
829c1af5427SAnton Mikaev 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8307b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
831c1af5427SAnton Mikaev 
8327b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
833c1af5427SAnton Mikaev 
8347b0c342fSNikita Danilov 	ring->rx_pending = cfg->rxds;
8357b0c342fSNikita Danilov 	ring->tx_pending = cfg->txds;
8367b0c342fSNikita Danilov 
8377b0c342fSNikita Danilov 	ring->rx_max_pending = cfg->aq_hw_caps->rxds_max;
8387b0c342fSNikita Danilov 	ring->tx_max_pending = cfg->aq_hw_caps->txds_max;
839c1af5427SAnton Mikaev }
840c1af5427SAnton Mikaev 
aq_set_ringparam(struct net_device * ndev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)841c1af5427SAnton Mikaev static int aq_set_ringparam(struct net_device *ndev,
84274624944SHao Chen 			    struct ethtool_ringparam *ring,
84374624944SHao Chen 			    struct kernel_ethtool_ringparam *kernel_ring,
84474624944SHao Chen 			    struct netlink_ext_ack *extack)
845c1af5427SAnton Mikaev {
846c1af5427SAnton Mikaev 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
8477b0c342fSNikita Danilov 	const struct aq_hw_caps_s *hw_caps;
8487b0c342fSNikita Danilov 	bool ndev_running = false;
8497b0c342fSNikita Danilov 	struct aq_nic_cfg_s *cfg;
8507b0c342fSNikita Danilov 	int err = 0;
8517b0c342fSNikita Danilov 
8527b0c342fSNikita Danilov 	cfg = aq_nic_get_cfg(aq_nic);
8537b0c342fSNikita Danilov 	hw_caps = cfg->aq_hw_caps;
854c1af5427SAnton Mikaev 
855c1af5427SAnton Mikaev 	if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
856c1af5427SAnton Mikaev 		err = -EOPNOTSUPP;
857c1af5427SAnton Mikaev 		goto err_exit;
858c1af5427SAnton Mikaev 	}
859c1af5427SAnton Mikaev 
860c1af5427SAnton Mikaev 	if (netif_running(ndev)) {
861c1af5427SAnton Mikaev 		ndev_running = true;
862*2a838911SIzabela Bakollari 		aq_ndev_close(ndev);
863c1af5427SAnton Mikaev 	}
864c1af5427SAnton Mikaev 
8657b0c342fSNikita Danilov 	cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
8667b0c342fSNikita Danilov 	cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
8677b0c342fSNikita Danilov 	cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
868c1af5427SAnton Mikaev 
8697b0c342fSNikita Danilov 	cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
8707b0c342fSNikita Danilov 	cfg->txds = min(cfg->txds, hw_caps->txds_max);
8717b0c342fSNikita Danilov 	cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);
872c1af5427SAnton Mikaev 
87314ef766bSMark Starovoytov 	err = aq_nic_realloc_vectors(aq_nic);
87414ef766bSMark Starovoytov 	if (err)
875c1af5427SAnton Mikaev 		goto err_exit;
87614ef766bSMark Starovoytov 
877c1af5427SAnton Mikaev 	if (ndev_running)
878*2a838911SIzabela Bakollari 		err = aq_ndev_open(ndev);
879c1af5427SAnton Mikaev 
880c1af5427SAnton Mikaev err_exit:
881c1af5427SAnton Mikaev 	return err;
882c1af5427SAnton Mikaev }
883c1af5427SAnton Mikaev 
aq_get_msg_level(struct net_device * ndev)88458128fa0SNikita Danilov static u32 aq_get_msg_level(struct net_device *ndev)
88558128fa0SNikita Danilov {
88658128fa0SNikita Danilov 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
88758128fa0SNikita Danilov 
88858128fa0SNikita Danilov 	return aq_nic->msg_enable;
88958128fa0SNikita Danilov }
89058128fa0SNikita Danilov 
aq_set_msg_level(struct net_device * ndev,u32 data)89158128fa0SNikita Danilov static void aq_set_msg_level(struct net_device *ndev, u32 data)
89258128fa0SNikita Danilov {
89358128fa0SNikita Danilov 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
89458128fa0SNikita Danilov 
89558128fa0SNikita Danilov 	aq_nic->msg_enable = data;
89658128fa0SNikita Danilov }
89758128fa0SNikita Danilov 
aq_ethtool_get_priv_flags(struct net_device * ndev)8987b094968Szhengbin static u32 aq_ethtool_get_priv_flags(struct net_device *ndev)
899ea4b4d7fSIgor Russkikh {
900ea4b4d7fSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
901ea4b4d7fSIgor Russkikh 
902ea4b4d7fSIgor Russkikh 	return aq_nic->aq_nic_cfg.priv_flags;
903ea4b4d7fSIgor Russkikh }
904ea4b4d7fSIgor Russkikh 
aq_ethtool_set_priv_flags(struct net_device * ndev,u32 flags)9057b094968Szhengbin static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
906ea4b4d7fSIgor Russkikh {
907ea4b4d7fSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
908ea4b4d7fSIgor Russkikh 	struct aq_nic_cfg_s *cfg;
909ea4b4d7fSIgor Russkikh 	u32 priv_flags;
910ecab7870SDmitry Bogdanov 	int ret = 0;
911ea4b4d7fSIgor Russkikh 
912ea4b4d7fSIgor Russkikh 	cfg = aq_nic_get_cfg(aq_nic);
913ea4b4d7fSIgor Russkikh 	priv_flags = cfg->priv_flags;
914ea4b4d7fSIgor Russkikh 
915ea4b4d7fSIgor Russkikh 	if (flags & ~AQ_PRIV_FLAGS_MASK)
916ea4b4d7fSIgor Russkikh 		return -EOPNOTSUPP;
917ea4b4d7fSIgor Russkikh 
918b42726fcSNikita Danilov 	if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
919b42726fcSNikita Danilov 		netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
920b42726fcSNikita Danilov 		return -EINVAL;
921b42726fcSNikita Danilov 	}
922b42726fcSNikita Danilov 
923ea4b4d7fSIgor Russkikh 	cfg->priv_flags = flags;
924ea4b4d7fSIgor Russkikh 
925ea4b4d7fSIgor Russkikh 	if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
926ea4b4d7fSIgor Russkikh 		if (netif_running(ndev)) {
927ea4b4d7fSIgor Russkikh 			dev_close(ndev);
928ea4b4d7fSIgor Russkikh 
929ea4b4d7fSIgor Russkikh 			dev_open(ndev, NULL);
930ea4b4d7fSIgor Russkikh 		}
931ea4b4d7fSIgor Russkikh 	} else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
932ecab7870SDmitry Bogdanov 		ret = aq_nic_set_loopback(aq_nic);
933ea4b4d7fSIgor Russkikh 	}
934ea4b4d7fSIgor Russkikh 
935ecab7870SDmitry Bogdanov 	return ret;
936ea4b4d7fSIgor Russkikh }
937ea4b4d7fSIgor Russkikh 
aq_ethtool_get_phy_tunable(struct net_device * ndev,const struct ethtool_tunable * tuna,void * data)938e193c3abSIgor Russkikh static int aq_ethtool_get_phy_tunable(struct net_device *ndev,
939e193c3abSIgor Russkikh 				      const struct ethtool_tunable *tuna, void *data)
940e193c3abSIgor Russkikh {
941e193c3abSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
942e193c3abSIgor Russkikh 
943e193c3abSIgor Russkikh 	switch (tuna->id) {
94460db5e40SIgor Russkikh 	case ETHTOOL_PHY_EDPD: {
94560db5e40SIgor Russkikh 		u16 *val = data;
94660db5e40SIgor Russkikh 
94760db5e40SIgor Russkikh 		*val = aq_nic->aq_nic_cfg.is_media_detect ? AQ_HW_MEDIA_DETECT_CNT : 0;
94860db5e40SIgor Russkikh 		break;
94960db5e40SIgor Russkikh 	}
950e193c3abSIgor Russkikh 	case ETHTOOL_PHY_DOWNSHIFT: {
951e193c3abSIgor Russkikh 		u8 *val = data;
952e193c3abSIgor Russkikh 
953e193c3abSIgor Russkikh 		*val = (u8)aq_nic->aq_nic_cfg.downshift_counter;
954e193c3abSIgor Russkikh 		break;
955e193c3abSIgor Russkikh 	}
956e193c3abSIgor Russkikh 	default:
957e193c3abSIgor Russkikh 		return -EOPNOTSUPP;
958e193c3abSIgor Russkikh 	}
959e193c3abSIgor Russkikh 
960e193c3abSIgor Russkikh 	return 0;
961e193c3abSIgor Russkikh }
962e193c3abSIgor Russkikh 
aq_ethtool_set_phy_tunable(struct net_device * ndev,const struct ethtool_tunable * tuna,const void * data)963e193c3abSIgor Russkikh static int aq_ethtool_set_phy_tunable(struct net_device *ndev,
964e193c3abSIgor Russkikh 				      const struct ethtool_tunable *tuna, const void *data)
965e193c3abSIgor Russkikh {
966e193c3abSIgor Russkikh 	int err = -EOPNOTSUPP;
967e193c3abSIgor Russkikh 	struct aq_nic_s *aq_nic = netdev_priv(ndev);
968e193c3abSIgor Russkikh 
969e193c3abSIgor Russkikh 	switch (tuna->id) {
97060db5e40SIgor Russkikh 	case ETHTOOL_PHY_EDPD: {
97160db5e40SIgor Russkikh 		const u16 *val = data;
97260db5e40SIgor Russkikh 
97360db5e40SIgor Russkikh 		err = aq_nic_set_media_detect(aq_nic, *val);
97460db5e40SIgor Russkikh 		break;
97560db5e40SIgor Russkikh 	}
976e193c3abSIgor Russkikh 	case ETHTOOL_PHY_DOWNSHIFT: {
977e193c3abSIgor Russkikh 		const u8 *val = data;
978e193c3abSIgor Russkikh 
979e193c3abSIgor Russkikh 		err = aq_nic_set_downshift(aq_nic, *val);
980e193c3abSIgor Russkikh 		break;
981e193c3abSIgor Russkikh 	}
982e193c3abSIgor Russkikh 	default:
983e193c3abSIgor Russkikh 		break;
984e193c3abSIgor Russkikh 	}
985e193c3abSIgor Russkikh 
986e193c3abSIgor Russkikh 	return err;
987e193c3abSIgor Russkikh }
988e193c3abSIgor Russkikh 
989c5760d03SDavid VomLehn const struct ethtool_ops aq_ethtool_ops = {
990fcca747fSJakub Kicinski 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
991fcca747fSJakub Kicinski 				     ETHTOOL_COALESCE_MAX_FRAMES,
992c5760d03SDavid VomLehn 	.get_link            = aq_ethtool_get_link,
993c5760d03SDavid VomLehn 	.get_regs_len        = aq_ethtool_get_regs_len,
994c5760d03SDavid VomLehn 	.get_regs            = aq_ethtool_get_regs,
995c5760d03SDavid VomLehn 	.get_drvinfo         = aq_ethtool_get_drvinfo,
996c5760d03SDavid VomLehn 	.get_strings         = aq_ethtool_get_strings,
997d1287ce4SNikita Danilov 	.set_phys_id         = aq_ethtool_set_phys_id,
998c5760d03SDavid VomLehn 	.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
999a0da96c0SYana Esina 	.get_wol             = aq_ethtool_get_wol,
1000a0da96c0SYana Esina 	.set_wol             = aq_ethtool_set_wol,
1001b8d68b62SAnton Mikaev 	.nway_reset          = aq_ethtool_nway_reset,
1002c1af5427SAnton Mikaev 	.get_ringparam       = aq_get_ringparam,
1003c1af5427SAnton Mikaev 	.set_ringparam       = aq_set_ringparam,
100492ab6407SYana Esina 	.get_eee             = aq_ethtool_get_eee,
100592ab6407SYana Esina 	.set_eee             = aq_ethtool_set_eee,
1006288551deSIgor Russkikh 	.get_pauseparam      = aq_ethtool_get_pauseparam,
1007288551deSIgor Russkikh 	.set_pauseparam      = aq_ethtool_set_pauseparam,
1008c5760d03SDavid VomLehn 	.get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
1009c5760d03SDavid VomLehn 	.get_rxfh            = aq_ethtool_get_rss,
101039163767SDmitry Bogdanov 	.set_rxfh            = aq_ethtool_set_rss,
1011c5760d03SDavid VomLehn 	.get_rxnfc           = aq_ethtool_get_rxnfc,
10128d0bcb01SDmitry Bogdanov 	.set_rxnfc           = aq_ethtool_set_rxnfc,
101358128fa0SNikita Danilov 	.get_msglevel        = aq_get_msg_level,
101458128fa0SNikita Danilov 	.set_msglevel        = aq_set_msg_level,
1015c5760d03SDavid VomLehn 	.get_sset_count      = aq_ethtool_get_sset_count,
1016f8244ab5SPhilippe Reynes 	.get_ethtool_stats   = aq_ethtool_stats,
1017ea4b4d7fSIgor Russkikh 	.get_priv_flags      = aq_ethtool_get_priv_flags,
1018ea4b4d7fSIgor Russkikh 	.set_priv_flags      = aq_ethtool_set_priv_flags,
1019f8244ab5SPhilippe Reynes 	.get_link_ksettings  = aq_ethtool_get_link_ksettings,
1020f8244ab5SPhilippe Reynes 	.set_link_ksettings  = aq_ethtool_set_link_ksettings,
1021b82ee71aSIgor Russkikh 	.get_coalesce	     = aq_ethtool_get_coalesce,
1022b82ee71aSIgor Russkikh 	.set_coalesce	     = aq_ethtool_set_coalesce,
102384989af0SEgor Pomozov 	.get_ts_info         = aq_ethtool_get_ts_info,
1024e193c3abSIgor Russkikh 	.get_phy_tunable     = aq_ethtool_get_phy_tunable,
1025e193c3abSIgor Russkikh 	.set_phy_tunable     = aq_ethtool_set_phy_tunable,
1026c5760d03SDavid VomLehn };
1027