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
aq_ethtool_get_regs(struct net_device * ndev,struct ethtool_regs * regs,void * p)21 static 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
aq_ethtool_get_regs_len(struct net_device * ndev)33 static 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
aq_ethtool_get_link(struct net_device * ndev)43 static u32 aq_ethtool_get_link(struct net_device *ndev)
44 {
45 return ethtool_op_get_link(ndev);
46 }
47
aq_ethtool_get_link_ksettings(struct net_device * ndev,struct ethtool_link_ksettings * cmd)48 static 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
60 static int
aq_ethtool_set_link_ksettings(struct net_device * ndev,const struct ethtool_link_ksettings * cmd)61 aq_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
69 static 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
94 static 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
113 static 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)
119 static 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
144 static 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
151 static 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
158 static 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
174 static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
175 "DMASystemLoopback",
176 "PKTSystemLoopback",
177 "DMANetworkLoopback",
178 "PHYInternalLoopback",
179 "PHYExternalLoopback",
180 };
181
aq_ethtool_n_stats(struct net_device * ndev)182 static 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
aq_ethtool_stats(struct net_device * ndev,struct ethtool_stats * stats,u64 * data)211 static 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
aq_ethtool_get_drvinfo(struct net_device * ndev,struct ethtool_drvinfo * drvinfo)226 static 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
aq_ethtool_get_strings(struct net_device * ndev,u32 stringset,u8 * data)251 static 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 unsigned 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%u ", tc);
279
280 for (i = 0; i < cfg->vecs; i++) {
281 for (si = 0; si < rx_stat_cnt; si++) {
282 ethtool_sprintf(&p,
283 aq_ethtool_queue_rx_stat_names[si],
284 tc_string,
285 AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
286 }
287 for (si = 0; si < tx_stat_cnt; si++) {
288 ethtool_sprintf(&p,
289 aq_ethtool_queue_tx_stat_names[si],
290 tc_string,
291 AQ_NIC_CFG_TCVEC2RING(cfg, tc, i));
292 }
293 }
294 }
295 #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
296 if (nic->aq_ptp) {
297 const int rx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_RX);
298 const int tx_ring_cnt = aq_ptp_get_ring_cnt(nic, ATL_RING_TX);
299 unsigned int ptp_ring_idx =
300 aq_ptp_ring_idx(nic->aq_nic_cfg.tc_mode);
301
302 snprintf(tc_string, 8, "PTP ");
303
304 for (i = 0; i < max(rx_ring_cnt, tx_ring_cnt); i++) {
305 for (si = 0; si < rx_stat_cnt; si++) {
306 ethtool_sprintf(&p,
307 aq_ethtool_queue_rx_stat_names[si],
308 tc_string,
309 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
310 }
311 if (i >= tx_ring_cnt)
312 continue;
313 for (si = 0; si < tx_stat_cnt; si++) {
314 ethtool_sprintf(&p,
315 aq_ethtool_queue_tx_stat_names[si],
316 tc_string,
317 i ? PTP_HWST_RING_IDX : ptp_ring_idx);
318 }
319 }
320 }
321 #endif
322 #if IS_ENABLED(CONFIG_MACSEC)
323 if (!nic->macsec_cfg)
324 break;
325
326 memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
327 p = p + sizeof(aq_macsec_stat_names);
328 for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
329 struct aq_macsec_txsc *aq_txsc;
330
331 if (!(test_bit(i, &nic->macsec_cfg->txsc_idx_busy)))
332 continue;
333
334 for (si = 0;
335 si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
336 si++) {
337 ethtool_sprintf(&p,
338 aq_macsec_txsc_stat_names[si], i);
339 }
340 aq_txsc = &nic->macsec_cfg->aq_txsc[i];
341 for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
342 if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
343 continue;
344 for (si = 0;
345 si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
346 si++) {
347 ethtool_sprintf(&p,
348 aq_macsec_txsa_stat_names[si],
349 i, sa);
350 }
351 }
352 }
353 for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
354 struct aq_macsec_rxsc *aq_rxsc;
355
356 if (!(test_bit(i, &nic->macsec_cfg->rxsc_idx_busy)))
357 continue;
358
359 aq_rxsc = &nic->macsec_cfg->aq_rxsc[i];
360 for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
361 if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
362 continue;
363 for (si = 0;
364 si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
365 si++) {
366 ethtool_sprintf(&p,
367 aq_macsec_rxsa_stat_names[si],
368 i, sa);
369 }
370 }
371 }
372 #endif
373 break;
374 }
375 case ETH_SS_PRIV_FLAGS:
376 memcpy(p, aq_ethtool_priv_flag_names,
377 sizeof(aq_ethtool_priv_flag_names));
378 break;
379 }
380 }
381
aq_ethtool_set_phys_id(struct net_device * ndev,enum ethtool_phys_id_state state)382 static int aq_ethtool_set_phys_id(struct net_device *ndev,
383 enum ethtool_phys_id_state state)
384 {
385 struct aq_nic_s *aq_nic = netdev_priv(ndev);
386 struct aq_hw_s *hw = aq_nic->aq_hw;
387 int ret = 0;
388
389 if (!aq_nic->aq_fw_ops->led_control)
390 return -EOPNOTSUPP;
391
392 mutex_lock(&aq_nic->fwreq_mutex);
393
394 switch (state) {
395 case ETHTOOL_ID_ACTIVE:
396 ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK |
397 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4);
398 break;
399 case ETHTOOL_ID_INACTIVE:
400 ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT);
401 break;
402 default:
403 break;
404 }
405
406 mutex_unlock(&aq_nic->fwreq_mutex);
407
408 return ret;
409 }
410
aq_ethtool_get_sset_count(struct net_device * ndev,int stringset)411 static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
412 {
413 int ret = 0;
414
415 switch (stringset) {
416 case ETH_SS_STATS:
417 ret = aq_ethtool_n_stats(ndev);
418 break;
419 case ETH_SS_PRIV_FLAGS:
420 ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
421 break;
422 default:
423 ret = -EOPNOTSUPP;
424 }
425
426 return ret;
427 }
428
aq_ethtool_get_rss_indir_size(struct net_device * ndev)429 static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
430 {
431 return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
432 }
433
aq_ethtool_get_rss_key_size(struct net_device * ndev)434 static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
435 {
436 struct aq_nic_s *aq_nic = netdev_priv(ndev);
437 struct aq_nic_cfg_s *cfg;
438
439 cfg = aq_nic_get_cfg(aq_nic);
440
441 return sizeof(cfg->aq_rss.hash_secret_key);
442 }
443
aq_ethtool_get_rss(struct net_device * ndev,struct ethtool_rxfh_param * rxfh)444 static int aq_ethtool_get_rss(struct net_device *ndev,
445 struct ethtool_rxfh_param *rxfh)
446 {
447 struct aq_nic_s *aq_nic = netdev_priv(ndev);
448 struct aq_nic_cfg_s *cfg;
449 unsigned int i = 0U;
450
451 cfg = aq_nic_get_cfg(aq_nic);
452
453 rxfh->hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
454 if (rxfh->indir) {
455 for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
456 rxfh->indir[i] = cfg->aq_rss.indirection_table[i];
457 }
458 if (rxfh->key)
459 memcpy(rxfh->key, cfg->aq_rss.hash_secret_key,
460 sizeof(cfg->aq_rss.hash_secret_key));
461
462 return 0;
463 }
464
aq_ethtool_set_rss(struct net_device * netdev,struct ethtool_rxfh_param * rxfh,struct netlink_ext_ack * extack)465 static int aq_ethtool_set_rss(struct net_device *netdev,
466 struct ethtool_rxfh_param *rxfh,
467 struct netlink_ext_ack *extack)
468 {
469 struct aq_nic_s *aq_nic = netdev_priv(netdev);
470 struct aq_nic_cfg_s *cfg;
471 unsigned int i = 0U;
472 u32 rss_entries;
473 int err = 0;
474
475 cfg = aq_nic_get_cfg(aq_nic);
476 rss_entries = cfg->aq_rss.indirection_table_size;
477
478 /* We do not allow change in unsupported parameters */
479 if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
480 rxfh->hfunc != ETH_RSS_HASH_TOP)
481 return -EOPNOTSUPP;
482 /* Fill out the redirection table */
483 if (rxfh->indir)
484 for (i = 0; i < rss_entries; i++)
485 cfg->aq_rss.indirection_table[i] = rxfh->indir[i];
486
487 /* Fill out the rss hash key */
488 if (rxfh->key) {
489 memcpy(cfg->aq_rss.hash_secret_key, rxfh->key,
490 sizeof(cfg->aq_rss.hash_secret_key));
491 err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
492 &cfg->aq_rss);
493 if (err)
494 return err;
495 }
496
497 err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
498
499 return err;
500 }
501
aq_ethtool_get_rxnfc(struct net_device * ndev,struct ethtool_rxnfc * cmd,u32 * rule_locs)502 static int aq_ethtool_get_rxnfc(struct net_device *ndev,
503 struct ethtool_rxnfc *cmd,
504 u32 *rule_locs)
505 {
506 struct aq_nic_s *aq_nic = netdev_priv(ndev);
507 struct aq_nic_cfg_s *cfg;
508 int err = 0;
509
510 cfg = aq_nic_get_cfg(aq_nic);
511
512 switch (cmd->cmd) {
513 case ETHTOOL_GRXRINGS:
514 cmd->data = cfg->vecs;
515 break;
516 case ETHTOOL_GRXCLSRLCNT:
517 cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
518 break;
519 case ETHTOOL_GRXCLSRULE:
520 err = aq_get_rxnfc_rule(aq_nic, cmd);
521 break;
522 case ETHTOOL_GRXCLSRLALL:
523 err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
524 break;
525 default:
526 err = -EOPNOTSUPP;
527 break;
528 }
529
530 return err;
531 }
532
aq_ethtool_set_rxnfc(struct net_device * ndev,struct ethtool_rxnfc * cmd)533 static int aq_ethtool_set_rxnfc(struct net_device *ndev,
534 struct ethtool_rxnfc *cmd)
535 {
536 struct aq_nic_s *aq_nic = netdev_priv(ndev);
537 int err = 0;
538
539 switch (cmd->cmd) {
540 case ETHTOOL_SRXCLSRLINS:
541 err = aq_add_rxnfc_rule(aq_nic, cmd);
542 break;
543 case ETHTOOL_SRXCLSRLDEL:
544 err = aq_del_rxnfc_rule(aq_nic, cmd);
545 break;
546 default:
547 err = -EOPNOTSUPP;
548 break;
549 }
550
551 return err;
552 }
553
aq_ethtool_get_coalesce(struct net_device * ndev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)554 static int aq_ethtool_get_coalesce(struct net_device *ndev,
555 struct ethtool_coalesce *coal,
556 struct kernel_ethtool_coalesce *kernel_coal,
557 struct netlink_ext_ack *extack)
558 {
559 struct aq_nic_s *aq_nic = netdev_priv(ndev);
560 struct aq_nic_cfg_s *cfg;
561
562 cfg = aq_nic_get_cfg(aq_nic);
563
564 if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
565 cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
566 coal->rx_coalesce_usecs = cfg->rx_itr;
567 coal->tx_coalesce_usecs = cfg->tx_itr;
568 coal->rx_max_coalesced_frames = 0;
569 coal->tx_max_coalesced_frames = 0;
570 } else {
571 coal->rx_coalesce_usecs = 0;
572 coal->tx_coalesce_usecs = 0;
573 coal->rx_max_coalesced_frames = 1;
574 coal->tx_max_coalesced_frames = 1;
575 }
576
577 return 0;
578 }
579
aq_ethtool_set_coalesce(struct net_device * ndev,struct ethtool_coalesce * coal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)580 static int aq_ethtool_set_coalesce(struct net_device *ndev,
581 struct ethtool_coalesce *coal,
582 struct kernel_ethtool_coalesce *kernel_coal,
583 struct netlink_ext_ack *extack)
584 {
585 struct aq_nic_s *aq_nic = netdev_priv(ndev);
586 struct aq_nic_cfg_s *cfg;
587
588 cfg = aq_nic_get_cfg(aq_nic);
589
590 /* Atlantic only supports timing based coalescing
591 */
592 if (coal->rx_max_coalesced_frames > 1 ||
593 coal->tx_max_coalesced_frames > 1)
594 return -EOPNOTSUPP;
595
596 /* We do not support frame counting. Check this
597 */
598 if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
599 return -EOPNOTSUPP;
600 if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
601 return -EOPNOTSUPP;
602
603 if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
604 coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
605 return -EINVAL;
606
607 cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
608
609 cfg->rx_itr = coal->rx_coalesce_usecs;
610 cfg->tx_itr = coal->tx_coalesce_usecs;
611
612 return aq_nic_update_interrupt_moderation_settings(aq_nic);
613 }
614
aq_ethtool_get_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)615 static void aq_ethtool_get_wol(struct net_device *ndev,
616 struct ethtool_wolinfo *wol)
617 {
618 struct aq_nic_s *aq_nic = netdev_priv(ndev);
619 struct aq_nic_cfg_s *cfg;
620
621 cfg = aq_nic_get_cfg(aq_nic);
622
623 wol->supported = AQ_NIC_WOL_MODES;
624 wol->wolopts = cfg->wol;
625 }
626
aq_ethtool_set_wol(struct net_device * ndev,struct ethtool_wolinfo * wol)627 static int aq_ethtool_set_wol(struct net_device *ndev,
628 struct ethtool_wolinfo *wol)
629 {
630 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
631 struct aq_nic_s *aq_nic = netdev_priv(ndev);
632 struct aq_nic_cfg_s *cfg;
633 int err = 0;
634
635 cfg = aq_nic_get_cfg(aq_nic);
636
637 if (wol->wolopts & ~AQ_NIC_WOL_MODES)
638 return -EOPNOTSUPP;
639
640 cfg->wol = wol->wolopts;
641
642 err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);
643
644 return err;
645 }
646
aq_ethtool_get_ts_info(struct net_device * ndev,struct kernel_ethtool_ts_info * info)647 static int aq_ethtool_get_ts_info(struct net_device *ndev,
648 struct kernel_ethtool_ts_info *info)
649 {
650 struct aq_nic_s *aq_nic = netdev_priv(ndev);
651
652 ethtool_op_get_ts_info(ndev, info);
653
654 if (!aq_nic->aq_ptp)
655 return 0;
656
657 info->so_timestamping |=
658 SOF_TIMESTAMPING_TX_HARDWARE |
659 SOF_TIMESTAMPING_RX_HARDWARE |
660 SOF_TIMESTAMPING_RAW_HARDWARE;
661
662 info->tx_types = BIT(HWTSTAMP_TX_OFF) |
663 BIT(HWTSTAMP_TX_ON);
664
665 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
666
667 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
668 BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
669 BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
670
671 #if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
672 info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
673 #endif
674
675 return 0;
676 }
677
eee_mask_to_ethtool_mask(unsigned long * mode,u32 speed)678 static void eee_mask_to_ethtool_mask(unsigned long *mode, u32 speed)
679 {
680 if (speed & AQ_NIC_RATE_EEE_10G)
681 linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, mode);
682
683 if (speed & AQ_NIC_RATE_EEE_1G)
684 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, mode);
685
686 if (speed & AQ_NIC_RATE_EEE_100M)
687 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, mode);
688 }
689
aq_ethtool_get_eee(struct net_device * ndev,struct ethtool_keee * eee)690 static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_keee *eee)
691 {
692 struct aq_nic_s *aq_nic = netdev_priv(ndev);
693 u32 rate, supported_rates;
694 int err = 0;
695
696 if (!aq_nic->aq_fw_ops->get_eee_rate)
697 return -EOPNOTSUPP;
698
699 mutex_lock(&aq_nic->fwreq_mutex);
700 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
701 &supported_rates);
702 mutex_unlock(&aq_nic->fwreq_mutex);
703 if (err < 0)
704 return err;
705
706 eee_mask_to_ethtool_mask(eee->supported, supported_rates);
707
708 if (aq_nic->aq_nic_cfg.eee_speeds)
709 linkmode_copy(eee->advertised, eee->supported);
710
711 eee_mask_to_ethtool_mask(eee->lp_advertised, rate);
712
713 eee->eee_enabled = !linkmode_empty(eee->advertised);
714
715 eee->tx_lpi_enabled = eee->eee_enabled;
716 if ((supported_rates & rate) & AQ_NIC_RATE_EEE_MSK)
717 eee->eee_active = true;
718
719 return 0;
720 }
721
aq_ethtool_set_eee(struct net_device * ndev,struct ethtool_keee * eee)722 static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_keee *eee)
723 {
724 struct aq_nic_s *aq_nic = netdev_priv(ndev);
725 u32 rate, supported_rates;
726 struct aq_nic_cfg_s *cfg;
727 int err = 0;
728
729 cfg = aq_nic_get_cfg(aq_nic);
730
731 if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
732 !aq_nic->aq_fw_ops->set_eee_rate))
733 return -EOPNOTSUPP;
734
735 mutex_lock(&aq_nic->fwreq_mutex);
736 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
737 &supported_rates);
738 mutex_unlock(&aq_nic->fwreq_mutex);
739 if (err < 0)
740 return err;
741
742 if (eee->eee_enabled) {
743 rate = supported_rates;
744 cfg->eee_speeds = rate;
745 } else {
746 rate = 0;
747 cfg->eee_speeds = 0;
748 }
749
750 mutex_lock(&aq_nic->fwreq_mutex);
751 err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
752 mutex_unlock(&aq_nic->fwreq_mutex);
753
754 return err;
755 }
756
aq_ethtool_nway_reset(struct net_device * ndev)757 static int aq_ethtool_nway_reset(struct net_device *ndev)
758 {
759 struct aq_nic_s *aq_nic = netdev_priv(ndev);
760 int err = 0;
761
762 if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
763 return -EOPNOTSUPP;
764
765 if (netif_running(ndev)) {
766 mutex_lock(&aq_nic->fwreq_mutex);
767 err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
768 mutex_unlock(&aq_nic->fwreq_mutex);
769 }
770
771 return err;
772 }
773
aq_ethtool_get_pauseparam(struct net_device * ndev,struct ethtool_pauseparam * pause)774 static void aq_ethtool_get_pauseparam(struct net_device *ndev,
775 struct ethtool_pauseparam *pause)
776 {
777 struct aq_nic_s *aq_nic = netdev_priv(ndev);
778 int fc = aq_nic->aq_nic_cfg.fc.req;
779
780 pause->autoneg = 0;
781
782 pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
783 pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
784 }
785
aq_ethtool_set_pauseparam(struct net_device * ndev,struct ethtool_pauseparam * pause)786 static int aq_ethtool_set_pauseparam(struct net_device *ndev,
787 struct ethtool_pauseparam *pause)
788 {
789 struct aq_nic_s *aq_nic = netdev_priv(ndev);
790 int err = 0;
791
792 if (!aq_nic->aq_fw_ops->set_flow_control)
793 return -EOPNOTSUPP;
794
795 if (pause->autoneg == AUTONEG_ENABLE)
796 return -EOPNOTSUPP;
797
798 if (pause->rx_pause)
799 aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
800 else
801 aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
802
803 if (pause->tx_pause)
804 aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
805 else
806 aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
807
808 mutex_lock(&aq_nic->fwreq_mutex);
809 err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
810 mutex_unlock(&aq_nic->fwreq_mutex);
811
812 return err;
813 }
814
aq_get_ringparam(struct net_device * ndev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)815 static void aq_get_ringparam(struct net_device *ndev,
816 struct ethtool_ringparam *ring,
817 struct kernel_ethtool_ringparam *kernel_ring,
818 struct netlink_ext_ack *extack)
819 {
820 struct aq_nic_s *aq_nic = netdev_priv(ndev);
821 struct aq_nic_cfg_s *cfg;
822
823 cfg = aq_nic_get_cfg(aq_nic);
824
825 ring->rx_pending = cfg->rxds;
826 ring->tx_pending = cfg->txds;
827
828 ring->rx_max_pending = cfg->aq_hw_caps->rxds_max;
829 ring->tx_max_pending = cfg->aq_hw_caps->txds_max;
830 }
831
aq_set_ringparam(struct net_device * ndev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)832 static int aq_set_ringparam(struct net_device *ndev,
833 struct ethtool_ringparam *ring,
834 struct kernel_ethtool_ringparam *kernel_ring,
835 struct netlink_ext_ack *extack)
836 {
837 struct aq_nic_s *aq_nic = netdev_priv(ndev);
838 const struct aq_hw_caps_s *hw_caps;
839 bool ndev_running = false;
840 struct aq_nic_cfg_s *cfg;
841 int err = 0;
842
843 cfg = aq_nic_get_cfg(aq_nic);
844 hw_caps = cfg->aq_hw_caps;
845
846 if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
847 err = -EOPNOTSUPP;
848 goto err_exit;
849 }
850
851 if (netif_running(ndev)) {
852 ndev_running = true;
853 aq_ndev_close(ndev);
854 }
855
856 cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
857 cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
858 cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
859
860 cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
861 cfg->txds = min(cfg->txds, hw_caps->txds_max);
862 cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);
863
864 err = aq_nic_realloc_vectors(aq_nic);
865 if (err)
866 goto err_exit;
867
868 if (ndev_running)
869 err = aq_ndev_open(ndev);
870
871 err_exit:
872 return err;
873 }
874
aq_get_msg_level(struct net_device * ndev)875 static u32 aq_get_msg_level(struct net_device *ndev)
876 {
877 struct aq_nic_s *aq_nic = netdev_priv(ndev);
878
879 return aq_nic->msg_enable;
880 }
881
aq_set_msg_level(struct net_device * ndev,u32 data)882 static void aq_set_msg_level(struct net_device *ndev, u32 data)
883 {
884 struct aq_nic_s *aq_nic = netdev_priv(ndev);
885
886 aq_nic->msg_enable = data;
887 }
888
aq_ethtool_get_priv_flags(struct net_device * ndev)889 static u32 aq_ethtool_get_priv_flags(struct net_device *ndev)
890 {
891 struct aq_nic_s *aq_nic = netdev_priv(ndev);
892
893 return aq_nic->aq_nic_cfg.priv_flags;
894 }
895
aq_ethtool_set_priv_flags(struct net_device * ndev,u32 flags)896 static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
897 {
898 struct aq_nic_s *aq_nic = netdev_priv(ndev);
899 struct aq_nic_cfg_s *cfg;
900 u32 priv_flags;
901 int ret = 0;
902
903 cfg = aq_nic_get_cfg(aq_nic);
904 priv_flags = cfg->priv_flags;
905
906 if (flags & ~AQ_PRIV_FLAGS_MASK)
907 return -EOPNOTSUPP;
908
909 if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
910 netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
911 return -EINVAL;
912 }
913
914 cfg->priv_flags = flags;
915
916 if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
917 if (netif_running(ndev)) {
918 dev_close(ndev);
919
920 dev_open(ndev, NULL);
921 }
922 } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
923 ret = aq_nic_set_loopback(aq_nic);
924 }
925
926 return ret;
927 }
928
aq_ethtool_get_phy_tunable(struct net_device * ndev,const struct ethtool_tunable * tuna,void * data)929 static int aq_ethtool_get_phy_tunable(struct net_device *ndev,
930 const struct ethtool_tunable *tuna, void *data)
931 {
932 struct aq_nic_s *aq_nic = netdev_priv(ndev);
933
934 switch (tuna->id) {
935 case ETHTOOL_PHY_EDPD: {
936 u16 *val = data;
937
938 *val = aq_nic->aq_nic_cfg.is_media_detect ? AQ_HW_MEDIA_DETECT_CNT : 0;
939 break;
940 }
941 case ETHTOOL_PHY_DOWNSHIFT: {
942 u8 *val = data;
943
944 *val = (u8)aq_nic->aq_nic_cfg.downshift_counter;
945 break;
946 }
947 default:
948 return -EOPNOTSUPP;
949 }
950
951 return 0;
952 }
953
aq_ethtool_set_phy_tunable(struct net_device * ndev,const struct ethtool_tunable * tuna,const void * data)954 static int aq_ethtool_set_phy_tunable(struct net_device *ndev,
955 const struct ethtool_tunable *tuna, const void *data)
956 {
957 int err = -EOPNOTSUPP;
958 struct aq_nic_s *aq_nic = netdev_priv(ndev);
959
960 switch (tuna->id) {
961 case ETHTOOL_PHY_EDPD: {
962 const u16 *val = data;
963
964 err = aq_nic_set_media_detect(aq_nic, *val);
965 break;
966 }
967 case ETHTOOL_PHY_DOWNSHIFT: {
968 const u8 *val = data;
969
970 err = aq_nic_set_downshift(aq_nic, *val);
971 break;
972 }
973 default:
974 break;
975 }
976
977 return err;
978 }
979
980 const struct ethtool_ops aq_ethtool_ops = {
981 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
982 ETHTOOL_COALESCE_MAX_FRAMES,
983 .get_link = aq_ethtool_get_link,
984 .get_regs_len = aq_ethtool_get_regs_len,
985 .get_regs = aq_ethtool_get_regs,
986 .get_drvinfo = aq_ethtool_get_drvinfo,
987 .get_strings = aq_ethtool_get_strings,
988 .set_phys_id = aq_ethtool_set_phys_id,
989 .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
990 .get_wol = aq_ethtool_get_wol,
991 .set_wol = aq_ethtool_set_wol,
992 .nway_reset = aq_ethtool_nway_reset,
993 .get_ringparam = aq_get_ringparam,
994 .set_ringparam = aq_set_ringparam,
995 .get_eee = aq_ethtool_get_eee,
996 .set_eee = aq_ethtool_set_eee,
997 .get_pauseparam = aq_ethtool_get_pauseparam,
998 .set_pauseparam = aq_ethtool_set_pauseparam,
999 .get_rxfh_key_size = aq_ethtool_get_rss_key_size,
1000 .get_rxfh = aq_ethtool_get_rss,
1001 .set_rxfh = aq_ethtool_set_rss,
1002 .get_rxnfc = aq_ethtool_get_rxnfc,
1003 .set_rxnfc = aq_ethtool_set_rxnfc,
1004 .get_msglevel = aq_get_msg_level,
1005 .set_msglevel = aq_set_msg_level,
1006 .get_sset_count = aq_ethtool_get_sset_count,
1007 .get_ethtool_stats = aq_ethtool_stats,
1008 .get_priv_flags = aq_ethtool_get_priv_flags,
1009 .set_priv_flags = aq_ethtool_set_priv_flags,
1010 .get_link_ksettings = aq_ethtool_get_link_ksettings,
1011 .set_link_ksettings = aq_ethtool_set_link_ksettings,
1012 .get_coalesce = aq_ethtool_get_coalesce,
1013 .set_coalesce = aq_ethtool_set_coalesce,
1014 .get_ts_info = aq_ethtool_get_ts_info,
1015 .get_phy_tunable = aq_ethtool_get_phy_tunable,
1016 .set_phy_tunable = aq_ethtool_set_phy_tunable,
1017 };
1018