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(dev: ndev);
25 u32 regs_count;
26
27 regs_count = aq_nic_get_regs_count(self: aq_nic);
28
29 memset(p, 0, regs_count * sizeof(u32));
30 aq_nic_get_regs(self: 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(dev: ndev);
36 u32 regs_count;
37
38 regs_count = aq_nic_get_regs_count(self: 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(dev: 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(dev: ndev);
52
53 aq_nic_get_link_ksettings(self: aq_nic, cmd);
54 cmd->base.speed = netif_carrier_ok(dev: ndev) ?
55 aq_nic_get_link_speed(self: 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(dev: ndev);
65
66 return aq_nic_set_link_ksettings(self: 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(dev: ndev);
187 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(self: 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(aq_nic: nic, ring_type: ATL_RING_RX) +
193 tx_stat_cnt * aq_ptp_get_ring_cnt(aq_nic: nic, ring_type: 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(dev: ndev);
215
216 memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
217 data = aq_nic_get_stats(self: 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(nic: 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(dev: ndev);
231 u32 firmware_version;
232 u32 regs_count;
233
234 firmware_version = aq_nic_get_fw_version(self: aq_nic);
235 regs_count = aq_nic_get_regs_count(self: aq_nic);
236
237 strlcat(p: drvinfo->driver, AQ_CFG_DRV_NAME, avail: sizeof(drvinfo->driver));
238
239 snprintf(buf: drvinfo->fw_version, size: sizeof(drvinfo->fw_version),
240 fmt: "%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(dev: 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(self: 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(buf: tc_string, size: 8, fmt: "TC%d ", tc);
279
280 for (i = 0; i < cfg->vecs; i++) {
281 for (si = 0; si < rx_stat_cnt; si++) {
282 snprintf(buf: p, ETH_GSTRING_LEN,
283 fmt: 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(buf: p, ETH_GSTRING_LEN,
290 fmt: 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(aq_nic: nic, ring_type: ATL_RING_RX);
300 const int tx_ring_cnt = aq_ptp_get_ring_cnt(aq_nic: nic, ring_type: ATL_RING_TX);
301 unsigned int ptp_ring_idx =
302 aq_ptp_ring_idx(tc_mode: nic->aq_nic_cfg.tc_mode);
303
304 snprintf(buf: tc_string, size: 8, fmt: "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(buf: p, ETH_GSTRING_LEN,
309 fmt: 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(buf: p, ETH_GSTRING_LEN,
318 fmt: 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(buf: p, ETH_GSTRING_LEN,
342 fmt: 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(buf: p, ETH_GSTRING_LEN,
353 fmt: 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(buf: p, ETH_GSTRING_LEN,
373 fmt: 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(dev: 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(lock: &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(dev: ndev);
444 struct aq_nic_cfg_s *cfg;
445
446 cfg = aq_nic_get_cfg(self: 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(dev: ndev);
455 struct aq_nic_cfg_s *cfg;
456 unsigned int i = 0U;
457
458 cfg = aq_nic_get_cfg(self: 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(dev: 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(self: 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(dev: ndev);
514 struct aq_nic_cfg_s *cfg;
515 int err = 0;
516
517 cfg = aq_nic_get_cfg(self: 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(dev: 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(dev: ndev);
567 struct aq_nic_cfg_s *cfg;
568
569 cfg = aq_nic_get_cfg(self: 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(dev: ndev);
593 struct aq_nic_cfg_s *cfg;
594
595 cfg = aq_nic_get_cfg(self: 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(self: 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(dev: ndev);
626 struct aq_nic_cfg_s *cfg;
627
628 cfg = aq_nic_get_cfg(self: 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(dev: ndev);
639 struct aq_nic_cfg_s *cfg;
640 int err = 0;
641
642 cfg = aq_nic_get_cfg(self: 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(dev: &pdev->dev, enable: !!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(dev: ndev);
658
659 ethtool_op_get_ts_info(dev: ndev, eti: 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(ptp: aq_ptp_get_ptp_clock(aq_ptp: 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(nr: ETHTOOL_LINK_MODE_10000baseT_Full_BIT, addr: mode);
689
690 if (speed & AQ_NIC_RATE_EEE_1G)
691 linkmode_set_bit(nr: ETHTOOL_LINK_MODE_1000baseT_Full_BIT, addr: mode);
692
693 if (speed & AQ_NIC_RATE_EEE_100M)
694 linkmode_set_bit(nr: ETHTOOL_LINK_MODE_100baseT_Full_BIT, addr: 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(dev: 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(lock: &aq_nic->fwreq_mutex);
710 if (err < 0)
711 return err;
712
713 eee_mask_to_ethtool_mask(mode: eee->supported, speed: supported_rates);
714
715 if (aq_nic->aq_nic_cfg.eee_speeds)
716 linkmode_copy(dst: eee->advertised, src: eee->supported);
717
718 eee_mask_to_ethtool_mask(mode: eee->lp_advertised, speed: rate);
719
720 eee->eee_enabled = !linkmode_empty(src: 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(dev: ndev);
732 u32 rate, supported_rates;
733 struct aq_nic_cfg_s *cfg;
734 int err = 0;
735
736 cfg = aq_nic_get_cfg(self: 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(lock: &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(lock: &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(dev: ndev);
767 int err = 0;
768
769 if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
770 return -EOPNOTSUPP;
771
772 if (netif_running(dev: ndev)) {
773 mutex_lock(&aq_nic->fwreq_mutex);
774 err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
775 mutex_unlock(lock: &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(dev: 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(dev: 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(lock: &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(dev: ndev);
828 struct aq_nic_cfg_s *cfg;
829
830 cfg = aq_nic_get_cfg(self: 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(dev: 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(self: 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(dev: 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(self: 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(dev: 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(dev: 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(dev: 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(dev: ndev);
906 struct aq_nic_cfg_s *cfg;
907 u32 priv_flags;
908 int ret = 0;
909
910 cfg = aq_nic_get_cfg(self: 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(dev: ndev, format: "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(dev: ndev)) {
925 dev_close(dev: ndev);
926
927 dev_open(dev: ndev, NULL);
928 }
929 } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
930 ret = aq_nic_set_loopback(self: 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(dev: 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(dev: ndev);
966
967 switch (tuna->id) {
968 case ETHTOOL_PHY_EDPD: {
969 const u16 *val = data;
970
971 err = aq_nic_set_media_detect(self: aq_nic, val: *val);
972 break;
973 }
974 case ETHTOOL_PHY_DOWNSHIFT: {
975 const u8 *val = data;
976
977 err = aq_nic_set_downshift(self: aq_nic, val: *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

source code of linux/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c