linux/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2017, 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 <rdma/ib_verbs.h>
  34#include <linux/mlx5/fs.h>
  35#include "en.h"
  36#include "en/params.h"
  37#include "ipoib.h"
  38
  39#define IB_DEFAULT_Q_KEY   0xb1b
  40#define MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE 9
  41
  42static int mlx5i_open(struct net_device *netdev);
  43static int mlx5i_close(struct net_device *netdev);
  44static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu);
  45
  46static const struct net_device_ops mlx5i_netdev_ops = {
  47        .ndo_open                = mlx5i_open,
  48        .ndo_stop                = mlx5i_close,
  49        .ndo_get_stats64         = mlx5i_get_stats,
  50        .ndo_init                = mlx5i_dev_init,
  51        .ndo_uninit              = mlx5i_dev_cleanup,
  52        .ndo_change_mtu          = mlx5i_change_mtu,
  53        .ndo_eth_ioctl            = mlx5i_ioctl,
  54};
  55
  56/* IPoIB mlx5 netdev profile */
  57static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev,
  58                                   struct mlx5e_params *params)
  59{
  60        /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */
  61        MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ, false);
  62        mlx5e_set_rq_type(mdev, params);
  63        mlx5e_init_rq_type_params(mdev, params);
  64
  65        /* RQ size in ipoib by default is 512 */
  66        params->log_rq_mtu_frames = is_kdump_kernel() ?
  67                MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE :
  68                MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE;
  69
  70        params->lro_en = false;
  71        params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN;
  72        params->tunneled_offload_en = false;
  73}
  74
  75/* Called directly after IPoIB netdevice was created to initialize SW structs */
  76int mlx5i_init(struct mlx5_core_dev *mdev, struct net_device *netdev)
  77{
  78        struct mlx5e_priv *priv  = mlx5i_epriv(netdev);
  79
  80        netif_carrier_off(netdev);
  81        mlx5e_set_netdev_mtu_boundaries(priv);
  82        netdev->mtu = netdev->max_mtu;
  83
  84        mlx5e_build_nic_params(priv, NULL, netdev->mtu);
  85        mlx5i_build_nic_params(mdev, &priv->channels.params);
  86
  87        mlx5e_timestamp_init(priv);
  88
  89        /* netdev init */
  90        netdev->hw_features    |= NETIF_F_SG;
  91        netdev->hw_features    |= NETIF_F_IP_CSUM;
  92        netdev->hw_features    |= NETIF_F_IPV6_CSUM;
  93        netdev->hw_features    |= NETIF_F_GRO;
  94        netdev->hw_features    |= NETIF_F_TSO;
  95        netdev->hw_features    |= NETIF_F_TSO6;
  96        netdev->hw_features    |= NETIF_F_RXCSUM;
  97        netdev->hw_features    |= NETIF_F_RXHASH;
  98
  99        netdev->netdev_ops = &mlx5i_netdev_ops;
 100        netdev->ethtool_ops = &mlx5i_ethtool_ops;
 101
 102        return 0;
 103}
 104
 105/* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */
 106void mlx5i_cleanup(struct mlx5e_priv *priv)
 107{
 108        mlx5e_priv_cleanup(priv);
 109}
 110
 111static void mlx5i_grp_sw_update_stats(struct mlx5e_priv *priv)
 112{
 113        struct mlx5e_sw_stats s = { 0 };
 114        int i, j;
 115
 116        for (i = 0; i < priv->stats_nch; i++) {
 117                struct mlx5e_channel_stats *channel_stats;
 118                struct mlx5e_rq_stats *rq_stats;
 119
 120                channel_stats = &priv->channel_stats[i];
 121                rq_stats = &channel_stats->rq;
 122
 123                s.rx_packets += rq_stats->packets;
 124                s.rx_bytes   += rq_stats->bytes;
 125
 126                for (j = 0; j < priv->max_opened_tc; j++) {
 127                        struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j];
 128
 129                        s.tx_packets           += sq_stats->packets;
 130                        s.tx_bytes             += sq_stats->bytes;
 131                        s.tx_queue_dropped     += sq_stats->dropped;
 132                }
 133        }
 134
 135        memcpy(&priv->stats.sw, &s, sizeof(s));
 136}
 137
 138void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 139{
 140        struct mlx5e_priv     *priv   = mlx5i_epriv(dev);
 141        struct mlx5e_sw_stats *sstats = &priv->stats.sw;
 142
 143        mlx5i_grp_sw_update_stats(priv);
 144
 145        stats->rx_packets = sstats->rx_packets;
 146        stats->rx_bytes   = sstats->rx_bytes;
 147        stats->tx_packets = sstats->tx_packets;
 148        stats->tx_bytes   = sstats->tx_bytes;
 149        stats->tx_dropped = sstats->tx_queue_dropped;
 150}
 151
 152int mlx5i_init_underlay_qp(struct mlx5e_priv *priv)
 153{
 154        struct mlx5_core_dev *mdev = priv->mdev;
 155        struct mlx5i_priv *ipriv = priv->ppriv;
 156        int ret;
 157
 158        {
 159                u32 in[MLX5_ST_SZ_DW(rst2init_qp_in)] = {};
 160                u32 *qpc;
 161
 162                qpc = MLX5_ADDR_OF(rst2init_qp_in, in, qpc);
 163
 164                MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
 165                MLX5_SET(qpc, qpc, primary_address_path.pkey_index,
 166                         ipriv->pkey_index);
 167                MLX5_SET(qpc, qpc, primary_address_path.vhca_port_num, 1);
 168                MLX5_SET(qpc, qpc, q_key, IB_DEFAULT_Q_KEY);
 169
 170                MLX5_SET(rst2init_qp_in, in, opcode, MLX5_CMD_OP_RST2INIT_QP);
 171                MLX5_SET(rst2init_qp_in, in, qpn, ipriv->qpn);
 172                ret = mlx5_cmd_exec_in(mdev, rst2init_qp, in);
 173                if (ret)
 174                        goto err_qp_modify_to_err;
 175        }
 176        {
 177                u32 in[MLX5_ST_SZ_DW(init2rtr_qp_in)] = {};
 178
 179                MLX5_SET(init2rtr_qp_in, in, opcode, MLX5_CMD_OP_INIT2RTR_QP);
 180                MLX5_SET(init2rtr_qp_in, in, qpn, ipriv->qpn);
 181                ret = mlx5_cmd_exec_in(mdev, init2rtr_qp, in);
 182                if (ret)
 183                        goto err_qp_modify_to_err;
 184        }
 185        {
 186                u32 in[MLX5_ST_SZ_DW(rtr2rts_qp_in)] = {};
 187
 188                MLX5_SET(rtr2rts_qp_in, in, opcode, MLX5_CMD_OP_RTR2RTS_QP);
 189                MLX5_SET(rtr2rts_qp_in, in, qpn, ipriv->qpn);
 190                ret = mlx5_cmd_exec_in(mdev, rtr2rts_qp, in);
 191                if (ret)
 192                        goto err_qp_modify_to_err;
 193        }
 194        return 0;
 195
 196err_qp_modify_to_err:
 197        {
 198                u32 in[MLX5_ST_SZ_DW(qp_2err_in)] = {};
 199
 200                MLX5_SET(qp_2err_in, in, opcode, MLX5_CMD_OP_2ERR_QP);
 201                MLX5_SET(qp_2err_in, in, qpn, ipriv->qpn);
 202                mlx5_cmd_exec_in(mdev, qp_2err, in);
 203        }
 204        return ret;
 205}
 206
 207void mlx5i_uninit_underlay_qp(struct mlx5e_priv *priv)
 208{
 209        struct mlx5i_priv *ipriv = priv->ppriv;
 210        struct mlx5_core_dev *mdev = priv->mdev;
 211        u32 in[MLX5_ST_SZ_DW(qp_2rst_in)] = {};
 212
 213        MLX5_SET(qp_2rst_in, in, opcode, MLX5_CMD_OP_2RST_QP);
 214        MLX5_SET(qp_2rst_in, in, qpn, ipriv->qpn);
 215        mlx5_cmd_exec_in(mdev, qp_2rst, in);
 216}
 217
 218#define MLX5_QP_ENHANCED_ULP_STATELESS_MODE 2
 219
 220int mlx5i_create_underlay_qp(struct mlx5e_priv *priv)
 221{
 222        unsigned char *dev_addr = priv->netdev->dev_addr;
 223        u32 out[MLX5_ST_SZ_DW(create_qp_out)] = {};
 224        u32 in[MLX5_ST_SZ_DW(create_qp_in)] = {};
 225        struct mlx5i_priv *ipriv = priv->ppriv;
 226        void *addr_path;
 227        int qpn = 0;
 228        int ret = 0;
 229        void *qpc;
 230
 231        if (MLX5_CAP_GEN(priv->mdev, mkey_by_name)) {
 232                qpn = (dev_addr[1] << 16) + (dev_addr[2] << 8) + dev_addr[3];
 233                MLX5_SET(create_qp_in, in, input_qpn, qpn);
 234        }
 235
 236        qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
 237        MLX5_SET(qpc, qpc, ts_format, mlx5_get_qp_default_ts(priv->mdev));
 238        MLX5_SET(qpc, qpc, st, MLX5_QP_ST_UD);
 239        MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
 240        MLX5_SET(qpc, qpc, ulp_stateless_offload_mode,
 241                 MLX5_QP_ENHANCED_ULP_STATELESS_MODE);
 242
 243        addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path);
 244        MLX5_SET(ads, addr_path, vhca_port_num, 1);
 245        MLX5_SET(ads, addr_path, grh, 1);
 246
 247        MLX5_SET(create_qp_in, in, opcode, MLX5_CMD_OP_CREATE_QP);
 248        ret = mlx5_cmd_exec_inout(priv->mdev, create_qp, in, out);
 249        if (ret)
 250                return ret;
 251
 252        ipriv->qpn = MLX5_GET(create_qp_out, out, qpn);
 253
 254        return 0;
 255}
 256
 257void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, u32 qpn)
 258{
 259        u32 in[MLX5_ST_SZ_DW(destroy_qp_in)] = {};
 260
 261        MLX5_SET(destroy_qp_in, in, opcode, MLX5_CMD_OP_DESTROY_QP);
 262        MLX5_SET(destroy_qp_in, in, qpn, qpn);
 263        mlx5_cmd_exec_in(mdev, destroy_qp, in);
 264}
 265
 266int mlx5i_update_nic_rx(struct mlx5e_priv *priv)
 267{
 268        return mlx5e_refresh_tirs(priv, true, true);
 269}
 270
 271int mlx5i_create_tis(struct mlx5_core_dev *mdev, u32 underlay_qpn, u32 *tisn)
 272{
 273        u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {};
 274        void *tisc;
 275
 276        tisc = MLX5_ADDR_OF(create_tis_in, in, ctx);
 277
 278        MLX5_SET(tisc, tisc, underlay_qpn, underlay_qpn);
 279
 280        return mlx5e_create_tis(mdev, in, tisn);
 281}
 282
 283static int mlx5i_init_tx(struct mlx5e_priv *priv)
 284{
 285        struct mlx5i_priv *ipriv = priv->ppriv;
 286        int err;
 287
 288        err = mlx5i_create_underlay_qp(priv);
 289        if (err) {
 290                mlx5_core_warn(priv->mdev, "create underlay QP failed, %d\n", err);
 291                return err;
 292        }
 293
 294        err = mlx5i_create_tis(priv->mdev, ipriv->qpn, &priv->tisn[0][0]);
 295        if (err) {
 296                mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err);
 297                goto err_destroy_underlay_qp;
 298        }
 299
 300        return 0;
 301
 302err_destroy_underlay_qp:
 303        mlx5i_destroy_underlay_qp(priv->mdev, ipriv->qpn);
 304        return err;
 305}
 306
 307static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)
 308{
 309        struct mlx5i_priv *ipriv = priv->ppriv;
 310
 311        mlx5e_destroy_tis(priv->mdev, priv->tisn[0][0]);
 312        mlx5i_destroy_underlay_qp(priv->mdev, ipriv->qpn);
 313}
 314
 315static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 316{
 317        int err;
 318
 319        priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
 320                                               MLX5_FLOW_NAMESPACE_KERNEL);
 321
 322        if (!priv->fs.ns)
 323                return -EINVAL;
 324
 325        err = mlx5e_arfs_create_tables(priv);
 326        if (err) {
 327                netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n",
 328                           err);
 329                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
 330        }
 331
 332        err = mlx5e_create_ttc_table(priv);
 333        if (err) {
 334                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
 335                           err);
 336                goto err_destroy_arfs_tables;
 337        }
 338
 339        return 0;
 340
 341err_destroy_arfs_tables:
 342        mlx5e_arfs_destroy_tables(priv);
 343
 344        return err;
 345}
 346
 347static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv)
 348{
 349        mlx5e_destroy_ttc_table(priv);
 350        mlx5e_arfs_destroy_tables(priv);
 351}
 352
 353static int mlx5i_init_rx(struct mlx5e_priv *priv)
 354{
 355        struct mlx5_core_dev *mdev = priv->mdev;
 356        struct mlx5e_lro_param lro_param;
 357        int err;
 358
 359        priv->rx_res = mlx5e_rx_res_alloc();
 360        if (!priv->rx_res)
 361                return -ENOMEM;
 362
 363        mlx5e_create_q_counters(priv);
 364
 365        err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
 366        if (err) {
 367                mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
 368                goto err_destroy_q_counters;
 369        }
 370
 371        lro_param = mlx5e_get_lro_param(&priv->channels.params);
 372        err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0,
 373                                priv->max_nch, priv->drop_rq.rqn, &lro_param,
 374                                priv->channels.params.num_channels);
 375        if (err)
 376                goto err_close_drop_rq;
 377
 378        err = mlx5i_create_flow_steering(priv);
 379        if (err)
 380                goto err_destroy_rx_res;
 381
 382        return 0;
 383
 384err_destroy_rx_res:
 385        mlx5e_rx_res_destroy(priv->rx_res);
 386err_close_drop_rq:
 387        mlx5e_close_drop_rq(&priv->drop_rq);
 388err_destroy_q_counters:
 389        mlx5e_destroy_q_counters(priv);
 390        mlx5e_rx_res_free(priv->rx_res);
 391        priv->rx_res = NULL;
 392        return err;
 393}
 394
 395static void mlx5i_cleanup_rx(struct mlx5e_priv *priv)
 396{
 397        mlx5i_destroy_flow_steering(priv);
 398        mlx5e_rx_res_destroy(priv->rx_res);
 399        mlx5e_close_drop_rq(&priv->drop_rq);
 400        mlx5e_destroy_q_counters(priv);
 401        mlx5e_rx_res_free(priv->rx_res);
 402        priv->rx_res = NULL;
 403}
 404
 405/* The stats groups order is opposite to the update_stats() order calls */
 406static mlx5e_stats_grp_t mlx5i_stats_grps[] = {
 407        &MLX5E_STATS_GRP(sw),
 408        &MLX5E_STATS_GRP(qcnt),
 409        &MLX5E_STATS_GRP(vnic_env),
 410        &MLX5E_STATS_GRP(vport),
 411        &MLX5E_STATS_GRP(802_3),
 412        &MLX5E_STATS_GRP(2863),
 413        &MLX5E_STATS_GRP(2819),
 414        &MLX5E_STATS_GRP(phy),
 415        &MLX5E_STATS_GRP(pcie),
 416        &MLX5E_STATS_GRP(per_prio),
 417        &MLX5E_STATS_GRP(pme),
 418        &MLX5E_STATS_GRP(channels),
 419        &MLX5E_STATS_GRP(per_port_buff_congest),
 420};
 421
 422static unsigned int mlx5i_stats_grps_num(struct mlx5e_priv *priv)
 423{
 424        return ARRAY_SIZE(mlx5i_stats_grps);
 425}
 426
 427static const struct mlx5e_profile mlx5i_nic_profile = {
 428        .init              = mlx5i_init,
 429        .cleanup           = mlx5i_cleanup,
 430        .init_tx           = mlx5i_init_tx,
 431        .cleanup_tx        = mlx5i_cleanup_tx,
 432        .init_rx           = mlx5i_init_rx,
 433        .cleanup_rx        = mlx5i_cleanup_rx,
 434        .enable            = NULL, /* mlx5i_enable */
 435        .disable           = NULL, /* mlx5i_disable */
 436        .update_rx         = mlx5i_update_nic_rx,
 437        .update_stats      = NULL, /* mlx5i_update_stats */
 438        .update_carrier    = NULL, /* no HW update in IB link */
 439        .rx_handlers       = &mlx5i_rx_handlers,
 440        .max_tc            = MLX5I_MAX_NUM_TC,
 441        .rq_groups         = MLX5E_NUM_RQ_GROUPS(REGULAR),
 442        .stats_grps        = mlx5i_stats_grps,
 443        .stats_grps_num    = mlx5i_stats_grps_num,
 444        .rx_ptp_support    = false,
 445};
 446
 447/* mlx5i netdev NDos */
 448
 449static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu)
 450{
 451        struct mlx5e_priv *priv = mlx5i_epriv(netdev);
 452        struct mlx5e_params new_params;
 453        int err = 0;
 454
 455        mutex_lock(&priv->state_lock);
 456
 457        new_params = priv->channels.params;
 458        new_params.sw_mtu = new_mtu;
 459
 460        err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true);
 461        if (err)
 462                goto out;
 463
 464        netdev->mtu = new_params.sw_mtu;
 465
 466out:
 467        mutex_unlock(&priv->state_lock);
 468        return err;
 469}
 470
 471int mlx5i_dev_init(struct net_device *dev)
 472{
 473        struct mlx5e_priv    *priv   = mlx5i_epriv(dev);
 474        struct mlx5i_priv    *ipriv  = priv->ppriv;
 475
 476        /* Set dev address using underlay QP */
 477        dev->dev_addr[1] = (ipriv->qpn >> 16) & 0xff;
 478        dev->dev_addr[2] = (ipriv->qpn >>  8) & 0xff;
 479        dev->dev_addr[3] = (ipriv->qpn) & 0xff;
 480
 481        /* Add QPN to net-device mapping to HT */
 482        mlx5i_pkey_add_qpn(dev, ipriv->qpn);
 483
 484        return 0;
 485}
 486
 487int mlx5i_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 488{
 489        struct mlx5e_priv *priv = mlx5i_epriv(dev);
 490
 491        switch (cmd) {
 492        case SIOCSHWTSTAMP:
 493                return mlx5e_hwstamp_set(priv, ifr);
 494        case SIOCGHWTSTAMP:
 495                return mlx5e_hwstamp_get(priv, ifr);
 496        default:
 497                return -EOPNOTSUPP;
 498        }
 499}
 500
 501void mlx5i_dev_cleanup(struct net_device *dev)
 502{
 503        struct mlx5e_priv    *priv   = mlx5i_epriv(dev);
 504        struct mlx5i_priv    *ipriv = priv->ppriv;
 505
 506        mlx5i_uninit_underlay_qp(priv);
 507
 508        /* Delete QPN to net-device mapping from HT */
 509        mlx5i_pkey_del_qpn(dev, ipriv->qpn);
 510}
 511
 512static int mlx5i_open(struct net_device *netdev)
 513{
 514        struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
 515        struct mlx5i_priv *ipriv = epriv->ppriv;
 516        struct mlx5_core_dev *mdev = epriv->mdev;
 517        int err;
 518
 519        mutex_lock(&epriv->state_lock);
 520
 521        set_bit(MLX5E_STATE_OPENED, &epriv->state);
 522
 523        err = mlx5i_init_underlay_qp(epriv);
 524        if (err) {
 525                mlx5_core_warn(mdev, "prepare underlay qp state failed, %d\n", err);
 526                goto err_clear_state_opened_flag;
 527        }
 528
 529        err = mlx5_fs_add_rx_underlay_qpn(mdev, ipriv->qpn);
 530        if (err) {
 531                mlx5_core_warn(mdev, "attach underlay qp to ft failed, %d\n", err);
 532                goto err_reset_qp;
 533        }
 534
 535        err = mlx5e_open_channels(epriv, &epriv->channels);
 536        if (err)
 537                goto err_remove_fs_underlay_qp;
 538
 539        epriv->profile->update_rx(epriv);
 540        mlx5e_activate_priv_channels(epriv);
 541
 542        mutex_unlock(&epriv->state_lock);
 543        return 0;
 544
 545err_remove_fs_underlay_qp:
 546        mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qpn);
 547err_reset_qp:
 548        mlx5i_uninit_underlay_qp(epriv);
 549err_clear_state_opened_flag:
 550        clear_bit(MLX5E_STATE_OPENED, &epriv->state);
 551        mutex_unlock(&epriv->state_lock);
 552        return err;
 553}
 554
 555static int mlx5i_close(struct net_device *netdev)
 556{
 557        struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
 558        struct mlx5i_priv *ipriv = epriv->ppriv;
 559        struct mlx5_core_dev *mdev = epriv->mdev;
 560
 561        /* May already be CLOSED in case a previous configuration operation
 562         * (e.g RX/TX queue size change) that involves close&open failed.
 563         */
 564        mutex_lock(&epriv->state_lock);
 565
 566        if (!test_bit(MLX5E_STATE_OPENED, &epriv->state))
 567                goto unlock;
 568
 569        clear_bit(MLX5E_STATE_OPENED, &epriv->state);
 570
 571        netif_carrier_off(epriv->netdev);
 572        mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qpn);
 573        mlx5e_deactivate_priv_channels(epriv);
 574        mlx5e_close_channels(&epriv->channels);
 575        mlx5i_uninit_underlay_qp(epriv);
 576unlock:
 577        mutex_unlock(&epriv->state_lock);
 578        return 0;
 579}
 580
 581/* IPoIB RDMA netdev callbacks */
 582static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca,
 583                              union ib_gid *gid, u16 lid, int set_qkey,
 584                              u32 qkey)
 585{
 586        struct mlx5e_priv    *epriv = mlx5i_epriv(netdev);
 587        struct mlx5_core_dev *mdev  = epriv->mdev;
 588        struct mlx5i_priv    *ipriv = epriv->ppriv;
 589        int err;
 590
 591        mlx5_core_dbg(mdev, "attaching QPN 0x%x, MGID %pI6\n", ipriv->qpn,
 592                      gid->raw);
 593        err = mlx5_core_attach_mcg(mdev, gid, ipriv->qpn);
 594        if (err)
 595                mlx5_core_warn(mdev, "failed attaching QPN 0x%x, MGID %pI6\n",
 596                               ipriv->qpn, gid->raw);
 597
 598        if (set_qkey) {
 599                mlx5_core_dbg(mdev, "%s setting qkey 0x%x\n",
 600                              netdev->name, qkey);
 601                ipriv->qkey = qkey;
 602        }
 603
 604        return err;
 605}
 606
 607static int mlx5i_detach_mcast(struct net_device *netdev, struct ib_device *hca,
 608                              union ib_gid *gid, u16 lid)
 609{
 610        struct mlx5e_priv    *epriv = mlx5i_epriv(netdev);
 611        struct mlx5_core_dev *mdev  = epriv->mdev;
 612        struct mlx5i_priv    *ipriv = epriv->ppriv;
 613        int err;
 614
 615        mlx5_core_dbg(mdev, "detaching QPN 0x%x, MGID %pI6\n", ipriv->qpn,
 616                      gid->raw);
 617
 618        err = mlx5_core_detach_mcg(mdev, gid, ipriv->qpn);
 619        if (err)
 620                mlx5_core_dbg(mdev, "failed detaching QPN 0x%x, MGID %pI6\n",
 621                              ipriv->qpn, gid->raw);
 622
 623        return err;
 624}
 625
 626static int mlx5i_xmit(struct net_device *dev, struct sk_buff *skb,
 627                      struct ib_ah *address, u32 dqpn)
 628{
 629        struct mlx5e_priv *epriv = mlx5i_epriv(dev);
 630        struct mlx5e_txqsq *sq   = epriv->txq2sq[skb_get_queue_mapping(skb)];
 631        struct mlx5_ib_ah *mah   = to_mah(address);
 632        struct mlx5i_priv *ipriv = epriv->ppriv;
 633
 634        mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, ipriv->qkey, netdev_xmit_more());
 635
 636        return NETDEV_TX_OK;
 637}
 638
 639static void mlx5i_set_pkey_index(struct net_device *netdev, int id)
 640{
 641        struct mlx5i_priv *ipriv = netdev_priv(netdev);
 642
 643        ipriv->pkey_index = (u16)id;
 644}
 645
 646static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev)
 647{
 648        if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_IB)
 649                return -EOPNOTSUPP;
 650
 651        if (!MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) {
 652                mlx5_core_warn(mdev, "IPoIB enhanced offloads are not supported\n");
 653                return -EOPNOTSUPP;
 654        }
 655
 656        return 0;
 657}
 658
 659static void mlx5_rdma_netdev_free(struct net_device *netdev)
 660{
 661        struct mlx5e_priv *priv = mlx5i_epriv(netdev);
 662        struct mlx5_core_dev *mdev = priv->mdev;
 663        struct mlx5i_priv *ipriv = priv->ppriv;
 664        const struct mlx5e_profile *profile = priv->profile;
 665
 666        mlx5e_detach_netdev(priv);
 667        profile->cleanup(priv);
 668
 669        if (!ipriv->sub_interface) {
 670                mlx5i_pkey_qpn_ht_cleanup(netdev);
 671                mlx5e_destroy_mdev_resources(mdev);
 672        }
 673}
 674
 675static bool mlx5_is_sub_interface(struct mlx5_core_dev *mdev)
 676{
 677        return mdev->mlx5e_res.hw_objs.pdn != 0;
 678}
 679
 680static const struct mlx5e_profile *mlx5_get_profile(struct mlx5_core_dev *mdev)
 681{
 682        if (mlx5_is_sub_interface(mdev))
 683                return mlx5i_pkey_get_profile();
 684        return &mlx5i_nic_profile;
 685}
 686
 687static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u32 port_num,
 688                              struct net_device *netdev, void *param)
 689{
 690        struct mlx5_core_dev *mdev = (struct mlx5_core_dev *)param;
 691        const struct mlx5e_profile *prof = mlx5_get_profile(mdev);
 692        struct mlx5i_priv *ipriv;
 693        struct mlx5e_priv *epriv;
 694        struct rdma_netdev *rn;
 695        int err;
 696
 697        ipriv = netdev_priv(netdev);
 698        epriv = mlx5i_epriv(netdev);
 699
 700        ipriv->sub_interface = mlx5_is_sub_interface(mdev);
 701        if (!ipriv->sub_interface) {
 702                err = mlx5i_pkey_qpn_ht_init(netdev);
 703                if (err) {
 704                        mlx5_core_warn(mdev, "allocate qpn_to_netdev ht failed\n");
 705                        return err;
 706                }
 707
 708                /* This should only be called once per mdev */
 709                err = mlx5e_create_mdev_resources(mdev);
 710                if (err)
 711                        goto destroy_ht;
 712        }
 713
 714        err = mlx5e_priv_init(epriv, prof, netdev, mdev);
 715        if (err)
 716                goto destroy_mdev_resources;
 717
 718        epriv->profile = prof;
 719        epriv->ppriv = ipriv;
 720
 721        prof->init(mdev, netdev);
 722
 723        err = mlx5e_attach_netdev(epriv);
 724        if (err)
 725                goto detach;
 726        netif_carrier_off(netdev);
 727
 728        /* set rdma_netdev func pointers */
 729        rn = &ipriv->rn;
 730        rn->hca  = ibdev;
 731        rn->send = mlx5i_xmit;
 732        rn->attach_mcast = mlx5i_attach_mcast;
 733        rn->detach_mcast = mlx5i_detach_mcast;
 734        rn->set_id = mlx5i_set_pkey_index;
 735
 736        netdev->priv_destructor = mlx5_rdma_netdev_free;
 737        netdev->needs_free_netdev = 1;
 738
 739        return 0;
 740
 741detach:
 742        prof->cleanup(epriv);
 743        if (ipriv->sub_interface)
 744                return err;
 745destroy_mdev_resources:
 746        mlx5e_destroy_mdev_resources(mdev);
 747destroy_ht:
 748        mlx5i_pkey_qpn_ht_cleanup(netdev);
 749        return err;
 750}
 751
 752int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev,
 753                            struct ib_device *device,
 754                            struct rdma_netdev_alloc_params *params)
 755{
 756        int nch;
 757        int rc;
 758
 759        rc = mlx5i_check_required_hca_cap(mdev);
 760        if (rc)
 761                return rc;
 762
 763        nch = mlx5e_get_max_num_channels(mdev);
 764
 765        *params = (struct rdma_netdev_alloc_params){
 766                .sizeof_priv = sizeof(struct mlx5i_priv) +
 767                               sizeof(struct mlx5e_priv),
 768                .txqs = nch * MLX5E_MAX_NUM_TC,
 769                .rxqs = nch,
 770                .param = mdev,
 771                .initialize_rdma_netdev = mlx5_rdma_setup_rn,
 772        };
 773
 774        return 0;
 775}
 776EXPORT_SYMBOL(mlx5_rdma_rn_get_params);
 777