]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/ethernet/mellanox/mlx5/core/en_main.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_main.c
index 246d98ebb58890c33005ba7d7abab5743e1b45d9..f14ca3385fdd683b12f434e289cc8e264040c1ed 100644 (file)
@@ -84,7 +84,8 @@ static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type)
        switch (priv->params.rq_wq_type) {
        case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
                priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW;
-               priv->params.mpwqe_log_stride_sz = priv->params.rx_cqe_compress ?
+               priv->params.mpwqe_log_stride_sz =
+                       MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS) ?
                        MLX5_MPWRQ_LOG_STRIDE_SIZE_CQE_COMPRESS :
                        MLX5_MPWRQ_LOG_STRIDE_SIZE;
                priv->params.mpwqe_log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ -
@@ -101,7 +102,7 @@ static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type)
                       priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ,
                       BIT(priv->params.log_rq_size),
                       BIT(priv->params.mpwqe_log_stride_sz),
-                      priv->params.rx_cqe_compress_admin);
+                      MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS));
 }
 
 static void mlx5e_set_rq_priv_params(struct mlx5e_priv *priv)
@@ -446,14 +447,50 @@ static void mlx5e_rq_free_mpwqe_info(struct mlx5e_rq *rq)
        kfree(rq->mpwqe.info);
 }
 
-static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
+static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv,
+                                u64 npages, u8 page_shift,
+                                struct mlx5_core_mkey *umr_mkey)
 {
-       struct mlx5_eswitch_rep *rep = (struct mlx5_eswitch_rep *)priv->ppriv;
+       struct mlx5_core_dev *mdev = priv->mdev;
+       int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
+       void *mkc;
+       u32 *in;
+       int err;
+
+       if (!MLX5E_VALID_NUM_MTTS(npages))
+               return -EINVAL;
+
+       in = mlx5_vzalloc(inlen);
+       if (!in)
+               return -ENOMEM;
+
+       mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
+
+       MLX5_SET(mkc, mkc, free, 1);
+       MLX5_SET(mkc, mkc, umr_en, 1);
+       MLX5_SET(mkc, mkc, lw, 1);
+       MLX5_SET(mkc, mkc, lr, 1);
+       MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
+
+       MLX5_SET(mkc, mkc, qpn, 0xffffff);
+       MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
+       MLX5_SET64(mkc, mkc, len, npages << page_shift);
+       MLX5_SET(mkc, mkc, translations_octword_size,
+                MLX5_MTT_OCTW(npages));
+       MLX5_SET(mkc, mkc, log_page_size, page_shift);
 
-       if (rep && rep->vport != FDB_UPLINK_VPORT)
-               return true;
+       err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
 
-       return false;
+       kvfree(in);
+       return err;
+}
+
+static int mlx5e_create_rq_umr_mkey(struct mlx5e_rq *rq)
+{
+       struct mlx5e_priv *priv = rq->priv;
+       u64 num_mtts = MLX5E_REQUIRED_MTTS(BIT(priv->params.log_rq_size));
+
+       return mlx5e_create_umr_mkey(priv, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
 }
 
 static int mlx5e_create_rq(struct mlx5e_channel *c,
@@ -489,7 +526,13 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
        rq->channel = c;
        rq->ix      = c->ix;
        rq->priv    = c->priv;
-       rq->xdp_prog = priv->xdp_prog;
+
+       rq->xdp_prog = priv->xdp_prog ? bpf_prog_inc(priv->xdp_prog) : NULL;
+       if (IS_ERR(rq->xdp_prog)) {
+               err = PTR_ERR(rq->xdp_prog);
+               rq->xdp_prog = NULL;
+               goto err_rq_wq_destroy;
+       }
 
        rq->buff.map_dir = DMA_FROM_DEVICE;
        if (rq->xdp_prog)
@@ -506,18 +549,20 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
                rq->alloc_wqe = mlx5e_alloc_rx_mpwqe;
                rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
 
-               rq->mpwqe.mtt_offset = c->ix *
-                       MLX5E_REQUIRED_MTTS(1, BIT(priv->params.log_rq_size));
-
                rq->mpwqe_stride_sz = BIT(priv->params.mpwqe_log_stride_sz);
                rq->mpwqe_num_strides = BIT(priv->params.mpwqe_log_num_strides);
 
                rq->buff.wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides;
                byte_count = rq->buff.wqe_sz;
-               rq->mkey_be = cpu_to_be32(c->priv->umr_mkey.key);
-               err = mlx5e_rq_alloc_mpwqe_info(rq, c);
+
+               err = mlx5e_create_rq_umr_mkey(rq);
                if (err)
                        goto err_rq_wq_destroy;
+               rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);
+
+               err = mlx5e_rq_alloc_mpwqe_info(rq, c);
+               if (err)
+                       goto err_destroy_umr_mkey;
                break;
        default: /* MLX5_WQ_TYPE_LINKED_LIST */
                rq->dma_info = kzalloc_node(wq_sz * sizeof(*rq->dma_info),
@@ -566,12 +611,14 @@ static int mlx5e_create_rq(struct mlx5e_channel *c,
        rq->page_cache.head = 0;
        rq->page_cache.tail = 0;
 
-       if (rq->xdp_prog)
-               bpf_prog_add(rq->xdp_prog, 1);
-
        return 0;
 
+err_destroy_umr_mkey:
+       mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
+
 err_rq_wq_destroy:
+       if (rq->xdp_prog)
+               bpf_prog_put(rq->xdp_prog);
        mlx5_wq_destroy(&rq->wq_ctrl);
 
        return err;
@@ -587,6 +634,7 @@ static void mlx5e_destroy_rq(struct mlx5e_rq *rq)
        switch (rq->wq_type) {
        case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
                mlx5e_rq_free_mpwqe_info(rq);
+               mlx5_core_destroy_mkey(rq->priv->mdev, &rq->umr_mkey);
                break;
        default: /* MLX5_WQ_TYPE_LINKED_LIST */
                kfree(rq->dma_info);
@@ -940,7 +988,7 @@ static int mlx5e_create_sq(struct mlx5e_channel *c,
        sq->bf_buf_size = (1 << MLX5_CAP_GEN(mdev, log_bf_reg_size)) / 2;
        sq->max_inline  = param->max_inline;
        sq->min_inline_mode =
-               MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5E_INLINE_MODE_VPORT_CONTEXT ?
+               MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5_CAP_INLINE_MODE_VPORT_CONTEXT ?
                param->min_inline_mode : 0;
 
        err = mlx5e_alloc_sq_db(sq, cpu_to_node(c->cpu));
@@ -1184,7 +1232,7 @@ static int mlx5e_create_cq(struct mlx5e_channel *c,
 
 static void mlx5e_destroy_cq(struct mlx5e_cq *cq)
 {
-       mlx5_wq_destroy(&cq->wq_ctrl);
+       mlx5_cqwq_destroy(&cq->wq_ctrl);
 }
 
 static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
@@ -1201,7 +1249,7 @@ static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
        int err;
 
        inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
-               sizeof(u64) * cq->wq_ctrl.buf.npages;
+               sizeof(u64) * cq->wq_ctrl.frag_buf.npages;
        in = mlx5_vzalloc(inlen);
        if (!in)
                return -ENOMEM;
@@ -1210,15 +1258,15 @@ static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
 
        memcpy(cqc, param->cqc, sizeof(param->cqc));
 
-       mlx5_fill_page_array(&cq->wq_ctrl.buf,
-                            (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
+       mlx5_fill_page_frag_array(&cq->wq_ctrl.frag_buf,
+                                 (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
 
        mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
 
        MLX5_SET(cqc,   cqc, cq_period_mode, param->cq_period_mode);
        MLX5_SET(cqc,   cqc, c_eqn,         eqn);
        MLX5_SET(cqc,   cqc, uar_page,      mcq->uar->index);
-       MLX5_SET(cqc,   cqc, log_page_size, cq->wq_ctrl.buf.page_shift -
+       MLX5_SET(cqc,   cqc, log_page_size, cq->wq_ctrl.frag_buf.page_shift -
                                            MLX5_ADAPTER_PAGE_SHIFT);
        MLX5_SET64(cqc, cqc, dbr_addr,      cq->wq_ctrl.db.dma);
 
@@ -1536,7 +1584,6 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
 
 err_napi_del:
        netif_napi_del(&c->napi);
-       napi_hash_del(&c->napi);
        kfree(c);
 
        return err;
@@ -1557,9 +1604,6 @@ static void mlx5e_close_channel(struct mlx5e_channel *c)
        mlx5e_close_cq(&c->icosq.cq);
        netif_napi_del(&c->napi);
 
-       napi_hash_del(&c->napi);
-       synchronize_rcu();
-
        kfree(c);
 }
 
@@ -1652,7 +1696,7 @@ static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv,
        }
 
        MLX5_SET(cqc, cqc, log_cq_size, log_cq_size);
-       if (priv->params.rx_cqe_compress) {
+       if (MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
                MLX5_SET(cqc, cqc, mini_cqe_res_format, MLX5_CQE_FORMAT_CSUM);
                MLX5_SET(cqc, cqc, cqe_comp_en, 1);
        }
@@ -1978,8 +2022,23 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
        MLX5_SET(tirc, tirc, lro_timeout_period_usecs, priv->params.lro_timeout);
 }
 
-void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
+void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
+                                   enum mlx5e_traffic_types tt)
 {
+       void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
+
+#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+                                MLX5_HASH_FIELD_SEL_DST_IP)
+
+#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+                                MLX5_HASH_FIELD_SEL_DST_IP   |\
+                                MLX5_HASH_FIELD_SEL_L4_SPORT |\
+                                MLX5_HASH_FIELD_SEL_L4_DPORT)
+
+#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+                                MLX5_HASH_FIELD_SEL_DST_IP   |\
+                                MLX5_HASH_FIELD_SEL_IPSEC_SPI)
+
        MLX5_SET(tirc, tirc, rx_hash_fn,
                 mlx5e_rx_hash_fn(priv->params.rss_hfunc));
        if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
@@ -1991,6 +2050,88 @@ void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
                MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
                memcpy(rss_key, priv->params.toeplitz_hash_key, len);
        }
+
+       switch (tt) {
+       case MLX5E_TT_IPV4_TCP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_TCP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV6_TCP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_TCP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV4_UDP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_UDP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV6_UDP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+                        MLX5_L4_PROT_TYPE_UDP);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_L4PORTS);
+               break;
+
+       case MLX5E_TT_IPV4_IPSEC_AH:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV6_IPSEC_AH:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV4_IPSEC_ESP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV6_IPSEC_ESP:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP_IPSEC_SPI);
+               break;
+
+       case MLX5E_TT_IPV4:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV4);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP);
+               break;
+
+       case MLX5E_TT_IPV6:
+               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+                        MLX5_L3_PROT_TYPE_IPV6);
+               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+                        MLX5_HASH_IP);
+               break;
+       default:
+               WARN_ONCE(true, "%s: bad traffic type!\n", __func__);
+       }
 }
 
 static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
@@ -2124,7 +2265,7 @@ int mlx5e_open_locked(struct net_device *netdev)
                goto err_clear_state_opened_flag;
        }
 
-       err = mlx5e_refresh_tirs_self_loopback_enable(priv->mdev);
+       err = mlx5e_refresh_tirs_self_loopback(priv->mdev, false);
        if (err) {
                netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n",
                           __func__, err);
@@ -2360,110 +2501,13 @@ void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
 static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
                                      enum mlx5e_traffic_types tt)
 {
-       void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
-
        MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
 
-#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-                                MLX5_HASH_FIELD_SEL_DST_IP)
-
-#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-                                MLX5_HASH_FIELD_SEL_DST_IP   |\
-                                MLX5_HASH_FIELD_SEL_L4_SPORT |\
-                                MLX5_HASH_FIELD_SEL_L4_DPORT)
-
-#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-                                MLX5_HASH_FIELD_SEL_DST_IP   |\
-                                MLX5_HASH_FIELD_SEL_IPSEC_SPI)
-
        mlx5e_build_tir_ctx_lro(tirc, priv);
 
        MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
        MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
-       mlx5e_build_tir_ctx_hash(tirc, priv);
-
-       switch (tt) {
-       case MLX5E_TT_IPV4_TCP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_TCP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV6_TCP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_TCP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV4_UDP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_UDP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV6_UDP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-                        MLX5_L4_PROT_TYPE_UDP);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_L4PORTS);
-               break;
-
-       case MLX5E_TT_IPV4_IPSEC_AH:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV6_IPSEC_AH:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV4_IPSEC_ESP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV6_IPSEC_ESP:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP_IPSEC_SPI);
-               break;
-
-       case MLX5E_TT_IPV4:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV4);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP);
-               break;
-
-       case MLX5E_TT_IPV6:
-               MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-                        MLX5_L3_PROT_TYPE_IPV6);
-               MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-                        MLX5_HASH_IP);
-               break;
-       default:
-               WARN_ONCE(true,
-                         "mlx5e_build_indir_tir_ctx: bad traffic type!\n");
-       }
+       mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
 }
 
 static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
@@ -2642,7 +2686,7 @@ static int mlx5e_ndo_setup_tc(struct net_device *dev, u32 handle,
        return mlx5e_setup_tc(dev, tc->tc);
 }
 
-struct rtnl_link_stats64 *
+static struct rtnl_link_stats64 *
 mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
@@ -2650,13 +2694,20 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
        struct mlx5e_vport_stats *vstats = &priv->stats.vport;
        struct mlx5e_pport_stats *pstats = &priv->stats.pport;
 
-       stats->rx_packets = sstats->rx_packets;
-       stats->rx_bytes   = sstats->rx_bytes;
-       stats->tx_packets = sstats->tx_packets;
-       stats->tx_bytes   = sstats->tx_bytes;
+       if (mlx5e_is_uplink_rep(priv)) {
+               stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
+               stats->rx_bytes   = PPORT_802_3_GET(pstats, a_octets_received_ok);
+               stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok);
+               stats->tx_bytes   = PPORT_802_3_GET(pstats, a_octets_transmitted_ok);
+       } else {
+               stats->rx_packets = sstats->rx_packets;
+               stats->rx_bytes   = sstats->rx_bytes;
+               stats->tx_packets = sstats->tx_packets;
+               stats->tx_bytes   = sstats->tx_bytes;
+               stats->tx_dropped = sstats->tx_queue_dropped;
+       }
 
        stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer;
-       stats->tx_dropped = sstats->tx_queue_dropped;
 
        stats->rx_length_errors =
                PPORT_802_3_GET(pstats, a_in_range_length_errors) +
@@ -2853,31 +2904,13 @@ static int mlx5e_set_features(struct net_device *netdev,
        return err ? -EINVAL : 0;
 }
 
-#define MXL5_HW_MIN_MTU 64
-#define MXL5E_MIN_MTU (MXL5_HW_MIN_MTU + ETH_FCS_LEN)
-
 static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-       struct mlx5_core_dev *mdev = priv->mdev;
        bool was_opened;
-       u16 max_mtu;
-       u16 min_mtu;
        int err = 0;
        bool reset;
 
-       mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
-
-       max_mtu = MLX5E_HW2SW_MTU(max_mtu);
-       min_mtu = MLX5E_HW2SW_MTU(MXL5E_MIN_MTU);
-
-       if (new_mtu > max_mtu || new_mtu < min_mtu) {
-               netdev_err(netdev,
-                          "%s: Bad MTU (%d), valid range is: [%d..%d]\n",
-                          __func__, new_mtu, min_mtu, max_mtu);
-               return -EINVAL;
-       }
-
        mutex_lock(&priv->state_lock);
 
        reset = !priv->params.lro_en &&
@@ -2947,6 +2980,20 @@ static int mlx5e_set_vf_trust(struct net_device *dev, int vf, bool setting)
 
        return mlx5_eswitch_set_vport_trust(mdev->priv.eswitch, vf + 1, setting);
 }
+
+static int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
+                            int max_tx_rate)
+{
+       struct mlx5e_priv *priv = netdev_priv(dev);
+       struct mlx5_core_dev *mdev = priv->mdev;
+
+       if (min_tx_rate)
+               return -EOPNOTSUPP;
+
+       return mlx5_eswitch_set_vport_rate(mdev->priv.eswitch, vf + 1,
+                                          max_tx_rate);
+}
+
 static int mlx5_vport_link2ifla(u8 esw_link)
 {
        switch (esw_link) {
@@ -3003,8 +3050,8 @@ static int mlx5e_get_vf_stats(struct net_device *dev,
                                            vf_stats);
 }
 
-static void mlx5e_add_vxlan_port(struct net_device *netdev,
-                                struct udp_tunnel_info *ti)
+void mlx5e_add_vxlan_port(struct net_device *netdev,
+                         struct udp_tunnel_info *ti)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
@@ -3017,8 +3064,8 @@ static void mlx5e_add_vxlan_port(struct net_device *netdev,
        mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1);
 }
 
-static void mlx5e_del_vxlan_port(struct net_device *netdev,
-                                struct udp_tunnel_info *ti)
+void mlx5e_del_vxlan_port(struct net_device *netdev,
+                         struct udp_tunnel_info *ti)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
@@ -3112,6 +3159,11 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
        bool reset, was_opened;
        int i;
 
+       if (prog && prog->xdp_adjust_head) {
+               netdev_err(netdev, "Does not support bpf_xdp_adjust_head()\n");
+               return -EOPNOTSUPP;
+       }
+
        mutex_lock(&priv->state_lock);
 
        if ((netdev->features & NETIF_F_LRO) && prog) {
@@ -3126,11 +3178,21 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
 
        if (was_opened && reset)
                mlx5e_close_locked(netdev);
+       if (was_opened && !reset) {
+               /* num_channels is invariant here, so we can take the
+                * batched reference right upfront.
+                */
+               prog = bpf_prog_add(prog, priv->params.num_channels);
+               if (IS_ERR(prog)) {
+                       err = PTR_ERR(prog);
+                       goto unlock;
+               }
+       }
 
-       /* exchange programs */
+       /* exchange programs, extra prog reference we got from caller
+        * as long as we don't fail from this point onwards.
+        */
        old_prog = xchg(&priv->xdp_prog, prog);
-       if (prog)
-               bpf_prog_add(prog, 1);
        if (old_prog)
                bpf_prog_put(old_prog);
 
@@ -3146,7 +3208,6 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
        /* exchanging programs w/o reset, we update ref counts on behalf
         * of the channels RQs here.
         */
-       bpf_prog_add(prog, priv->params.num_channels);
        for (i = 0; i < priv->params.num_channels; i++) {
                struct mlx5e_channel *c = priv->channel[i];
 
@@ -3254,6 +3315,7 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
        .ndo_set_vf_vlan         = mlx5e_set_vf_vlan,
        .ndo_set_vf_spoofchk     = mlx5e_set_vf_spoofchk,
        .ndo_set_vf_trust        = mlx5e_set_vf_trust,
+       .ndo_set_vf_rate         = mlx5e_set_vf_rate,
        .ndo_get_vf_config       = mlx5e_get_vf_config,
        .ndo_set_vf_link_state   = mlx5e_set_vf_link_state,
        .ndo_get_vf_stats        = mlx5e_get_vf_stats,
@@ -3262,12 +3324,14 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller     = mlx5e_netpoll,
 #endif
+       .ndo_has_offload_stats   = mlx5e_has_offload_stats,
+       .ndo_get_offload_stats   = mlx5e_get_offload_stats,
 };
 
 static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
 {
        if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        if (!MLX5_CAP_GEN(mdev, eth_net_offloads) ||
            !MLX5_CAP_GEN(mdev, nic_flow_table) ||
            !MLX5_CAP_ETH(mdev, csum_cap) ||
@@ -3279,7 +3343,7 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
                               < 3) {
                mlx5_core_warn(mdev,
                               "Not creating net device, some required device capabilities are missing\n");
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
        if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
                mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
@@ -3298,24 +3362,6 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
               2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/;
 }
 
-#ifdef CONFIG_MLX5_CORE_EN_DCB
-static void mlx5e_ets_init(struct mlx5e_priv *priv)
-{
-       int i;
-
-       priv->params.ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
-       for (i = 0; i < priv->params.ets.ets_cap; i++) {
-               priv->params.ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
-               priv->params.ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
-               priv->params.ets.prio_tc[i] = i;
-       }
-
-       /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
-       priv->params.ets.prio_tc[0] = 1;
-       priv->params.ets.prio_tc[1] = 0;
-}
-#endif
-
 void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev,
                                   u32 *indirection_rqt, int len,
                                   int num_channels)
@@ -3390,14 +3436,13 @@ static void mlx5e_query_min_inline(struct mlx5_core_dev *mdev,
                                   u8 *min_inline_mode)
 {
        switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) {
-       case MLX5E_INLINE_MODE_L2:
+       case MLX5_CAP_INLINE_MODE_L2:
                *min_inline_mode = MLX5_INLINE_MODE_L2;
                break;
-       case MLX5E_INLINE_MODE_VPORT_CONTEXT:
-               mlx5_query_nic_vport_min_inline(mdev,
-                                               min_inline_mode);
+       case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
+               mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode);
                break;
-       case MLX5_INLINE_MODE_NOT_REQUIRED:
+       case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
                *min_inline_mode = MLX5_INLINE_MODE_NONE;
                break;
        }
@@ -3439,17 +3484,16 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
        priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
 
        /* set CQE compression */
-       priv->params.rx_cqe_compress_admin = false;
+       priv->params.rx_cqe_compress_def = false;
        if (MLX5_CAP_GEN(mdev, cqe_compression) &&
            MLX5_CAP_GEN(mdev, vport_group_manager)) {
                mlx5e_get_max_linkspeed(mdev, &link_speed);
                mlx5e_get_pci_bw(mdev, &pci_bw);
                mlx5_core_dbg(mdev, "Max link speed = %d, PCI BW = %d\n",
                              link_speed, pci_bw);
-               priv->params.rx_cqe_compress_admin =
+               priv->params.rx_cqe_compress_def =
                        cqe_compress_heuristic(link_speed, pci_bw);
        }
-       priv->params.rx_cqe_compress = priv->params.rx_cqe_compress_admin;
 
        mlx5e_set_rq_priv_params(priv);
        if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
@@ -3480,12 +3524,9 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
                SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
        /* Initialize pflags */
-       MLX5E_SET_PRIV_FLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
-                           priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
-
-#ifdef CONFIG_MLX5_CORE_EN_DCB
-       mlx5e_ets_init(priv);
-#endif
+       MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
+                       priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
+       MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, priv->params.rx_cqe_compress_def);
 
        mutex_init(&priv->state_lock);
 
@@ -3523,7 +3564,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
        if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
                netdev->netdev_ops = &mlx5e_netdev_ops_sriov;
 #ifdef CONFIG_MLX5_CORE_EN_DCB
-               netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
+               if (MLX5_CAP_GEN(mdev, qos))
+                       netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
 #endif
        } else {
                netdev->netdev_ops = &mlx5e_netdev_ops_basic;
@@ -3619,43 +3661,6 @@ static void mlx5e_destroy_q_counter(struct mlx5e_priv *priv)
        mlx5_core_dealloc_q_counter(priv->mdev, priv->q_counter);
 }
 
-static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv)
-{
-       struct mlx5_core_dev *mdev = priv->mdev;
-       u64 npages = MLX5E_REQUIRED_MTTS(priv->profile->max_nch(mdev),
-                                        BIT(MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW));
-       int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
-       void *mkc;
-       u32 *in;
-       int err;
-
-       in = mlx5_vzalloc(inlen);
-       if (!in)
-               return -ENOMEM;
-
-       mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
-
-       npages = min_t(u32, ALIGN(U16_MAX, 4) * 2, npages);
-
-       MLX5_SET(mkc, mkc, free, 1);
-       MLX5_SET(mkc, mkc, umr_en, 1);
-       MLX5_SET(mkc, mkc, lw, 1);
-       MLX5_SET(mkc, mkc, lr, 1);
-       MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
-
-       MLX5_SET(mkc, mkc, qpn, 0xffffff);
-       MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
-       MLX5_SET64(mkc, mkc, len, npages << PAGE_SHIFT);
-       MLX5_SET(mkc, mkc, translations_octword_size,
-                MLX5_MTT_OCTW(npages));
-       MLX5_SET(mkc, mkc, log_page_size, PAGE_SHIFT);
-
-       err = mlx5_core_create_mkey(mdev, &priv->umr_mkey, in, inlen);
-
-       kvfree(in);
-       return err;
-}
-
 static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
                           struct net_device *netdev,
                           const struct mlx5e_profile *profile,
@@ -3670,13 +3675,10 @@ static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
 
 static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
 {
-       struct mlx5_core_dev *mdev = priv->mdev;
-       struct mlx5_eswitch *esw = mdev->priv.eswitch;
-
        mlx5e_vxlan_cleanup(priv);
 
-       if (MLX5_CAP_GEN(mdev, vport_group_manager))
-               mlx5_eswitch_unregister_vport_rep(esw, 0);
+       if (priv->xdp_prog)
+               bpf_prog_put(priv->xdp_prog);
 }
 
 static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
@@ -3759,7 +3761,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
        }
 
 #ifdef CONFIG_MLX5_CORE_EN_DCB
-       mlx5e_dcbnl_ieee_setets_core(priv, &priv->params.ets);
+       mlx5e_dcbnl_initialize(priv);
 #endif
        return 0;
 }
@@ -3773,30 +3775,40 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 
        mlx5_lag_add(mdev, netdev);
 
-       if (mlx5e_vxlan_allowed(mdev)) {
-               rtnl_lock();
-               udp_tunnel_get_rx_info(netdev);
-               rtnl_unlock();
-       }
-
        mlx5e_enable_async_events(priv);
-       queue_work(priv->wq, &priv->set_rx_mode_work);
 
        if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
                mlx5_query_nic_vport_mac_address(mdev, 0, rep.hw_id);
                rep.load = mlx5e_nic_rep_load;
                rep.unload = mlx5e_nic_rep_unload;
                rep.vport = FDB_UPLINK_VPORT;
-               rep.priv_data = priv;
+               rep.netdev = netdev;
                mlx5_eswitch_register_vport_rep(esw, 0, &rep);
        }
+
+       if (netdev->reg_state != NETREG_REGISTERED)
+               return;
+
+       /* Device already registered: sync netdev system state */
+       if (mlx5e_vxlan_allowed(mdev)) {
+               rtnl_lock();
+               udp_tunnel_get_rx_info(netdev);
+               rtnl_unlock();
+       }
+
+       queue_work(priv->wq, &priv->set_rx_mode_work);
 }
 
 static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 {
+       struct mlx5_core_dev *mdev = priv->mdev;
+       struct mlx5_eswitch *esw = mdev->priv.eswitch;
+
        queue_work(priv->wq, &priv->set_rx_mode_work);
+       if (MLX5_CAP_GEN(mdev, vport_group_manager))
+               mlx5_eswitch_unregister_vport_rep(esw, 0);
        mlx5e_disable_async_events(priv);
-       mlx5_lag_remove(priv->mdev);
+       mlx5_lag_remove(mdev);
 }
 
 static const struct mlx5e_profile mlx5e_nic_profile = {
@@ -3852,21 +3864,16 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
 {
        const struct mlx5e_profile *profile;
        struct mlx5e_priv *priv;
+       u16 max_mtu;
        int err;
 
        priv = netdev_priv(netdev);
        profile = priv->profile;
        clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
 
-       err = mlx5e_create_umr_mkey(priv);
-       if (err) {
-               mlx5_core_err(mdev, "create umr mkey failed, %d\n", err);
-               goto out;
-       }
-
        err = profile->init_tx(priv);
        if (err)
-               goto err_destroy_umr_mkey;
+               goto out;
 
        err = mlx5e_open_drop_rq(priv);
        if (err) {
@@ -3882,6 +3889,11 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
 
        mlx5e_init_l2_addr(priv);
 
+       /* MTU range: 68 - hw-specific max */
+       netdev->min_mtu = ETH_MIN_MTU;
+       mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
+       netdev->max_mtu = MLX5E_HW2SW_MTU(max_mtu);
+
        mlx5e_set_dev_port_mtu(netdev);
 
        if (profile->enable)
@@ -3901,9 +3913,6 @@ int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
 err_cleanup_tx:
        profile->cleanup_tx(priv);
 
-err_destroy_umr_mkey:
-       mlx5_core_destroy_mkey(mdev, &priv->umr_mkey);
-
 out:
        return err;
 }
@@ -3937,10 +3946,6 @@ void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
        const struct mlx5e_profile *profile = priv->profile;
 
        set_bit(MLX5E_STATE_DESTROYING, &priv->state);
-       if (profile->disable)
-               profile->disable(priv);
-
-       flush_workqueue(priv->wq);
 
        rtnl_lock();
        if (netif_running(netdev))
@@ -3948,11 +3953,14 @@ void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev)
        netif_device_detach(netdev);
        rtnl_unlock();
 
+       if (profile->disable)
+               profile->disable(priv);
+       flush_workqueue(priv->wq);
+
        mlx5e_destroy_q_counter(priv);
        profile->cleanup_rx(priv);
        mlx5e_close_drop_rq(priv);
        profile->cleanup_tx(priv);
-       mlx5_core_destroy_mkey(priv->mdev, &priv->umr_mkey);
        cancel_delayed_work_sync(&priv->update_stats_work);
 }