linux/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
<<
>>
Prefs
   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
  35static 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
  51static 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_1000BASE_T]    = {
 142                .supported  = SUPPORTED_1000baseT_Full,
 143                .advertised = ADVERTISED_1000baseT_Full,
 144                .speed      = 1000,
 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
 168static 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
 184static 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 (tc = 0; tc < priv->params.num_tc; tc++)
 215                        for (i = 0; i < priv->params.num_channels; i++)
 216                                for (j = 0; j < NUM_SQ_STATS; j++)
 217                                        sprintf(data +
 218                                              (idx++) * ETH_GSTRING_LEN,
 219                                              "tx%d_%s",
 220                                              priv->channeltc_to_txq_map[i][tc],
 221                                              sq_stats_strings[j]);
 222                break;
 223        }
 224}
 225
 226static void mlx5e_get_ethtool_stats(struct net_device *dev,
 227                                    struct ethtool_stats *stats, u64 *data)
 228{
 229        struct mlx5e_priv *priv = netdev_priv(dev);
 230        int i, j, tc, idx = 0;
 231
 232        if (!data)
 233                return;
 234
 235        mutex_lock(&priv->state_lock);
 236        if (test_bit(MLX5E_STATE_OPENED, &priv->state))
 237                mlx5e_update_stats(priv);
 238        mutex_unlock(&priv->state_lock);
 239
 240        for (i = 0; i < NUM_VPORT_COUNTERS; i++)
 241                data[idx++] = ((u64 *)&priv->stats.vport)[i];
 242
 243        for (i = 0; i < NUM_PPORT_COUNTERS; i++)
 244                data[idx++] = be64_to_cpu(((__be64 *)&priv->stats.pport)[i]);
 245
 246        /* per channel counters */
 247        for (i = 0; i < priv->params.num_channels; i++)
 248                for (j = 0; j < NUM_RQ_STATS; j++)
 249                        data[idx++] = !test_bit(MLX5E_STATE_OPENED,
 250                                                &priv->state) ? 0 :
 251                                       ((u64 *)&priv->channel[i]->rq.stats)[j];
 252
 253        for (tc = 0; tc < priv->params.num_tc; tc++)
 254                for (i = 0; i < priv->params.num_channels; i++)
 255                        for (j = 0; j < NUM_SQ_STATS; j++)
 256                                data[idx++] = !test_bit(MLX5E_STATE_OPENED,
 257                                                        &priv->state) ? 0 :
 258                                ((u64 *)&priv->channel[i]->sq[tc].stats)[j];
 259}
 260
 261static void mlx5e_get_ringparam(struct net_device *dev,
 262                                struct ethtool_ringparam *param)
 263{
 264        struct mlx5e_priv *priv = netdev_priv(dev);
 265
 266        param->rx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE;
 267        param->tx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE;
 268        param->rx_pending     = 1 << priv->params.log_rq_size;
 269        param->tx_pending     = 1 << priv->params.log_sq_size;
 270}
 271
 272static int mlx5e_set_ringparam(struct net_device *dev,
 273                               struct ethtool_ringparam *param)
 274{
 275        struct mlx5e_priv *priv = netdev_priv(dev);
 276        bool was_opened;
 277        u16 min_rx_wqes;
 278        u8 log_rq_size;
 279        u8 log_sq_size;
 280        int err = 0;
 281
 282        if (param->rx_jumbo_pending) {
 283                netdev_info(dev, "%s: rx_jumbo_pending not supported\n",
 284                            __func__);
 285                return -EINVAL;
 286        }
 287        if (param->rx_mini_pending) {
 288                netdev_info(dev, "%s: rx_mini_pending not supported\n",
 289                            __func__);
 290                return -EINVAL;
 291        }
 292        if (param->rx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) {
 293                netdev_info(dev, "%s: rx_pending (%d) < min (%d)\n",
 294                            __func__, param->rx_pending,
 295                            1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE);
 296                return -EINVAL;
 297        }
 298        if (param->rx_pending > (1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE)) {
 299                netdev_info(dev, "%s: rx_pending (%d) > max (%d)\n",
 300                            __func__, param->rx_pending,
 301                            1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE);
 302                return -EINVAL;
 303        }
 304        if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) {
 305                netdev_info(dev, "%s: tx_pending (%d) < min (%d)\n",
 306                            __func__, param->tx_pending,
 307                            1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE);
 308                return -EINVAL;
 309        }
 310        if (param->tx_pending > (1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE)) {
 311                netdev_info(dev, "%s: tx_pending (%d) > max (%d)\n",
 312                            __func__, param->tx_pending,
 313                            1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE);
 314                return -EINVAL;
 315        }
 316
 317        log_rq_size = order_base_2(param->rx_pending);
 318        log_sq_size = order_base_2(param->tx_pending);
 319        min_rx_wqes = min_t(u16, param->rx_pending - 1,
 320                            MLX5E_PARAMS_DEFAULT_MIN_RX_WQES);
 321
 322        if (log_rq_size == priv->params.log_rq_size &&
 323            log_sq_size == priv->params.log_sq_size &&
 324            min_rx_wqes == priv->params.min_rx_wqes)
 325                return 0;
 326
 327        mutex_lock(&priv->state_lock);
 328
 329        was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
 330        if (was_opened)
 331                mlx5e_close_locked(dev);
 332
 333        priv->params.log_rq_size = log_rq_size;
 334        priv->params.log_sq_size = log_sq_size;
 335        priv->params.min_rx_wqes = min_rx_wqes;
 336
 337        if (was_opened)
 338                err = mlx5e_open_locked(dev);
 339
 340        mutex_unlock(&priv->state_lock);
 341
 342        return err;
 343}
 344
 345static void mlx5e_get_channels(struct net_device *dev,
 346                               struct ethtool_channels *ch)
 347{
 348        struct mlx5e_priv *priv = netdev_priv(dev);
 349
 350        ch->max_combined   = mlx5e_get_max_num_channels(priv->mdev);
 351        ch->combined_count = priv->params.num_channels;
 352}
 353
 354static int mlx5e_set_channels(struct net_device *dev,
 355                              struct ethtool_channels *ch)
 356{
 357        struct mlx5e_priv *priv = netdev_priv(dev);
 358        int ncv = mlx5e_get_max_num_channels(priv->mdev);
 359        unsigned int count = ch->combined_count;
 360        bool was_opened;
 361        int err = 0;
 362
 363        if (!count) {
 364                netdev_info(dev, "%s: combined_count=0 not supported\n",
 365                            __func__);
 366                return -EINVAL;
 367        }
 368        if (ch->rx_count || ch->tx_count) {
 369                netdev_info(dev, "%s: separate rx/tx count not supported\n",
 370                            __func__);
 371                return -EINVAL;
 372        }
 373        if (count > ncv) {
 374                netdev_info(dev, "%s: count (%d) > max (%d)\n",
 375                            __func__, count, ncv);
 376                return -EINVAL;
 377        }
 378
 379        if (priv->params.num_channels == count)
 380                return 0;
 381
 382        mutex_lock(&priv->state_lock);
 383
 384        was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
 385        if (was_opened)
 386                mlx5e_close_locked(dev);
 387
 388        priv->params.num_channels = count;
 389        mlx5e_build_default_indir_rqt(priv->params.indirection_rqt,
 390                                      MLX5E_INDIR_RQT_SIZE, count);
 391
 392        if (was_opened)
 393                err = mlx5e_open_locked(dev);
 394
 395        mutex_unlock(&priv->state_lock);
 396
 397        return err;
 398}
 399
 400static int mlx5e_get_coalesce(struct net_device *netdev,
 401                              struct ethtool_coalesce *coal)
 402{
 403        struct mlx5e_priv *priv = netdev_priv(netdev);
 404
 405        if (!MLX5_CAP_GEN(priv->mdev, cq_moderation))
 406                return -ENOTSUPP;
 407
 408        coal->rx_coalesce_usecs       = priv->params.rx_cq_moderation_usec;
 409        coal->rx_max_coalesced_frames = priv->params.rx_cq_moderation_pkts;
 410        coal->tx_coalesce_usecs       = priv->params.tx_cq_moderation_usec;
 411        coal->tx_max_coalesced_frames = priv->params.tx_cq_moderation_pkts;
 412
 413        return 0;
 414}
 415
 416static int mlx5e_set_coalesce(struct net_device *netdev,
 417                              struct ethtool_coalesce *coal)
 418{
 419        struct mlx5e_priv *priv    = netdev_priv(netdev);
 420        struct mlx5_core_dev *mdev = priv->mdev;
 421        struct mlx5e_channel *c;
 422        int tc;
 423        int i;
 424
 425        if (!MLX5_CAP_GEN(mdev, cq_moderation))
 426                return -ENOTSUPP;
 427
 428        mutex_lock(&priv->state_lock);
 429        priv->params.tx_cq_moderation_usec = coal->tx_coalesce_usecs;
 430        priv->params.tx_cq_moderation_pkts = coal->tx_max_coalesced_frames;
 431        priv->params.rx_cq_moderation_usec = coal->rx_coalesce_usecs;
 432        priv->params.rx_cq_moderation_pkts = coal->rx_max_coalesced_frames;
 433
 434        if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
 435                goto out;
 436
 437        for (i = 0; i < priv->params.num_channels; ++i) {
 438                c = priv->channel[i];
 439
 440                for (tc = 0; tc < c->num_tc; tc++) {
 441                        mlx5_core_modify_cq_moderation(mdev,
 442                                                &c->sq[tc].cq.mcq,
 443                                                coal->tx_coalesce_usecs,
 444                                                coal->tx_max_coalesced_frames);
 445                }
 446
 447                mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq,
 448                                               coal->rx_coalesce_usecs,
 449                                               coal->rx_max_coalesced_frames);
 450        }
 451
 452out:
 453        mutex_unlock(&priv->state_lock);
 454        return 0;
 455}
 456
 457static u32 ptys2ethtool_supported_link(u32 eth_proto_cap)
 458{
 459        int i;
 460        u32 supported_modes = 0;
 461
 462        for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
 463                if (eth_proto_cap & MLX5E_PROT_MASK(i))
 464                        supported_modes |= ptys2ethtool_table[i].supported;
 465        }
 466        return supported_modes;
 467}
 468
 469static u32 ptys2ethtool_adver_link(u32 eth_proto_cap)
 470{
 471        int i;
 472        u32 advertising_modes = 0;
 473
 474        for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
 475                if (eth_proto_cap & MLX5E_PROT_MASK(i))
 476                        advertising_modes |= ptys2ethtool_table[i].advertised;
 477        }
 478        return advertising_modes;
 479}
 480
 481static u32 ptys2ethtool_supported_port(u32 eth_proto_cap)
 482{
 483        if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
 484                           | MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
 485                           | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
 486                           | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
 487                           | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
 488                           | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
 489                return SUPPORTED_FIBRE;
 490        }
 491
 492        if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_100GBASE_KR4)
 493                           | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4)
 494                           | MLX5E_PROT_MASK(MLX5E_10GBASE_KR)
 495                           | MLX5E_PROT_MASK(MLX5E_10GBASE_KX4)
 496                           | MLX5E_PROT_MASK(MLX5E_1000BASE_KX))) {
 497                return SUPPORTED_Backplane;
 498        }
 499        return 0;
 500}
 501
 502static void get_speed_duplex(struct net_device *netdev,
 503                             u32 eth_proto_oper,
 504                             struct ethtool_cmd *cmd)
 505{
 506        int i;
 507        u32 speed = SPEED_UNKNOWN;
 508        u8 duplex = DUPLEX_UNKNOWN;
 509
 510        if (!netif_carrier_ok(netdev))
 511                goto out;
 512
 513        for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
 514                if (eth_proto_oper & MLX5E_PROT_MASK(i)) {
 515                        speed = ptys2ethtool_table[i].speed;
 516                        duplex = DUPLEX_FULL;
 517                        break;
 518                }
 519        }
 520out:
 521        ethtool_cmd_speed_set(cmd, speed);
 522        cmd->duplex = duplex;
 523}
 524
 525static void get_supported(u32 eth_proto_cap, u32 *supported)
 526{
 527        *supported |= ptys2ethtool_supported_port(eth_proto_cap);
 528        *supported |= ptys2ethtool_supported_link(eth_proto_cap);
 529        *supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 530}
 531
 532static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
 533                            u8 rx_pause, u32 *advertising)
 534{
 535        *advertising |= ptys2ethtool_adver_link(eth_proto_cap);
 536        *advertising |= tx_pause ? ADVERTISED_Pause : 0;
 537        *advertising |= (tx_pause ^ rx_pause) ? ADVERTISED_Asym_Pause : 0;
 538}
 539
 540static u8 get_connector_port(u32 eth_proto)
 541{
 542        if (eth_proto & (MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
 543                         | MLX5E_PROT_MASK(MLX5E_40GBASE_SR4)
 544                         | MLX5E_PROT_MASK(MLX5E_100GBASE_SR4)
 545                         | MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII))) {
 546                        return PORT_FIBRE;
 547        }
 548
 549        if (eth_proto & (MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
 550                         | MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
 551                         | MLX5E_PROT_MASK(MLX5E_100GBASE_CR4))) {
 552                        return PORT_DA;
 553        }
 554
 555        if (eth_proto & (MLX5E_PROT_MASK(MLX5E_10GBASE_KX4)
 556                         | MLX5E_PROT_MASK(MLX5E_10GBASE_KR)
 557                         | MLX5E_PROT_MASK(MLX5E_40GBASE_KR4)
 558                         | MLX5E_PROT_MASK(MLX5E_100GBASE_KR4))) {
 559                        return PORT_NONE;
 560        }
 561
 562        return PORT_OTHER;
 563}
 564
 565static void get_lp_advertising(u32 eth_proto_lp, u32 *lp_advertising)
 566{
 567        *lp_advertising = ptys2ethtool_adver_link(eth_proto_lp);
 568}
 569
 570static int mlx5e_get_settings(struct net_device *netdev,
 571                              struct ethtool_cmd *cmd)
 572{
 573        struct mlx5e_priv *priv    = netdev_priv(netdev);
 574        struct mlx5_core_dev *mdev = priv->mdev;
 575        u32 out[MLX5_ST_SZ_DW(ptys_reg)];
 576        u32 eth_proto_cap;
 577        u32 eth_proto_admin;
 578        u32 eth_proto_lp;
 579        u32 eth_proto_oper;
 580        int err;
 581
 582        err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1);
 583
 584        if (err) {
 585                netdev_err(netdev, "%s: query port ptys failed: %d\n",
 586                           __func__, err);
 587                goto err_query_ptys;
 588        }
 589
 590        eth_proto_cap   = MLX5_GET(ptys_reg, out, eth_proto_capability);
 591        eth_proto_admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
 592        eth_proto_oper  = MLX5_GET(ptys_reg, out, eth_proto_oper);
 593        eth_proto_lp    = MLX5_GET(ptys_reg, out, eth_proto_lp_advertise);
 594
 595        cmd->supported   = 0;
 596        cmd->advertising = 0;
 597
 598        get_supported(eth_proto_cap, &cmd->supported);
 599        get_advertising(eth_proto_admin, 0, 0, &cmd->advertising);
 600        get_speed_duplex(netdev, eth_proto_oper, cmd);
 601
 602        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
 603
 604        cmd->port = get_connector_port(eth_proto_oper);
 605        get_lp_advertising(eth_proto_lp, &cmd->lp_advertising);
 606
 607        cmd->transceiver = XCVR_INTERNAL;
 608
 609err_query_ptys:
 610        return err;
 611}
 612
 613static u32 mlx5e_ethtool2ptys_adver_link(u32 link_modes)
 614{
 615        u32 i, ptys_modes = 0;
 616
 617        for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
 618                if (ptys2ethtool_table[i].advertised & link_modes)
 619                        ptys_modes |= MLX5E_PROT_MASK(i);
 620        }
 621
 622        return ptys_modes;
 623}
 624
 625static u32 mlx5e_ethtool2ptys_speed_link(u32 speed)
 626{
 627        u32 i, speed_links = 0;
 628
 629        for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
 630                if (ptys2ethtool_table[i].speed == speed)
 631                        speed_links |= MLX5E_PROT_MASK(i);
 632        }
 633
 634        return speed_links;
 635}
 636
 637static int mlx5e_set_settings(struct net_device *netdev,
 638                              struct ethtool_cmd *cmd)
 639{
 640        struct mlx5e_priv *priv    = netdev_priv(netdev);
 641        struct mlx5_core_dev *mdev = priv->mdev;
 642        u32 link_modes;
 643        u32 speed;
 644        u32 eth_proto_cap, eth_proto_admin;
 645        enum mlx5_port_status ps;
 646        int err;
 647
 648        speed = ethtool_cmd_speed(cmd);
 649
 650        link_modes = cmd->autoneg == AUTONEG_ENABLE ?
 651                mlx5e_ethtool2ptys_adver_link(cmd->advertising) :
 652                mlx5e_ethtool2ptys_speed_link(speed);
 653
 654        err = mlx5_query_port_proto_cap(mdev, &eth_proto_cap, MLX5_PTYS_EN);
 655        if (err) {
 656                netdev_err(netdev, "%s: query port eth proto cap failed: %d\n",
 657                           __func__, err);
 658                goto out;
 659        }
 660
 661        link_modes = link_modes & eth_proto_cap;
 662        if (!link_modes) {
 663                netdev_err(netdev, "%s: Not supported link mode(s) requested",
 664                           __func__);
 665                err = -EINVAL;
 666                goto out;
 667        }
 668
 669        err = mlx5_query_port_proto_admin(mdev, &eth_proto_admin, MLX5_PTYS_EN);
 670        if (err) {
 671                netdev_err(netdev, "%s: query port eth proto admin failed: %d\n",
 672                           __func__, err);
 673                goto out;
 674        }
 675
 676        if (link_modes == eth_proto_admin)
 677                goto out;
 678
 679        mlx5_query_port_admin_status(mdev, &ps);
 680        if (ps == MLX5_PORT_UP)
 681                mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);
 682        mlx5_set_port_proto(mdev, link_modes, MLX5_PTYS_EN);
 683        if (ps == MLX5_PORT_UP)
 684                mlx5_set_port_admin_status(mdev, MLX5_PORT_UP);
 685
 686out:
 687        return err;
 688}
 689
 690static u32 mlx5e_get_rxfh_key_size(struct net_device *netdev)
 691{
 692        struct mlx5e_priv *priv = netdev_priv(netdev);
 693
 694        return sizeof(priv->params.toeplitz_hash_key);
 695}
 696
 697static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
 698{
 699        return MLX5E_INDIR_RQT_SIZE;
 700}
 701
 702static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
 703                          u8 *hfunc)
 704{
 705        struct mlx5e_priv *priv = netdev_priv(netdev);
 706
 707        if (indir)
 708                memcpy(indir, priv->params.indirection_rqt,
 709                       sizeof(priv->params.indirection_rqt));
 710
 711        if (key)
 712                memcpy(key, priv->params.toeplitz_hash_key,
 713                       sizeof(priv->params.toeplitz_hash_key));
 714
 715        if (hfunc)
 716                *hfunc = priv->params.rss_hfunc;
 717
 718        return 0;
 719}
 720
 721static void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
 722{
 723        struct mlx5_core_dev *mdev = priv->mdev;
 724        void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
 725        int i;
 726
 727        MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
 728        mlx5e_build_tir_ctx_hash(tirc, priv);
 729
 730        for (i = 0; i < MLX5E_NUM_TT; i++)
 731                if (IS_HASHING_TT(i))
 732                        mlx5_core_modify_tir(mdev, priv->tirn[i], in, inlen);
 733}
 734
 735static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
 736                          const u8 *key, const u8 hfunc)
 737{
 738        struct mlx5e_priv *priv = netdev_priv(dev);
 739        int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
 740        void *in;
 741
 742        if ((hfunc != ETH_RSS_HASH_NO_CHANGE) &&
 743            (hfunc != ETH_RSS_HASH_XOR) &&
 744            (hfunc != ETH_RSS_HASH_TOP))
 745                return -EINVAL;
 746
 747        in = mlx5_vzalloc(inlen);
 748        if (!in)
 749                return -ENOMEM;
 750
 751        mutex_lock(&priv->state_lock);
 752
 753        if (indir) {
 754                memcpy(priv->params.indirection_rqt, indir,
 755                       sizeof(priv->params.indirection_rqt));
 756                mlx5e_redirect_rqt(priv, MLX5E_INDIRECTION_RQT);
 757        }
 758
 759        if (key)
 760                memcpy(priv->params.toeplitz_hash_key, key,
 761                       sizeof(priv->params.toeplitz_hash_key));
 762
 763        if (hfunc != ETH_RSS_HASH_NO_CHANGE)
 764                priv->params.rss_hfunc = hfunc;
 765
 766        mlx5e_modify_tirs_hash(priv, in, inlen);
 767
 768        mutex_unlock(&priv->state_lock);
 769
 770        kvfree(in);
 771
 772        return 0;
 773}
 774
 775static int mlx5e_get_rxnfc(struct net_device *netdev,
 776                           struct ethtool_rxnfc *info, u32 *rule_locs)
 777{
 778        struct mlx5e_priv *priv = netdev_priv(netdev);
 779        int err = 0;
 780
 781        switch (info->cmd) {
 782        case ETHTOOL_GRXRINGS:
 783                info->data = priv->params.num_channels;
 784                break;
 785        default:
 786                err = -EOPNOTSUPP;
 787                break;
 788        }
 789
 790        return err;
 791}
 792
 793static int mlx5e_get_tunable(struct net_device *dev,
 794                             const struct ethtool_tunable *tuna,
 795                             void *data)
 796{
 797        const struct mlx5e_priv *priv = netdev_priv(dev);
 798        int err = 0;
 799
 800        switch (tuna->id) {
 801        case ETHTOOL_TX_COPYBREAK:
 802                *(u32 *)data = priv->params.tx_max_inline;
 803                break;
 804        default:
 805                err = -EINVAL;
 806                break;
 807        }
 808
 809        return err;
 810}
 811
 812static int mlx5e_set_tunable(struct net_device *dev,
 813                             const struct ethtool_tunable *tuna,
 814                             const void *data)
 815{
 816        struct mlx5e_priv *priv = netdev_priv(dev);
 817        struct mlx5_core_dev *mdev = priv->mdev;
 818        bool was_opened;
 819        u32 val;
 820        int err = 0;
 821
 822        switch (tuna->id) {
 823        case ETHTOOL_TX_COPYBREAK:
 824                val = *(u32 *)data;
 825                if (val > mlx5e_get_max_inline_cap(mdev)) {
 826                        err = -EINVAL;
 827                        break;
 828                }
 829
 830                mutex_lock(&priv->state_lock);
 831
 832                was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
 833                if (was_opened)
 834                        mlx5e_close_locked(dev);
 835
 836                priv->params.tx_max_inline = val;
 837
 838                if (was_opened)
 839                        err = mlx5e_open_locked(dev);
 840
 841                mutex_unlock(&priv->state_lock);
 842                break;
 843        default:
 844                err = -EINVAL;
 845                break;
 846        }
 847
 848        return err;
 849}
 850
 851static void mlx5e_get_pauseparam(struct net_device *netdev,
 852                                 struct ethtool_pauseparam *pauseparam)
 853{
 854        struct mlx5e_priv *priv    = netdev_priv(netdev);
 855        struct mlx5_core_dev *mdev = priv->mdev;
 856        int err;
 857
 858        err = mlx5_query_port_pause(mdev, &pauseparam->rx_pause,
 859                                    &pauseparam->tx_pause);
 860        if (err) {
 861                netdev_err(netdev, "%s: mlx5_query_port_pause failed:0x%x\n",
 862                           __func__, err);
 863        }
 864}
 865
 866static int mlx5e_set_pauseparam(struct net_device *netdev,
 867                                struct ethtool_pauseparam *pauseparam)
 868{
 869        struct mlx5e_priv *priv    = netdev_priv(netdev);
 870        struct mlx5_core_dev *mdev = priv->mdev;
 871        int err;
 872
 873        if (pauseparam->autoneg)
 874                return -EINVAL;
 875
 876        err = mlx5_set_port_pause(mdev,
 877                                  pauseparam->rx_pause ? 1 : 0,
 878                                  pauseparam->tx_pause ? 1 : 0);
 879        if (err) {
 880                netdev_err(netdev, "%s: mlx5_set_port_pause failed:0x%x\n",
 881                           __func__, err);
 882        }
 883
 884        return err;
 885}
 886
 887static int mlx5e_get_ts_info(struct net_device *dev,
 888                             struct ethtool_ts_info *info)
 889{
 890        struct mlx5e_priv *priv = netdev_priv(dev);
 891        int ret;
 892
 893        ret = ethtool_op_get_ts_info(dev, info);
 894        if (ret)
 895                return ret;
 896
 897        info->phc_index = priv->tstamp.ptp ?
 898                          ptp_clock_index(priv->tstamp.ptp) : -1;
 899
 900        if (!MLX5_CAP_GEN(priv->mdev, device_frequency_khz))
 901                return 0;
 902
 903        info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE |
 904                                 SOF_TIMESTAMPING_RX_HARDWARE |
 905                                 SOF_TIMESTAMPING_RAW_HARDWARE;
 906
 907        info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) |
 908                         (BIT(1) << HWTSTAMP_TX_ON);
 909
 910        info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) |
 911                           (BIT(1) << HWTSTAMP_FILTER_ALL);
 912
 913        return 0;
 914}
 915
 916static __u32 mlx5e_get_wol_supported(struct mlx5_core_dev *mdev)
 917{
 918        __u32 ret = 0;
 919
 920        if (MLX5_CAP_GEN(mdev, wol_g))
 921                ret |= WAKE_MAGIC;
 922
 923        if (MLX5_CAP_GEN(mdev, wol_s))
 924                ret |= WAKE_MAGICSECURE;
 925
 926        if (MLX5_CAP_GEN(mdev, wol_a))
 927                ret |= WAKE_ARP;
 928
 929        if (MLX5_CAP_GEN(mdev, wol_b))
 930                ret |= WAKE_BCAST;
 931
 932        if (MLX5_CAP_GEN(mdev, wol_m))
 933                ret |= WAKE_MCAST;
 934
 935        if (MLX5_CAP_GEN(mdev, wol_u))
 936                ret |= WAKE_UCAST;
 937
 938        if (MLX5_CAP_GEN(mdev, wol_p))
 939                ret |= WAKE_PHY;
 940
 941        return ret;
 942}
 943
 944static __u32 mlx5e_refomrat_wol_mode_mlx5_to_linux(u8 mode)
 945{
 946        __u32 ret = 0;
 947
 948        if (mode & MLX5_WOL_MAGIC)
 949                ret |= WAKE_MAGIC;
 950
 951        if (mode & MLX5_WOL_SECURED_MAGIC)
 952                ret |= WAKE_MAGICSECURE;
 953
 954        if (mode & MLX5_WOL_ARP)
 955                ret |= WAKE_ARP;
 956
 957        if (mode & MLX5_WOL_BROADCAST)
 958                ret |= WAKE_BCAST;
 959
 960        if (mode & MLX5_WOL_MULTICAST)
 961                ret |= WAKE_MCAST;
 962
 963        if (mode & MLX5_WOL_UNICAST)
 964                ret |= WAKE_UCAST;
 965
 966        if (mode & MLX5_WOL_PHY_ACTIVITY)
 967                ret |= WAKE_PHY;
 968
 969        return ret;
 970}
 971
 972static u8 mlx5e_refomrat_wol_mode_linux_to_mlx5(__u32 mode)
 973{
 974        u8 ret = 0;
 975
 976        if (mode & WAKE_MAGIC)
 977                ret |= MLX5_WOL_MAGIC;
 978
 979        if (mode & WAKE_MAGICSECURE)
 980                ret |= MLX5_WOL_SECURED_MAGIC;
 981
 982        if (mode & WAKE_ARP)
 983                ret |= MLX5_WOL_ARP;
 984
 985        if (mode & WAKE_BCAST)
 986                ret |= MLX5_WOL_BROADCAST;
 987
 988        if (mode & WAKE_MCAST)
 989                ret |= MLX5_WOL_MULTICAST;
 990
 991        if (mode & WAKE_UCAST)
 992                ret |= MLX5_WOL_UNICAST;
 993
 994        if (mode & WAKE_PHY)
 995                ret |= MLX5_WOL_PHY_ACTIVITY;
 996
 997        return ret;
 998}
 999
1000static void mlx5e_get_wol(struct net_device *netdev,
1001                          struct ethtool_wolinfo *wol)
1002{
1003        struct mlx5e_priv *priv = netdev_priv(netdev);
1004        struct mlx5_core_dev *mdev = priv->mdev;
1005        u8 mlx5_wol_mode;
1006        int err;
1007
1008        memset(wol, 0, sizeof(*wol));
1009
1010        wol->supported = mlx5e_get_wol_supported(mdev);
1011        if (!wol->supported)
1012                return;
1013
1014        err = mlx5_query_port_wol(mdev, &mlx5_wol_mode);
1015        if (err)
1016                return;
1017
1018        wol->wolopts = mlx5e_refomrat_wol_mode_mlx5_to_linux(mlx5_wol_mode);
1019}
1020
1021static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
1022{
1023        struct mlx5e_priv *priv = netdev_priv(netdev);
1024        struct mlx5_core_dev *mdev = priv->mdev;
1025        __u32 wol_supported = mlx5e_get_wol_supported(mdev);
1026        u32 mlx5_wol_mode;
1027
1028        if (!wol_supported)
1029                return -ENOTSUPP;
1030
1031        if (wol->wolopts & ~wol_supported)
1032                return -EINVAL;
1033
1034        mlx5_wol_mode = mlx5e_refomrat_wol_mode_linux_to_mlx5(wol->wolopts);
1035
1036        return mlx5_set_port_wol(mdev, mlx5_wol_mode);
1037}
1038
1039const struct ethtool_ops mlx5e_ethtool_ops = {
1040        .get_drvinfo       = mlx5e_get_drvinfo,
1041        .get_link          = ethtool_op_get_link,
1042        .get_strings       = mlx5e_get_strings,
1043        .get_sset_count    = mlx5e_get_sset_count,
1044        .get_ethtool_stats = mlx5e_get_ethtool_stats,
1045        .get_ringparam     = mlx5e_get_ringparam,
1046        .set_ringparam     = mlx5e_set_ringparam,
1047        .get_channels      = mlx5e_get_channels,
1048        .set_channels      = mlx5e_set_channels,
1049        .get_coalesce      = mlx5e_get_coalesce,
1050        .set_coalesce      = mlx5e_set_coalesce,
1051        .get_settings      = mlx5e_get_settings,
1052        .set_settings      = mlx5e_set_settings,
1053        .get_rxfh_key_size   = mlx5e_get_rxfh_key_size,
1054        .get_rxfh_indir_size = mlx5e_get_rxfh_indir_size,
1055        .get_rxfh          = mlx5e_get_rxfh,
1056        .set_rxfh          = mlx5e_set_rxfh,
1057        .get_rxnfc         = mlx5e_get_rxnfc,
1058        .get_tunable       = mlx5e_get_tunable,
1059        .set_tunable       = mlx5e_set_tunable,
1060        .get_pauseparam    = mlx5e_get_pauseparam,
1061        .set_pauseparam    = mlx5e_set_pauseparam,
1062        .get_ts_info       = mlx5e_get_ts_info,
1063        .get_wol           = mlx5e_get_wol,
1064        .set_wol           = mlx5e_set_wol,
1065};
1066