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