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