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