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