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