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 */ 6 7 /* File aq_ethtool.c: Definition of ethertool related functions. */ 8 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 15 #include <linux/ptp_clock_kernel.h> 16 17 static void aq_ethtool_get_regs(struct net_device *ndev, 18 struct ethtool_regs *regs, void *p) 19 { 20 struct aq_nic_s *aq_nic = netdev_priv(ndev); 21 u32 regs_count; 22 23 regs_count = aq_nic_get_regs_count(aq_nic); 24 25 memset(p, 0, regs_count * sizeof(u32)); 26 aq_nic_get_regs(aq_nic, regs, p); 27 } 28 29 static int aq_ethtool_get_regs_len(struct net_device *ndev) 30 { 31 struct aq_nic_s *aq_nic = netdev_priv(ndev); 32 u32 regs_count; 33 34 regs_count = aq_nic_get_regs_count(aq_nic); 35 36 return regs_count * sizeof(u32); 37 } 38 39 static u32 aq_ethtool_get_link(struct net_device *ndev) 40 { 41 return ethtool_op_get_link(ndev); 42 } 43 44 static int aq_ethtool_get_link_ksettings(struct net_device *ndev, 45 struct ethtool_link_ksettings *cmd) 46 { 47 struct aq_nic_s *aq_nic = netdev_priv(ndev); 48 49 aq_nic_get_link_ksettings(aq_nic, cmd); 50 cmd->base.speed = netif_carrier_ok(ndev) ? 51 aq_nic_get_link_speed(aq_nic) : 0U; 52 53 return 0; 54 } 55 56 static int 57 aq_ethtool_set_link_ksettings(struct net_device *ndev, 58 const struct ethtool_link_ksettings *cmd) 59 { 60 struct aq_nic_s *aq_nic = netdev_priv(ndev); 61 62 return aq_nic_set_link_ksettings(aq_nic, cmd); 63 } 64 65 static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { 66 "InPackets", 67 "InUCast", 68 "InMCast", 69 "InBCast", 70 "InErrors", 71 "OutPackets", 72 "OutUCast", 73 "OutMCast", 74 "OutBCast", 75 "InUCastOctets", 76 "OutUCastOctets", 77 "InMCastOctets", 78 "OutMCastOctets", 79 "InBCastOctets", 80 "OutBCastOctets", 81 "InOctets", 82 "OutOctets", 83 "InPacketsDma", 84 "OutPacketsDma", 85 "InOctetsDma", 86 "OutOctetsDma", 87 "InDroppedDma", 88 }; 89 90 static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { 91 "Queue[%d] InPackets", 92 "Queue[%d] OutPackets", 93 "Queue[%d] Restarts", 94 "Queue[%d] InJumboPackets", 95 "Queue[%d] InLroPackets", 96 "Queue[%d] InErrors", 97 }; 98 99 static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { 100 "DMASystemLoopback", 101 "PKTSystemLoopback", 102 "DMANetworkLoopback", 103 "PHYInternalLoopback", 104 "PHYExternalLoopback", 105 }; 106 107 static void aq_ethtool_stats(struct net_device *ndev, 108 struct ethtool_stats *stats, u64 *data) 109 { 110 struct aq_nic_s *aq_nic = netdev_priv(ndev); 111 struct aq_nic_cfg_s *cfg; 112 113 cfg = aq_nic_get_cfg(aq_nic); 114 115 memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) + 116 ARRAY_SIZE(aq_ethtool_queue_stat_names) * 117 cfg->vecs) * sizeof(u64)); 118 aq_nic_get_stats(aq_nic, data); 119 } 120 121 static void aq_ethtool_get_drvinfo(struct net_device *ndev, 122 struct ethtool_drvinfo *drvinfo) 123 { 124 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); 125 struct aq_nic_s *aq_nic = netdev_priv(ndev); 126 struct aq_nic_cfg_s *cfg; 127 u32 firmware_version; 128 u32 regs_count; 129 130 cfg = aq_nic_get_cfg(aq_nic); 131 firmware_version = aq_nic_get_fw_version(aq_nic); 132 regs_count = aq_nic_get_regs_count(aq_nic); 133 134 strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver)); 135 136 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 137 "%u.%u.%u", firmware_version >> 24, 138 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU); 139 140 strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "", 141 sizeof(drvinfo->bus_info)); 142 drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + 143 cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); 144 drvinfo->testinfo_len = 0; 145 drvinfo->regdump_len = regs_count; 146 drvinfo->eedump_len = 0; 147 } 148 149 static void aq_ethtool_get_strings(struct net_device *ndev, 150 u32 stringset, u8 *data) 151 { 152 struct aq_nic_s *aq_nic = netdev_priv(ndev); 153 struct aq_nic_cfg_s *cfg; 154 u8 *p = data; 155 int i, si; 156 157 cfg = aq_nic_get_cfg(aq_nic); 158 159 switch (stringset) { 160 case ETH_SS_STATS: 161 memcpy(p, aq_ethtool_stat_names, 162 sizeof(aq_ethtool_stat_names)); 163 p = p + sizeof(aq_ethtool_stat_names); 164 for (i = 0; i < cfg->vecs; i++) { 165 for (si = 0; 166 si < ARRAY_SIZE(aq_ethtool_queue_stat_names); 167 si++) { 168 snprintf(p, ETH_GSTRING_LEN, 169 aq_ethtool_queue_stat_names[si], i); 170 p += ETH_GSTRING_LEN; 171 } 172 } 173 break; 174 case ETH_SS_PRIV_FLAGS: 175 memcpy(p, aq_ethtool_priv_flag_names, 176 sizeof(aq_ethtool_priv_flag_names)); 177 break; 178 } 179 } 180 181 static int aq_ethtool_set_phys_id(struct net_device *ndev, 182 enum ethtool_phys_id_state state) 183 { 184 struct aq_nic_s *aq_nic = netdev_priv(ndev); 185 struct aq_hw_s *hw = aq_nic->aq_hw; 186 int ret = 0; 187 188 if (!aq_nic->aq_fw_ops->led_control) 189 return -EOPNOTSUPP; 190 191 mutex_lock(&aq_nic->fwreq_mutex); 192 193 switch (state) { 194 case ETHTOOL_ID_ACTIVE: 195 ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_BLINK | 196 AQ_HW_LED_BLINK << 2 | AQ_HW_LED_BLINK << 4); 197 break; 198 case ETHTOOL_ID_INACTIVE: 199 ret = aq_nic->aq_fw_ops->led_control(hw, AQ_HW_LED_DEFAULT); 200 break; 201 default: 202 break; 203 } 204 205 mutex_unlock(&aq_nic->fwreq_mutex); 206 207 return ret; 208 } 209 210 static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) 211 { 212 struct aq_nic_s *aq_nic = netdev_priv(ndev); 213 struct aq_nic_cfg_s *cfg; 214 int ret = 0; 215 216 cfg = aq_nic_get_cfg(aq_nic); 217 218 switch (stringset) { 219 case ETH_SS_STATS: 220 ret = ARRAY_SIZE(aq_ethtool_stat_names) + 221 cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); 222 break; 223 case ETH_SS_PRIV_FLAGS: 224 ret = ARRAY_SIZE(aq_ethtool_priv_flag_names); 225 break; 226 default: 227 ret = -EOPNOTSUPP; 228 } 229 230 return ret; 231 } 232 233 static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev) 234 { 235 return AQ_CFG_RSS_INDIRECTION_TABLE_MAX; 236 } 237 238 static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev) 239 { 240 struct aq_nic_s *aq_nic = netdev_priv(ndev); 241 struct aq_nic_cfg_s *cfg; 242 243 cfg = aq_nic_get_cfg(aq_nic); 244 245 return sizeof(cfg->aq_rss.hash_secret_key); 246 } 247 248 static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key, 249 u8 *hfunc) 250 { 251 struct aq_nic_s *aq_nic = netdev_priv(ndev); 252 struct aq_nic_cfg_s *cfg; 253 unsigned int i = 0U; 254 255 cfg = aq_nic_get_cfg(aq_nic); 256 257 if (hfunc) 258 *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */ 259 if (indir) { 260 for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++) 261 indir[i] = cfg->aq_rss.indirection_table[i]; 262 } 263 if (key) 264 memcpy(key, cfg->aq_rss.hash_secret_key, 265 sizeof(cfg->aq_rss.hash_secret_key)); 266 267 return 0; 268 } 269 270 static int aq_ethtool_set_rss(struct net_device *netdev, const u32 *indir, 271 const u8 *key, const u8 hfunc) 272 { 273 struct aq_nic_s *aq_nic = netdev_priv(netdev); 274 struct aq_nic_cfg_s *cfg; 275 unsigned int i = 0U; 276 u32 rss_entries; 277 int err = 0; 278 279 cfg = aq_nic_get_cfg(aq_nic); 280 rss_entries = cfg->aq_rss.indirection_table_size; 281 282 /* We do not allow change in unsupported parameters */ 283 if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 284 return -EOPNOTSUPP; 285 /* Fill out the redirection table */ 286 if (indir) 287 for (i = 0; i < rss_entries; i++) 288 cfg->aq_rss.indirection_table[i] = indir[i]; 289 290 /* Fill out the rss hash key */ 291 if (key) { 292 memcpy(cfg->aq_rss.hash_secret_key, key, 293 sizeof(cfg->aq_rss.hash_secret_key)); 294 err = aq_nic->aq_hw_ops->hw_rss_hash_set(aq_nic->aq_hw, 295 &cfg->aq_rss); 296 if (err) 297 return err; 298 } 299 300 err = aq_nic->aq_hw_ops->hw_rss_set(aq_nic->aq_hw, &cfg->aq_rss); 301 302 return err; 303 } 304 305 static int aq_ethtool_get_rxnfc(struct net_device *ndev, 306 struct ethtool_rxnfc *cmd, 307 u32 *rule_locs) 308 { 309 struct aq_nic_s *aq_nic = netdev_priv(ndev); 310 struct aq_nic_cfg_s *cfg; 311 int err = 0; 312 313 cfg = aq_nic_get_cfg(aq_nic); 314 315 switch (cmd->cmd) { 316 case ETHTOOL_GRXRINGS: 317 cmd->data = cfg->vecs; 318 break; 319 case ETHTOOL_GRXCLSRLCNT: 320 cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic); 321 break; 322 case ETHTOOL_GRXCLSRULE: 323 err = aq_get_rxnfc_rule(aq_nic, cmd); 324 break; 325 case ETHTOOL_GRXCLSRLALL: 326 err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs); 327 break; 328 default: 329 err = -EOPNOTSUPP; 330 break; 331 } 332 333 return err; 334 } 335 336 static int aq_ethtool_set_rxnfc(struct net_device *ndev, 337 struct ethtool_rxnfc *cmd) 338 { 339 struct aq_nic_s *aq_nic = netdev_priv(ndev); 340 int err = 0; 341 342 switch (cmd->cmd) { 343 case ETHTOOL_SRXCLSRLINS: 344 err = aq_add_rxnfc_rule(aq_nic, cmd); 345 break; 346 case ETHTOOL_SRXCLSRLDEL: 347 err = aq_del_rxnfc_rule(aq_nic, cmd); 348 break; 349 default: 350 err = -EOPNOTSUPP; 351 break; 352 } 353 354 return err; 355 } 356 357 static int aq_ethtool_get_coalesce(struct net_device *ndev, 358 struct ethtool_coalesce *coal) 359 { 360 struct aq_nic_s *aq_nic = netdev_priv(ndev); 361 struct aq_nic_cfg_s *cfg; 362 363 cfg = aq_nic_get_cfg(aq_nic); 364 365 if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON || 366 cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) { 367 coal->rx_coalesce_usecs = cfg->rx_itr; 368 coal->tx_coalesce_usecs = cfg->tx_itr; 369 coal->rx_max_coalesced_frames = 0; 370 coal->tx_max_coalesced_frames = 0; 371 } else { 372 coal->rx_coalesce_usecs = 0; 373 coal->tx_coalesce_usecs = 0; 374 coal->rx_max_coalesced_frames = 1; 375 coal->tx_max_coalesced_frames = 1; 376 } 377 378 return 0; 379 } 380 381 static int aq_ethtool_set_coalesce(struct net_device *ndev, 382 struct ethtool_coalesce *coal) 383 { 384 struct aq_nic_s *aq_nic = netdev_priv(ndev); 385 struct aq_nic_cfg_s *cfg; 386 387 cfg = aq_nic_get_cfg(aq_nic); 388 389 /* Atlantic only supports timing based coalescing 390 */ 391 if (coal->rx_max_coalesced_frames > 1 || 392 coal->tx_max_coalesced_frames > 1) 393 return -EOPNOTSUPP; 394 395 /* We do not support frame counting. Check this 396 */ 397 if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs)) 398 return -EOPNOTSUPP; 399 if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs)) 400 return -EOPNOTSUPP; 401 402 if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX || 403 coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX) 404 return -EINVAL; 405 406 cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON; 407 408 cfg->rx_itr = coal->rx_coalesce_usecs; 409 cfg->tx_itr = coal->tx_coalesce_usecs; 410 411 return aq_nic_update_interrupt_moderation_settings(aq_nic); 412 } 413 414 static void aq_ethtool_get_wol(struct net_device *ndev, 415 struct ethtool_wolinfo *wol) 416 { 417 struct aq_nic_s *aq_nic = netdev_priv(ndev); 418 struct aq_nic_cfg_s *cfg; 419 420 cfg = aq_nic_get_cfg(aq_nic); 421 422 wol->supported = AQ_NIC_WOL_MODES; 423 wol->wolopts = cfg->wol; 424 } 425 426 static int aq_ethtool_set_wol(struct net_device *ndev, 427 struct ethtool_wolinfo *wol) 428 { 429 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); 430 struct aq_nic_s *aq_nic = netdev_priv(ndev); 431 struct aq_nic_cfg_s *cfg; 432 int err = 0; 433 434 cfg = aq_nic_get_cfg(aq_nic); 435 436 if (wol->wolopts & ~AQ_NIC_WOL_MODES) 437 return -EOPNOTSUPP; 438 439 cfg->wol = wol->wolopts; 440 441 err = device_set_wakeup_enable(&pdev->dev, !!cfg->wol); 442 443 return err; 444 } 445 446 static int aq_ethtool_get_ts_info(struct net_device *ndev, 447 struct ethtool_ts_info *info) 448 { 449 struct aq_nic_s *aq_nic = netdev_priv(ndev); 450 451 ethtool_op_get_ts_info(ndev, info); 452 453 if (!aq_nic->aq_ptp) 454 return 0; 455 456 info->so_timestamping |= 457 SOF_TIMESTAMPING_TX_HARDWARE | 458 SOF_TIMESTAMPING_RX_HARDWARE | 459 SOF_TIMESTAMPING_RAW_HARDWARE; 460 461 info->tx_types = BIT(HWTSTAMP_TX_OFF) | 462 BIT(HWTSTAMP_TX_ON); 463 464 info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); 465 466 info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | 467 BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | 468 BIT(HWTSTAMP_FILTER_PTP_V2_EVENT); 469 470 info->phc_index = ptp_clock_index(aq_ptp_get_ptp_clock(aq_nic->aq_ptp)); 471 472 return 0; 473 } 474 475 static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) 476 { 477 u32 rate = 0; 478 479 if (speed & AQ_NIC_RATE_EEE_10G) 480 rate |= SUPPORTED_10000baseT_Full; 481 482 if (speed & AQ_NIC_RATE_EEE_2GS) 483 rate |= SUPPORTED_2500baseX_Full; 484 485 if (speed & AQ_NIC_RATE_EEE_1G) 486 rate |= SUPPORTED_1000baseT_Full; 487 488 return rate; 489 } 490 491 static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee) 492 { 493 struct aq_nic_s *aq_nic = netdev_priv(ndev); 494 u32 rate, supported_rates; 495 int err = 0; 496 497 if (!aq_nic->aq_fw_ops->get_eee_rate) 498 return -EOPNOTSUPP; 499 500 mutex_lock(&aq_nic->fwreq_mutex); 501 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, 502 &supported_rates); 503 mutex_unlock(&aq_nic->fwreq_mutex); 504 if (err < 0) 505 return err; 506 507 eee->supported = eee_mask_to_ethtool_mask(supported_rates); 508 509 if (aq_nic->aq_nic_cfg.eee_speeds) 510 eee->advertised = eee->supported; 511 512 eee->lp_advertised = eee_mask_to_ethtool_mask(rate); 513 514 eee->eee_enabled = !!eee->advertised; 515 516 eee->tx_lpi_enabled = eee->eee_enabled; 517 if (eee->advertised & eee->lp_advertised) 518 eee->eee_active = true; 519 520 return 0; 521 } 522 523 static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee) 524 { 525 struct aq_nic_s *aq_nic = netdev_priv(ndev); 526 u32 rate, supported_rates; 527 struct aq_nic_cfg_s *cfg; 528 int err = 0; 529 530 cfg = aq_nic_get_cfg(aq_nic); 531 532 if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate || 533 !aq_nic->aq_fw_ops->set_eee_rate)) 534 return -EOPNOTSUPP; 535 536 mutex_lock(&aq_nic->fwreq_mutex); 537 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, 538 &supported_rates); 539 mutex_unlock(&aq_nic->fwreq_mutex); 540 if (err < 0) 541 return err; 542 543 if (eee->eee_enabled) { 544 rate = supported_rates; 545 cfg->eee_speeds = rate; 546 } else { 547 rate = 0; 548 cfg->eee_speeds = 0; 549 } 550 551 mutex_lock(&aq_nic->fwreq_mutex); 552 err = aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate); 553 mutex_unlock(&aq_nic->fwreq_mutex); 554 555 return err; 556 } 557 558 static int aq_ethtool_nway_reset(struct net_device *ndev) 559 { 560 struct aq_nic_s *aq_nic = netdev_priv(ndev); 561 int err = 0; 562 563 if (unlikely(!aq_nic->aq_fw_ops->renegotiate)) 564 return -EOPNOTSUPP; 565 566 if (netif_running(ndev)) { 567 mutex_lock(&aq_nic->fwreq_mutex); 568 err = aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw); 569 mutex_unlock(&aq_nic->fwreq_mutex); 570 } 571 572 return err; 573 } 574 575 static void aq_ethtool_get_pauseparam(struct net_device *ndev, 576 struct ethtool_pauseparam *pause) 577 { 578 struct aq_nic_s *aq_nic = netdev_priv(ndev); 579 u32 fc = aq_nic->aq_nic_cfg.fc.req; 580 581 pause->autoneg = 0; 582 583 pause->rx_pause = !!(fc & AQ_NIC_FC_RX); 584 pause->tx_pause = !!(fc & AQ_NIC_FC_TX); 585 586 } 587 588 static int aq_ethtool_set_pauseparam(struct net_device *ndev, 589 struct ethtool_pauseparam *pause) 590 { 591 struct aq_nic_s *aq_nic = netdev_priv(ndev); 592 int err = 0; 593 594 if (!aq_nic->aq_fw_ops->set_flow_control) 595 return -EOPNOTSUPP; 596 597 if (pause->autoneg == AUTONEG_ENABLE) 598 return -EOPNOTSUPP; 599 600 if (pause->rx_pause) 601 aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX; 602 else 603 aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX; 604 605 if (pause->tx_pause) 606 aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX; 607 else 608 aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX; 609 610 mutex_lock(&aq_nic->fwreq_mutex); 611 err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw); 612 mutex_unlock(&aq_nic->fwreq_mutex); 613 614 return err; 615 } 616 617 static void aq_get_ringparam(struct net_device *ndev, 618 struct ethtool_ringparam *ring) 619 { 620 struct aq_nic_s *aq_nic = netdev_priv(ndev); 621 struct aq_nic_cfg_s *cfg; 622 623 cfg = aq_nic_get_cfg(aq_nic); 624 625 ring->rx_pending = cfg->rxds; 626 ring->tx_pending = cfg->txds; 627 628 ring->rx_max_pending = cfg->aq_hw_caps->rxds_max; 629 ring->tx_max_pending = cfg->aq_hw_caps->txds_max; 630 } 631 632 static int aq_set_ringparam(struct net_device *ndev, 633 struct ethtool_ringparam *ring) 634 { 635 struct aq_nic_s *aq_nic = netdev_priv(ndev); 636 const struct aq_hw_caps_s *hw_caps; 637 bool ndev_running = false; 638 struct aq_nic_cfg_s *cfg; 639 int err = 0; 640 641 cfg = aq_nic_get_cfg(aq_nic); 642 hw_caps = cfg->aq_hw_caps; 643 644 if (ring->rx_mini_pending || ring->rx_jumbo_pending) { 645 err = -EOPNOTSUPP; 646 goto err_exit; 647 } 648 649 if (netif_running(ndev)) { 650 ndev_running = true; 651 dev_close(ndev); 652 } 653 654 aq_nic_free_vectors(aq_nic); 655 656 cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); 657 cfg->rxds = min(cfg->rxds, hw_caps->rxds_max); 658 cfg->rxds = ALIGN(cfg->rxds, AQ_HW_RXD_MULTIPLE); 659 660 cfg->txds = max(ring->tx_pending, hw_caps->txds_min); 661 cfg->txds = min(cfg->txds, hw_caps->txds_max); 662 cfg->txds = ALIGN(cfg->txds, AQ_HW_TXD_MULTIPLE); 663 664 for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < cfg->vecs; 665 aq_nic->aq_vecs++) { 666 aq_nic->aq_vec[aq_nic->aq_vecs] = 667 aq_vec_alloc(aq_nic, aq_nic->aq_vecs, cfg); 668 if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) { 669 err = -ENOMEM; 670 goto err_exit; 671 } 672 } 673 if (ndev_running) 674 err = dev_open(ndev, NULL); 675 676 err_exit: 677 return err; 678 } 679 680 static u32 aq_get_msg_level(struct net_device *ndev) 681 { 682 struct aq_nic_s *aq_nic = netdev_priv(ndev); 683 684 return aq_nic->msg_enable; 685 } 686 687 static void aq_set_msg_level(struct net_device *ndev, u32 data) 688 { 689 struct aq_nic_s *aq_nic = netdev_priv(ndev); 690 691 aq_nic->msg_enable = data; 692 } 693 694 static u32 aq_ethtool_get_priv_flags(struct net_device *ndev) 695 { 696 struct aq_nic_s *aq_nic = netdev_priv(ndev); 697 698 return aq_nic->aq_nic_cfg.priv_flags; 699 } 700 701 static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags) 702 { 703 struct aq_nic_s *aq_nic = netdev_priv(ndev); 704 struct aq_nic_cfg_s *cfg; 705 u32 priv_flags; 706 707 cfg = aq_nic_get_cfg(aq_nic); 708 priv_flags = cfg->priv_flags; 709 710 if (flags & ~AQ_PRIV_FLAGS_MASK) 711 return -EOPNOTSUPP; 712 713 if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) { 714 netdev_info(ndev, "Can't enable more than one loopback simultaneously\n"); 715 return -EINVAL; 716 } 717 718 cfg->priv_flags = flags; 719 720 if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) { 721 if (netif_running(ndev)) { 722 dev_close(ndev); 723 724 dev_open(ndev, NULL); 725 } 726 } else if ((priv_flags ^ flags) & AQ_HW_LOOPBACK_MASK) { 727 aq_nic_set_loopback(aq_nic); 728 } 729 730 return 0; 731 } 732 733 const struct ethtool_ops aq_ethtool_ops = { 734 .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 735 ETHTOOL_COALESCE_MAX_FRAMES, 736 .get_link = aq_ethtool_get_link, 737 .get_regs_len = aq_ethtool_get_regs_len, 738 .get_regs = aq_ethtool_get_regs, 739 .get_drvinfo = aq_ethtool_get_drvinfo, 740 .get_strings = aq_ethtool_get_strings, 741 .set_phys_id = aq_ethtool_set_phys_id, 742 .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size, 743 .get_wol = aq_ethtool_get_wol, 744 .set_wol = aq_ethtool_set_wol, 745 .nway_reset = aq_ethtool_nway_reset, 746 .get_ringparam = aq_get_ringparam, 747 .set_ringparam = aq_set_ringparam, 748 .get_eee = aq_ethtool_get_eee, 749 .set_eee = aq_ethtool_set_eee, 750 .get_pauseparam = aq_ethtool_get_pauseparam, 751 .set_pauseparam = aq_ethtool_set_pauseparam, 752 .get_rxfh_key_size = aq_ethtool_get_rss_key_size, 753 .get_rxfh = aq_ethtool_get_rss, 754 .set_rxfh = aq_ethtool_set_rss, 755 .get_rxnfc = aq_ethtool_get_rxnfc, 756 .set_rxnfc = aq_ethtool_set_rxnfc, 757 .get_msglevel = aq_get_msg_level, 758 .set_msglevel = aq_set_msg_level, 759 .get_sset_count = aq_ethtool_get_sset_count, 760 .get_ethtool_stats = aq_ethtool_stats, 761 .get_priv_flags = aq_ethtool_get_priv_flags, 762 .set_priv_flags = aq_ethtool_set_priv_flags, 763 .get_link_ksettings = aq_ethtool_get_link_ksettings, 764 .set_link_ksettings = aq_ethtool_set_link_ksettings, 765 .get_coalesce = aq_ethtool_get_coalesce, 766 .set_coalesce = aq_ethtool_set_coalesce, 767 .get_ts_info = aq_ethtool_get_ts_info, 768 }; 769