1 /* 2 * Copyright (c) 2015, Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33 #include "en.h" 34 35 static void mlx5e_get_drvinfo(struct net_device *dev, 36 struct ethtool_drvinfo *drvinfo) 37 { 38 struct mlx5e_priv *priv = netdev_priv(dev); 39 struct mlx5_core_dev *mdev = priv->mdev; 40 41 strlcpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver)); 42 strlcpy(drvinfo->version, DRIVER_VERSION " (" DRIVER_RELDATE ")", 43 sizeof(drvinfo->version)); 44 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 45 "%d.%d.%d", 46 fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev)); 47 strlcpy(drvinfo->bus_info, pci_name(mdev->pdev), 48 sizeof(drvinfo->bus_info)); 49 } 50 51 static const struct { 52 u32 supported; 53 u32 advertised; 54 u32 speed; 55 } ptys2ethtool_table[MLX5E_LINK_MODES_NUMBER] = { 56 [MLX5E_1000BASE_CX_SGMII] = { 57 .supported = SUPPORTED_1000baseKX_Full, 58 .advertised = ADVERTISED_1000baseKX_Full, 59 .speed = 1000, 60 }, 61 [MLX5E_1000BASE_KX] = { 62 .supported = SUPPORTED_1000baseKX_Full, 63 .advertised = ADVERTISED_1000baseKX_Full, 64 .speed = 1000, 65 }, 66 [MLX5E_10GBASE_CX4] = { 67 .supported = SUPPORTED_10000baseKX4_Full, 68 .advertised = ADVERTISED_10000baseKX4_Full, 69 .speed = 10000, 70 }, 71 [MLX5E_10GBASE_KX4] = { 72 .supported = SUPPORTED_10000baseKX4_Full, 73 .advertised = ADVERTISED_10000baseKX4_Full, 74 .speed = 10000, 75 }, 76 [MLX5E_10GBASE_KR] = { 77 .supported = SUPPORTED_10000baseKR_Full, 78 .advertised = ADVERTISED_10000baseKR_Full, 79 .speed = 10000, 80 }, 81 [MLX5E_20GBASE_KR2] = { 82 .supported = SUPPORTED_20000baseKR2_Full, 83 .advertised = ADVERTISED_20000baseKR2_Full, 84 .speed = 20000, 85 }, 86 [MLX5E_40GBASE_CR4] = { 87 .supported = SUPPORTED_40000baseCR4_Full, 88 .advertised = ADVERTISED_40000baseCR4_Full, 89 .speed = 40000, 90 }, 91 [MLX5E_40GBASE_KR4] = { 92 .supported = SUPPORTED_40000baseKR4_Full, 93 .advertised = ADVERTISED_40000baseKR4_Full, 94 .speed = 40000, 95 }, 96 [MLX5E_56GBASE_R4] = { 97 .supported = SUPPORTED_56000baseKR4_Full, 98 .advertised = ADVERTISED_56000baseKR4_Full, 99 .speed = 56000, 100 }, 101 [MLX5E_10GBASE_CR] = { 102 .supported = SUPPORTED_10000baseKR_Full, 103 .advertised = ADVERTISED_10000baseKR_Full, 104 .speed = 10000, 105 }, 106 [MLX5E_10GBASE_SR] = { 107 .supported = SUPPORTED_10000baseKR_Full, 108 .advertised = ADVERTISED_10000baseKR_Full, 109 .speed = 10000, 110 }, 111 [MLX5E_10GBASE_ER] = { 112 .supported = SUPPORTED_10000baseKR_Full, 113 .advertised = ADVERTISED_10000baseKR_Full, 114 .speed = 10000, 115 }, 116 [MLX5E_40GBASE_SR4] = { 117 .supported = SUPPORTED_40000baseSR4_Full, 118 .advertised = ADVERTISED_40000baseSR4_Full, 119 .speed = 40000, 120 }, 121 [MLX5E_40GBASE_LR4] = { 122 .supported = SUPPORTED_40000baseLR4_Full, 123 .advertised = ADVERTISED_40000baseLR4_Full, 124 .speed = 40000, 125 }, 126 [MLX5E_100GBASE_CR4] = { 127 .speed = 100000, 128 }, 129 [MLX5E_100GBASE_SR4] = { 130 .speed = 100000, 131 }, 132 [MLX5E_100GBASE_KR4] = { 133 .speed = 100000, 134 }, 135 [MLX5E_100GBASE_LR4] = { 136 .speed = 100000, 137 }, 138 [MLX5E_100BASE_TX] = { 139 .speed = 100, 140 }, 141 [MLX5E_100BASE_T] = { 142 .supported = SUPPORTED_100baseT_Full, 143 .advertised = ADVERTISED_100baseT_Full, 144 .speed = 100, 145 }, 146 [MLX5E_10GBASE_T] = { 147 .supported = SUPPORTED_10000baseT_Full, 148 .advertised = ADVERTISED_10000baseT_Full, 149 .speed = 1000, 150 }, 151 [MLX5E_25GBASE_CR] = { 152 .speed = 25000, 153 }, 154 [MLX5E_25GBASE_KR] = { 155 .speed = 25000, 156 }, 157 [MLX5E_25GBASE_SR] = { 158 .speed = 25000, 159 }, 160 [MLX5E_50GBASE_CR2] = { 161 .speed = 50000, 162 }, 163 [MLX5E_50GBASE_KR2] = { 164 .speed = 50000, 165 }, 166 }; 167 168 static int mlx5e_get_sset_count(struct net_device *dev, int sset) 169 { 170 struct mlx5e_priv *priv = netdev_priv(dev); 171 172 switch (sset) { 173 case ETH_SS_STATS: 174 return NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS + 175 priv->params.num_channels * NUM_RQ_STATS + 176 priv->params.num_channels * priv->params.num_tc * 177 NUM_SQ_STATS; 178 /* fallthrough */ 179 default: 180 return -EOPNOTSUPP; 181 } 182 } 183 184 static void mlx5e_get_strings(struct net_device *dev, 185 uint32_t stringset, uint8_t *data) 186 { 187 int i, j, tc, idx = 0; 188 struct mlx5e_priv *priv = netdev_priv(dev); 189 190 switch (stringset) { 191 case ETH_SS_PRIV_FLAGS: 192 break; 193 194 case ETH_SS_TEST: 195 break; 196 197 case ETH_SS_STATS: 198 /* VPORT counters */ 199 for (i = 0; i < NUM_VPORT_COUNTERS; i++) 200 strcpy(data + (idx++) * ETH_GSTRING_LEN, 201 vport_strings[i]); 202 203 /* PPORT counters */ 204 for (i = 0; i < NUM_PPORT_COUNTERS; i++) 205 strcpy(data + (idx++) * ETH_GSTRING_LEN, 206 pport_strings[i]); 207 208 /* per channel counters */ 209 for (i = 0; i < priv->params.num_channels; i++) 210 for (j = 0; j < NUM_RQ_STATS; j++) 211 sprintf(data + (idx++) * ETH_GSTRING_LEN, 212 "rx%d_%s", i, rq_stats_strings[j]); 213 214 for (i = 0; i < priv->params.num_channels; i++) 215 for (tc = 0; tc < priv->params.num_tc; tc++) 216 for (j = 0; j < NUM_SQ_STATS; j++) 217 sprintf(data + 218 (idx++) * ETH_GSTRING_LEN, 219 "tx%d_%d_%s", i, tc, 220 sq_stats_strings[j]); 221 break; 222 } 223 } 224 225 static void mlx5e_get_ethtool_stats(struct net_device *dev, 226 struct ethtool_stats *stats, u64 *data) 227 { 228 struct mlx5e_priv *priv = netdev_priv(dev); 229 int i, j, tc, idx = 0; 230 231 if (!data) 232 return; 233 234 mutex_lock(&priv->state_lock); 235 if (test_bit(MLX5E_STATE_OPENED, &priv->state)) 236 mlx5e_update_stats(priv); 237 mutex_unlock(&priv->state_lock); 238 239 for (i = 0; i < NUM_VPORT_COUNTERS; i++) 240 data[idx++] = ((u64 *)&priv->stats.vport)[i]; 241 242 for (i = 0; i < NUM_PPORT_COUNTERS; i++) 243 data[idx++] = be64_to_cpu(((__be64 *)&priv->stats.pport)[i]); 244 245 /* per channel counters */ 246 for (i = 0; i < priv->params.num_channels; i++) 247 for (j = 0; j < NUM_RQ_STATS; j++) 248 data[idx++] = !test_bit(MLX5E_STATE_OPENED, 249 &priv->state) ? 0 : 250 ((u64 *)&priv->channel[i]->rq.stats)[j]; 251 252 for (i = 0; i < priv->params.num_channels; i++) 253 for (tc = 0; tc < priv->params.num_tc; tc++) 254 for (j = 0; j < NUM_SQ_STATS; j++) 255 data[idx++] = !test_bit(MLX5E_STATE_OPENED, 256 &priv->state) ? 0 : 257 ((u64 *)&priv->channel[i]->sq[tc].stats)[j]; 258 } 259 260 static void mlx5e_get_ringparam(struct net_device *dev, 261 struct ethtool_ringparam *param) 262 { 263 struct mlx5e_priv *priv = netdev_priv(dev); 264 265 param->rx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 266 param->tx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 267 param->rx_pending = 1 << priv->params.log_rq_size; 268 param->tx_pending = 1 << priv->params.log_sq_size; 269 } 270 271 static int mlx5e_set_ringparam(struct net_device *dev, 272 struct ethtool_ringparam *param) 273 { 274 struct mlx5e_priv *priv = netdev_priv(dev); 275 bool was_opened; 276 u16 min_rx_wqes; 277 u8 log_rq_size; 278 u8 log_sq_size; 279 int err = 0; 280 281 if (param->rx_jumbo_pending) { 282 netdev_info(dev, "%s: rx_jumbo_pending not supported\n", 283 __func__); 284 return -EINVAL; 285 } 286 if (param->rx_mini_pending) { 287 netdev_info(dev, "%s: rx_mini_pending not supported\n", 288 __func__); 289 return -EINVAL; 290 } 291 if (param->rx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { 292 netdev_info(dev, "%s: rx_pending (%d) < min (%d)\n", 293 __func__, param->rx_pending, 294 1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); 295 return -EINVAL; 296 } 297 if (param->rx_pending > (1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE)) { 298 netdev_info(dev, "%s: rx_pending (%d) > max (%d)\n", 299 __func__, param->rx_pending, 300 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE); 301 return -EINVAL; 302 } 303 if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { 304 netdev_info(dev, "%s: tx_pending (%d) < min (%d)\n", 305 __func__, param->tx_pending, 306 1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); 307 return -EINVAL; 308 } 309 if (param->tx_pending > (1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE)) { 310 netdev_info(dev, "%s: tx_pending (%d) > max (%d)\n", 311 __func__, param->tx_pending, 312 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE); 313 return -EINVAL; 314 } 315 316 log_rq_size = order_base_2(param->rx_pending); 317 log_sq_size = order_base_2(param->tx_pending); 318 min_rx_wqes = min_t(u16, param->rx_pending - 1, 319 MLX5E_PARAMS_DEFAULT_MIN_RX_WQES); 320 321 if (log_rq_size == priv->params.log_rq_size && 322 log_sq_size == priv->params.log_sq_size && 323 min_rx_wqes == priv->params.min_rx_wqes) 324 return 0; 325 326 mutex_lock(&priv->state_lock); 327 328 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 329 if (was_opened) 330 mlx5e_close_locked(dev); 331 332 priv->params.log_rq_size = log_rq_size; 333 priv->params.log_sq_size = log_sq_size; 334 priv->params.min_rx_wqes = min_rx_wqes; 335 336 if (was_opened) 337 err = mlx5e_open_locked(dev); 338 339 mutex_unlock(&priv->state_lock); 340 341 return err; 342 } 343 344 static void mlx5e_get_channels(struct net_device *dev, 345 struct ethtool_channels *ch) 346 { 347 struct mlx5e_priv *priv = netdev_priv(dev); 348 349 ch->max_combined = mlx5e_get_max_num_channels(priv->mdev); 350 ch->combined_count = priv->params.num_channels; 351 } 352 353 static int mlx5e_set_channels(struct net_device *dev, 354 struct ethtool_channels *ch) 355 { 356 struct mlx5e_priv *priv = netdev_priv(dev); 357 int ncv = mlx5e_get_max_num_channels(priv->mdev); 358 unsigned int count = ch->combined_count; 359 bool was_opened; 360 int err = 0; 361 362 if (!count) { 363 netdev_info(dev, "%s: combined_count=0 not supported\n", 364 __func__); 365 return -EINVAL; 366 } 367 if (ch->rx_count || ch->tx_count) { 368 netdev_info(dev, "%s: separate rx/tx count not supported\n", 369 __func__); 370 return -EINVAL; 371 } 372 if (count > ncv) { 373 netdev_info(dev, "%s: count (%d) > max (%d)\n", 374 __func__, count, ncv); 375 return -EINVAL; 376 } 377 378 if (priv->params.num_channels == count) 379 return 0; 380 381 mutex_lock(&priv->state_lock); 382 383 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 384 if (was_opened) 385 mlx5e_close_locked(dev); 386 387 priv->params.num_channels = count; 388 389 if (was_opened) 390 err = mlx5e_open_locked(dev); 391 392 mutex_unlock(&priv->state_lock); 393 394 return err; 395 } 396 397 static int mlx5e_get_coalesce(struct net_device *netdev, 398 struct ethtool_coalesce *coal) 399 { 400 struct mlx5e_priv *priv = netdev_priv(netdev); 401 402 coal->rx_coalesce_usecs = priv->params.rx_cq_moderation_usec; 403 coal->rx_max_coalesced_frames = priv->params.rx_cq_moderation_pkts; 404 coal->tx_coalesce_usecs = priv->params.tx_cq_moderation_usec; 405 coal->tx_max_coalesced_frames = priv->params.tx_cq_moderation_pkts; 406 407 return 0; 408 } 409 410 static int mlx5e_set_coalesce(struct net_device *netdev, 411 struct ethtool_coalesce *coal) 412 { 413 struct mlx5e_priv *priv = netdev_priv(netdev); 414 struct mlx5_core_dev *mdev = priv->mdev; 415 struct mlx5e_channel *c; 416 int tc; 417 int i; 418 419 priv->params.tx_cq_moderation_usec = coal->tx_coalesce_usecs; 420 priv->params.tx_cq_moderation_pkts = coal->tx_max_coalesced_frames; 421 priv->params.rx_cq_moderation_usec = coal->rx_coalesce_usecs; 422 priv->params.rx_cq_moderation_pkts = coal->rx_max_coalesced_frames; 423 424 for (i = 0; i < priv->params.num_channels; ++i) { 425 c = priv->channel[i]; 426 427 for (tc = 0; tc < c->num_tc; tc++) { 428 mlx5_core_modify_cq_moderation(mdev, 429 &c->sq[tc].cq.mcq, 430 coal->tx_coalesce_usecs, 431 coal->tx_max_coalesced_frames); 432 } 433 434 mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq, 435 coal->rx_coalesce_usecs, 436 coal->rx_max_coalesced_frames); 437 } 438 439 return 0; 440 } 441 442 static u32 ptys2ethtool_supported_link(u32 eth_proto_cap) 443 { 444 int i; 445 u32 supported_modes = 0; 446 447 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 448 if (eth_proto_cap & MLX5E_PROT_MASK(i)) 449 supported_modes |= ptys2ethtool_table[i].supported; 450 } 451 return supported_modes; 452 } 453 454 static u32 ptys2ethtool_adver_link(u32 eth_proto_cap) 455 { 456 int i; 457 u32 advertising_modes = 0; 458 459 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 460 if (eth_proto_cap & MLX5E_PROT_MASK(i)) 461 advertising_modes |= ptys2ethtool_table[i].advertised; 462 } 463 return advertising_modes; 464 } 465 466 static u32 ptys2ethtool_supported_port(u32 eth_proto_cap) 467 { 468 if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR) 469 | MLX5E_PROT_MASK(MLX5E_10GBASE_SR) 470 | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4) 471 | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4) 472 | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4) 473 | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) { 474 return SUPPORTED_FIBRE; 475 } 476 477 if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_100GBASE_KR4) 478 | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4) 479 | MLX5E_PROT_MASK(MLX5E_10GBASE_KR) 480 | MLX5E_PROT_MASK(MLX5E_10GBASE_KX4) 481 | MLX5E_PROT_MASK(MLX5E_1000BASE_KX))) { 482 return SUPPORTED_Backplane; 483 } 484 return 0; 485 } 486 487 static void get_speed_duplex(struct net_device *netdev, 488 u32 eth_proto_oper, 489 struct ethtool_cmd *cmd) 490 { 491 int i; 492 u32 speed = SPEED_UNKNOWN; 493 u8 duplex = DUPLEX_UNKNOWN; 494 495 if (!netif_carrier_ok(netdev)) 496 goto out; 497 498 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 499 if (eth_proto_oper & MLX5E_PROT_MASK(i)) { 500 speed = ptys2ethtool_table[i].speed; 501 duplex = DUPLEX_FULL; 502 break; 503 } 504 } 505 out: 506 ethtool_cmd_speed_set(cmd, speed); 507 cmd->duplex = duplex; 508 } 509 510 static void get_supported(u32 eth_proto_cap, u32 *supported) 511 { 512 *supported |= ptys2ethtool_supported_port(eth_proto_cap); 513 *supported |= ptys2ethtool_supported_link(eth_proto_cap); 514 *supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause; 515 } 516 517 static void get_advertising(u32 eth_proto_cap, u8 tx_pause, 518 u8 rx_pause, u32 *advertising) 519 { 520 *advertising |= ptys2ethtool_adver_link(eth_proto_cap); 521 *advertising |= tx_pause ? ADVERTISED_Pause : 0; 522 *advertising |= (tx_pause ^ rx_pause) ? ADVERTISED_Asym_Pause : 0; 523 } 524 525 static u8 get_connector_port(u32 eth_proto) 526 { 527 if (eth_proto & (MLX5E_PROT_MASK(MLX5E_10GBASE_SR) 528 | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4) 529 | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4) 530 | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) { 531 return PORT_FIBRE; 532 } 533 534 if (eth_proto & (MLX5E_PROT_MASK(MLX5E_40GBASE_CR4) 535 | MLX5E_PROT_MASK(MLX5E_10GBASE_CR) 536 | MLX5E_PROT_MASK(MLX5E_100GBASE_CR4))) { 537 return PORT_DA; 538 } 539 540 if (eth_proto & (MLX5E_PROT_MASK(MLX5E_10GBASE_KX4) 541 | MLX5E_PROT_MASK(MLX5E_10GBASE_KR) 542 | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4) 543 | MLX5E_PROT_MASK(MLX5E_100GBASE_KR4))) { 544 return PORT_NONE; 545 } 546 547 return PORT_OTHER; 548 } 549 550 static void get_lp_advertising(u32 eth_proto_lp, u32 *lp_advertising) 551 { 552 *lp_advertising = ptys2ethtool_adver_link(eth_proto_lp); 553 } 554 555 static int mlx5e_get_settings(struct net_device *netdev, 556 struct ethtool_cmd *cmd) 557 { 558 struct mlx5e_priv *priv = netdev_priv(netdev); 559 struct mlx5_core_dev *mdev = priv->mdev; 560 u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 561 u32 eth_proto_cap; 562 u32 eth_proto_admin; 563 u32 eth_proto_lp; 564 u32 eth_proto_oper; 565 int err; 566 567 err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1); 568 569 if (err) { 570 netdev_err(netdev, "%s: query port ptys failed: %d\n", 571 __func__, err); 572 goto err_query_ptys; 573 } 574 575 eth_proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability); 576 eth_proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin); 577 eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 578 eth_proto_lp = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise); 579 580 cmd->supported = 0; 581 cmd->advertising = 0; 582 583 get_supported(eth_proto_cap, &cmd->supported); 584 get_advertising(eth_proto_admin, 0, 0, &cmd->advertising); 585 get_speed_duplex(netdev, eth_proto_oper, cmd); 586 587 eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap; 588 589 cmd->port = get_connector_port(eth_proto_oper); 590 get_lp_advertising(eth_proto_lp, &cmd->lp_advertising); 591 592 cmd->transceiver = XCVR_INTERNAL; 593 594 err_query_ptys: 595 return err; 596 } 597 598 static u32 mlx5e_ethtool2ptys_adver_link(u32 link_modes) 599 { 600 u32 i, ptys_modes = 0; 601 602 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 603 if (ptys2ethtool_table[i].advertised & link_modes) 604 ptys_modes |= MLX5E_PROT_MASK(i); 605 } 606 607 return ptys_modes; 608 } 609 610 static u32 mlx5e_ethtool2ptys_speed_link(u32 speed) 611 { 612 u32 i, speed_links = 0; 613 614 for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 615 if (ptys2ethtool_table[i].speed == speed) 616 speed_links |= MLX5E_PROT_MASK(i); 617 } 618 619 return speed_links; 620 } 621 622 static int mlx5e_set_settings(struct net_device *netdev, 623 struct ethtool_cmd *cmd) 624 { 625 struct mlx5e_priv *priv = netdev_priv(netdev); 626 struct mlx5_core_dev *mdev = priv->mdev; 627 u32 link_modes; 628 u32 speed; 629 u32 eth_proto_cap, eth_proto_admin; 630 enum mlx5_port_status ps; 631 int err; 632 633 speed = ethtool_cmd_speed(cmd); 634 635 link_modes = cmd->autoneg == AUTONEG_ENABLE ? 636 mlx5e_ethtool2ptys_adver_link(cmd->advertising) : 637 mlx5e_ethtool2ptys_speed_link(speed); 638 639 err = mlx5_query_port_proto_cap(mdev, ð_proto_cap, MLX5_PTYS_EN); 640 if (err) { 641 netdev_err(netdev, "%s: query port eth proto cap failed: %d\n", 642 __func__, err); 643 goto out; 644 } 645 646 link_modes = link_modes & eth_proto_cap; 647 if (!link_modes) { 648 netdev_err(netdev, "%s: Not supported link mode(s) requested", 649 __func__); 650 err = -EINVAL; 651 goto out; 652 } 653 654 err = mlx5_query_port_proto_admin(mdev, ð_proto_admin, MLX5_PTYS_EN); 655 if (err) { 656 netdev_err(netdev, "%s: query port eth proto admin failed: %d\n", 657 __func__, err); 658 goto out; 659 } 660 661 if (link_modes == eth_proto_admin) 662 goto out; 663 664 mlx5_query_port_admin_status(mdev, &ps); 665 if (ps == MLX5_PORT_UP) 666 mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN); 667 mlx5_set_port_proto(mdev, link_modes, MLX5_PTYS_EN); 668 if (ps == MLX5_PORT_UP) 669 mlx5_set_port_admin_status(mdev, MLX5_PORT_UP); 670 671 out: 672 return err; 673 } 674 675 static u32 mlx5e_get_rxfh_key_size(struct net_device *netdev) 676 { 677 struct mlx5e_priv *priv = netdev_priv(netdev); 678 679 return sizeof(priv->params.toeplitz_hash_key); 680 } 681 682 static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev) 683 { 684 return MLX5E_INDIR_RQT_SIZE; 685 } 686 687 static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, 688 u8 *hfunc) 689 { 690 struct mlx5e_priv *priv = netdev_priv(netdev); 691 692 if (indir) 693 memcpy(indir, priv->params.indirection_rqt, 694 sizeof(priv->params.indirection_rqt)); 695 696 if (key) 697 memcpy(key, priv->params.toeplitz_hash_key, 698 sizeof(priv->params.toeplitz_hash_key)); 699 700 if (hfunc) 701 *hfunc = priv->params.rss_hfunc; 702 703 return 0; 704 } 705 706 static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir, 707 const u8 *key, const u8 hfunc) 708 { 709 struct mlx5e_priv *priv = netdev_priv(dev); 710 bool close_open; 711 int err = 0; 712 713 if ((hfunc != ETH_RSS_HASH_NO_CHANGE) && 714 (hfunc != ETH_RSS_HASH_XOR) && 715 (hfunc != ETH_RSS_HASH_TOP)) 716 return -EINVAL; 717 718 mutex_lock(&priv->state_lock); 719 720 if (indir) { 721 memcpy(priv->params.indirection_rqt, indir, 722 sizeof(priv->params.indirection_rqt)); 723 mlx5e_redirect_rqt(priv, MLX5E_INDIRECTION_RQT); 724 } 725 726 close_open = (key || (hfunc != ETH_RSS_HASH_NO_CHANGE)) && 727 test_bit(MLX5E_STATE_OPENED, &priv->state); 728 if (close_open) 729 mlx5e_close_locked(dev); 730 731 if (key) 732 memcpy(priv->params.toeplitz_hash_key, key, 733 sizeof(priv->params.toeplitz_hash_key)); 734 735 if (hfunc != ETH_RSS_HASH_NO_CHANGE) 736 priv->params.rss_hfunc = hfunc; 737 738 if (close_open) 739 err = mlx5e_open_locked(priv->netdev); 740 741 mutex_unlock(&priv->state_lock); 742 743 return err; 744 } 745 746 static int mlx5e_get_rxnfc(struct net_device *netdev, 747 struct ethtool_rxnfc *info, u32 *rule_locs) 748 { 749 struct mlx5e_priv *priv = netdev_priv(netdev); 750 int err = 0; 751 752 switch (info->cmd) { 753 case ETHTOOL_GRXRINGS: 754 info->data = priv->params.num_channels; 755 break; 756 default: 757 err = -EOPNOTSUPP; 758 break; 759 } 760 761 return err; 762 } 763 764 static int mlx5e_get_tunable(struct net_device *dev, 765 const struct ethtool_tunable *tuna, 766 void *data) 767 { 768 const struct mlx5e_priv *priv = netdev_priv(dev); 769 int err = 0; 770 771 switch (tuna->id) { 772 case ETHTOOL_TX_COPYBREAK: 773 *(u32 *)data = priv->params.tx_max_inline; 774 break; 775 default: 776 err = -EINVAL; 777 break; 778 } 779 780 return err; 781 } 782 783 static int mlx5e_set_tunable(struct net_device *dev, 784 const struct ethtool_tunable *tuna, 785 const void *data) 786 { 787 struct mlx5e_priv *priv = netdev_priv(dev); 788 struct mlx5_core_dev *mdev = priv->mdev; 789 bool was_opened; 790 u32 val; 791 int err = 0; 792 793 switch (tuna->id) { 794 case ETHTOOL_TX_COPYBREAK: 795 val = *(u32 *)data; 796 if (val > mlx5e_get_max_inline_cap(mdev)) { 797 err = -EINVAL; 798 break; 799 } 800 801 mutex_lock(&priv->state_lock); 802 803 was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 804 if (was_opened) 805 mlx5e_close_locked(dev); 806 807 priv->params.tx_max_inline = val; 808 809 if (was_opened) 810 err = mlx5e_open_locked(dev); 811 812 mutex_unlock(&priv->state_lock); 813 break; 814 default: 815 err = -EINVAL; 816 break; 817 } 818 819 return err; 820 } 821 822 static void mlx5e_get_pauseparam(struct net_device *netdev, 823 struct ethtool_pauseparam *pauseparam) 824 { 825 struct mlx5e_priv *priv = netdev_priv(netdev); 826 struct mlx5_core_dev *mdev = priv->mdev; 827 int err; 828 829 err = mlx5_query_port_pause(mdev, &pauseparam->rx_pause, 830 &pauseparam->tx_pause); 831 if (err) { 832 netdev_err(netdev, "%s: mlx5_query_port_pause failed:0x%x\n", 833 __func__, err); 834 } 835 } 836 837 static int mlx5e_set_pauseparam(struct net_device *netdev, 838 struct ethtool_pauseparam *pauseparam) 839 { 840 struct mlx5e_priv *priv = netdev_priv(netdev); 841 struct mlx5_core_dev *mdev = priv->mdev; 842 int err; 843 844 if (pauseparam->autoneg) 845 return -EINVAL; 846 847 err = mlx5_set_port_pause(mdev, 848 pauseparam->rx_pause ? 1 : 0, 849 pauseparam->tx_pause ? 1 : 0); 850 if (err) { 851 netdev_err(netdev, "%s: mlx5_set_port_pause failed:0x%x\n", 852 __func__, err); 853 } 854 855 return err; 856 } 857 858 const struct ethtool_ops mlx5e_ethtool_ops = { 859 .get_drvinfo = mlx5e_get_drvinfo, 860 .get_link = ethtool_op_get_link, 861 .get_strings = mlx5e_get_strings, 862 .get_sset_count = mlx5e_get_sset_count, 863 .get_ethtool_stats = mlx5e_get_ethtool_stats, 864 .get_ringparam = mlx5e_get_ringparam, 865 .set_ringparam = mlx5e_set_ringparam, 866 .get_channels = mlx5e_get_channels, 867 .set_channels = mlx5e_set_channels, 868 .get_coalesce = mlx5e_get_coalesce, 869 .set_coalesce = mlx5e_set_coalesce, 870 .get_settings = mlx5e_get_settings, 871 .set_settings = mlx5e_set_settings, 872 .get_rxfh_key_size = mlx5e_get_rxfh_key_size, 873 .get_rxfh_indir_size = mlx5e_get_rxfh_indir_size, 874 .get_rxfh = mlx5e_get_rxfh, 875 .set_rxfh = mlx5e_set_rxfh, 876 .get_rxnfc = mlx5e_get_rxnfc, 877 .get_tunable = mlx5e_get_tunable, 878 .set_tunable = mlx5e_set_tunable, 879 .get_pauseparam = mlx5e_get_pauseparam, 880 .set_pauseparam = mlx5e_set_pauseparam, 881 }; 882