gpio: rcar: Fix runtime PM imbalance on error
[linux/fpc-iii.git] / drivers / net / ethernet / aquantia / atlantic / aq_ethtool.c
blob7241cf92b43a5f2da81af4ce7f062a1290699838
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * aQuantia Corporation Network Driver
4 * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
5 */
7 /* File aq_ethtool.c: Definition of ethertool related functions. */
9 #include "aq_ethtool.h"
10 #include "aq_nic.h"
11 #include "aq_vec.h"
12 #include "aq_ptp.h"
13 #include "aq_filters.h"
14 #include "aq_macsec.h"
16 #include <linux/ptp_clock_kernel.h>
18 static void aq_ethtool_get_regs(struct net_device *ndev,
19 struct ethtool_regs *regs, void *p)
21 struct aq_nic_s *aq_nic = netdev_priv(ndev);
22 u32 regs_count;
24 regs_count = aq_nic_get_regs_count(aq_nic);
26 memset(p, 0, regs_count * sizeof(u32));
27 aq_nic_get_regs(aq_nic, regs, p);
30 static int aq_ethtool_get_regs_len(struct net_device *ndev)
32 struct aq_nic_s *aq_nic = netdev_priv(ndev);
33 u32 regs_count;
35 regs_count = aq_nic_get_regs_count(aq_nic);
37 return regs_count * sizeof(u32);
40 static u32 aq_ethtool_get_link(struct net_device *ndev)
42 return ethtool_op_get_link(ndev);
45 static int aq_ethtool_get_link_ksettings(struct net_device *ndev,
46 struct ethtool_link_ksettings *cmd)
48 struct aq_nic_s *aq_nic = netdev_priv(ndev);
50 aq_nic_get_link_ksettings(aq_nic, cmd);
51 cmd->base.speed = netif_carrier_ok(ndev) ?
52 aq_nic_get_link_speed(aq_nic) : 0U;
54 return 0;
57 static int
58 aq_ethtool_set_link_ksettings(struct net_device *ndev,
59 const struct ethtool_link_ksettings *cmd)
61 struct aq_nic_s *aq_nic = netdev_priv(ndev);
63 return aq_nic_set_link_ksettings(aq_nic, cmd);
66 static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = {
67 "InPackets",
68 "InUCast",
69 "InMCast",
70 "InBCast",
71 "InErrors",
72 "OutPackets",
73 "OutUCast",
74 "OutMCast",
75 "OutBCast",
76 "InUCastOctets",
77 "OutUCastOctets",
78 "InMCastOctets",
79 "OutMCastOctets",
80 "InBCastOctets",
81 "OutBCastOctets",
82 "InOctets",
83 "OutOctets",
84 "InPacketsDma",
85 "OutPacketsDma",
86 "InOctetsDma",
87 "OutOctetsDma",
88 "InDroppedDma",
91 static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
92 "Queue[%d] InPackets",
93 "Queue[%d] OutPackets",
94 "Queue[%d] Restarts",
95 "Queue[%d] InJumboPackets",
96 "Queue[%d] InLroPackets",
97 "Queue[%d] InErrors",
100 #if IS_ENABLED(CONFIG_MACSEC)
101 static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
102 "MACSec InCtlPackets",
103 "MACSec InTaggedMissPackets",
104 "MACSec InUntaggedMissPackets",
105 "MACSec InNotagPackets",
106 "MACSec InUntaggedPackets",
107 "MACSec InBadTagPackets",
108 "MACSec InNoSciPackets",
109 "MACSec InUnknownSciPackets",
110 "MACSec InCtrlPortPassPackets",
111 "MACSec InUnctrlPortPassPackets",
112 "MACSec InCtrlPortFailPackets",
113 "MACSec InUnctrlPortFailPackets",
114 "MACSec InTooLongPackets",
115 "MACSec InIgpocCtlPackets",
116 "MACSec InEccErrorPackets",
117 "MACSec InUnctrlHitDropRedir",
118 "MACSec OutCtlPackets",
119 "MACSec OutUnknownSaPackets",
120 "MACSec OutUntaggedPackets",
121 "MACSec OutTooLong",
122 "MACSec OutEccErrorPackets",
123 "MACSec OutUnctrlHitDropRedir",
126 static const char *aq_macsec_txsc_stat_names[] = {
127 "MACSecTXSC%d ProtectedPkts",
128 "MACSecTXSC%d EncryptedPkts",
129 "MACSecTXSC%d ProtectedOctets",
130 "MACSecTXSC%d EncryptedOctets",
133 static const char *aq_macsec_txsa_stat_names[] = {
134 "MACSecTXSC%dSA%d HitDropRedirect",
135 "MACSecTXSC%dSA%d Protected2Pkts",
136 "MACSecTXSC%dSA%d ProtectedPkts",
137 "MACSecTXSC%dSA%d EncryptedPkts",
140 static const char *aq_macsec_rxsa_stat_names[] = {
141 "MACSecRXSC%dSA%d UntaggedHitPkts",
142 "MACSecRXSC%dSA%d CtrlHitDrpRedir",
143 "MACSecRXSC%dSA%d NotUsingSa",
144 "MACSecRXSC%dSA%d UnusedSa",
145 "MACSecRXSC%dSA%d NotValidPkts",
146 "MACSecRXSC%dSA%d InvalidPkts",
147 "MACSecRXSC%dSA%d OkPkts",
148 "MACSecRXSC%dSA%d LatePkts",
149 "MACSecRXSC%dSA%d DelayedPkts",
150 "MACSecRXSC%dSA%d UncheckedPkts",
151 "MACSecRXSC%dSA%d ValidatedOctets",
152 "MACSecRXSC%dSA%d DecryptedOctets",
154 #endif
156 static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
157 "DMASystemLoopback",
158 "PKTSystemLoopback",
159 "DMANetworkLoopback",
160 "PHYInternalLoopback",
161 "PHYExternalLoopback",
164 static u32 aq_ethtool_n_stats(struct net_device *ndev)
166 struct aq_nic_s *nic = netdev_priv(ndev);
167 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
168 u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
169 ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs;
171 #if IS_ENABLED(CONFIG_MACSEC)
172 if (nic->macsec_cfg) {
173 n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
174 ARRAY_SIZE(aq_macsec_txsc_stat_names) *
175 aq_macsec_tx_sc_cnt(nic) +
176 ARRAY_SIZE(aq_macsec_txsa_stat_names) *
177 aq_macsec_tx_sa_cnt(nic) +
178 ARRAY_SIZE(aq_macsec_rxsa_stat_names) *
179 aq_macsec_rx_sa_cnt(nic);
181 #endif
183 return n_stats;
186 static void aq_ethtool_stats(struct net_device *ndev,
187 struct ethtool_stats *stats, u64 *data)
189 struct aq_nic_s *aq_nic = netdev_priv(ndev);
191 memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
192 data = aq_nic_get_stats(aq_nic, data);
193 #if IS_ENABLED(CONFIG_MACSEC)
194 data = aq_macsec_get_stats(aq_nic, data);
195 #endif
198 static void aq_ethtool_get_drvinfo(struct net_device *ndev,
199 struct ethtool_drvinfo *drvinfo)
201 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
202 struct aq_nic_s *aq_nic = netdev_priv(ndev);
203 u32 firmware_version;
204 u32 regs_count;
206 firmware_version = aq_nic_get_fw_version(aq_nic);
207 regs_count = aq_nic_get_regs_count(aq_nic);
209 strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver));
211 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
212 "%u.%u.%u", firmware_version >> 24,
213 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
215 strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
216 sizeof(drvinfo->bus_info));
217 drvinfo->n_stats = aq_ethtool_n_stats(ndev);
218 drvinfo->testinfo_len = 0;
219 drvinfo->regdump_len = regs_count;
220 drvinfo->eedump_len = 0;
223 static void aq_ethtool_get_strings(struct net_device *ndev,
224 u32 stringset, u8 *data)
226 struct aq_nic_s *aq_nic = netdev_priv(ndev);
227 struct aq_nic_cfg_s *cfg;
228 u8 *p = data;
229 int i, si;
230 #if IS_ENABLED(CONFIG_MACSEC)
231 int sa;
232 #endif
234 cfg = aq_nic_get_cfg(aq_nic);
236 switch (stringset) {
237 case ETH_SS_STATS:
238 memcpy(p, aq_ethtool_stat_names,
239 sizeof(aq_ethtool_stat_names));
240 p = p + sizeof(aq_ethtool_stat_names);
241 for (i = 0; i < cfg->vecs; i++) {
242 for (si = 0;
243 si < ARRAY_SIZE(aq_ethtool_queue_stat_names);
244 si++) {
245 snprintf(p, ETH_GSTRING_LEN,
246 aq_ethtool_queue_stat_names[si], i);
247 p += ETH_GSTRING_LEN;
250 #if IS_ENABLED(CONFIG_MACSEC)
251 if (!aq_nic->macsec_cfg)
252 break;
254 memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
255 p = p + sizeof(aq_macsec_stat_names);
256 for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
257 struct aq_macsec_txsc *aq_txsc;
259 if (!(test_bit(i, &aq_nic->macsec_cfg->txsc_idx_busy)))
260 continue;
262 for (si = 0;
263 si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
264 si++) {
265 snprintf(p, ETH_GSTRING_LEN,
266 aq_macsec_txsc_stat_names[si], i);
267 p += ETH_GSTRING_LEN;
269 aq_txsc = &aq_nic->macsec_cfg->aq_txsc[i];
270 for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
271 if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
272 continue;
273 for (si = 0;
274 si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
275 si++) {
276 snprintf(p, ETH_GSTRING_LEN,
277 aq_macsec_txsa_stat_names[si],
278 i, sa);
279 p += ETH_GSTRING_LEN;
283 for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
284 struct aq_macsec_rxsc *aq_rxsc;
286 if (!(test_bit(i, &aq_nic->macsec_cfg->rxsc_idx_busy)))
287 continue;
289 aq_rxsc = &aq_nic->macsec_cfg->aq_rxsc[i];
290 for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
291 if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
292 continue;
293 for (si = 0;
294 si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
295 si++) {
296 snprintf(p, ETH_GSTRING_LEN,
297 aq_macsec_rxsa_stat_names[si],
298 i, sa);
299 p += ETH_GSTRING_LEN;
303 #endif
304 break;
305 case ETH_SS_PRIV_FLAGS:
306 memcpy(p, aq_ethtool_priv_flag_names,
307 sizeof(aq_ethtool_priv_flag_names));
308 break;
312 static int aq_ethtool_set_phys_id(struct net_device *ndev,
313 enum ethtool_phys_id_state state)
315 struct aq_nic_s *aq_nic = netdev_priv(ndev);
316 struct aq_hw_s *hw = aq_nic->aq_hw;
317 int ret = 0;
319 if (!aq_nic->aq_fw_ops->led_control)
320 return -EOPNOTSUPP;
322 mutex_lock(&aq_nic->fwreq_mutex);
324 switch (state) {
325 case ETHTOOL_ID_ACTIVE:
326 ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK |
327 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4);
328 break;
329 case ETHTOOL_ID_INACTIVE:
330 ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT);
331 break;
332 default:
333 break;
336 mutex_unlock(&aq_nic->fwreq_mutex);
338 return ret;
341 static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
343 int ret = 0;
345 switch (stringset) {
346 case ETH_SS_STATS:
347 ret = aq_ethtool_n_stats(ndev);
348 break;
349 case ETH_SS_PRIV_FLAGS:
350 ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
351 break;
352 default:
353 ret = -EOPNOTSUPP;
356 return ret;
359 static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev)
361 return AQ_CFG_RSS_INDIRECTION_TABLE_MAX;
364 static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev)
366 struct aq_nic_s *aq_nic = netdev_priv(ndev);
367 struct aq_nic_cfg_s *cfg;
369 cfg = aq_nic_get_cfg(aq_nic);
371 return sizeof(cfg->aq_rss.hash_secret_key);
374 static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key,
375 u8 *hfunc)
377 struct aq_nic_s *aq_nic = netdev_priv(ndev);
378 struct aq_nic_cfg_s *cfg;
379 unsigned int i = 0U;
381 cfg = aq_nic_get_cfg(aq_nic);
383 if (hfunc)
384 *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
385 if (indir) {
386 for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++)
387 indir[i] = cfg->aq_rss.indirection_table[i];
389 if (key)
390 memcpy(key, cfg->aq_rss.hash_secret_key,
391 sizeof(cfg->aq_rss.hash_secret_key));
393 return 0;
396 static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir,
397 const u8 *key, const u8 hfunc)
399 struct aq_nic_s *aq_nic = netdev_priv(netdev);
400 struct aq_nic_cfg_s *cfg;
401 unsigned int i = 0U;
402 u32 rss_entries;
403 int err = 0;
405 cfg = aq_nic_get_cfg(aq_nic);
406 rss_entries = cfg->aq_rss.indirection_table_size;
408 /* We do not allow change in unsupported parameters */
409 if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
410 return -EOPNOTSUPP;
411 /* Fill out the redirection table */
412 if (indir)
413 for (i = 0; i < rss_entries; i++)
414 cfg->aq_rss.indirection_table[i] = indir[i];
416 /* Fill out the rss hash key */
417 if (key) {
418 memcpy(cfg->aq_rss.hash_secret_key, key,
419 sizeof(cfg->aq_rss.hash_secret_key));
420 err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw,
421 &cfg->aq_rss);
422 if (err)
423 return err;
426 err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss);
428 return err;
431 static int aq_ethtool_get_rxnfc(struct net_device *ndev,
432 struct ethtool_rxnfc *cmd,
433 u32 *rule_locs)
435 struct aq_nic_s *aq_nic = netdev_priv(ndev);
436 struct aq_nic_cfg_s *cfg;
437 int err = 0;
439 cfg = aq_nic_get_cfg(aq_nic);
441 switch (cmd->cmd) {
442 case ETHTOOL_GRXRINGS:
443 cmd->data = cfg->vecs;
444 break;
445 case ETHTOOL_GRXCLSRLCNT:
446 cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic);
447 break;
448 case ETHTOOL_GRXCLSRULE:
449 err = aq_get_rxnfc_rule(aq_nic, cmd);
450 break;
451 case ETHTOOL_GRXCLSRLALL:
452 err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs);
453 break;
454 default:
455 err = -EOPNOTSUPP;
456 break;
459 return err;
462 static int aq_ethtool_set_rxnfc(struct net_device *ndev,
463 struct ethtool_rxnfc *cmd)
465 struct aq_nic_s *aq_nic = netdev_priv(ndev);
466 int err = 0;
468 switch (cmd->cmd) {
469 case ETHTOOL_SRXCLSRLINS:
470 err = aq_add_rxnfc_rule(aq_nic, cmd);
471 break;
472 case ETHTOOL_SRXCLSRLDEL:
473 err = aq_del_rxnfc_rule(aq_nic, cmd);
474 break;
475 default:
476 err = -EOPNOTSUPP;
477 break;
480 return err;
483 static int aq_ethtool_get_coalesce(struct net_device *ndev,
484 struct ethtool_coalesce *coal)
486 struct aq_nic_s *aq_nic = netdev_priv(ndev);
487 struct aq_nic_cfg_s *cfg;
489 cfg = aq_nic_get_cfg(aq_nic);
491 if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON ||
492 cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) {
493 coal->rx_coalesce_usecs = cfg->rx_itr;
494 coal->tx_coalesce_usecs = cfg->tx_itr;
495 coal->rx_max_coalesced_frames = 0;
496 coal->tx_max_coalesced_frames = 0;
497 } else {
498 coal->rx_coalesce_usecs = 0;
499 coal->tx_coalesce_usecs = 0;
500 coal->rx_max_coalesced_frames = 1;
501 coal->tx_max_coalesced_frames = 1;
504 return 0;
507 static int aq_ethtool_set_coalesce(struct net_device *ndev,
508 struct ethtool_coalesce *coal)
510 struct aq_nic_s *aq_nic = netdev_priv(ndev);
511 struct aq_nic_cfg_s *cfg;
513 cfg = aq_nic_get_cfg(aq_nic);
515 /* Atlantic only supports timing based coalescing
517 if (coal->rx_max_coalesced_frames > 1 ||
518 coal->tx_max_coalesced_frames > 1)
519 return -EOPNOTSUPP;
521 /* We do not support frame counting. Check this
523 if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs))
524 return -EOPNOTSUPP;
525 if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs))
526 return -EOPNOTSUPP;
528 if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX ||
529 coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX)
530 return -EINVAL;
532 cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON;
534 cfg->rx_itr = coal->rx_coalesce_usecs;
535 cfg->tx_itr = coal->tx_coalesce_usecs;
537 return aq_nic_update_interrupt_moderation_settings(aq_nic);
540 static void aq_ethtool_get_wol(struct net_device *ndev,
541 struct ethtool_wolinfo *wol)
543 struct aq_nic_s *aq_nic = netdev_priv(ndev);
544 struct aq_nic_cfg_s *cfg;
546 cfg = aq_nic_get_cfg(aq_nic);
548 wol->supported = AQ_NIC_WOL_MODES;
549 wol->wolopts = cfg->wol;
552 static int aq_ethtool_set_wol(struct net_device *ndev,
553 struct ethtool_wolinfo *wol)
555 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
556 struct aq_nic_s *aq_nic = netdev_priv(ndev);
557 struct aq_nic_cfg_s *cfg;
558 int err = 0;
560 cfg = aq_nic_get_cfg(aq_nic);
562 if (wol->wolopts & ~AQ_NIC_WOL_MODES)
563 return -EOPNOTSUPP;
565 cfg->wol = wol->wolopts;
567 err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol);
569 return err;
572 static int aq_ethtool_get_ts_info(struct net_device *ndev,
573 struct ethtool_ts_info *info)
575 struct aq_nic_s *aq_nic = netdev_priv(ndev);
577 ethtool_op_get_ts_info(ndev, info);
579 if (!aq_nic->aq_ptp)
580 return 0;
582 info->so_timestamping |=
583 SOF_TIMESTAMPING_TX_HARDWARE |
584 SOF_TIMESTAMPING_RX_HARDWARE |
585 SOF_TIMESTAMPING_RAW_HARDWARE;
587 info->tx_types = BIT(HWTSTAMP_TX_OFF) |
588 BIT(HWTSTAMP_TX_ON);
590 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
592 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
593 BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
594 BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
596 info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp));
598 return 0;
601 static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed)
603 u32 rate = 0;
605 if (speed & AQ_NIC_RATE_EEE_10G)
606 rate |= SUPPORTED_10000baseT_Full;
608 if (speed & AQ_NIC_RATE_EEE_2GS)
609 rate |= SUPPORTED_2500baseX_Full;
611 if (speed & AQ_NIC_RATE_EEE_1G)
612 rate |= SUPPORTED_1000baseT_Full;
614 return rate;
617 static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee)
619 struct aq_nic_s *aq_nic = netdev_priv(ndev);
620 u32 rate, supported_rates;
621 int err = 0;
623 if (!aq_nic->aq_fw_ops->get_eee_rate)
624 return -EOPNOTSUPP;
626 mutex_lock(&aq_nic->fwreq_mutex);
627 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
628 &supported_rates);
629 mutex_unlock(&aq_nic->fwreq_mutex);
630 if (err < 0)
631 return err;
633 eee->supported = eee_mask_to_ethtool_mask(supported_rates);
635 if (aq_nic->aq_nic_cfg.eee_speeds)
636 eee->advertised = eee->supported;
638 eee->lp_advertised = eee_mask_to_ethtool_mask(rate);
640 eee->eee_enabled = !!eee->advertised;
642 eee->tx_lpi_enabled = eee->eee_enabled;
643 if (eee->advertised & eee->lp_advertised)
644 eee->eee_active = true;
646 return 0;
649 static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee)
651 struct aq_nic_s *aq_nic = netdev_priv(ndev);
652 u32 rate, supported_rates;
653 struct aq_nic_cfg_s *cfg;
654 int err = 0;
656 cfg = aq_nic_get_cfg(aq_nic);
658 if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate ||
659 !aq_nic->aq_fw_ops->set_eee_rate))
660 return -EOPNOTSUPP;
662 mutex_lock(&aq_nic->fwreq_mutex);
663 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate,
664 &supported_rates);
665 mutex_unlock(&aq_nic->fwreq_mutex);
666 if (err < 0)
667 return err;
669 if (eee->eee_enabled) {
670 rate = supported_rates;
671 cfg->eee_speeds = rate;
672 } else {
673 rate = 0;
674 cfg->eee_speeds = 0;
677 mutex_lock(&aq_nic->fwreq_mutex);
678 err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate);
679 mutex_unlock(&aq_nic->fwreq_mutex);
681 return err;
684 static int aq_ethtool_nway_reset(struct net_device *ndev)
686 struct aq_nic_s *aq_nic = netdev_priv(ndev);
687 int err = 0;
689 if (unlikely(!aq_nic->aq_fw_ops->renegotiate))
690 return -EOPNOTSUPP;
692 if (netif_running(ndev)) {
693 mutex_lock(&aq_nic->fwreq_mutex);
694 err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw);
695 mutex_unlock(&aq_nic->fwreq_mutex);
698 return err;
701 static void aq_ethtool_get_pauseparam(struct net_device *ndev,
702 struct ethtool_pauseparam *pause)
704 struct aq_nic_s *aq_nic = netdev_priv(ndev);
705 u32 fc = aq_nic->aq_nic_cfg.fc.req;
707 pause->autoneg = 0;
709 pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
710 pause->tx_pause = !!(fc & AQ_NIC_FC_TX);
714 static int aq_ethtool_set_pauseparam(struct net_device *ndev,
715 struct ethtool_pauseparam *pause)
717 struct aq_nic_s *aq_nic = netdev_priv(ndev);
718 int err = 0;
720 if (!aq_nic->aq_fw_ops->set_flow_control)
721 return -EOPNOTSUPP;
723 if (pause->autoneg == AUTONEG_ENABLE)
724 return -EOPNOTSUPP;
726 if (pause->rx_pause)
727 aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
728 else
729 aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
731 if (pause->tx_pause)
732 aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
733 else
734 aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
736 mutex_lock(&aq_nic->fwreq_mutex);
737 err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
738 mutex_unlock(&aq_nic->fwreq_mutex);
740 return err;
743 static void aq_get_ringparam(struct net_device *ndev,
744 struct ethtool_ringparam *ring)
746 struct aq_nic_s *aq_nic = netdev_priv(ndev);
747 struct aq_nic_cfg_s *cfg;
749 cfg = aq_nic_get_cfg(aq_nic);
751 ring->rx_pending = cfg->rxds;
752 ring->tx_pending = cfg->txds;
754 ring->rx_max_pending = cfg->aq_hw_caps->rxds_max;
755 ring->tx_max_pending = cfg->aq_hw_caps->txds_max;
758 static int aq_set_ringparam(struct net_device *ndev,
759 struct ethtool_ringparam *ring)
761 struct aq_nic_s *aq_nic = netdev_priv(ndev);
762 const struct aq_hw_caps_s *hw_caps;
763 bool ndev_running = false;
764 struct aq_nic_cfg_s *cfg;
765 int err = 0;
767 cfg = aq_nic_get_cfg(aq_nic);
768 hw_caps = cfg->aq_hw_caps;
770 if (ring->rx_mini_pending || ring->rx_jumbo_pending) {
771 err = -EOPNOTSUPP;
772 goto err_exit;
775 if (netif_running(ndev)) {
776 ndev_running = true;
777 dev_close(ndev);
780 aq_nic_free_vectors(aq_nic);
782 cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min);
783 cfg->rxds = min(cfg->rxds, hw_caps->rxds_max);
784 cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE);
786 cfg->txds = max(ring->tx_pending, hw_caps->txds_min);
787 cfg->txds = min(cfg->txds, hw_caps->txds_max);
788 cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE);
790 for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < cfg->vecs;
791 aq_nic->aq_vecs++) {
792 aq_nic->aq_vec[aq_nic->aq_vecs] =
793 aq_vec_alloc(aq_nic, aq_nic->aq_vecs, cfg);
794 if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) {
795 err = -ENOMEM;
796 goto err_exit;
799 if (ndev_running)
800 err = dev_open(ndev, NULL);
802 err_exit:
803 return err;
806 static u32 aq_get_msg_level(struct net_device *ndev)
808 struct aq_nic_s *aq_nic = netdev_priv(ndev);
810 return aq_nic->msg_enable;
813 static void aq_set_msg_level(struct net_device *ndev, u32 data)
815 struct aq_nic_s *aq_nic = netdev_priv(ndev);
817 aq_nic->msg_enable = data;
820 static u32 aq_ethtool_get_priv_flags(struct net_device *ndev)
822 struct aq_nic_s *aq_nic = netdev_priv(ndev);
824 return aq_nic->aq_nic_cfg.priv_flags;
827 static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
829 struct aq_nic_s *aq_nic = netdev_priv(ndev);
830 struct aq_nic_cfg_s *cfg;
831 u32 priv_flags;
833 cfg = aq_nic_get_cfg(aq_nic);
834 priv_flags = cfg->priv_flags;
836 if (flags & ~AQ_PRIV_FLAGS_MASK)
837 return -EOPNOTSUPP;
839 if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
840 netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
841 return -EINVAL;
844 cfg->priv_flags = flags;
846 if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
847 if (netif_running(ndev)) {
848 dev_close(ndev);
850 dev_open(ndev, NULL);
852 } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) {
853 aq_nic_set_loopback(aq_nic);
856 return 0;
859 const struct ethtool_ops aq_ethtool_ops = {
860 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
861 ETHTOOL_COALESCE_MAX_FRAMES,
862 .get_link = aq_ethtool_get_link,
863 .get_regs_len = aq_ethtool_get_regs_len,
864 .get_regs = aq_ethtool_get_regs,
865 .get_drvinfo = aq_ethtool_get_drvinfo,
866 .get_strings = aq_ethtool_get_strings,
867 .set_phys_id = aq_ethtool_set_phys_id,
868 .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size,
869 .get_wol = aq_ethtool_get_wol,
870 .set_wol = aq_ethtool_set_wol,
871 .nway_reset = aq_ethtool_nway_reset,
872 .get_ringparam = aq_get_ringparam,
873 .set_ringparam = aq_set_ringparam,
874 .get_eee = aq_ethtool_get_eee,
875 .set_eee = aq_ethtool_set_eee,
876 .get_pauseparam = aq_ethtool_get_pauseparam,
877 .set_pauseparam = aq_ethtool_set_pauseparam,
878 .get_rxfh_key_size = aq_ethtool_get_rss_key_size,
879 .get_rxfh = aq_ethtool_get_rss,
880 .set_rxfh = aq_ethtool_set_rss,
881 .get_rxnfc = aq_ethtool_get_rxnfc,
882 .set_rxnfc = aq_ethtool_set_rxnfc,
883 .get_msglevel = aq_get_msg_level,
884 .set_msglevel = aq_set_msg_level,
885 .get_sset_count = aq_ethtool_get_sset_count,
886 .get_ethtool_stats = aq_ethtool_stats,
887 .get_priv_flags = aq_ethtool_get_priv_flags,
888 .set_priv_flags = aq_ethtool_set_priv_flags,
889 .get_link_ksettings = aq_ethtool_get_link_ksettings,
890 .set_link_ksettings = aq_ethtool_set_link_ksettings,
891 .get_coalesce = aq_ethtool_get_coalesce,
892 .set_coalesce = aq_ethtool_set_coalesce,
893 .get_ts_info = aq_ethtool_get_ts_info,