Merge tag 'irq-core-2020-12-23' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_main.c
index 9bcf73f..7a79d33 100644 (file)
@@ -64,6 +64,7 @@
 #include "en/hv_vhca_stats.h"
 #include "en/devlink.h"
 #include "lib/mlx5.h"
+#include "en/ptp.h"
 
 bool mlx5e_check_fragmented_striding_rq_cap(struct mlx5_core_dev *mdev)
 {
@@ -412,9 +413,10 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
        rq->wq_type = params->rq_wq_type;
        rq->pdev    = c->pdev;
        rq->netdev  = c->netdev;
+       rq->priv    = c->priv;
        rq->tstamp  = c->tstamp;
        rq->clock   = &mdev->clock;
-       rq->channel = c;
+       rq->icosq   = &c->icosq;
        rq->ix      = c->ix;
        rq->mdev    = mdev;
        rq->hw_mtu  = MLX5E_SW2HW_MTU(params, params->sw_mtu);
@@ -434,7 +436,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
        rq_xdp_ix = rq->ix;
        if (xsk)
                rq_xdp_ix += params->num_channels * MLX5E_RQ_GROUP_XSK;
-       err = xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq_xdp_ix);
+       err = xdp_rxq_info_reg(&rq->xdp_rxq, rq->netdev, rq_xdp_ix, 0);
        if (err < 0)
                goto err_rq_xdp_prog;
 
@@ -613,14 +615,11 @@ err_rq_xdp_prog:
 
 static void mlx5e_free_rq(struct mlx5e_rq *rq)
 {
-       struct mlx5e_channel *c = rq->channel;
-       struct bpf_prog *old_prog = NULL;
+       struct bpf_prog *old_prog;
        int i;
 
-       /* drop_rq has neither channel nor xdp_prog. */
-       if (c)
-               old_prog = rcu_dereference_protected(rq->xdp_prog,
-                                                    lockdep_is_held(&c->priv->state_lock));
+       old_prog = rcu_dereference_protected(rq->xdp_prog,
+                                            lockdep_is_held(&rq->priv->state_lock));
        if (old_prog)
                bpf_prog_put(old_prog);
 
@@ -720,9 +719,7 @@ int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_state)
 
 static int mlx5e_modify_rq_scatter_fcs(struct mlx5e_rq *rq, bool enable)
 {
-       struct mlx5e_channel *c = rq->channel;
-       struct mlx5e_priv *priv = c->priv;
-       struct mlx5_core_dev *mdev = priv->mdev;
+       struct mlx5_core_dev *mdev = rq->mdev;
 
        void *in;
        void *rqc;
@@ -751,8 +748,7 @@ static int mlx5e_modify_rq_scatter_fcs(struct mlx5e_rq *rq, bool enable)
 
 static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
 {
-       struct mlx5e_channel *c = rq->channel;
-       struct mlx5_core_dev *mdev = c->mdev;
+       struct mlx5_core_dev *mdev = rq->mdev;
        void *in;
        void *rqc;
        int inlen;
@@ -786,7 +782,6 @@ static void mlx5e_destroy_rq(struct mlx5e_rq *rq)
 int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time)
 {
        unsigned long exp_time = jiffies + msecs_to_jiffies(wait_time);
-       struct mlx5e_channel *c = rq->channel;
 
        u16 min_wqes = mlx5_min_rx_wqes(rq->wq_type, mlx5e_rqwq_get_size(rq));
 
@@ -797,8 +792,8 @@ int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time)
                msleep(20);
        } while (time_before(jiffies, exp_time));
 
-       netdev_warn(c->netdev, "Failed to get min RX wqes on Channel[%d] RQN[0x%x] wq cur_sz(%d) min_rx_wqes(%d)\n",
-                   c->ix, rq->rqn, mlx5e_rqwq_get_cur_sz(rq), min_wqes);
+       netdev_warn(rq->netdev, "Failed to get min RX wqes on Channel[%d] RQN[0x%x] wq cur_sz(%d) min_rx_wqes(%d)\n",
+                   rq->ix, rq->rqn, mlx5e_rqwq_get_cur_sz(rq), min_wqes);
 
        mlx5e_reporter_rx_timeout(rq);
        return -ETIMEDOUT;
@@ -913,7 +908,7 @@ err_free_rq:
 void mlx5e_activate_rq(struct mlx5e_rq *rq)
 {
        set_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
-       mlx5e_trigger_irq(&rq->channel->icosq);
+       mlx5e_trigger_irq(rq->icosq);
 }
 
 void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
@@ -925,7 +920,7 @@ void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
 void mlx5e_close_rq(struct mlx5e_rq *rq)
 {
        cancel_work_sync(&rq->dim.work);
-       cancel_work_sync(&rq->channel->icosq.recover_work);
+       cancel_work_sync(&rq->icosq->recover_work);
        cancel_work_sync(&rq->recover_work);
        mlx5e_destroy_rq(rq);
        mlx5e_free_rx_descs(rq);
@@ -1089,14 +1084,14 @@ static void mlx5e_free_icosq(struct mlx5e_icosq *sq)
        mlx5_wq_destroy(&sq->wq_ctrl);
 }
 
-static void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq)
+void mlx5e_free_txqsq_db(struct mlx5e_txqsq *sq)
 {
        kvfree(sq->db.wqe_info);
-       kvfree(sq->db.skb_fifo);
+       kvfree(sq->db.skb_fifo.fifo);
        kvfree(sq->db.dma_fifo);
 }
 
-static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
+int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
 {
        int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
        int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS;
@@ -1104,46 +1099,26 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
        sq->db.dma_fifo = kvzalloc_node(array_size(df_sz,
                                                   sizeof(*sq->db.dma_fifo)),
                                        GFP_KERNEL, numa);
-       sq->db.skb_fifo = kvzalloc_node(array_size(df_sz,
-                                                  sizeof(*sq->db.skb_fifo)),
+       sq->db.skb_fifo.fifo = kvzalloc_node(array_size(df_sz,
+                                                       sizeof(*sq->db.skb_fifo.fifo)),
                                        GFP_KERNEL, numa);
        sq->db.wqe_info = kvzalloc_node(array_size(wq_sz,
                                                   sizeof(*sq->db.wqe_info)),
                                        GFP_KERNEL, numa);
-       if (!sq->db.dma_fifo || !sq->db.skb_fifo || !sq->db.wqe_info) {
+       if (!sq->db.dma_fifo || !sq->db.skb_fifo.fifo || !sq->db.wqe_info) {
                mlx5e_free_txqsq_db(sq);
                return -ENOMEM;
        }
 
        sq->dma_fifo_mask = df_sz - 1;
-       sq->skb_fifo_mask = df_sz - 1;
-
-       return 0;
-}
-
-static int mlx5e_calc_sq_stop_room(struct mlx5e_txqsq *sq, u8 log_sq_size)
-{
-       int sq_size = 1 << log_sq_size;
 
-       sq->stop_room  = mlx5e_tls_get_stop_room(sq);
-       sq->stop_room += mlx5e_stop_room_for_wqe(MLX5_SEND_WQE_MAX_WQEBBS);
-       if (test_bit(MLX5E_SQ_STATE_MPWQE, &sq->state))
-               /* A MPWQE can take up to the maximum-sized WQE + all the normal
-                * stop room can be taken if a new packet breaks the active
-                * MPWQE session and allocates its WQEs right away.
-                */
-               sq->stop_room += mlx5e_stop_room_for_wqe(MLX5_SEND_WQE_MAX_WQEBBS);
-
-       if (WARN_ON(sq->stop_room >= sq_size)) {
-               netdev_err(sq->channel->netdev, "Stop room %hu is bigger than the SQ size %d\n",
-                          sq->stop_room, sq_size);
-               return -ENOSPC;
-       }
+       sq->db.skb_fifo.pc   = &sq->skb_fifo_pc;
+       sq->db.skb_fifo.cc   = &sq->skb_fifo_cc;
+       sq->db.skb_fifo.mask = df_sz - 1;
 
        return 0;
 }
 
-static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work);
 static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
                             int txq_ix,
                             struct mlx5e_params *params,
@@ -1160,7 +1135,9 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
        sq->tstamp    = c->tstamp;
        sq->clock     = &mdev->clock;
        sq->mkey_be   = c->mkey_be;
-       sq->channel   = c;
+       sq->netdev    = c->netdev;
+       sq->mdev      = c->mdev;
+       sq->priv      = c->priv;
        sq->ch_ix     = c->ix;
        sq->txq_ix    = txq_ix;
        sq->uar_map   = mdev->mlx5e_res.bfreg.map;
@@ -1176,9 +1153,7 @@ static int mlx5e_alloc_txqsq(struct mlx5e_channel *c,
                set_bit(MLX5E_SQ_STATE_TLS, &sq->state);
        if (param->is_mpw)
                set_bit(MLX5E_SQ_STATE_MPWQE, &sq->state);
-       err = mlx5e_calc_sq_stop_room(sq, params->log_sq_size);
-       if (err)
-               return err;
+       sq->stop_room = param->stop_room;
 
        param->wq.db_numa_node = cpu_to_node(c->cpu);
        err = mlx5_wq_cyc_create(mdev, &param->wq, sqc_wq, wq, &sq->wq_ctrl);
@@ -1201,20 +1176,12 @@ err_sq_wq_destroy:
        return err;
 }
 
-static void mlx5e_free_txqsq(struct mlx5e_txqsq *sq)
+void mlx5e_free_txqsq(struct mlx5e_txqsq *sq)
 {
        mlx5e_free_txqsq_db(sq);
        mlx5_wq_destroy(&sq->wq_ctrl);
 }
 
-struct mlx5e_create_sq_param {
-       struct mlx5_wq_ctrl        *wq_ctrl;
-       u32                         cqn;
-       u32                         tisn;
-       u8                          tis_lst_sz;
-       u8                          min_inline_mode;
-};
-
 static int mlx5e_create_sq(struct mlx5_core_dev *mdev,
                           struct mlx5e_sq_param *param,
                           struct mlx5e_create_sq_param *csp,
@@ -1239,6 +1206,7 @@ static int mlx5e_create_sq(struct mlx5_core_dev *mdev,
        MLX5_SET(sqc,  sqc, tis_lst_sz, csp->tis_lst_sz);
        MLX5_SET(sqc,  sqc, tis_num_0, csp->tisn);
        MLX5_SET(sqc,  sqc, cqn, csp->cqn);
+       MLX5_SET(sqc,  sqc, ts_cqe_to_dest_cqn, csp->ts_cqe_to_dest_cqn);
 
        if (MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
                MLX5_SET(sqc,  sqc, min_wqe_inline_mode, csp->min_inline_mode);
@@ -1296,10 +1264,10 @@ static void mlx5e_destroy_sq(struct mlx5_core_dev *mdev, u32 sqn)
        mlx5_core_destroy_sq(mdev, sqn);
 }
 
-static int mlx5e_create_sq_rdy(struct mlx5_core_dev *mdev,
-                              struct mlx5e_sq_param *param,
-                              struct mlx5e_create_sq_param *csp,
-                              u32 *sqn)
+int mlx5e_create_sq_rdy(struct mlx5_core_dev *mdev,
+                       struct mlx5e_sq_param *param,
+                       struct mlx5e_create_sq_param *csp,
+                       u32 *sqn)
 {
        struct mlx5e_modify_sq_param msp = {0};
        int err;
@@ -1362,7 +1330,7 @@ err_free_txqsq:
 
 void mlx5e_activate_txqsq(struct mlx5e_txqsq *sq)
 {
-       sq->txq = netdev_get_tx_queue(sq->channel->netdev, sq->txq_ix);
+       sq->txq = netdev_get_tx_queue(sq->netdev, sq->txq_ix);
        set_bit(MLX5E_SQ_STATE_ENABLED, &sq->state);
        netdev_tx_reset_queue(sq->txq);
        netif_tx_start_queue(sq->txq);
@@ -1375,7 +1343,7 @@ void mlx5e_tx_disable_queue(struct netdev_queue *txq)
        __netif_tx_unlock_bh(txq);
 }
 
-static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
+void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
 {
        struct mlx5_wq_cyc *wq = &sq->wq;
 
@@ -1400,8 +1368,7 @@ static void mlx5e_deactivate_txqsq(struct mlx5e_txqsq *sq)
 
 static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq)
 {
-       struct mlx5e_channel *c = sq->channel;
-       struct mlx5_core_dev *mdev = c->mdev;
+       struct mlx5_core_dev *mdev = sq->mdev;
        struct mlx5_rate_limit rl = {0};
 
        cancel_work_sync(&sq->dim.work);
@@ -1415,7 +1382,7 @@ static void mlx5e_close_txqsq(struct mlx5e_txqsq *sq)
        mlx5e_free_txqsq(sq);
 }
 
-static void mlx5e_tx_err_cqe_work(struct work_struct *recover_work)
+void mlx5e_tx_err_cqe_work(struct work_struct *recover_work)
 {
        struct mlx5e_txqsq *sq = container_of(recover_work, struct mlx5e_txqsq,
                                              recover_work);
@@ -1542,10 +1509,11 @@ void mlx5e_close_xdpsq(struct mlx5e_xdpsq *sq)
        mlx5e_free_xdpsq(sq);
 }
 
-static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,
+static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv,
                                 struct mlx5e_cq_param *param,
                                 struct mlx5e_cq *cq)
 {
+       struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5_core_cq *mcq = &cq->mcq;
        int eqn_not_used;
        unsigned int irqn;
@@ -1578,25 +1546,27 @@ static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,
        }
 
        cq->mdev = mdev;
+       cq->netdev = priv->netdev;
+       cq->priv = priv;
 
        return 0;
 }
 
-static int mlx5e_alloc_cq(struct mlx5e_channel *c,
+static int mlx5e_alloc_cq(struct mlx5e_priv *priv,
                          struct mlx5e_cq_param *param,
+                         struct mlx5e_create_cq_param *ccp,
                          struct mlx5e_cq *cq)
 {
-       struct mlx5_core_dev *mdev = c->priv->mdev;
        int err;
 
-       param->wq.buf_numa_node = cpu_to_node(c->cpu);
-       param->wq.db_numa_node  = cpu_to_node(c->cpu);
-       param->eq_ix   = c->ix;
+       param->wq.buf_numa_node = ccp->node;
+       param->wq.db_numa_node  = ccp->node;
+       param->eq_ix            = ccp->ix;
 
-       err = mlx5e_alloc_cq_common(mdev, param, cq);
+       err = mlx5e_alloc_cq_common(priv, param, cq);
 
-       cq->napi    = &c->napi;
-       cq->channel = c;
+       cq->napi     = ccp->napi;
+       cq->ch_stats = ccp->ch_stats;
 
        return err;
 }
@@ -1660,13 +1630,14 @@ static void mlx5e_destroy_cq(struct mlx5e_cq *cq)
        mlx5_core_destroy_cq(cq->mdev, &cq->mcq);
 }
 
-int mlx5e_open_cq(struct mlx5e_channel *c, struct dim_cq_moder moder,
-                 struct mlx5e_cq_param *param, struct mlx5e_cq *cq)
+int mlx5e_open_cq(struct mlx5e_priv *priv, struct dim_cq_moder moder,
+                 struct mlx5e_cq_param *param, struct mlx5e_create_cq_param *ccp,
+                 struct mlx5e_cq *cq)
 {
-       struct mlx5_core_dev *mdev = c->mdev;
+       struct mlx5_core_dev *mdev = priv->mdev;
        int err;
 
-       err = mlx5e_alloc_cq(c, param, cq);
+       err = mlx5e_alloc_cq(priv, param, ccp, cq);
        if (err)
                return err;
 
@@ -1692,14 +1663,15 @@ void mlx5e_close_cq(struct mlx5e_cq *cq)
 
 static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
                             struct mlx5e_params *params,
+                            struct mlx5e_create_cq_param *ccp,
                             struct mlx5e_channel_param *cparam)
 {
        int err;
        int tc;
 
        for (tc = 0; tc < c->num_tc; tc++) {
-               err = mlx5e_open_cq(c, params->tx_cq_moderation,
-                                   &cparam->txq_sq.cqp, &c->sq[tc].cq);
+               err = mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->txq_sq.cqp,
+                                   ccp, &c->sq[tc].cq);
                if (err)
                        goto err_close_tx_cqs;
        }
@@ -1834,35 +1806,52 @@ static int mlx5e_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
        return err;
 }
 
+void mlx5e_build_create_cq_param(struct mlx5e_create_cq_param *ccp, struct mlx5e_channel *c)
+{
+       *ccp = (struct mlx5e_create_cq_param) {
+               .napi = &c->napi,
+               .ch_stats = c->stats,
+               .node = cpu_to_node(c->cpu),
+               .ix = c->ix,
+       };
+}
+
 static int mlx5e_open_queues(struct mlx5e_channel *c,
                             struct mlx5e_params *params,
                             struct mlx5e_channel_param *cparam)
 {
        struct dim_cq_moder icocq_moder = {0, 0};
+       struct mlx5e_create_cq_param ccp;
        int err;
 
-       err = mlx5e_open_cq(c, icocq_moder, &cparam->icosq.cqp, &c->async_icosq.cq);
+       mlx5e_build_create_cq_param(&ccp, c);
+
+       err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->icosq.cqp, &ccp,
+                           &c->async_icosq.cq);
        if (err)
                return err;
 
-       err = mlx5e_open_cq(c, icocq_moder, &cparam->async_icosq.cqp, &c->icosq.cq);
+       err = mlx5e_open_cq(c->priv, icocq_moder, &cparam->async_icosq.cqp, &ccp,
+                           &c->icosq.cq);
        if (err)
                goto err_close_async_icosq_cq;
 
-       err = mlx5e_open_tx_cqs(c, params, cparam);
+       err = mlx5e_open_tx_cqs(c, params, &ccp, cparam);
        if (err)
                goto err_close_icosq_cq;
 
-       err = mlx5e_open_cq(c, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &c->xdpsq.cq);
+       err = mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->xdp_sq.cqp, &ccp,
+                           &c->xdpsq.cq);
        if (err)
                goto err_close_tx_cqs;
 
-       err = mlx5e_open_cq(c, params->rx_cq_moderation, &cparam->rq.cqp, &c->rq.cq);
+       err = mlx5e_open_cq(c->priv, params->rx_cq_moderation, &cparam->rq.cqp, &ccp,
+                           &c->rq.cq);
        if (err)
                goto err_close_xdp_tx_cqs;
 
-       err = c->xdp ? mlx5e_open_cq(c, params->tx_cq_moderation,
-                                    &cparam->xdp_sq.cqp, &c->rq_xdpsq.cq) : 0;
+       err = c->xdp ? mlx5e_open_cq(c->priv, params->tx_cq_moderation, &cparam->xdp_sq.cqp,
+                                    &ccp, &c->rq_xdpsq.cq) : 0;
        if (err)
                goto err_close_rx_cq;
 
@@ -2225,6 +2214,7 @@ static void mlx5e_build_sq_param(struct mlx5e_priv *priv,
        MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size);
        MLX5_SET(sqc, sqc, allow_swp, allow_swp);
        param->is_mpw = MLX5E_GET_PFLAG(params, MLX5E_PFLAG_SKB_TX_MPWQE);
+       param->stop_room = mlx5e_calc_sq_stop_room(priv->mdev, params);
        mlx5e_build_tx_cq_param(priv, params, &param->cqp);
 }
 
@@ -2384,6 +2374,13 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
                        goto err_close_channels;
        }
 
+       if (MLX5E_GET_PFLAG(&chs->params, MLX5E_PFLAG_TX_PORT_TS)) {
+               err = mlx5e_port_ptp_open(priv, &chs->params, chs->c[0]->lag_port,
+                                         &chs->port_ptp);
+               if (err)
+                       goto err_close_channels;
+       }
+
        mlx5e_health_channels_update(priv);
        kvfree(cparam);
        return 0;
@@ -2405,6 +2402,9 @@ static void mlx5e_activate_channels(struct mlx5e_channels *chs)
 
        for (i = 0; i < chs->num; i++)
                mlx5e_activate_channel(chs->c[i]);
+
+       if (chs->port_ptp)
+               mlx5e_ptp_activate_channel(chs->port_ptp);
 }
 
 #define MLX5E_RQ_WQES_TIMEOUT 20000 /* msecs */
@@ -2431,6 +2431,9 @@ static void mlx5e_deactivate_channels(struct mlx5e_channels *chs)
 {
        int i;
 
+       if (chs->port_ptp)
+               mlx5e_ptp_deactivate_channel(chs->port_ptp);
+
        for (i = 0; i < chs->num; i++)
                mlx5e_deactivate_channel(chs->c[i]);
 }
@@ -2439,6 +2442,9 @@ void mlx5e_close_channels(struct mlx5e_channels *chs)
 {
        int i;
 
+       if (chs->port_ptp)
+               mlx5e_port_ptp_close(chs->port_ptp);
+
        for (i = 0; i < chs->num; i++)
                mlx5e_close_channel(chs->c[i]);
 
@@ -2924,6 +2930,8 @@ static int mlx5e_update_netdev_queues(struct mlx5e_priv *priv)
        nch = priv->channels.params.num_channels;
        ntc = priv->channels.params.num_tc;
        num_txqs = nch * ntc;
+       if (MLX5E_GET_PFLAG(&priv->channels.params, MLX5E_PFLAG_TX_PORT_TS))
+               num_txqs += ntc;
        num_rxqs = nch * priv->profile->rq_groups;
 
        mlx5e_netdev_set_tcs(netdev, nch, ntc);
@@ -2997,14 +3005,13 @@ MLX5E_DEFINE_PREACTIVATE_WRAPPER_CTX(mlx5e_num_channels_changed);
 
 static void mlx5e_build_txq_maps(struct mlx5e_priv *priv)
 {
-       int i, ch;
+       int i, ch, tc, num_tc;
 
        ch = priv->channels.num;
+       num_tc = priv->channels.params.num_tc;
 
        for (i = 0; i < ch; i++) {
-               int tc;
-
-               for (tc = 0; tc < priv->channels.params.num_tc; tc++) {
+               for (tc = 0; tc < num_tc; tc++) {
                        struct mlx5e_channel *c = priv->channels.c[i];
                        struct mlx5e_txqsq *sq = &c->sq[tc];
 
@@ -3012,10 +3019,29 @@ static void mlx5e_build_txq_maps(struct mlx5e_priv *priv)
                        priv->channel_tc2realtxq[i][tc] = i + tc * ch;
                }
        }
+
+       if (!priv->channels.port_ptp)
+               return;
+
+       for (tc = 0; tc < num_tc; tc++) {
+               struct mlx5e_port_ptp *c = priv->channels.port_ptp;
+               struct mlx5e_txqsq *sq = &c->ptpsq[tc].txqsq;
+
+               priv->txq2sq[sq->txq_ix] = sq;
+               priv->port_ptp_tc2realtxq[tc] = priv->num_tc_x_num_ch + tc;
+       }
+}
+
+static void mlx5e_update_num_tc_x_num_ch(struct mlx5e_priv *priv)
+{
+       /* Sync with mlx5e_select_queue. */
+       WRITE_ONCE(priv->num_tc_x_num_ch,
+                  priv->channels.params.num_tc * priv->channels.num);
 }
 
 void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 {
+       mlx5e_update_num_tc_x_num_ch(priv);
        mlx5e_build_txq_maps(priv);
        mlx5e_activate_channels(&priv->channels);
        mlx5e_xdp_tx_enable(priv);
@@ -3135,7 +3161,7 @@ static void mlx5e_modify_admin_state(struct mlx5_core_dev *mdev,
 
        mlx5_set_port_admin_status(mdev, state);
 
-       if (!MLX5_ESWITCH_MANAGER(mdev) ||  mlx5_eswitch_mode(esw) == MLX5_ESWITCH_OFFLOADS)
+       if (mlx5_eswitch_mode(mdev) != MLX5_ESWITCH_LEGACY)
                return;
 
        if (state == MLX5_PORT_UP)
@@ -3219,6 +3245,11 @@ int mlx5e_close(struct net_device *netdev)
        return err;
 }
 
+static void mlx5e_free_drop_rq(struct mlx5e_rq *rq)
+{
+       mlx5_wq_destroy(&rq->wq_ctrl);
+}
+
 static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
                               struct mlx5e_rq *rq,
                               struct mlx5e_rq_param *param)
@@ -3242,14 +3273,16 @@ static int mlx5e_alloc_drop_rq(struct mlx5_core_dev *mdev,
        return 0;
 }
 
-static int mlx5e_alloc_drop_cq(struct mlx5_core_dev *mdev,
+static int mlx5e_alloc_drop_cq(struct mlx5e_priv *priv,
                               struct mlx5e_cq *cq,
                               struct mlx5e_cq_param *param)
 {
+       struct mlx5_core_dev *mdev = priv->mdev;
+
        param->wq.buf_numa_node = dev_to_node(mlx5_core_dma_dev(mdev));
        param->wq.db_numa_node  = dev_to_node(mlx5_core_dma_dev(mdev));
 
-       return mlx5e_alloc_cq_common(mdev, param, cq);
+       return mlx5e_alloc_cq_common(priv, param, cq);
 }
 
 int mlx5e_open_drop_rq(struct mlx5e_priv *priv,
@@ -3263,7 +3296,7 @@ int mlx5e_open_drop_rq(struct mlx5e_priv *priv,
 
        mlx5e_build_drop_rq_param(priv, &rq_param);
 
-       err = mlx5e_alloc_drop_cq(mdev, cq, &cq_param);
+       err = mlx5e_alloc_drop_cq(priv, cq, &cq_param);
        if (err)
                return err;
 
@@ -3286,7 +3319,7 @@ int mlx5e_open_drop_rq(struct mlx5e_priv *priv,
        return 0;
 
 err_free_rq:
-       mlx5e_free_rq(drop_rq);
+       mlx5e_free_drop_rq(drop_rq);
 
 err_destroy_cq:
        mlx5e_destroy_cq(cq);
@@ -3300,7 +3333,7 @@ err_free_cq:
 void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq)
 {
        mlx5e_destroy_rq(drop_rq);
-       mlx5e_free_rq(drop_rq);
+       mlx5e_free_drop_rq(drop_rq);
        mlx5e_destroy_cq(&drop_rq->cq);
        mlx5e_free_cq(&drop_rq->cq);
 }
@@ -3999,6 +4032,9 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
 
        new_channels.params = *params;
        new_channels.params.sw_mtu = new_mtu;
+       err = mlx5e_validate_params(priv, &new_channels.params);
+       if (err)
+               goto out;
 
        if (params->xdp_prog &&
            !mlx5e_rx_is_linear_skb(&new_channels.params, NULL)) {
@@ -4251,6 +4287,20 @@ int mlx5e_get_vf_stats(struct net_device *dev,
 }
 #endif
 
+static bool mlx5e_tunnel_proto_supported_tx(struct mlx5_core_dev *mdev, u8 proto_type)
+{
+       switch (proto_type) {
+       case IPPROTO_GRE:
+               return MLX5_CAP_ETH(mdev, tunnel_stateless_gre);
+       case IPPROTO_IPIP:
+       case IPPROTO_IPV6:
+               return (MLX5_CAP_ETH(mdev, tunnel_stateless_ip_over_ip) ||
+                       MLX5_CAP_ETH(mdev, tunnel_stateless_ip_over_ip_tx));
+       default:
+               return false;
+       }
+}
+
 static bool mlx5e_gre_tunnel_inner_proto_offload_supported(struct mlx5_core_dev *mdev,
                                                           struct sk_buff *skb)
 {
@@ -4293,7 +4343,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
                break;
        case IPPROTO_IPIP:
        case IPPROTO_IPV6:
-               if (mlx5e_tunnel_proto_supported(priv->mdev, IPPROTO_IPIP))
+               if (mlx5e_tunnel_proto_supported_tx(priv->mdev, IPPROTO_IPIP))
                        return features;
                break;
        case IPPROTO_UDP:
@@ -4342,6 +4392,7 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)
 {
        struct mlx5e_priv *priv = container_of(work, struct mlx5e_priv,
                                               tx_timeout_work);
+       struct net_device *netdev = priv->netdev;
        int i;
 
        rtnl_lock();
@@ -4350,9 +4401,9 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
                goto unlock;
 
-       for (i = 0; i < priv->channels.num * priv->channels.params.num_tc; i++) {
+       for (i = 0; i < netdev->real_num_tx_queues; i++) {
                struct netdev_queue *dev_queue =
-                       netdev_get_tx_queue(priv->netdev, i);
+                       netdev_get_tx_queue(netdev, i);
                struct mlx5e_txqsq *sq = priv->txq2sq[i];
 
                if (!netif_xmit_stopped(dev_queue))
@@ -4412,7 +4463,7 @@ static void mlx5e_rq_replace_xdp_prog(struct mlx5e_rq *rq, struct bpf_prog *prog
        struct bpf_prog *old_prog;
 
        old_prog = rcu_replace_pointer(rq->xdp_prog, prog,
-                                      lockdep_is_held(&rq->channel->priv->state_lock));
+                                      lockdep_is_held(&rq->priv->state_lock));
        if (old_prog)
                bpf_prog_put(old_prog);
 }
@@ -4597,31 +4648,6 @@ const struct net_device_ops mlx5e_netdev_ops = {
        .ndo_get_devlink_port    = mlx5e_get_devlink_port,
 };
 
-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 -EOPNOTSUPP;
-       if (!MLX5_CAP_GEN(mdev, eth_net_offloads) ||
-           !MLX5_CAP_GEN(mdev, nic_flow_table) ||
-           !MLX5_CAP_ETH(mdev, csum_cap) ||
-           !MLX5_CAP_ETH(mdev, max_lso_cap) ||
-           !MLX5_CAP_ETH(mdev, vlan_cap) ||
-           !MLX5_CAP_ETH(mdev, rss_ind_tbl_cap) ||
-           MLX5_CAP_FLOWTABLE(mdev,
-                              flow_table_properties_nic_receive.max_ft_level)
-                              < 3) {
-               mlx5_core_warn(mdev,
-                              "Not creating net device, some required device capabilities are missing\n");
-               return -EOPNOTSUPP;
-       }
-       if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
-               mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
-       if (!MLX5_CAP_GEN(mdev, cq_moderation))
-               mlx5_core_warn(mdev, "CQ moderation is not supported\n");
-
-       return 0;
-}
-
 void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
                                   int num_channels)
 {
@@ -4877,6 +4903,17 @@ void mlx5e_vxlan_set_netdev_info(struct mlx5e_priv *priv)
        priv->netdev->udp_tunnel_nic_info = &priv->nic_info;
 }
 
+static bool mlx5e_tunnel_any_tx_proto_supported(struct mlx5_core_dev *mdev)
+{
+       int tt;
+
+       for (tt = 0; tt < MLX5E_NUM_TUNNEL_TT; tt++) {
+               if (mlx5e_tunnel_proto_supported_tx(mdev, mlx5e_get_proto_by_tunnel_type(tt)))
+                       return true;
+       }
+       return (mlx5_vxlan_allowed(mdev->vxlan) || mlx5_geneve_tx_allowed(mdev));
+}
+
 static void mlx5e_build_nic_netdev(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -4922,8 +4959,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
 
        mlx5e_vxlan_set_netdev_info(priv);
 
-       if (mlx5_vxlan_allowed(mdev->vxlan) || mlx5_geneve_tx_allowed(mdev) ||
-           mlx5e_any_tunnel_proto_supported(mdev)) {
+       if (mlx5e_tunnel_any_tx_proto_supported(mdev)) {
                netdev->hw_enc_features |= NETIF_F_HW_CSUM;
                netdev->hw_enc_features |= NETIF_F_TSO;
                netdev->hw_enc_features |= NETIF_F_TSO6;
@@ -4940,7 +4976,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
                                         NETIF_F_GSO_UDP_TUNNEL_CSUM;
        }
 
-       if (mlx5e_tunnel_proto_supported(mdev, IPPROTO_GRE)) {
+       if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_GRE)) {
                netdev->hw_features     |= NETIF_F_GSO_GRE |
                                           NETIF_F_GSO_GRE_CSUM;
                netdev->hw_enc_features |= NETIF_F_GSO_GRE |
@@ -4949,7 +4985,7 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
                                                NETIF_F_GSO_GRE_CSUM;
        }
 
-       if (mlx5e_tunnel_proto_supported(mdev, IPPROTO_IPIP)) {
+       if (mlx5e_tunnel_proto_supported_tx(mdev, IPPROTO_IPIP)) {
                netdev->hw_features |= NETIF_F_GSO_IPXIP4 |
                                       NETIF_F_GSO_IPXIP6;
                netdev->hw_enc_features |= NETIF_F_GSO_IPXIP4 |
@@ -5334,10 +5370,14 @@ struct net_device *mlx5e_create_netdev(struct mlx5_core_dev *mdev,
                                       void *ppriv)
 {
        struct net_device *netdev;
+       unsigned int ptp_txqs = 0;
        int err;
 
+       if (MLX5_CAP_GEN(mdev, ts_cqe_to_dest_cqn))
+               ptp_txqs = profile->max_tc;
+
        netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv),
-                                   nch * profile->max_tc,
+                                   nch * profile->max_tc + ptp_txqs,
                                    nch * profile->rq_groups);
        if (!netdev) {
                mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
@@ -5441,13 +5481,12 @@ void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
        free_netdev(netdev);
 }
 
-/* mlx5e_attach and mlx5e_detach scope should be only creating/destroying
- * hardware contexts and to connect it to the current netdev.
- */
-static int mlx5e_attach(struct mlx5_core_dev *mdev, void *vpriv)
+static int mlx5e_resume(struct auxiliary_device *adev)
 {
-       struct mlx5e_priv *priv = vpriv;
+       struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
+       struct mlx5e_priv *priv = dev_get_drvdata(&adev->dev);
        struct net_device *netdev = priv->netdev;
+       struct mlx5_core_dev *mdev = edev->mdev;
        int err;
 
        if (netif_device_present(netdev))
@@ -5466,109 +5505,111 @@ static int mlx5e_attach(struct mlx5_core_dev *mdev, void *vpriv)
        return 0;
 }
 
-static void mlx5e_detach(struct mlx5_core_dev *mdev, void *vpriv)
+static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state)
 {
-       struct mlx5e_priv *priv = vpriv;
+       struct mlx5e_priv *priv = dev_get_drvdata(&adev->dev);
        struct net_device *netdev = priv->netdev;
-
-#ifdef CONFIG_MLX5_ESWITCH
-       if (MLX5_ESWITCH_MANAGER(mdev) && vpriv == mdev)
-               return;
-#endif
+       struct mlx5_core_dev *mdev = priv->mdev;
 
        if (!netif_device_present(netdev))
-               return;
+               return -ENODEV;
 
        mlx5e_detach_netdev(priv);
        mlx5e_destroy_mdev_resources(mdev);
+       return 0;
 }
 
-static void *mlx5e_add(struct mlx5_core_dev *mdev)
+static int mlx5e_probe(struct auxiliary_device *adev,
+                      const struct auxiliary_device_id *id)
 {
+       struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
+       struct mlx5_core_dev *mdev = edev->mdev;
        struct net_device *netdev;
+       pm_message_t state = {};
        void *priv;
        int err;
        int nch;
 
-       err = mlx5e_check_required_hca_cap(mdev);
-       if (err)
-               return NULL;
-
-#ifdef CONFIG_MLX5_ESWITCH
-       if (MLX5_ESWITCH_MANAGER(mdev) &&
-           mlx5_eswitch_mode(mdev->priv.eswitch) == MLX5_ESWITCH_OFFLOADS) {
-               mlx5e_rep_register_vport_reps(mdev);
-               return mdev;
-       }
-#endif
-
        nch = mlx5e_get_max_num_channels(mdev);
        netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, nch, NULL);
        if (!netdev) {
                mlx5_core_err(mdev, "mlx5e_create_netdev failed\n");
-               return NULL;
+               return -ENOMEM;
        }
 
        dev_net_set(netdev, mlx5_core_net(mdev));
        priv = netdev_priv(netdev);
+       dev_set_drvdata(&adev->dev, priv);
 
-       err = mlx5e_attach(mdev, priv);
+       err = mlx5e_resume(adev);
        if (err) {
-               mlx5_core_err(mdev, "mlx5e_attach failed, %d\n", err);
+               mlx5_core_err(mdev, "mlx5e_resume failed, %d\n", err);
                goto err_destroy_netdev;
        }
 
        err = register_netdev(netdev);
        if (err) {
                mlx5_core_err(mdev, "register_netdev failed, %d\n", err);
-               goto err_detach;
+               goto err_resume;
        }
 
        mlx5e_devlink_port_type_eth_set(priv);
 
        mlx5e_dcbnl_init_app(priv);
-       return priv;
+       return 0;
 
-err_detach:
-       mlx5e_detach(mdev, priv);
+err_resume:
+       mlx5e_suspend(adev, state);
 err_destroy_netdev:
        mlx5e_destroy_netdev(priv);
-       return NULL;
+       return err;
 }
 
-static void mlx5e_remove(struct mlx5_core_dev *mdev, void *vpriv)
+static void mlx5e_remove(struct auxiliary_device *adev)
 {
-       struct mlx5e_priv *priv;
+       struct mlx5e_priv *priv = dev_get_drvdata(&adev->dev);
+       pm_message_t state = {};
 
-#ifdef CONFIG_MLX5_ESWITCH
-       if (MLX5_ESWITCH_MANAGER(mdev) && vpriv == mdev) {
-               mlx5e_rep_unregister_vport_reps(mdev);
-               return;
-       }
-#endif
-       priv = vpriv;
        mlx5e_dcbnl_delete_app(priv);
        unregister_netdev(priv->netdev);
-       mlx5e_detach(mdev, vpriv);
+       mlx5e_suspend(adev, state);
        mlx5e_destroy_netdev(priv);
 }
 
-static struct mlx5_interface mlx5e_interface = {
-       .add       = mlx5e_add,
-       .remove    = mlx5e_remove,
-       .attach    = mlx5e_attach,
-       .detach    = mlx5e_detach,
-       .protocol  = MLX5_INTERFACE_PROTOCOL_ETH,
+static const struct auxiliary_device_id mlx5e_id_table[] = {
+       { .name = MLX5_ADEV_NAME ".eth", },
+       {},
+};
+
+MODULE_DEVICE_TABLE(auxiliary, mlx5e_id_table);
+
+static struct auxiliary_driver mlx5e_driver = {
+       .name = "eth",
+       .probe = mlx5e_probe,
+       .remove = mlx5e_remove,
+       .suspend = mlx5e_suspend,
+       .resume = mlx5e_resume,
+       .id_table = mlx5e_id_table,
 };
 
-void mlx5e_init(void)
+int mlx5e_init(void)
 {
+       int ret;
+
        mlx5e_ipsec_build_inverse_table();
        mlx5e_build_ptys2ethtool_map();
-       mlx5_register_interface(&mlx5e_interface);
+       ret = mlx5e_rep_init();
+       if (ret)
+               return ret;
+
+       ret = auxiliary_driver_register(&mlx5e_driver);
+       if (ret)
+               mlx5e_rep_cleanup();
+       return ret;
 }
 
 void mlx5e_cleanup(void)
 {
-       mlx5_unregister_interface(&mlx5e_interface);
+       auxiliary_driver_unregister(&mlx5e_driver);
+       mlx5e_rep_cleanup();
 }