1// SPDX-License-Identifier: GPL-2.0-only
2/* Atlantic Network Driver
3 *
4 * Copyright (C) 2014-2019 aQuantia Corporation
5 * Copyright (C) 2019-2020 Marvell International Ltd.
6 */
7
8/* File aq_ethtool.c: Definition of ethertool related functions. */
9
10#include "aq_ethtool.h"
11#include "aq_nic.h"
12#include "aq_vec.h"
13#include "aq_ptp.h"
14#include "aq_filters.h"
15#include "aq_macsec.h"
16#include "aq_main.h"
17
18#include <linux/linkmode.h>
19#include <linux/ptp_clock_kernel.h>
20
21static void aq_ethtool_get_regs(struct net_device *ndev,
22				struct ethtool_regs *regs, void *p)
23{
24	struct aq_nic_s *aq_nic = netdev_priv(ndev);
25	u32 regs_count;
26
27	regs_count = aq_nic_get_regs_count(aq_nic);
28
29	memset(p, 0, regs_count * sizeof(u32));
30	aq_nic_get_regs(aq_nic, regs, p);
31}
32
33static int aq_ethtool_get_regs_len(struct net_device *ndev)
34{
35	struct aq_nic_s *aq_nic = netdev_priv(ndev);
36	u32 regs_count;
37
38	regs_count = aq_nic_get_regs_count(aq_nic);
39
40	return regs_count * sizeof(u32);
41}
42
43static u32 aq_ethtool_get_link(struct net_device *ndev)
44{
45	return ethtool_op_get_link(ndev);
46}
47
48static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
49					 struct ethtool_link_ksettings *cmd)
50{
51	struct aq_nic_s *aq_nic = netdev_priv(ndev);
52
53	aq_nic_get_link_ksettings(aq_nic, cmd);
54	cmd->base.speed = netif_carrier_ok(ndev) ?
55				aq_nic_get_link_speed(aq_nic) : 0U;
56
57	return 0;
58}
59
60static int
61aq_ethtool_set_link_ksettings(struct net_device *ndev,
62			      const struct ethtool_link_ksettings *cmd)
63{
64	struct aq_nic_s *aq_nic = netdev_priv(ndev);
65
66	return aq_nic_set_link_ksettings(aq_nic, cmd);
67}
68
69static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
70	"InPackets",
71	"InUCast",
72	"InMCast",
73	"InBCast",
74	"InErrors",
75	"OutPackets",
76	"OutUCast",
77	"OutMCast",
78	"OutBCast",
79	"InUCastOctets",
80	"OutUCastOctets",
81	"InMCastOctets",
82	"OutMCastOctets",
83	"InBCastOctets",
84	"OutBCastOctets",
85	"InOctets",
86	"OutOctets",
87	"InPacketsDma",
88	"OutPacketsDma",
89	"InOctetsDma",
90	"OutOctetsDma",
91	"InDroppedDma",
92};
93
94static const char * const aq_ethtool_queue_rx_stat_names[] = {
95	"%sQueue[%d] InPackets",
96	"%sQueue[%d] InJumboPackets",
97	"%sQueue[%d] InLroPackets",
98	"%sQueue[%d] InErrors",
99	"%sQueue[%d] AllocFails",
100	"%sQueue[%d] SkbAllocFails",
101	"%sQueue[%d] Polls",
102	"%sQueue[%d] PageFlips",
103	"%sQueue[%d] PageReuses",
104	"%sQueue[%d] PageFrees",
105	"%sQueue[%d] XdpAbort",
106	"%sQueue[%d] XdpDrop",
107	"%sQueue[%d] XdpPass",
108	"%sQueue[%d] XdpTx",
109	"%sQueue[%d] XdpInvalid",
110	"%sQueue[%d] XdpRedirect",
111};
112
113static const char * const aq_ethtool_queue_tx_stat_names[] = {
114	"%sQueue[%d] OutPackets",
115	"%sQueue[%d] Restarts",
116};
117
118#if IS_ENABLED(CONFIG_MACSEC)
119static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
120	"MACSec InCtlPackets",
121	"MACSec InTaggedMissPackets",
122	"MACSec InUntaggedMissPackets",
123	"MACSec InNotagPackets",
124	"MACSec InUntaggedPackets",
125	"MACSec InBadTagPackets",
126	"MACSec InNoSciPackets",
127	"MACSec InUnknownSciPackets",
128	"MACSec InCtrlPortPassPackets",
129	"MACSec InUnctrlPortPassPackets",
130	"MACSec InCtrlPortFailPackets",
131	"MACSec InUnctrlPortFailPackets",
132	"MACSec InTooLongPackets",
133	"MACSec InIgpocCtlPackets",
134	"MACSec InEccErrorPackets",
135	"MACSec InUnctrlHitDropRedir",
136	"MACSec OutCtlPackets",
137	"MACSec OutUnknownSaPackets",
138	"MACSec OutUntaggedPackets",
139	"MACSec OutTooLong",
140	"MACSec OutEccErrorPackets",
141	"MACSec OutUnctrlHitDropRedir",
142};
143
144static const char * const aq_macsec_txsc_stat_names[] = {
145	"MACSecTXSC%d ProtectedPkts",
146	"MACSecTXSC%d EncryptedPkts",
147	"MACSecTXSC%d ProtectedOctets",
148	"MACSecTXSC%d EncryptedOctets",
149};
150
151static const char * const aq_macsec_txsa_stat_names[] = {
152	"MACSecTXSC%dSA%d HitDropRedirect",
153	"MACSecTXSC%dSA%d Protected2Pkts",
154	"MACSecTXSC%dSA%d ProtectedPkts",
155	"MACSecTXSC%dSA%d EncryptedPkts",
156};
157
158static const char * const aq_macsec_rxsa_stat_names[] = {
159	"MACSecRXSC%dSA%d UntaggedHitPkts",
160	"MACSecRXSC%dSA%d CtrlHitDrpRedir",
161	"MACSecRXSC%dSA%d NotUsingSa",
162	"MACSecRXSC%dSA%d UnusedSa",
163	"MACSecRXSC%dSA%d NotValidPkts",
164	"MACSecRXSC%dSA%d InvalidPkts",
165	"MACSecRXSC%dSA%d OkPkts",
166	"MACSecRXSC%dSA%d LatePkts",
167	"MACSecRXSC%dSA%d DelayedPkts",
168	"MACSecRXSC%dSA%d UncheckedPkts",
169	"MACSecRXSC%dSA%d ValidatedOctets",
170	"MACSecRXSC%dSA%d DecryptedOctets",
171};
172#endif
173
174static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
175	"DMASystemLoopback",
176	"PKTSystemLoopback",
177	"DMANetworkLoopback",
178	"PHYInternalLoopback",
179	"PHYExternalLoopback",
180};
181
182static u32 aq_ethtool_n_stats(struct net_device *ndev)
183{
184	const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
185	const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
186	struct aq_nic_s *nic = netdev_priv(ndev);
187	struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
188	u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
189		      (rx_stat_cnt + tx_stat_cnt) * cfg->vecs * cfg->tcs;
190
191#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
192	n_stats += rx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_RX) +
193		   tx_stat_cnt * aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
194#endif
195
196#if IS_ENABLED(CONFIG_MACSEC)
197	if (nic->macsec_cfg) {
198		n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
199			   ARRAY_SIZE(aq_macsec_txsc_stat_names) *
200				   aq_macsec_tx_sc_cnt(nic) +
201			   ARRAY_SIZE(aq_macsec_txsa_stat_names) *
202				   aq_macsec_tx_sa_cnt(nic) +
203			   ARRAY_SIZE(aq_macsec_rxsa_stat_names) *
204				   aq_macsec_rx_sa_cnt(nic);
205	}
206#endif
207
208	return n_stats;
209}
210
211static void aq_ethtool_stats(struct net_device *ndev,
212			     struct ethtool_stats *stats, u64 *data)
213{
214	struct aq_nic_s *aq_nic = netdev_priv(ndev);
215
216	memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
217	data = aq_nic_get_stats(aq_nic, data);
218#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
219	data = aq_ptp_get_stats(aq_nic, data);
220#endif
221#if IS_ENABLED(CONFIG_MACSEC)
222	data = aq_macsec_get_stats(aq_nic, data);
223#endif
224}
225
226static void aq_ethtool_get_drvinfo(struct net_device *ndev,
227				   struct ethtool_drvinfo *drvinfo)
228{
229	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
230	struct aq_nic_s *aq_nic = netdev_priv(ndev);
231	u32 firmware_version;
232	u32 regs_count;
233
234	firmware_version = aq_nic_get_fw_version(aq_nic);
235	regs_count = aq_nic_get_regs_count(aq_nic);
236
237	strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
238
239	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
240		 "%u.%u.%u", firmware_version >> 24,
241		 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
242
243	strscpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
244		sizeof(drvinfo->bus_info));
245	drvinfo->n_stats = aq_ethtool_n_stats(ndev);
246	drvinfo->testinfo_len = 0;
247	drvinfo->regdump_len = regs_count;
248	drvinfo->eedump_len = 0;
249}
250
251static void aq_ethtool_get_strings(struct net_device *ndev,
252				   u32 stringset, u8 *data)
253{
254	struct aq_nic_s *nic = netdev_priv(ndev);
255	struct aq_nic_cfg_s *cfg;
256	u8 *p = data;
257	int i, si;
258#if IS_ENABLED(CONFIG_MACSEC)
259	int sa;
260#endif
261
262	cfg = aq_nic_get_cfg(nic);
263
264	switch (stringset) {
265	case ETH_SS_STATS: {
266		const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names);
267		const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names);
268		char tc_string[8];
269		int tc;
270
271		memset(tc_string, 0, sizeof(tc_string));
272		memcpy(p, aq_ethtool_stat_names,
273		       sizeof(aq_ethtool_stat_names));
274		p = p + sizeof(aq_ethtool_stat_names);
275
276		for (tc = 0; tc < cfg->tcs; tc++) {
277			if (cfg->is_qos)
278				snprintf(tc_string, 8, "TC%d ", tc);
279
280			for (i = 0; i < cfg->vecs; i++) {
281				for (si = 0; si < rx_stat_cnt; si++) {
282					snprintf(p, ETH_GSTRING_LEN,
283					     aq_ethtool_queue_rx_stat_names[si],
284					     tc_string,
285					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
286					p += ETH_GSTRING_LEN;
287				}
288				for (si = 0; si < tx_stat_cnt; si++) {
289					snprintf(p, ETH_GSTRING_LEN,
290					     aq_ethtool_queue_tx_stat_names[si],
291					     tc_string,
292					     AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
293					p += ETH_GSTRING_LEN;
294				}
295			}
296		}
297#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
298		if (nic->aq_ptp) {
299			const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX);
300			const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
301			unsigned int ptp_ring_idx =
302				aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode);
303
304			snprintf(tc_string, 8, "PTP ");
305
306			for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) {
307				for (si = 0; si < rx_stat_cnt; si++) {
308					snprintf(p, ETH_GSTRING_LEN,
309						 aq_ethtool_queue_rx_stat_names[si],
310						 tc_string,
311						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
312					p += ETH_GSTRING_LEN;
313				}
314				if (i >= tx_ring_cnt)
315					continue;
316				for (si = 0; si < tx_stat_cnt; si++) {
317					snprintf(p, ETH_GSTRING_LEN,
318						 aq_ethtool_queue_tx_stat_names[si],
319						 tc_string,
320						 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
321					p += ETH_GSTRING_LEN;
322				}
323			}
324		}
325#endif
326#if IS_ENABLED(CONFIG_MACSEC)
327		if (!nic->macsec_cfg)
328			break;
329
330		memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
331		p = p + sizeof(aq_macsec_stat_names);
332		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
333			struct aq_macsec_txsc *aq_txsc;
334
335			if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
336				continue;
337
338			for (si = 0;
339				si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
340				si++) {
341				snprintf(p, ETH_GSTRING_LEN,
342					 aq_macsec_txsc_stat_names[si], i);
343				p += ETH_GSTRING_LEN;
344			}
345			aq_txsc = &nic->macsec_cfg->aq_txsc[i];
346			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
347				if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
348					continue;
349				for (si = 0;
350				     si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
351				     si++) {
352					snprintf(p, ETH_GSTRING_LEN,
353						 aq_macsec_txsa_stat_names[si],
354						 i, sa);
355					p += ETH_GSTRING_LEN;
356				}
357			}
358		}
359		for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
360			struct aq_macsec_rxsc *aq_rxsc;
361
362			if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
363				continue;
364
365			aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
366			for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
367				if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
368					continue;
369				for (si = 0;
370				     si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
371				     si++) {
372					snprintf(p, ETH_GSTRING_LEN,
373						 aq_macsec_rxsa_stat_names[si],
374						 i, sa);
375					p += ETH_GSTRING_LEN;
376				}
377			}
378		}
379#endif
380		break;
381	}
382	case ETH_SS_PRIV_FLAGS:
383		memcpy(p, aq_ethtool_priv_flag_names,
384		       sizeof(aq_ethtool_priv_flag_names));
385		break;
386	}
387}
388
389static int aq_ethtool_set_phys_id(struct net_device *ndev,
390				  enum ethtool_phys_id_state state)
391{
392	struct aq_nic_s *aq_nic = netdev_priv(ndev);
393	struct aq_hw_s *hw = aq_nic->aq_hw;
394	int ret = 0;
395
396	if (!aq_nic->aq_fw_ops->led_control)
397		return -EOPNOTSUPP;
398
399	mutex_lock(&aq_nic->fwreq_mutex);
400
401	switch (state) {
402	case ETHTOOL_ID_ACTIVE:
403		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK |
404				 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4);
405		break;
406	case ETHTOOL_ID_INACTIVE:
407		ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT);
408		break;
409	default:
410		break;
411	}
412
413	mutex_unlock(&aq_nic->fwreq_mutex);
414
415	return ret;
416}
417
418static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
419{
420	int ret = 0;
421
422	switch (stringset) {
423	case ETH_SS_STATS:
424		ret = aq_ethtool_n_stats(ndev);
425		break;
426	case ETH_SS_PRIV_FLAGS:
427		ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
428		break;
429	default:
430		ret = -EOPNOTSUPP;
431	}
432
433	return ret;
434}
435
436static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
437{
438	return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
439}
440
441static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
442{
443	struct aq_nic_s *aq_nic = netdev_priv(ndev);
444	struct aq_nic_cfg_s *cfg;
445
446	cfg = aq_nic_get_cfg(aq_nic);
447
448	return sizeof(cfg->aq_rss.hash_secret_key);
449}
450
451static int aq_ethtool_get_rss(struct net_device *ndev,
452			      struct ethtool_rxfh_param *rxfh)
453{
454	struct aq_nic_s *aq_nic = netdev_priv(ndev);
455	struct aq_nic_cfg_s *cfg;
456	unsigned int i = 0U;
457
458	cfg = aq_nic_get_cfg(aq_nic);
459
460	rxfh->hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
461	if (rxfh->indir) {
462		for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
463			rxfh->indir[i] = cfg->aq_rss.indirection_table[i];
464	}
465	if (rxfh->key)
466		memcpy(rxfh->key, cfg->aq_rss.hash_secret_key,
467		       sizeof(cfg->aq_rss.hash_secret_key));
468
469	return 0;
470}
471
472static int aq_ethtool_set_rss(struct net_device *netdev,
473			      struct ethtool_rxfh_param *rxfh,
474			      struct netlink_ext_ack *extack)
475{
476	struct aq_nic_s *aq_nic = netdev_priv(netdev);
477	struct aq_nic_cfg_s *cfg;
478	unsigned int i = 0U;
479	u32 rss_entries;
480	int err = 0;
481
482	cfg = aq_nic_get_cfg(aq_nic);
483	rss_entries = cfg->aq_rss.indirection_table_size;
484
485	/* We do not allow change in unsupported parameters */
486	if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
487	    rxfh->hfunc != ETH_RSS_HASH_TOP)
488		return -EOPNOTSUPP;
489	/* Fill out the redirection table */
490	if (rxfh->indir)
491		for (i = 0; i < rss_entries; i++)
492			cfg->aq_rss.indirection_table[i] = rxfh->indir[i];
493
494	/* Fill out the rss hash key */
495	if (rxfh->key) {
496		memcpy(cfg->aq_rss.hash_secret_key, rxfh->key,
497		       sizeof(cfg->aq_rss.hash_secret_key));
498		err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
499			&cfg->aq_rss);
500		if (err)
501			return err;
502	}
503
504	err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
505
506	return err;
507}
508
509static int aq_ethtool_get_rxnfc(struct net_device *ndev,
510				struct ethtool_rxnfc *cmd,
511				u32 *rule_locs)
512{
513	struct aq_nic_s *aq_nic = netdev_priv(ndev);
514	struct aq_nic_cfg_s *cfg;
515	int err = 0;
516
517	cfg = aq_nic_get_cfg(aq_nic);
518
519	switch (cmd->cmd) {
520	case ETHTOOL_GRXRINGS:
521		cmd->data = cfg->vecs;
522		break;
523	case ETHTOOL_GRXCLSRLCNT:
524		cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
525		break;
526	case ETHTOOL_GRXCLSRULE:
527		err = aq_get_rxnfc_rule(aq_nic, cmd);
528		break;
529	case ETHTOOL_GRXCLSRLALL:
530		err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
531		break;
532	default:
533		err = -EOPNOTSUPP;
534		break;
535	}
536
537	return err;
538}
539
540static int aq_ethtool_set_rxnfc(struct net_device *ndev,
541				struct ethtool_rxnfc *cmd)
542{
543	struct aq_nic_s *aq_nic = netdev_priv(ndev);
544	int err = 0;
545
546	switch (cmd->cmd) {
547	case ETHTOOL_SRXCLSRLINS:
548		err = aq_add_rxnfc_rule(aq_nic, cmd);
549		break;
550	case ETHTOOL_SRXCLSRLDEL:
551		err = aq_del_rxnfc_rule(aq_nic, cmd);
552		break;
553	default:
554		err = -EOPNOTSUPP;
555		break;
556	}
557
558	return err;
559}
560
561static int aq_ethtool_get_coalesce(struct net_device *ndev,
562				   struct ethtool_coalesce *coal,
563				   struct kernel_ethtool_coalesce *kernel_coal,
564				   struct netlink_ext_ack *extack)
565{
566	struct aq_nic_s *aq_nic = netdev_priv(ndev);
567	struct aq_nic_cfg_s *cfg;
568
569	cfg = aq_nic_get_cfg(aq_nic);
570
571	if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
572	    cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
573		coal->rx_coalesce_usecs = cfg->rx_itr;
574		coal->tx_coalesce_usecs = cfg->tx_itr;
575		coal->rx_max_coalesced_frames = 0;
576		coal->tx_max_coalesced_frames = 0;
577	} else {
578		coal->rx_coalesce_usecs = 0;
579		coal->tx_coalesce_usecs = 0;
580		coal->rx_max_coalesced_frames = 1;
581		coal->tx_max_coalesced_frames = 1;
582	}
583
584	return 0;
585}
586
587static int aq_ethtool_set_coalesce(struct net_device *ndev,
588				   struct ethtool_coalesce *coal,
589				   struct kernel_ethtool_coalesce *kernel_coal,
590				   struct netlink_ext_ack *extack)
591{
592	struct aq_nic_s *aq_nic = netdev_priv(ndev);
593	struct aq_nic_cfg_s *cfg;
594
595	cfg = aq_nic_get_cfg(aq_nic);
596
597	/* Atlantic only supports timing based coalescing
598	 */
599	if (coal->rx_max_coalesced_frames > 1 ||
600	    coal->tx_max_coalesced_frames > 1)
601		return -EOPNOTSUPP;
602
603	/* We do not support frame counting. Check this
604	 */
605	if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
606		return -EOPNOTSUPP;
607	if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
608		return -EOPNOTSUPP;
609
610	if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
611	    coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
612		return -EINVAL;
613
614	cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
615
616	cfg->rx_itr = coal->rx_coalesce_usecs;
617	cfg->tx_itr = coal->tx_coalesce_usecs;
618
619	return aq_nic_update_interrupt_moderation_settings(aq_nic);
620}
621
622static void aq_ethtool_get_wol(struct net_device *ndev,
623			       struct ethtool_wolinfo *wol)
624{
625	struct aq_nic_s *aq_nic = netdev_priv(ndev);
626	struct aq_nic_cfg_s *cfg;
627
628	cfg = aq_nic_get_cfg(aq_nic);
629
630	wol->supported = AQ_NIC_WOL_MODES;
631	wol->wolopts = cfg->wol;
632}
633
634static int aq_ethtool_set_wol(struct net_device *ndev,
635			      struct ethtool_wolinfo *wol)
636{
637	struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
638	struct aq_nic_s *aq_nic = netdev_priv(ndev);
639	struct aq_nic_cfg_s *cfg;
640	int err = 0;
641
642	cfg = aq_nic_get_cfg(aq_nic);
643
644	if (wol->wolopts & ~AQ_NIC_WOL_MODES)
645		return -EOPNOTSUPP;
646
647	cfg->wol = wol->wolopts;
648
649	err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);
650
651	return err;
652}
653
654static int aq_ethtool_get_ts_info(struct net_device *ndev,
655				  struct ethtool_ts_info *info)
656{
657	struct aq_nic_s *aq_nic = netdev_priv(ndev);
658
659	ethtool_op_get_ts_info(ndev, info);
660
661	if (!aq_nic->aq_ptp)
662		return 0;
663
664	info->so_timestamping |=
665		SOF_TIMESTAMPING_TX_HARDWARE |
666		SOF_TIMESTAMPING_RX_HARDWARE |
667		SOF_TIMESTAMPING_RAW_HARDWARE;
668
669	info->tx_types = BIT(HWTSTAMP_TX_OFF) |
670			 BIT(HWTSTAMP_TX_ON);
671
672	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
673
674	info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
675			    BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
676			    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
677
678#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
679	info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
680#endif
681
682	return 0;
683}
684
685static void eee_mask_to_ethtool_mask(unsigned long *mode, u32 speed)
686{
687	if (speed & AQ_NIC_RATE_EEE_10G)
688		linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, mode);
689
690	if (speed & AQ_NIC_RATE_EEE_1G)
691		linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, mode);
692
693	if (speed & AQ_NIC_RATE_EEE_100M)
694		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, mode);
695}
696
697static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_keee *eee)
698{
699	struct aq_nic_s *aq_nic = netdev_priv(ndev);
700	u32 rate, supported_rates;
701	int err = 0;
702
703	if (!aq_nic->aq_fw_ops->get_eee_rate)
704		return -EOPNOTSUPP;
705
706	mutex_lock(&aq_nic->fwreq_mutex);
707	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
708					      &supported_rates);
709	mutex_unlock(&aq_nic->fwreq_mutex);
710	if (err < 0)
711		return err;
712
713	eee_mask_to_ethtool_mask(eee->supported, supported_rates);
714
715	if (aq_nic->aq_nic_cfg.eee_speeds)
716		linkmode_copy(eee->advertised, eee->supported);
717
718	eee_mask_to_ethtool_mask(eee->lp_advertised, rate);
719
720	eee->eee_enabled = !linkmode_empty(eee->advertised);
721
722	eee->tx_lpi_enabled = eee->eee_enabled;
723	if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK)
724		eee->eee_active = true;
725
726	return 0;
727}
728
729static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_keee *eee)
730{
731	struct aq_nic_s *aq_nic = netdev_priv(ndev);
732	u32 rate, supported_rates;
733	struct aq_nic_cfg_s *cfg;
734	int err = 0;
735
736	cfg = aq_nic_get_cfg(aq_nic);
737
738	if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
739		     !aq_nic->aq_fw_ops->set_eee_rate))
740		return -EOPNOTSUPP;
741
742	mutex_lock(&aq_nic->fwreq_mutex);
743	err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
744					      &supported_rates);
745	mutex_unlock(&aq_nic->fwreq_mutex);
746	if (err < 0)
747		return err;
748
749	if (eee->eee_enabled) {
750		rate = supported_rates;
751		cfg->eee_speeds = rate;
752	} else {
753		rate = 0;
754		cfg->eee_speeds = 0;
755	}
756
757	mutex_lock(&aq_nic->fwreq_mutex);
758	err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
759	mutex_unlock(&aq_nic->fwreq_mutex);
760
761	return err;
762}
763
764static int aq_ethtool_nway_reset(struct net_device *ndev)
765{
766	struct aq_nic_s *aq_nic = netdev_priv(ndev);
767	int err = 0;
768
769	if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
770		return -EOPNOTSUPP;
771
772	if (netif_running(ndev)) {
773		mutex_lock(&aq_nic->fwreq_mutex);
774		err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
775		mutex_unlock(&aq_nic->fwreq_mutex);
776	}
777
778	return err;
779}
780
781static void aq_ethtool_get_pauseparam(struct net_device *ndev,
782				      struct ethtool_pauseparam *pause)
783{
784	struct aq_nic_s *aq_nic = netdev_priv(ndev);
785	int fc = aq_nic->aq_nic_cfg.fc.req;
786
787	pause->autoneg = 0;
788
789	pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
790	pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
791}
792
793static int aq_ethtool_set_pauseparam(struct net_device *ndev,
794				     struct ethtool_pauseparam *pause)
795{
796	struct aq_nic_s *aq_nic = netdev_priv(ndev);
797	int err = 0;
798
799	if (!aq_nic->aq_fw_ops->set_flow_control)
800		return -EOPNOTSUPP;
801
802	if (pause->autoneg == AUTONEG_ENABLE)
803		return -EOPNOTSUPP;
804
805	if (pause->rx_pause)
806		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
807	else
808		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
809
810	if (pause->tx_pause)
811		aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
812	else
813		aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
814
815	mutex_lock(&aq_nic->fwreq_mutex);
816	err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
817	mutex_unlock(&aq_nic->fwreq_mutex);
818
819	return err;
820}
821
822static void aq_get_ringparam(struct net_device *ndev,
823			     struct ethtool_ringparam *ring,
824			     struct kernel_ethtool_ringparam *kernel_ring,
825			     struct netlink_ext_ack *extack)
826{
827	struct aq_nic_s *aq_nic = netdev_priv(ndev);
828	struct aq_nic_cfg_s *cfg;
829
830	cfg = aq_nic_get_cfg(aq_nic);
831
832	ring->rx_pending = cfg->rxds;
833	ring->tx_pending = cfg->txds;
834
835	ring->rx_max_pending = cfg->aq_hw_caps->rxds_max;
836	ring->tx_max_pending = cfg->aq_hw_caps->txds_max;
837}
838
839static int aq_set_ringparam(struct net_device *ndev,
840			    struct ethtool_ringparam *ring,
841			    struct kernel_ethtool_ringparam *kernel_ring,
842			    struct netlink_ext_ack *extack)
843{
844	struct aq_nic_s *aq_nic = netdev_priv(ndev);
845	const struct aq_hw_caps_s *hw_caps;
846	bool ndev_running = false;
847	struct aq_nic_cfg_s *cfg;
848	int err = 0;
849
850	cfg = aq_nic_get_cfg(aq_nic);
851	hw_caps = cfg->aq_hw_caps;
852
853	if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
854		err = -EOPNOTSUPP;
855		goto err_exit;
856	}
857
858	if (netif_running(ndev)) {
859		ndev_running = true;
860		aq_ndev_close(ndev);
861	}
862
863	cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
864	cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
865	cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
866
867	cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
868	cfg->txds = min(cfg->txds, hw_caps->txds_max);
869	cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);
870
871	err = aq_nic_realloc_vectors(aq_nic);
872	if (err)
873		goto err_exit;
874
875	if (ndev_running)
876		err = aq_ndev_open(ndev);
877
878err_exit:
879	return err;
880}
881
882static u32 aq_get_msg_level(struct net_device *ndev)
883{
884	struct aq_nic_s *aq_nic = netdev_priv(ndev);
885
886	return aq_nic->msg_enable;
887}
888
889static void aq_set_msg_level(struct net_device *ndev, u32 data)
890{
891	struct aq_nic_s *aq_nic = netdev_priv(ndev);
892
893	aq_nic->msg_enable = data;
894}
895
896static u32 aq_ethtool_get_priv_flags(struct net_device *ndev)
897{
898	struct aq_nic_s *aq_nic = netdev_priv(ndev);
899
900	return aq_nic->aq_nic_cfg.priv_flags;
901}
902
903static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
904{
905	struct aq_nic_s *aq_nic = netdev_priv(ndev);
906	struct aq_nic_cfg_s *cfg;
907	u32 priv_flags;
908	int ret = 0;
909
910	cfg = aq_nic_get_cfg(aq_nic);
911	priv_flags = cfg->priv_flags;
912
913	if (flags & ~AQ_PRIV_FLAGS_MASK)
914		return -EOPNOTSUPP;
915
916	if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
917		netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
918		return -EINVAL;
919	}
920
921	cfg->priv_flags = flags;
922
923	if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
924		if (netif_running(ndev)) {
925			dev_close(ndev);
926
927			dev_open(ndev, NULL);
928		}
929	} else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
930		ret = aq_nic_set_loopback(aq_nic);
931	}
932
933	return ret;
934}
935
936static int aq_ethtool_get_phy_tunable(struct net_device *ndev,
937				      const struct ethtool_tunable *tuna, void *data)
938{
939	struct aq_nic_s *aq_nic = netdev_priv(ndev);
940
941	switch (tuna->id) {
942	case ETHTOOL_PHY_EDPD: {
943		u16 *val = data;
944
945		*val = aq_nic->aq_nic_cfg.is_media_detect ? AQ_HW_MEDIA_DETECT_CNT : 0;
946		break;
947	}
948	case ETHTOOL_PHY_DOWNSHIFT: {
949		u8 *val = data;
950
951		*val = (u8)aq_nic->aq_nic_cfg.downshift_counter;
952		break;
953	}
954	default:
955		return -EOPNOTSUPP;
956	}
957
958	return 0;
959}
960
961static int aq_ethtool_set_phy_tunable(struct net_device *ndev,
962				      const struct ethtool_tunable *tuna, const void *data)
963{
964	int err = -EOPNOTSUPP;
965	struct aq_nic_s *aq_nic = netdev_priv(ndev);
966
967	switch (tuna->id) {
968	case ETHTOOL_PHY_EDPD: {
969		const u16 *val = data;
970
971		err = aq_nic_set_media_detect(aq_nic, *val);
972		break;
973	}
974	case ETHTOOL_PHY_DOWNSHIFT: {
975		const u8 *val = data;
976
977		err = aq_nic_set_downshift(aq_nic, *val);
978		break;
979	}
980	default:
981		break;
982	}
983
984	return err;
985}
986
987const struct ethtool_ops aq_ethtool_ops = {
988	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
989				     ETHTOOL_COALESCE_MAX_FRAMES,
990	.get_link            = aq_ethtool_get_link,
991	.get_regs_len        = aq_ethtool_get_regs_len,
992	.get_regs            = aq_ethtool_get_regs,
993	.get_drvinfo         = aq_ethtool_get_drvinfo,
994	.get_strings         = aq_ethtool_get_strings,
995	.set_phys_id         = aq_ethtool_set_phys_id,
996	.get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
997	.get_wol             = aq_ethtool_get_wol,
998	.set_wol             = aq_ethtool_set_wol,
999	.nway_reset          = aq_ethtool_nway_reset,
1000	.get_ringparam       = aq_get_ringparam,
1001	.set_ringparam       = aq_set_ringparam,
1002	.get_eee             = aq_ethtool_get_eee,
1003	.set_eee             = aq_ethtool_set_eee,
1004	.get_pauseparam      = aq_ethtool_get_pauseparam,
1005	.set_pauseparam      = aq_ethtool_set_pauseparam,
1006	.get_rxfh_key_size   = aq_ethtool_get_rss_key_size,
1007	.get_rxfh            = aq_ethtool_get_rss,
1008	.set_rxfh            = aq_ethtool_set_rss,
1009	.get_rxnfc           = aq_ethtool_get_rxnfc,
1010	.set_rxnfc           = aq_ethtool_set_rxnfc,
1011	.get_msglevel        = aq_get_msg_level,
1012	.set_msglevel        = aq_set_msg_level,
1013	.get_sset_count      = aq_ethtool_get_sset_count,
1014	.get_ethtool_stats   = aq_ethtool_stats,
1015	.get_priv_flags      = aq_ethtool_get_priv_flags,
1016	.set_priv_flags      = aq_ethtool_set_priv_flags,
1017	.get_link_ksettings  = aq_ethtool_get_link_ksettings,
1018	.set_link_ksettings  = aq_ethtool_set_link_ksettings,
1019	.get_coalesce	     = aq_ethtool_get_coalesce,
1020	.set_coalesce	     = aq_ethtool_set_coalesce,
1021	.get_ts_info         = aq_ethtool_get_ts_info,
1022	.get_phy_tunable     = aq_ethtool_get_phy_tunable,
1023	.set_phy_tunable     = aq_ethtool_set_phy_tunable,
1024};
1025