1 /* 2 * aQuantia Corporation Network Driver 3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 */ 9 10 /* File aq_ethtool.c: Definition of ethertool related functions. */ 11 12 #include "aq_ethtool.h" 13 #include "aq_nic.h" 14 #include "aq_vec.h" 15 #include "aq_filters.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 = aq_nic_get_regs_count(aq_nic); 22 23 memset(p, 0, regs_count * sizeof(u32)); 24 aq_nic_get_regs(aq_nic, regs, p); 25 } 26 27 static int aq_ethtool_get_regs_len(struct net_device *ndev) 28 { 29 struct aq_nic_s *aq_nic = netdev_priv(ndev); 30 u32 regs_count = aq_nic_get_regs_count(aq_nic); 31 32 return regs_count * sizeof(u32); 33 } 34 35 static u32 aq_ethtool_get_link(struct net_device *ndev) 36 { 37 return ethtool_op_get_link(ndev); 38 } 39 40 static int aq_ethtool_get_link_ksettings(struct net_device *ndev, 41 struct ethtool_link_ksettings *cmd) 42 { 43 struct aq_nic_s *aq_nic = netdev_priv(ndev); 44 45 aq_nic_get_link_ksettings(aq_nic, cmd); 46 cmd->base.speed = netif_carrier_ok(ndev) ? 47 aq_nic_get_link_speed(aq_nic) : 0U; 48 49 return 0; 50 } 51 52 static int 53 aq_ethtool_set_link_ksettings(struct net_device *ndev, 54 const struct ethtool_link_ksettings *cmd) 55 { 56 struct aq_nic_s *aq_nic = netdev_priv(ndev); 57 58 return aq_nic_set_link_ksettings(aq_nic, cmd); 59 } 60 61 static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { 62 "InPackets", 63 "InUCast", 64 "InMCast", 65 "InBCast", 66 "InErrors", 67 "OutPackets", 68 "OutUCast", 69 "OutMCast", 70 "OutBCast", 71 "InUCastOctets", 72 "OutUCastOctets", 73 "InMCastOctets", 74 "OutMCastOctets", 75 "InBCastOctets", 76 "OutBCastOctets", 77 "InOctets", 78 "OutOctets", 79 "InPacketsDma", 80 "OutPacketsDma", 81 "InOctetsDma", 82 "OutOctetsDma", 83 "InDroppedDma", 84 }; 85 86 static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { 87 "Queue[%d] InPackets", 88 "Queue[%d] OutPackets", 89 "Queue[%d] Restarts", 90 "Queue[%d] InJumboPackets", 91 "Queue[%d] InLroPackets", 92 "Queue[%d] InErrors", 93 }; 94 95 static void aq_ethtool_stats(struct net_device *ndev, 96 struct ethtool_stats *stats, u64 *data) 97 { 98 struct aq_nic_s *aq_nic = netdev_priv(ndev); 99 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 100 101 memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) + 102 ARRAY_SIZE(aq_ethtool_queue_stat_names) * 103 cfg->vecs) * sizeof(u64)); 104 aq_nic_get_stats(aq_nic, data); 105 } 106 107 static void aq_ethtool_get_drvinfo(struct net_device *ndev, 108 struct ethtool_drvinfo *drvinfo) 109 { 110 struct aq_nic_s *aq_nic = netdev_priv(ndev); 111 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 112 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); 113 u32 firmware_version = aq_nic_get_fw_version(aq_nic); 114 u32 regs_count = aq_nic_get_regs_count(aq_nic); 115 116 strlcat(drvinfo->driver, AQ_CFG_DRV_NAME, sizeof(drvinfo->driver)); 117 strlcat(drvinfo->version, AQ_CFG_DRV_VERSION, sizeof(drvinfo->version)); 118 119 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 120 "%u.%u.%u", firmware_version >> 24, 121 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU); 122 123 strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "", 124 sizeof(drvinfo->bus_info)); 125 drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + 126 cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); 127 drvinfo->testinfo_len = 0; 128 drvinfo->regdump_len = regs_count; 129 drvinfo->eedump_len = 0; 130 } 131 132 static void aq_ethtool_get_strings(struct net_device *ndev, 133 u32 stringset, u8 *data) 134 { 135 int i, si; 136 struct aq_nic_s *aq_nic = netdev_priv(ndev); 137 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 138 u8 *p = data; 139 140 if (stringset == ETH_SS_STATS) { 141 memcpy(p, *aq_ethtool_stat_names, 142 sizeof(aq_ethtool_stat_names)); 143 p = p + sizeof(aq_ethtool_stat_names); 144 for (i = 0; i < cfg->vecs; i++) { 145 for (si = 0; 146 si < ARRAY_SIZE(aq_ethtool_queue_stat_names); 147 si++) { 148 snprintf(p, ETH_GSTRING_LEN, 149 aq_ethtool_queue_stat_names[si], i); 150 p += ETH_GSTRING_LEN; 151 } 152 } 153 } 154 } 155 156 static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) 157 { 158 int ret = 0; 159 struct aq_nic_s *aq_nic = netdev_priv(ndev); 160 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 161 162 switch (stringset) { 163 case ETH_SS_STATS: 164 ret = ARRAY_SIZE(aq_ethtool_stat_names) + 165 cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); 166 break; 167 default: 168 ret = -EOPNOTSUPP; 169 } 170 return ret; 171 } 172 173 static u32 aq_ethtool_get_rss_indir_size(struct net_device *ndev) 174 { 175 return AQ_CFG_RSS_INDIRECTION_TABLE_MAX; 176 } 177 178 static u32 aq_ethtool_get_rss_key_size(struct net_device *ndev) 179 { 180 struct aq_nic_s *aq_nic = netdev_priv(ndev); 181 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 182 183 return sizeof(cfg->aq_rss.hash_secret_key); 184 } 185 186 static int aq_ethtool_get_rss(struct net_device *ndev, u32 *indir, u8 *key, 187 u8 *hfunc) 188 { 189 struct aq_nic_s *aq_nic = netdev_priv(ndev); 190 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 191 unsigned int i = 0U; 192 193 if (hfunc) 194 *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */ 195 if (indir) { 196 for (i = 0; i < AQ_CFG_RSS_INDIRECTION_TABLE_MAX; i++) 197 indir[i] = cfg->aq_rss.indirection_table[i]; 198 } 199 if (key) 200 memcpy(key, cfg->aq_rss.hash_secret_key, 201 sizeof(cfg->aq_rss.hash_secret_key)); 202 return 0; 203 } 204 205 static int aq_ethtool_get_rxnfc(struct net_device *ndev, 206 struct ethtool_rxnfc *cmd, 207 u32 *rule_locs) 208 { 209 struct aq_nic_s *aq_nic = netdev_priv(ndev); 210 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 211 int err = 0; 212 213 switch (cmd->cmd) { 214 case ETHTOOL_GRXRINGS: 215 cmd->data = cfg->vecs; 216 break; 217 case ETHTOOL_GRXCLSRLCNT: 218 cmd->rule_cnt = aq_get_rxnfc_count_all_rules(aq_nic); 219 break; 220 case ETHTOOL_GRXCLSRULE: 221 err = aq_get_rxnfc_rule(aq_nic, cmd); 222 break; 223 case ETHTOOL_GRXCLSRLALL: 224 err = aq_get_rxnfc_all_rules(aq_nic, cmd, rule_locs); 225 break; 226 default: 227 err = -EOPNOTSUPP; 228 break; 229 } 230 231 return err; 232 } 233 234 static int aq_ethtool_set_rxnfc(struct net_device *ndev, 235 struct ethtool_rxnfc *cmd) 236 { 237 int err = 0; 238 struct aq_nic_s *aq_nic = netdev_priv(ndev); 239 240 switch (cmd->cmd) { 241 case ETHTOOL_SRXCLSRLINS: 242 err = aq_add_rxnfc_rule(aq_nic, cmd); 243 break; 244 case ETHTOOL_SRXCLSRLDEL: 245 err = aq_del_rxnfc_rule(aq_nic, cmd); 246 break; 247 default: 248 err = -EOPNOTSUPP; 249 break; 250 } 251 252 return err; 253 } 254 255 static int aq_ethtool_get_coalesce(struct net_device *ndev, 256 struct ethtool_coalesce *coal) 257 { 258 struct aq_nic_s *aq_nic = netdev_priv(ndev); 259 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 260 261 if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON || 262 cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) { 263 coal->rx_coalesce_usecs = cfg->rx_itr; 264 coal->tx_coalesce_usecs = cfg->tx_itr; 265 coal->rx_max_coalesced_frames = 0; 266 coal->tx_max_coalesced_frames = 0; 267 } else { 268 coal->rx_coalesce_usecs = 0; 269 coal->tx_coalesce_usecs = 0; 270 coal->rx_max_coalesced_frames = 1; 271 coal->tx_max_coalesced_frames = 1; 272 } 273 return 0; 274 } 275 276 static int aq_ethtool_set_coalesce(struct net_device *ndev, 277 struct ethtool_coalesce *coal) 278 { 279 struct aq_nic_s *aq_nic = netdev_priv(ndev); 280 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 281 282 /* This is not yet supported 283 */ 284 if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce) 285 return -EOPNOTSUPP; 286 287 /* Atlantic only supports timing based coalescing 288 */ 289 if (coal->rx_max_coalesced_frames > 1 || 290 coal->rx_coalesce_usecs_irq || 291 coal->rx_max_coalesced_frames_irq) 292 return -EOPNOTSUPP; 293 294 if (coal->tx_max_coalesced_frames > 1 || 295 coal->tx_coalesce_usecs_irq || 296 coal->tx_max_coalesced_frames_irq) 297 return -EOPNOTSUPP; 298 299 /* We do not support frame counting. Check this 300 */ 301 if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs)) 302 return -EOPNOTSUPP; 303 if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs)) 304 return -EOPNOTSUPP; 305 306 if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX || 307 coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX) 308 return -EINVAL; 309 310 cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON; 311 312 cfg->rx_itr = coal->rx_coalesce_usecs; 313 cfg->tx_itr = coal->tx_coalesce_usecs; 314 315 return aq_nic_update_interrupt_moderation_settings(aq_nic); 316 } 317 318 static void aq_ethtool_get_wol(struct net_device *ndev, 319 struct ethtool_wolinfo *wol) 320 { 321 struct aq_nic_s *aq_nic = netdev_priv(ndev); 322 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 323 324 wol->supported = WAKE_MAGIC; 325 wol->wolopts = 0; 326 327 if (cfg->wol) 328 wol->wolopts |= WAKE_MAGIC; 329 } 330 331 static int aq_ethtool_set_wol(struct net_device *ndev, 332 struct ethtool_wolinfo *wol) 333 { 334 struct pci_dev *pdev = to_pci_dev(ndev->dev.parent); 335 struct aq_nic_s *aq_nic = netdev_priv(ndev); 336 struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); 337 int err = 0; 338 339 if (wol->wolopts & WAKE_MAGIC) 340 cfg->wol |= AQ_NIC_WOL_ENABLED; 341 else 342 cfg->wol &= ~AQ_NIC_WOL_ENABLED; 343 err = device_set_wakeup_enable(&pdev->dev, wol->wolopts); 344 345 return err; 346 } 347 348 static enum hw_atl_fw2x_rate eee_mask_to_ethtool_mask(u32 speed) 349 { 350 u32 rate = 0; 351 352 if (speed & AQ_NIC_RATE_EEE_10G) 353 rate |= SUPPORTED_10000baseT_Full; 354 355 if (speed & AQ_NIC_RATE_EEE_2GS) 356 rate |= SUPPORTED_2500baseX_Full; 357 358 if (speed & AQ_NIC_RATE_EEE_1G) 359 rate |= SUPPORTED_1000baseT_Full; 360 361 return rate; 362 } 363 364 static int aq_ethtool_get_eee(struct net_device *ndev, struct ethtool_eee *eee) 365 { 366 struct aq_nic_s *aq_nic = netdev_priv(ndev); 367 u32 rate, supported_rates; 368 int err = 0; 369 370 if (!aq_nic->aq_fw_ops->get_eee_rate) 371 return -EOPNOTSUPP; 372 373 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, 374 &supported_rates); 375 if (err < 0) 376 return err; 377 378 eee->supported = eee_mask_to_ethtool_mask(supported_rates); 379 380 if (aq_nic->aq_nic_cfg.eee_speeds) 381 eee->advertised = eee->supported; 382 383 eee->lp_advertised = eee_mask_to_ethtool_mask(rate); 384 385 eee->eee_enabled = !!eee->advertised; 386 387 eee->tx_lpi_enabled = eee->eee_enabled; 388 if (eee->advertised & eee->lp_advertised) 389 eee->eee_active = true; 390 391 return 0; 392 } 393 394 static int aq_ethtool_set_eee(struct net_device *ndev, struct ethtool_eee *eee) 395 { 396 struct aq_nic_s *aq_nic = netdev_priv(ndev); 397 u32 rate, supported_rates; 398 struct aq_nic_cfg_s *cfg; 399 int err = 0; 400 401 cfg = aq_nic_get_cfg(aq_nic); 402 403 if (unlikely(!aq_nic->aq_fw_ops->get_eee_rate || 404 !aq_nic->aq_fw_ops->set_eee_rate)) 405 return -EOPNOTSUPP; 406 407 err = aq_nic->aq_fw_ops->get_eee_rate(aq_nic->aq_hw, &rate, 408 &supported_rates); 409 if (err < 0) 410 return err; 411 412 if (eee->eee_enabled) { 413 rate = supported_rates; 414 cfg->eee_speeds = rate; 415 } else { 416 rate = 0; 417 cfg->eee_speeds = 0; 418 } 419 420 return aq_nic->aq_fw_ops->set_eee_rate(aq_nic->aq_hw, rate); 421 } 422 423 static int aq_ethtool_nway_reset(struct net_device *ndev) 424 { 425 struct aq_nic_s *aq_nic = netdev_priv(ndev); 426 427 if (unlikely(!aq_nic->aq_fw_ops->renegotiate)) 428 return -EOPNOTSUPP; 429 430 if (netif_running(ndev)) 431 return aq_nic->aq_fw_ops->renegotiate(aq_nic->aq_hw); 432 433 return 0; 434 } 435 436 static void aq_ethtool_get_pauseparam(struct net_device *ndev, 437 struct ethtool_pauseparam *pause) 438 { 439 struct aq_nic_s *aq_nic = netdev_priv(ndev); 440 u32 fc = aq_nic->aq_nic_cfg.flow_control; 441 442 pause->autoneg = 0; 443 444 pause->rx_pause = !!(fc & AQ_NIC_FC_RX); 445 pause->tx_pause = !!(fc & AQ_NIC_FC_TX); 446 447 } 448 449 static int aq_ethtool_set_pauseparam(struct net_device *ndev, 450 struct ethtool_pauseparam *pause) 451 { 452 struct aq_nic_s *aq_nic = netdev_priv(ndev); 453 int err = 0; 454 455 if (!aq_nic->aq_fw_ops->set_flow_control) 456 return -EOPNOTSUPP; 457 458 if (pause->autoneg == AUTONEG_ENABLE) 459 return -EOPNOTSUPP; 460 461 if (pause->rx_pause) 462 aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX; 463 else 464 aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX; 465 466 if (pause->tx_pause) 467 aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX; 468 else 469 aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX; 470 471 err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw); 472 473 return err; 474 } 475 476 static void aq_get_ringparam(struct net_device *ndev, 477 struct ethtool_ringparam *ring) 478 { 479 struct aq_nic_s *aq_nic = netdev_priv(ndev); 480 struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic); 481 482 ring->rx_pending = aq_nic_cfg->rxds; 483 ring->tx_pending = aq_nic_cfg->txds; 484 485 ring->rx_max_pending = aq_nic_cfg->aq_hw_caps->rxds_max; 486 ring->tx_max_pending = aq_nic_cfg->aq_hw_caps->txds_max; 487 } 488 489 static int aq_set_ringparam(struct net_device *ndev, 490 struct ethtool_ringparam *ring) 491 { 492 int err = 0; 493 bool ndev_running = false; 494 struct aq_nic_s *aq_nic = netdev_priv(ndev); 495 struct aq_nic_cfg_s *aq_nic_cfg = aq_nic_get_cfg(aq_nic); 496 const struct aq_hw_caps_s *hw_caps = aq_nic_cfg->aq_hw_caps; 497 498 if (ring->rx_mini_pending || ring->rx_jumbo_pending) { 499 err = -EOPNOTSUPP; 500 goto err_exit; 501 } 502 503 if (netif_running(ndev)) { 504 ndev_running = true; 505 dev_close(ndev); 506 } 507 508 aq_nic_free_vectors(aq_nic); 509 510 aq_nic_cfg->rxds = max(ring->rx_pending, hw_caps->rxds_min); 511 aq_nic_cfg->rxds = min(aq_nic_cfg->rxds, hw_caps->rxds_max); 512 aq_nic_cfg->rxds = ALIGN(aq_nic_cfg->rxds, AQ_HW_RXD_MULTIPLE); 513 514 aq_nic_cfg->txds = max(ring->tx_pending, hw_caps->txds_min); 515 aq_nic_cfg->txds = min(aq_nic_cfg->txds, hw_caps->txds_max); 516 aq_nic_cfg->txds = ALIGN(aq_nic_cfg->txds, AQ_HW_TXD_MULTIPLE); 517 518 for (aq_nic->aq_vecs = 0; aq_nic->aq_vecs < aq_nic_cfg->vecs; 519 aq_nic->aq_vecs++) { 520 aq_nic->aq_vec[aq_nic->aq_vecs] = 521 aq_vec_alloc(aq_nic, aq_nic->aq_vecs, aq_nic_cfg); 522 if (unlikely(!aq_nic->aq_vec[aq_nic->aq_vecs])) { 523 err = -ENOMEM; 524 goto err_exit; 525 } 526 } 527 if (ndev_running) 528 err = dev_open(ndev); 529 530 err_exit: 531 return err; 532 } 533 534 const struct ethtool_ops aq_ethtool_ops = { 535 .get_link = aq_ethtool_get_link, 536 .get_regs_len = aq_ethtool_get_regs_len, 537 .get_regs = aq_ethtool_get_regs, 538 .get_drvinfo = aq_ethtool_get_drvinfo, 539 .get_strings = aq_ethtool_get_strings, 540 .get_rxfh_indir_size = aq_ethtool_get_rss_indir_size, 541 .get_wol = aq_ethtool_get_wol, 542 .set_wol = aq_ethtool_set_wol, 543 .nway_reset = aq_ethtool_nway_reset, 544 .get_ringparam = aq_get_ringparam, 545 .set_ringparam = aq_set_ringparam, 546 .get_eee = aq_ethtool_get_eee, 547 .set_eee = aq_ethtool_set_eee, 548 .get_pauseparam = aq_ethtool_get_pauseparam, 549 .set_pauseparam = aq_ethtool_set_pauseparam, 550 .get_rxfh_key_size = aq_ethtool_get_rss_key_size, 551 .get_rxfh = aq_ethtool_get_rss, 552 .get_rxnfc = aq_ethtool_get_rxnfc, 553 .set_rxnfc = aq_ethtool_set_rxnfc, 554 .get_sset_count = aq_ethtool_get_sset_count, 555 .get_ethtool_stats = aq_ethtool_stats, 556 .get_link_ksettings = aq_ethtool_get_link_ksettings, 557 .set_link_ksettings = aq_ethtool_set_link_ksettings, 558 .get_coalesce = aq_ethtool_get_coalesce, 559 .set_coalesce = aq_ethtool_set_coalesce, 560 }; 561