Merge branch 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox...
authorSaeed Mahameed <saeedm@mellanox.com>
Mon, 10 Dec 2018 23:43:47 +0000 (15:43 -0800)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 10 Dec 2018 23:50:50 +0000 (15:50 -0800)
mlx5-next shared branch with rdma subtree to avoid mlx5 rdma v.s. netdev
conflicts.

Highlights:

1) RDMA ODP  (On Demand Paging) improvements and moving ODP logic to
mlx5 RDMA driver
2) Improved mlx5 core driver and device events handling and provided API
for upper layers to subscribe to device events.
3) RDMA only code cleanup from mlx5 core
4) Add helper to get CQE opcode
5) Rework handling of port module events
6) shared mlx5_ifc.h updates to avoid conflicts

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
1  2 
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/odp.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c

index 676c1fd1119d80a17d4542d035a319300332842f,e334480b56bf9ab791ea064a4d5fda14d3e0e84a..9608681224e668d92ebe1c4b1b2004e61a930160
@@@ -137,6 -137,15 +137,6 @@@ static void ib_umem_notifier_release(st
        up_read(&per_mm->umem_rwsem);
  }
  
 -static int invalidate_page_trampoline(struct ib_umem_odp *item, u64 start,
 -                                    u64 end, void *cookie)
 -{
 -      ib_umem_notifier_start_account(item);
 -      item->umem.context->invalidate_range(item, start, start + PAGE_SIZE);
 -      ib_umem_notifier_end_account(item);
 -      return 0;
 -}
 -
  static int invalidate_range_start_trampoline(struct ib_umem_odp *item,
                                             u64 start, u64 end, void *cookie)
  {
@@@ -544,13 -553,12 +544,13 @@@ out
                put_page(page);
  
        if (remove_existing_mapping && umem->context->invalidate_range) {
 -              invalidate_page_trampoline(
 +              ib_umem_notifier_start_account(umem_odp);
 +              umem->context->invalidate_range(
                        umem_odp,
 -                      ib_umem_start(umem) + (page_index >> umem->page_shift),
 -                      ib_umem_start(umem) + ((page_index + 1) >>
 -                                             umem->page_shift),
 -                      NULL);
 +                      ib_umem_start(umem) + (page_index << umem->page_shift),
 +                      ib_umem_start(umem) +
 +                              ((page_index + 1) << umem->page_shift));
 +              ib_umem_notifier_end_account(umem_odp);
                ret = -EAGAIN;
        }
  
@@@ -647,8 -655,13 +647,13 @@@ int ib_umem_odp_map_dma_pages(struct ib
                                flags, local_page_list, NULL, NULL);
                up_read(&owning_mm->mmap_sem);
  
-               if (npages < 0)
+               if (npages < 0) {
+                       if (npages != -EAGAIN)
+                               pr_warn("fail to get %zu user pages with error %d\n", gup_num_pages, npages);
+                       else
+                               pr_debug("fail to get %zu user pages with error %d\n", gup_num_pages, npages);
                        break;
+               }
  
                bcnt -= min_t(size_t, npages << PAGE_SHIFT, bcnt);
                mutex_lock(&umem_odp->umem_mutex);
                        ret = ib_umem_odp_map_dma_single_page(
                                        umem_odp, k, local_page_list[j],
                                        access_mask, current_seq);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               if (ret != -EAGAIN)
+                                       pr_warn("ib_umem_odp_map_dma_single_page failed with error %d\n", ret);
+                               else
+                                       pr_debug("ib_umem_odp_map_dma_single_page failed with error %d\n", ret);
                                break;
+                       }
  
                        p = page_to_phys(local_page_list[j]);
                        k++;
index 3569fda07e07f47b9286b7e1251c2716f9169203,2560996fce79b1cd11b7b4c6bc5d00264bdb61ae..0eeefff09c1eba8918d301cdb39408b457cf7f68
@@@ -60,6 -60,7 +60,7 @@@
  #include "mlx5_ib.h"
  #include "ib_rep.h"
  #include "cmd.h"
+ #include "srq.h"
  #include <linux/mlx5/fs_helpers.h>
  #include <linux/mlx5/accel.h>
  #include <rdma/uverbs_std_types.h>
@@@ -82,10 -83,13 +83,13 @@@ static char mlx5_version[] 
  
  struct mlx5_ib_event_work {
        struct work_struct      work;
-       struct mlx5_core_dev    *dev;
-       void                    *context;
-       enum mlx5_dev_event     event;
-       unsigned long           param;
+       union {
+               struct mlx5_ib_dev            *dev;
+               struct mlx5_ib_multiport_info *mpi;
+       };
+       bool                    is_slave;
+       unsigned int            event;
+       void                    *param;
  };
  
  enum {
@@@ -1094,26 -1098,31 +1098,26 @@@ enum mlx5_ib_width 
        MLX5_IB_WIDTH_12X       = 1 << 4
  };
  
 -static int translate_active_width(struct ib_device *ibdev, u8 active_width,
 +static void translate_active_width(struct ib_device *ibdev, u8 active_width,
                                  u8 *ib_width)
  {
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
 -      int err = 0;
  
 -      if (active_width & MLX5_IB_WIDTH_1X) {
 +      if (active_width & MLX5_IB_WIDTH_1X)
                *ib_width = IB_WIDTH_1X;
 -      } else if (active_width & MLX5_IB_WIDTH_2X) {
 -              mlx5_ib_dbg(dev, "active_width %d is not supported by IB spec\n",
 -                          (int)active_width);
 -              err = -EINVAL;
 -      } else if (active_width & MLX5_IB_WIDTH_4X) {
 +      else if (active_width & MLX5_IB_WIDTH_4X)
                *ib_width = IB_WIDTH_4X;
 -      } else if (active_width & MLX5_IB_WIDTH_8X) {
 +      else if (active_width & MLX5_IB_WIDTH_8X)
                *ib_width = IB_WIDTH_8X;
 -      } else if (active_width & MLX5_IB_WIDTH_12X) {
 +      else if (active_width & MLX5_IB_WIDTH_12X)
                *ib_width = IB_WIDTH_12X;
 -      else {
 -              mlx5_ib_dbg(dev, "Invalid active_width %d\n",
 +      else {
 +              mlx5_ib_dbg(dev, "Invalid active_width %d, setting width to default value: 4x\n",
                            (int)active_width);
 -              err = -EINVAL;
 +              *ib_width = IB_WIDTH_4X;
        }
  
 -      return err;
 +      return;
  }
  
  static int mlx5_mtu_to_ib_mtu(int mtu)
@@@ -1220,8 -1229,10 +1224,8 @@@ static int mlx5_query_hca_port(struct i
        if (err)
                goto out;
  
 -      err = translate_active_width(ibdev, ib_link_width_oper,
 -                                   &props->active_width);
 -      if (err)
 -              goto out;
 +      translate_active_width(ibdev, ib_link_width_oper, &props->active_width);
 +
        err = mlx5_query_port_ib_proto_oper(mdev, &props->active_speed, port);
        if (err)
                goto out;
@@@ -2669,11 -2680,11 +2673,11 @@@ static int parse_flow_attr(struct mlx5_
                         ntohs(ib_spec->gre.val.protocol));
  
                memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_c,
-                                   gre_key_h),
+                                   gre_key.nvgre.hi),
                       &ib_spec->gre.mask.key,
                       sizeof(ib_spec->gre.mask.key));
                memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_v,
-                                   gre_key_h),
+                                   gre_key.nvgre.hi),
                       &ib_spec->gre.val.key,
                       sizeof(ib_spec->gre.val.key));
                break;
@@@ -4226,6 -4237,63 +4230,63 @@@ static void delay_drop_handler(struct w
        mutex_unlock(&delay_drop->lock);
  }
  
+ static void handle_general_event(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe,
+                                struct ib_event *ibev)
+ {
+       switch (eqe->sub_type) {
+       case MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT:
+               schedule_work(&ibdev->delay_drop.delay_drop_work);
+               break;
+       default: /* do nothing */
+               return;
+       }
+ }
+ static int handle_port_change(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe,
+                             struct ib_event *ibev)
+ {
+       u8 port = (eqe->data.port.port >> 4) & 0xf;
+       ibev->element.port_num = port;
+       switch (eqe->sub_type) {
+       case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
+       case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
+       case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED:
+               /* In RoCE, port up/down events are handled in
+                * mlx5_netdev_event().
+                */
+               if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==
+                                           IB_LINK_LAYER_ETHERNET)
+                       return -EINVAL;
+               ibev->event = (eqe->sub_type == MLX5_PORT_CHANGE_SUBTYPE_ACTIVE) ?
+                               IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
+               break;
+       case MLX5_PORT_CHANGE_SUBTYPE_LID:
+               ibev->event = IB_EVENT_LID_CHANGE;
+               break;
+       case MLX5_PORT_CHANGE_SUBTYPE_PKEY:
+               ibev->event = IB_EVENT_PKEY_CHANGE;
+               schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work);
+               break;
+       case MLX5_PORT_CHANGE_SUBTYPE_GUID:
+               ibev->event = IB_EVENT_GID_CHANGE;
+               break;
+       case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG:
+               ibev->event = IB_EVENT_CLIENT_REREGISTER;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+ }
  static void mlx5_ib_handle_event(struct work_struct *_work)
  {
        struct mlx5_ib_event_work *work =
        struct mlx5_ib_dev *ibdev;
        struct ib_event ibev;
        bool fatal = false;
-       u8 port = (u8)work->param;
  
-       if (mlx5_core_is_mp_slave(work->dev)) {
-               ibdev = mlx5_ib_get_ibdev_from_mpi(work->context);
+       if (work->is_slave) {
+               ibdev = mlx5_ib_get_ibdev_from_mpi(work->mpi);
                if (!ibdev)
                        goto out;
        } else {
-               ibdev = work->context;
+               ibdev = work->dev;
        }
  
        switch (work->event) {
        case MLX5_DEV_EVENT_SYS_ERROR:
                ibev.event = IB_EVENT_DEVICE_FATAL;
                mlx5_ib_handle_internal_error(ibdev);
+               ibev.element.port_num  = (u8)(unsigned long)work->param;
                fatal = true;
                break;
-       case MLX5_DEV_EVENT_PORT_UP:
-       case MLX5_DEV_EVENT_PORT_DOWN:
-       case MLX5_DEV_EVENT_PORT_INITIALIZED:
-               /* In RoCE, port up/down events are handled in
-                * mlx5_netdev_event().
-                */
-               if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==
-                       IB_LINK_LAYER_ETHERNET)
+       case MLX5_EVENT_TYPE_PORT_CHANGE:
+               if (handle_port_change(ibdev, work->param, &ibev))
                        goto out;
-               ibev.event = (work->event == MLX5_DEV_EVENT_PORT_UP) ?
-                            IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
                break;
-       case MLX5_DEV_EVENT_LID_CHANGE:
-               ibev.event = IB_EVENT_LID_CHANGE;
-               break;
-       case MLX5_DEV_EVENT_PKEY_CHANGE:
-               ibev.event = IB_EVENT_PKEY_CHANGE;
-               schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work);
-               break;
-       case MLX5_DEV_EVENT_GUID_CHANGE:
-               ibev.event = IB_EVENT_GID_CHANGE;
-               break;
-       case MLX5_DEV_EVENT_CLIENT_REREG:
-               ibev.event = IB_EVENT_CLIENT_REREGISTER;
-               break;
-       case MLX5_DEV_EVENT_DELAY_DROP_TIMEOUT:
-               schedule_work(&ibdev->delay_drop.delay_drop_work);
-               goto out;
+       case MLX5_EVENT_TYPE_GENERAL_EVENT:
+               handle_general_event(ibdev, work->param, &ibev);
+               /* fall through */
        default:
                goto out;
        }
  
-       ibev.device           = &ibdev->ib_dev;
-       ibev.element.port_num = port;
+       ibev.device = &ibdev->ib_dev;
  
-       if (!rdma_is_port_valid(&ibdev->ib_dev, port)) {
-               mlx5_ib_warn(ibdev, "warning: event on port %d\n", port);
+       if (!rdma_is_port_valid(&ibdev->ib_dev, ibev.element.port_num)) {
+               mlx5_ib_warn(ibdev, "warning: event on port %d\n",  ibev.element.port_num);
                goto out;
        }
  
        kfree(work);
  }
  
- static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
-                         enum mlx5_dev_event event, unsigned long param)
+ static int mlx5_ib_event(struct notifier_block *nb,
+                        unsigned long event, void *param)
  {
        struct mlx5_ib_event_work *work;
  
        work = kmalloc(sizeof(*work), GFP_ATOMIC);
        if (!work)
-               return;
+               return NOTIFY_DONE;
  
        INIT_WORK(&work->work, mlx5_ib_handle_event);
-       work->dev = dev;
+       work->dev = container_of(nb, struct mlx5_ib_dev, mdev_events);
+       work->is_slave = false;
        work->param = param;
-       work->context = context;
        work->event = event;
  
        queue_work(mlx5_ib_event_wq, &work->work);
+       return NOTIFY_OK;
+ }
+ static int mlx5_ib_event_slave_port(struct notifier_block *nb,
+                                   unsigned long event, void *param)
+ {
+       struct mlx5_ib_event_work *work;
+       work = kmalloc(sizeof(*work), GFP_ATOMIC);
+       if (!work)
+               return NOTIFY_DONE;
+       INIT_WORK(&work->work, mlx5_ib_handle_event);
+       work->mpi = container_of(nb, struct mlx5_ib_multiport_info, mdev_events);
+       work->is_slave = true;
+       work->param = param;
+       work->event = event;
+       queue_work(mlx5_ib_event_wq, &work->work);
+       return NOTIFY_OK;
  }
  
  static int set_has_smi_cap(struct mlx5_ib_dev *dev)
@@@ -5330,7 -5391,7 +5384,7 @@@ mlx5_ib_get_vector_affinity(struct ib_d
  {
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
  
-       return mlx5_get_vector_affinity_hint(dev->mdev, comp_vector);
+       return mlx5_comp_irq_get_affinity_mask(dev->mdev, comp_vector);
  }
  
  /* The mlx5_ib_multiport_mutex should be held when calling this function */
@@@ -5350,6 -5411,11 +5404,11 @@@ static void mlx5_ib_unbind_slave_port(s
                spin_unlock(&port->mp.mpi_lock);
                return;
        }
+       if (mpi->mdev_events.notifier_call)
+               mlx5_notifier_unregister(mpi->mdev, &mpi->mdev_events);
+       mpi->mdev_events.notifier_call = NULL;
        mpi->ibdev = NULL;
  
        spin_unlock(&port->mp.mpi_lock);
@@@ -5405,6 -5471,7 +5464,7 @@@ static bool mlx5_ib_bind_slave_port(str
  
        ibdev->port[port_num].mp.mpi = mpi;
        mpi->ibdev = ibdev;
+       mpi->mdev_events.notifier_call = NULL;
        spin_unlock(&ibdev->port[port_num].mp.mpi_lock);
  
        err = mlx5_nic_vport_affiliate_multiport(ibdev->mdev, mpi->mdev);
                goto unbind;
        }
  
+       mpi->mdev_events.notifier_call = mlx5_ib_event_slave_port;
+       mlx5_notifier_register(mpi->mdev, &mpi->mdev_events);
        err = mlx5_ib_init_cong_debugfs(ibdev, port_num);
        if (err)
                goto unbind;
@@@ -5694,8 -5764,7 +5757,7 @@@ int mlx5_ib_stage_init_init(struct mlx5
        dev->ib_dev.node_type           = RDMA_NODE_IB_CA;
        dev->ib_dev.local_dma_lkey      = 0 /* not supported for now */;
        dev->ib_dev.phys_port_cnt       = dev->num_ports;
-       dev->ib_dev.num_comp_vectors    =
-               dev->mdev->priv.eq_table.num_comp_vectors;
+       dev->ib_dev.num_comp_vectors    = mlx5_comp_vectors_count(mdev);
        dev->ib_dev.dev.parent          = &mdev->pdev->dev;
  
        mutex_init(&dev->cap_mask_mutex);
@@@ -6034,6 -6103,11 +6096,11 @@@ static int mlx5_ib_stage_odp_init(struc
        return mlx5_ib_odp_init_one(dev);
  }
  
+ void mlx5_ib_stage_odp_cleanup(struct mlx5_ib_dev *dev)
+ {
+       mlx5_ib_odp_cleanup_one(dev);
+ }
  int mlx5_ib_stage_counters_init(struct mlx5_ib_dev *dev)
  {
        if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) {
@@@ -6152,6 -6226,34 +6219,34 @@@ static void mlx5_ib_stage_rep_reg_clean
        mlx5_ib_unregister_vport_reps(dev);
  }
  
+ static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev)
+ {
+       dev->mdev_events.notifier_call = mlx5_ib_event;
+       mlx5_notifier_register(dev->mdev, &dev->mdev_events);
+       return 0;
+ }
+ static void mlx5_ib_stage_dev_notifier_cleanup(struct mlx5_ib_dev *dev)
+ {
+       mlx5_notifier_unregister(dev->mdev, &dev->mdev_events);
+ }
+ static int mlx5_ib_stage_devx_init(struct mlx5_ib_dev *dev)
+ {
+       int uid;
+       uid = mlx5_ib_devx_create(dev);
+       if (uid > 0)
+               dev->devx_whitelist_uid = uid;
+       return 0;
+ }
+ static void mlx5_ib_stage_devx_cleanup(struct mlx5_ib_dev *dev)
+ {
+       if (dev->devx_whitelist_uid)
+               mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid);
+ }
  void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
                      const struct mlx5_ib_profile *profile,
                      int stage)
                        profile->stage[stage].cleanup(dev);
        }
  
-       if (dev->devx_whitelist_uid)
-               mlx5_ib_devx_destroy(dev, dev->devx_whitelist_uid);
        ib_dealloc_device((struct ib_device *)dev);
  }
  
@@@ -6173,7 -6273,6 +6266,6 @@@ void *__mlx5_ib_add(struct mlx5_ib_dev 
  {
        int err;
        int i;
-       int uid;
  
        for (i = 0; i < MLX5_IB_STAGE_MAX; i++) {
                if (profile->stage[i].init) {
                }
        }
  
-       uid = mlx5_ib_devx_create(dev);
-       if (uid > 0)
-               dev->devx_whitelist_uid = uid;
        dev->profile = profile;
        dev->ib_active = true;
  
@@@ -6214,12 -6309,18 +6302,18 @@@ static const struct mlx5_ib_profile pf_
        STAGE_CREATE(MLX5_IB_STAGE_ROCE,
                     mlx5_ib_stage_roce_init,
                     mlx5_ib_stage_roce_cleanup),
+       STAGE_CREATE(MLX5_IB_STAGE_SRQ,
+                    mlx5_init_srq_table,
+                    mlx5_cleanup_srq_table),
        STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
                     mlx5_ib_stage_dev_res_init,
                     mlx5_ib_stage_dev_res_cleanup),
+       STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
+                    mlx5_ib_stage_dev_notifier_init,
+                    mlx5_ib_stage_dev_notifier_cleanup),
        STAGE_CREATE(MLX5_IB_STAGE_ODP,
                     mlx5_ib_stage_odp_init,
-                    NULL),
+                    mlx5_ib_stage_odp_cleanup),
        STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
                     mlx5_ib_stage_counters_init,
                     mlx5_ib_stage_counters_cleanup),
        STAGE_CREATE(MLX5_IB_STAGE_SPECS,
                     mlx5_ib_stage_populate_specs,
                     NULL),
+       STAGE_CREATE(MLX5_IB_STAGE_WHITELIST_UID,
+                    mlx5_ib_stage_devx_init,
+                    mlx5_ib_stage_devx_cleanup),
        STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
                     mlx5_ib_stage_ib_reg_init,
                     mlx5_ib_stage_ib_reg_cleanup),
@@@ -6265,9 -6369,15 +6362,15 @@@ static const struct mlx5_ib_profile nic
        STAGE_CREATE(MLX5_IB_STAGE_ROCE,
                     mlx5_ib_stage_rep_roce_init,
                     mlx5_ib_stage_rep_roce_cleanup),
+       STAGE_CREATE(MLX5_IB_STAGE_SRQ,
+                    mlx5_init_srq_table,
+                    mlx5_cleanup_srq_table),
        STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
                     mlx5_ib_stage_dev_res_init,
                     mlx5_ib_stage_dev_res_cleanup),
+       STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,
+                    mlx5_ib_stage_dev_notifier_init,
+                    mlx5_ib_stage_dev_notifier_cleanup),
        STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
                     mlx5_ib_stage_counters_init,
                     mlx5_ib_stage_counters_cleanup),
@@@ -6388,10 -6498,6 +6491,6 @@@ static void mlx5_ib_remove(struct mlx5_
  static struct mlx5_interface mlx5_ib_interface = {
        .add            = mlx5_ib_add,
        .remove         = mlx5_ib_remove,
-       .event          = mlx5_ib_event,
- #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
-       .pfault         = mlx5_ib_pfault,
- #endif
        .protocol       = MLX5_INTERFACE_PROTOCOL_IB,
  };
  
index 2cc3d69ab6f64dde00ee48c82ff93c5edca697f4,416d141322a0dd02195ac3c9969e2bd1d1b0ae44..4ead8c0fff5ad46d6d68f676194badda71938f4f
  #include "mlx5_ib.h"
  #include "cmd.h"
  
+ #include <linux/mlx5/eq.h>
+ /* Contains the details of a pagefault. */
+ struct mlx5_pagefault {
+       u32                     bytes_committed;
+       u32                     token;
+       u8                      event_subtype;
+       u8                      type;
+       union {
+               /* Initiator or send message responder pagefault details. */
+               struct {
+                       /* Received packet size, only valid for responders. */
+                       u32     packet_size;
+                       /*
+                        * Number of resource holding WQE, depends on type.
+                        */
+                       u32     wq_num;
+                       /*
+                        * WQE index. Refers to either the send queue or
+                        * receive queue, according to event_subtype.
+                        */
+                       u16     wqe_index;
+               } wqe;
+               /* RDMA responder pagefault details */
+               struct {
+                       u32     r_key;
+                       /*
+                        * Received packet size, minimal size page fault
+                        * resolution required for forward progress.
+                        */
+                       u32     packet_size;
+                       u32     rdma_op_len;
+                       u64     rdma_va;
+               } rdma;
+       };
+       struct mlx5_ib_pf_eq    *eq;
+       struct work_struct      work;
+ };
  #define MAX_PREFETCH_LEN (4*1024*1024U)
  
  /* Timeout in ms to wait for an active mmu notifier to complete when handling
@@@ -304,14 -344,20 +344,20 @@@ static void mlx5_ib_page_fault_resume(s
  {
        int wq_num = pfault->event_subtype == MLX5_PFAULT_SUBTYPE_WQE ?
                     pfault->wqe.wq_num : pfault->token;
-       int ret = mlx5_core_page_fault_resume(dev->mdev,
-                                             pfault->token,
-                                             wq_num,
-                                             pfault->type,
-                                             error);
-       if (ret)
-               mlx5_ib_err(dev, "Failed to resolve the page fault on WQ 0x%x\n",
-                           wq_num);
+       u32 out[MLX5_ST_SZ_DW(page_fault_resume_out)] = { };
+       u32 in[MLX5_ST_SZ_DW(page_fault_resume_in)]   = { };
+       int err;
+       MLX5_SET(page_fault_resume_in, in, opcode, MLX5_CMD_OP_PAGE_FAULT_RESUME);
+       MLX5_SET(page_fault_resume_in, in, page_fault_type, pfault->type);
+       MLX5_SET(page_fault_resume_in, in, token, pfault->token);
+       MLX5_SET(page_fault_resume_in, in, wq_number, wq_num);
+       MLX5_SET(page_fault_resume_in, in, error, !!error);
+       err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
+       if (err)
+               mlx5_ib_err(dev, "Failed to resolve the page fault on WQ 0x%x err %d\n",
+                           wq_num, err);
  }
  
  static struct mlx5_ib_mr *implicit_mr_alloc(struct ib_pd *pd,
@@@ -607,8 -653,8 +653,8 @@@ out
                        if (!wait_for_completion_timeout(
                                        &odp->notifier_completion,
                                        timeout)) {
-                               mlx5_ib_warn(dev, "timeout waiting for mmu notifier. seq %d against %d\n",
-                                            current_seq, odp->notifiers_seq);
+                               mlx5_ib_warn(dev, "timeout waiting for mmu notifier. seq %d against %d. notifiers_count=%d\n",
+                                            current_seq, odp->notifiers_seq, odp->notifiers_count);
                        }
                } else {
                        /* The MR is being killed, kill the QP as well. */
@@@ -674,15 -720,6 +720,15 @@@ next_mr
                        goto srcu_unlock;
                }
  
 +              if (!mr->umem->is_odp) {
 +                      mlx5_ib_dbg(dev, "skipping non ODP MR (lkey=0x%06x) in page fault handler.\n",
 +                                  key);
 +                      if (bytes_mapped)
 +                              *bytes_mapped += bcnt;
 +                      ret = 0;
 +                      goto srcu_unlock;
 +              }
 +
                ret = pagefault_mr(dev, mr, io_virt, bcnt, bytes_mapped);
                if (ret < 0)
                        goto srcu_unlock;
                        head = frame;
  
                        bcnt -= frame->bcnt;
 +                      offset = 0;
                }
                break;
  
@@@ -1026,16 -1062,31 +1072,31 @@@ invalid_transport_or_opcode
        return 0;
  }
  
- static struct mlx5_ib_qp *mlx5_ib_odp_find_qp(struct mlx5_ib_dev *dev,
-                                             u32 wq_num)
+ static inline struct mlx5_core_rsc_common *odp_get_rsc(struct mlx5_ib_dev *dev,
+                                                      u32 wq_num, int pf_type)
  {
-       struct mlx5_core_qp *mqp = __mlx5_qp_lookup(dev->mdev, wq_num);
+       enum mlx5_res_type res_type;
  
-       if (!mqp) {
-               mlx5_ib_err(dev, "QPN 0x%6x not found\n", wq_num);
+       switch (pf_type) {
+       case MLX5_WQE_PF_TYPE_RMP:
+               res_type = MLX5_RES_SRQ;
+               break;
+       case MLX5_WQE_PF_TYPE_REQ_SEND_OR_WRITE:
+       case MLX5_WQE_PF_TYPE_RESP:
+       case MLX5_WQE_PF_TYPE_REQ_READ_OR_ATOMIC:
+               res_type = MLX5_RES_QP;
+               break;
+       default:
                return NULL;
        }
  
+       return mlx5_core_res_hold(dev->mdev, wq_num, res_type);
+ }
+ static inline struct mlx5_ib_qp *res_to_qp(struct mlx5_core_rsc_common *res)
+ {
+       struct mlx5_core_qp *mqp = (struct mlx5_core_qp *)res;
        return to_mibqp(mqp);
  }
  
@@@ -1049,18 -1100,30 +1110,30 @@@ static void mlx5_ib_mr_wqe_pfault_handl
        int resume_with_error = 1;
        u16 wqe_index = pfault->wqe.wqe_index;
        int requestor = pfault->type & MLX5_PFAULT_REQUESTOR;
+       struct mlx5_core_rsc_common *res;
        struct mlx5_ib_qp *qp;
  
+       res = odp_get_rsc(dev, pfault->wqe.wq_num, pfault->type);
+       if (!res) {
+               mlx5_ib_dbg(dev, "wqe page fault for missing resource %d\n", pfault->wqe.wq_num);
+               return;
+       }
+       switch (res->res) {
+       case MLX5_RES_QP:
+               qp = res_to_qp(res);
+               break;
+       default:
+               mlx5_ib_err(dev, "wqe page fault for unsupported type %d\n", pfault->type);
+               goto resolve_page_fault;
+       }
        buffer = (char *)__get_free_page(GFP_KERNEL);
        if (!buffer) {
                mlx5_ib_err(dev, "Error allocating memory for IO page fault handling.\n");
                goto resolve_page_fault;
        }
  
-       qp = mlx5_ib_odp_find_qp(dev, pfault->wqe.wq_num);
-       if (!qp)
-               goto resolve_page_fault;
        ret = mlx5_ib_read_user_wqe(qp, requestor, wqe_index, buffer,
                                    PAGE_SIZE, &qp->trans_qp.base);
        if (ret < 0) {
@@@ -1100,6 -1163,7 +1173,7 @@@ resolve_page_fault
        mlx5_ib_dbg(dev, "PAGE FAULT completed. QP 0x%x resume_with_error=%d, type: 0x%x\n",
                    pfault->wqe.wq_num, resume_with_error,
                    pfault->type);
+       mlx5_core_res_put(res);
        free_page((unsigned long)buffer);
  }
  
@@@ -1178,10 -1242,8 +1252,8 @@@ static void mlx5_ib_mr_rdma_pfault_hand
        }
  }
  
- void mlx5_ib_pfault(struct mlx5_core_dev *mdev, void *context,
-                   struct mlx5_pagefault *pfault)
+ static void mlx5_ib_pfault(struct mlx5_ib_dev *dev, struct mlx5_pagefault *pfault)
  {
-       struct mlx5_ib_dev *dev = context;
        u8 event_subtype = pfault->event_subtype;
  
        switch (event_subtype) {
        }
  }
  
+ static void mlx5_ib_eqe_pf_action(struct work_struct *work)
+ {
+       struct mlx5_pagefault *pfault = container_of(work,
+                                                    struct mlx5_pagefault,
+                                                    work);
+       struct mlx5_ib_pf_eq *eq = pfault->eq;
+       mlx5_ib_pfault(eq->dev, pfault);
+       mempool_free(pfault, eq->pool);
+ }
+ static void mlx5_ib_eq_pf_process(struct mlx5_ib_pf_eq *eq)
+ {
+       struct mlx5_eqe_page_fault *pf_eqe;
+       struct mlx5_pagefault *pfault;
+       struct mlx5_eqe *eqe;
+       int cc = 0;
+       while ((eqe = mlx5_eq_get_eqe(eq->core, cc))) {
+               pfault = mempool_alloc(eq->pool, GFP_ATOMIC);
+               if (!pfault) {
+                       schedule_work(&eq->work);
+                       break;
+               }
+               pf_eqe = &eqe->data.page_fault;
+               pfault->event_subtype = eqe->sub_type;
+               pfault->bytes_committed = be32_to_cpu(pf_eqe->bytes_committed);
+               mlx5_ib_dbg(eq->dev,
+                           "PAGE_FAULT: subtype: 0x%02x, bytes_committed: 0x%06x\n",
+                           eqe->sub_type, pfault->bytes_committed);
+               switch (eqe->sub_type) {
+               case MLX5_PFAULT_SUBTYPE_RDMA:
+                       /* RDMA based event */
+                       pfault->type =
+                               be32_to_cpu(pf_eqe->rdma.pftype_token) >> 24;
+                       pfault->token =
+                               be32_to_cpu(pf_eqe->rdma.pftype_token) &
+                               MLX5_24BIT_MASK;
+                       pfault->rdma.r_key =
+                               be32_to_cpu(pf_eqe->rdma.r_key);
+                       pfault->rdma.packet_size =
+                               be16_to_cpu(pf_eqe->rdma.packet_length);
+                       pfault->rdma.rdma_op_len =
+                               be32_to_cpu(pf_eqe->rdma.rdma_op_len);
+                       pfault->rdma.rdma_va =
+                               be64_to_cpu(pf_eqe->rdma.rdma_va);
+                       mlx5_ib_dbg(eq->dev,
+                                   "PAGE_FAULT: type:0x%x, token: 0x%06x, r_key: 0x%08x\n",
+                                   pfault->type, pfault->token,
+                                   pfault->rdma.r_key);
+                       mlx5_ib_dbg(eq->dev,
+                                   "PAGE_FAULT: rdma_op_len: 0x%08x, rdma_va: 0x%016llx\n",
+                                   pfault->rdma.rdma_op_len,
+                                   pfault->rdma.rdma_va);
+                       break;
+               case MLX5_PFAULT_SUBTYPE_WQE:
+                       /* WQE based event */
+                       pfault->type =
+                               (be32_to_cpu(pf_eqe->wqe.pftype_wq) >> 24) & 0x7;
+                       pfault->token =
+                               be32_to_cpu(pf_eqe->wqe.token);
+                       pfault->wqe.wq_num =
+                               be32_to_cpu(pf_eqe->wqe.pftype_wq) &
+                               MLX5_24BIT_MASK;
+                       pfault->wqe.wqe_index =
+                               be16_to_cpu(pf_eqe->wqe.wqe_index);
+                       pfault->wqe.packet_size =
+                               be16_to_cpu(pf_eqe->wqe.packet_length);
+                       mlx5_ib_dbg(eq->dev,
+                                   "PAGE_FAULT: type:0x%x, token: 0x%06x, wq_num: 0x%06x, wqe_index: 0x%04x\n",
+                                   pfault->type, pfault->token,
+                                   pfault->wqe.wq_num,
+                                   pfault->wqe.wqe_index);
+                       break;
+               default:
+                       mlx5_ib_warn(eq->dev,
+                                    "Unsupported page fault event sub-type: 0x%02hhx\n",
+                                    eqe->sub_type);
+                       /* Unsupported page faults should still be
+                        * resolved by the page fault handler
+                        */
+               }
+               pfault->eq = eq;
+               INIT_WORK(&pfault->work, mlx5_ib_eqe_pf_action);
+               queue_work(eq->wq, &pfault->work);
+               cc = mlx5_eq_update_cc(eq->core, ++cc);
+       }
+       mlx5_eq_update_ci(eq->core, cc, 1);
+ }
+ static irqreturn_t mlx5_ib_eq_pf_int(int irq, void *eq_ptr)
+ {
+       struct mlx5_ib_pf_eq *eq = eq_ptr;
+       unsigned long flags;
+       if (spin_trylock_irqsave(&eq->lock, flags)) {
+               mlx5_ib_eq_pf_process(eq);
+               spin_unlock_irqrestore(&eq->lock, flags);
+       } else {
+               schedule_work(&eq->work);
+       }
+       return IRQ_HANDLED;
+ }
+ /* mempool_refill() was proposed but unfortunately wasn't accepted
+  * http://lkml.iu.edu/hypermail/linux/kernel/1512.1/05073.html
+  * Cheap workaround.
+  */
+ static void mempool_refill(mempool_t *pool)
+ {
+       while (pool->curr_nr < pool->min_nr)
+               mempool_free(mempool_alloc(pool, GFP_KERNEL), pool);
+ }
+ static void mlx5_ib_eq_pf_action(struct work_struct *work)
+ {
+       struct mlx5_ib_pf_eq *eq =
+               container_of(work, struct mlx5_ib_pf_eq, work);
+       mempool_refill(eq->pool);
+       spin_lock_irq(&eq->lock);
+       mlx5_ib_eq_pf_process(eq);
+       spin_unlock_irq(&eq->lock);
+ }
+ enum {
+       MLX5_IB_NUM_PF_EQE      = 0x1000,
+       MLX5_IB_NUM_PF_DRAIN    = 64,
+ };
+ static int
+ mlx5_ib_create_pf_eq(struct mlx5_ib_dev *dev, struct mlx5_ib_pf_eq *eq)
+ {
+       struct mlx5_eq_param param = {};
+       int err;
+       INIT_WORK(&eq->work, mlx5_ib_eq_pf_action);
+       spin_lock_init(&eq->lock);
+       eq->dev = dev;
+       eq->pool = mempool_create_kmalloc_pool(MLX5_IB_NUM_PF_DRAIN,
+                                              sizeof(struct mlx5_pagefault));
+       if (!eq->pool)
+               return -ENOMEM;
+       eq->wq = alloc_workqueue("mlx5_ib_page_fault",
+                                WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM,
+                                MLX5_NUM_CMD_EQE);
+       if (!eq->wq) {
+               err = -ENOMEM;
+               goto err_mempool;
+       }
+       param = (struct mlx5_eq_param) {
+               .index = MLX5_EQ_PFAULT_IDX,
+               .mask = 1 << MLX5_EVENT_TYPE_PAGE_FAULT,
+               .nent = MLX5_IB_NUM_PF_EQE,
+               .context = eq,
+               .handler = mlx5_ib_eq_pf_int
+       };
+       eq->core = mlx5_eq_create_generic(dev->mdev, "mlx5_ib_page_fault_eq", &param);
+       if (IS_ERR(eq->core)) {
+               err = PTR_ERR(eq->core);
+               goto err_wq;
+       }
+       return 0;
+ err_wq:
+       destroy_workqueue(eq->wq);
+ err_mempool:
+       mempool_destroy(eq->pool);
+       return err;
+ }
+ static int
+ mlx5_ib_destroy_pf_eq(struct mlx5_ib_dev *dev, struct mlx5_ib_pf_eq *eq)
+ {
+       int err;
+       err = mlx5_eq_destroy_generic(dev->mdev, eq->core);
+       cancel_work_sync(&eq->work);
+       destroy_workqueue(eq->wq);
+       mempool_destroy(eq->pool);
+       return err;
+ }
  void mlx5_odp_init_mr_cache_entry(struct mlx5_cache_ent *ent)
  {
        if (!(ent->dev->odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT))
  
  int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
  {
-       int ret;
+       int ret = 0;
  
        if (dev->odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT) {
                ret = mlx5_cmd_null_mkey(dev->mdev, &dev->null_mkey);
                }
        }
  
-       return 0;
+       if (!MLX5_CAP_GEN(dev->mdev, pg))
+               return ret;
+       ret = mlx5_ib_create_pf_eq(dev, &dev->odp_pf_eq);
+       return ret;
+ }
+ void mlx5_ib_odp_cleanup_one(struct mlx5_ib_dev *dev)
+ {
+       if (!MLX5_CAP_GEN(dev->mdev, pg))
+               return;
+       mlx5_ib_destroy_pf_eq(dev, &dev->odp_pf_eq);
  }
  
  int mlx5_ib_odp_init(void)
  
        return 0;
  }
index 8760d10ad5a113f1017994e30eecce0014c5cbb8,13d8a74d3db5d8de4f478f2a2da9c593bd95930a..9ea0f853c3bb82e0e3d821b9fba8b6869bd7dc8c
@@@ -49,7 -49,6 +49,7 @@@
  #include <net/switchdev.h>
  #include <net/xdp.h>
  #include <linux/net_dim.h>
 +#include <linux/bits.h>
  #include "wq.h"
  #include "mlx5_core.h"
  #include "en_stats.h"
@@@ -148,6 -147,9 +148,6 @@@ struct page_pool
               MLX5_UMR_MTT_ALIGNMENT))
  #define MLX5E_UMR_WQEBBS \
        (DIV_ROUND_UP(MLX5E_UMR_WQE_INLINE_SZ, MLX5_SEND_WQE_BB))
 -#define MLX5E_ICOSQ_MAX_WQEBBS MLX5E_UMR_WQEBBS
 -
 -#define MLX5E_NUM_MAIN_GROUPS 9
  
  #define MLX5E_MSG_LEVEL                       NETIF_MSG_LINK
  
@@@ -176,8 -178,7 +176,7 @@@ static inline int mlx5e_get_max_num_cha
  {
        return is_kdump_kernel() ?
                MLX5E_MIN_NUM_CHANNELS :
-               min_t(int, mdev->priv.eq_table.num_comp_vectors,
-                     MLX5E_MAX_NUM_CHANNELS);
+               min_t(int, mlx5_comp_vectors_count(mdev), MLX5E_MAX_NUM_CHANNELS);
  }
  
  /* Use this function to get max num channels after netdev was created */
@@@ -212,23 -213,22 +211,23 @@@ struct mlx5e_umr_wqe 
  extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
  
  enum mlx5e_priv_flag {
 -      MLX5E_PFLAG_RX_CQE_BASED_MODER = (1 << 0),
 -      MLX5E_PFLAG_TX_CQE_BASED_MODER = (1 << 1),
 -      MLX5E_PFLAG_RX_CQE_COMPRESS = (1 << 2),
 -      MLX5E_PFLAG_RX_STRIDING_RQ = (1 << 3),
 -      MLX5E_PFLAG_RX_NO_CSUM_COMPLETE = (1 << 4),
 +      MLX5E_PFLAG_RX_CQE_BASED_MODER,
 +      MLX5E_PFLAG_TX_CQE_BASED_MODER,
 +      MLX5E_PFLAG_RX_CQE_COMPRESS,
 +      MLX5E_PFLAG_RX_STRIDING_RQ,
 +      MLX5E_PFLAG_RX_NO_CSUM_COMPLETE,
 +      MLX5E_NUM_PFLAGS, /* Keep last */
  };
  
  #define MLX5E_SET_PFLAG(params, pflag, enable)                        \
        do {                                                    \
                if (enable)                                     \
 -                      (params)->pflags |= (pflag);            \
 +                      (params)->pflags |= BIT(pflag);         \
                else                                            \
 -                      (params)->pflags &= ~(pflag);           \
 +                      (params)->pflags &= ~(BIT(pflag));      \
        } while (0)
  
 -#define MLX5E_GET_PFLAG(params, pflag) (!!((params)->pflags & (pflag)))
 +#define MLX5E_GET_PFLAG(params, pflag) (!!((params)->pflags & (BIT(pflag))))
  
  #ifdef CONFIG_MLX5_CORE_EN_DCB
  #define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */
@@@ -246,6 -246,9 +245,6 @@@ struct mlx5e_params 
        bool lro_en;
        u32 lro_wqe_sz;
        u8  tx_min_inline_mode;
 -      u8  rss_hfunc;
 -      u8  toeplitz_hash_key[40];
 -      u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
        bool vlan_strip_disable;
        bool scatter_fcs_en;
        bool rx_dim_enabled;
@@@ -565,7 -568,6 +564,7 @@@ struct mlx5e_rq 
  
        unsigned long          state;
        int                    ix;
 +      unsigned int           hw_mtu;
  
        struct net_dim         dim; /* Dynamic Interrupt Moderation */
  
@@@ -629,7 -631,6 +628,6 @@@ struct mlx5e_channel_stats 
  } ____cacheline_aligned_in_smp;
  
  enum {
-       MLX5E_STATE_ASYNC_EVENTS_ENABLED,
        MLX5E_STATE_OPENED,
        MLX5E_STATE_DESTROYING,
  };
@@@ -650,13 -651,6 +648,13 @@@ enum 
        MLX5E_NIC_PRIO
  };
  
 +struct mlx5e_rss_params {
 +      u32     indirection_rqt[MLX5E_INDIR_RQT_SIZE];
 +      u32     rx_hash_fields[MLX5E_NUM_INDIR_TIRS];
 +      u8      toeplitz_hash_key[40];
 +      u8      hfunc;
 +};
 +
  struct mlx5e_priv {
        /* priv data path fields - start */
        struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC];
        struct mlx5e_tir           indir_tir[MLX5E_NUM_INDIR_TIRS];
        struct mlx5e_tir           inner_indir_tir[MLX5E_NUM_INDIR_TIRS];
        struct mlx5e_tir           direct_tir[MLX5E_MAX_NUM_CHANNELS];
 +      struct mlx5e_rss_params    rss_params;
        u32                        tx_rates[MLX5E_MAX_NUM_SQS];
  
        struct mlx5e_flow_steering fs;
        struct hwtstamp_config     tstamp;
        u16                        q_counter;
        u16                        drop_rq_q_counter;
+       struct notifier_block      events_nb;
  #ifdef CONFIG_MLX5_CORE_EN_DCB
        struct mlx5e_dcbx          dcbx;
  #endif
@@@ -803,11 -798,9 +803,11 @@@ struct mlx5e_redirect_rqt_param 
  
  int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz,
                       struct mlx5e_redirect_rqt_param rrp);
 -void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_params *params,
 -                                  enum mlx5e_traffic_types tt,
 +void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_rss_params *rss_params,
 +                                  const struct mlx5e_tirc_config *ttconfig,
                                    void *tirc, bool inner);
 +void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen);
 +struct mlx5e_tirc_config mlx5e_tirc_get_default_config(enum mlx5e_traffic_types tt);
  
  int mlx5e_open_locked(struct net_device *netdev);
  int mlx5e_close_locked(struct net_device *netdev);
@@@ -989,13 -982,11 +989,13 @@@ int mlx5e_attach_netdev(struct mlx5e_pr
  void mlx5e_detach_netdev(struct mlx5e_priv *priv);
  void mlx5e_destroy_netdev(struct mlx5e_priv *priv);
  void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
 +                          struct mlx5e_rss_params *rss_params,
                            struct mlx5e_params *params,
                            u16 max_channels, u16 mtu);
  void mlx5e_build_rq_params(struct mlx5_core_dev *mdev,
                           struct mlx5e_params *params);
 -void mlx5e_build_rss_params(struct mlx5e_params *params);
 +void mlx5e_build_rss_params(struct mlx5e_rss_params *rss_params,
 +                          u16 num_channels);
  u8 mlx5e_params_calculate_tx_min_inline(struct mlx5_core_dev *mdev);
  void mlx5e_rx_dim_work(struct work_struct *work);
  void mlx5e_tx_dim_work(struct work_struct *work);
index 544c287c648139b9cbcd519d1f1e057baef45e3b,a43092de3cc08ab6f7bd5be5a88950cf7e84d069..06b1c0172a7bd2c4596ceb5ea76570225e7c5ec6
@@@ -49,6 -49,7 +49,7 @@@
  #include "lib/clock.h"
  #include "en/port.h"
  #include "en/xdp.h"
+ #include "lib/eq.h"
  
  struct mlx5e_rq_param {
        u32                     rqc[MLX5_ST_SZ_DW(rqc)];
@@@ -293,33 -294,35 +294,35 @@@ void mlx5e_queue_update_stats(struct ml
        queue_work(priv->wq, &priv->update_stats_work);
  }
  
- static void mlx5e_async_event(struct mlx5_core_dev *mdev, void *vpriv,
-                             enum mlx5_dev_event event, unsigned long param)
+ static int async_event(struct notifier_block *nb, unsigned long event, void *data)
  {
-       struct mlx5e_priv *priv = vpriv;
+       struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb);
+       struct mlx5_eqe   *eqe = data;
  
-       if (!test_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state))
-               return;
+       if (event != MLX5_EVENT_TYPE_PORT_CHANGE)
+               return NOTIFY_DONE;
  
-       switch (event) {
-       case MLX5_DEV_EVENT_PORT_UP:
-       case MLX5_DEV_EVENT_PORT_DOWN:
+       switch (eqe->sub_type) {
+       case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
+       case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
                queue_work(priv->wq, &priv->update_carrier_work);
                break;
        default:
-               break;
+               return NOTIFY_DONE;
        }
+       return NOTIFY_OK;
  }
  
  static void mlx5e_enable_async_events(struct mlx5e_priv *priv)
  {
-       set_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state);
+       priv->events_nb.notifier_call = async_event;
+       mlx5_notifier_register(priv->mdev, &priv->events_nb);
  }
  
  static void mlx5e_disable_async_events(struct mlx5e_priv *priv)
  {
-       clear_bit(MLX5E_STATE_ASYNC_EVENTS_ENABLED, &priv->state);
-       synchronize_irq(pci_irq_vector(priv->mdev->pdev, MLX5_EQ_VEC_ASYNC));
+       mlx5_notifier_unregister(priv->mdev, &priv->events_nb);
  }
  
  static inline void mlx5e_build_umr_wqe(struct mlx5e_rq *rq,
@@@ -502,7 -505,6 +505,7 @@@ static int mlx5e_alloc_rq(struct mlx5e_
        rq->channel = c;
        rq->ix      = c->ix;
        rq->mdev    = mdev;
 +      rq->hw_mtu  = MLX5E_SW2HW_MTU(params, params->sw_mtu);
        rq->stats   = &c->priv->channel_stats[c->ix].rq;
  
        rq->xdp_prog = params->xdp_prog ? bpf_prog_inc(params->xdp_prog) : NULL;
@@@ -1624,15 -1626,13 +1627,15 @@@ static int mlx5e_alloc_cq_common(struc
        int err;
        u32 i;
  
 +      err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);
 +      if (err)
 +              return err;
 +
        err = mlx5_cqwq_create(mdev, &param->wq, param->cqc, &cq->wq,
                               &cq->wq_ctrl);
        if (err)
                return err;
  
 -      mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);
 -
        mcq->cqe_sz     = 64;
        mcq->set_ci_db  = cq->wq_ctrl.db.db;
        mcq->arm_db     = cq->wq_ctrl.db.db + 1;
@@@ -1690,10 -1690,6 +1693,10 @@@ static int mlx5e_create_cq(struct mlx5e
        int eqn;
        int err;
  
 +      err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
 +      if (err)
 +              return err;
 +
        inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
                sizeof(u64) * cq->wq_ctrl.buf.npages;
        in = kvzalloc(inlen, GFP_KERNEL);
        mlx5_fill_page_frag_array(&cq->wq_ctrl.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,      mdev->priv.uar->index);
@@@ -1763,11 -1761,6 +1766,6 @@@ static void mlx5e_close_cq(struct mlx5e
        mlx5e_free_cq(cq);
  }
  
- static int mlx5e_get_cpu(struct mlx5e_priv *priv, int ix)
- {
-       return cpumask_first(priv->mdev->priv.irq_info[ix].mask);
- }
  static int mlx5e_open_tx_cqs(struct mlx5e_channel *c,
                             struct mlx5e_params *params,
                             struct mlx5e_channel_param *cparam)
@@@ -1918,18 -1911,14 +1916,18 @@@ static int mlx5e_open_channel(struct ml
                              struct mlx5e_channel_param *cparam,
                              struct mlx5e_channel **cp)
  {
+       int cpu = cpumask_first(mlx5_comp_irq_get_affinity_mask(priv->mdev, ix));
        struct net_dim_cq_moder icocq_moder = {0, 0};
        struct net_device *netdev = priv->netdev;
-       int cpu = mlx5e_get_cpu(priv, ix);
        struct mlx5e_channel *c;
        unsigned int irq;
        int err;
        int eqn;
  
 +      err = mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);
 +      if (err)
 +              return err;
 +
        c = kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
        if (!c)
                return -ENOMEM;
        c->xdp      = !!params->xdp_prog;
        c->stats    = &priv->channel_stats[ix].ch;
  
 -      mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);
        c->irq_desc = irq_to_desc(irq);
  
        netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64);
@@@ -2504,7 -2494,7 +2502,7 @@@ static void mlx5e_fill_rqt_rqns(struct 
                        if (rrp.rss.hfunc == ETH_RSS_HASH_XOR)
                                ix = mlx5e_bits_invert(i, ilog2(sz));
  
 -                      ix = priv->channels.params.indirection_rqt[ix];
 +                      ix = priv->rss_params.indirection_rqt[ix];
                        rqn = rrp.rss.channels->c[ix]->rq.rqn;
                } else {
                        rqn = rrp.rqn;
@@@ -2587,7 -2577,7 +2585,7 @@@ static void mlx5e_redirect_rqts_to_chan
                {
                        .rss = {
                                .channels  = chs,
 -                              .hfunc     = chs->params.rss_hfunc,
 +                              .hfunc     = priv->rss_params.hfunc,
                        }
                },
        };
@@@ -2607,54 -2597,6 +2605,54 @@@ static void mlx5e_redirect_rqts_to_drop
        mlx5e_redirect_rqts(priv, drop_rrp);
  }
  
 +static const struct mlx5e_tirc_config tirc_default_config[MLX5E_NUM_INDIR_TIRS] = {
 +      [MLX5E_TT_IPV4_TCP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
 +                              .l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
 +                              .rx_hash_fields = MLX5_HASH_IP_L4PORTS,
 +      },
 +      [MLX5E_TT_IPV6_TCP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
 +                              .l4_prot_type = MLX5_L4_PROT_TYPE_TCP,
 +                              .rx_hash_fields = MLX5_HASH_IP_L4PORTS,
 +      },
 +      [MLX5E_TT_IPV4_UDP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
 +                              .l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
 +                              .rx_hash_fields = MLX5_HASH_IP_L4PORTS,
 +      },
 +      [MLX5E_TT_IPV6_UDP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
 +                              .l4_prot_type = MLX5_L4_PROT_TYPE_UDP,
 +                              .rx_hash_fields = MLX5_HASH_IP_L4PORTS,
 +      },
 +      [MLX5E_TT_IPV4_IPSEC_AH] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
 +                                   .l4_prot_type = 0,
 +                                   .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
 +      },
 +      [MLX5E_TT_IPV6_IPSEC_AH] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
 +                                   .l4_prot_type = 0,
 +                                   .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
 +      },
 +      [MLX5E_TT_IPV4_IPSEC_ESP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
 +                                    .l4_prot_type = 0,
 +                                    .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
 +      },
 +      [MLX5E_TT_IPV6_IPSEC_ESP] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
 +                                    .l4_prot_type = 0,
 +                                    .rx_hash_fields = MLX5_HASH_IP_IPSEC_SPI,
 +      },
 +      [MLX5E_TT_IPV4] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV4,
 +                          .l4_prot_type = 0,
 +                          .rx_hash_fields = MLX5_HASH_IP,
 +      },
 +      [MLX5E_TT_IPV6] = { .l3_prot_type = MLX5_L3_PROT_TYPE_IPV6,
 +                          .l4_prot_type = 0,
 +                          .rx_hash_fields = MLX5_HASH_IP,
 +      },
 +};
 +
 +struct mlx5e_tirc_config mlx5e_tirc_get_default_config(enum mlx5e_traffic_types tt)
 +{
 +      return tirc_default_config[tt];
 +}
 +
  static void mlx5e_build_tir_ctx_lro(struct mlx5e_params *params, void *tirc)
  {
        if (!params->lro_en)
        MLX5_SET(tirc, tirc, lro_timeout_period_usecs, params->lro_timeout);
  }
  
 -void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_params *params,
 -                                  enum mlx5e_traffic_types tt,
 +void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_rss_params *rss_params,
 +                                  const struct mlx5e_tirc_config *ttconfig,
                                    void *tirc, bool inner)
  {
        void *hfso = inner ? MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_inner) :
                             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(params->rss_hfunc));
 -      if (params->rss_hfunc == ETH_RSS_HASH_TOP) {
 +      MLX5_SET(tirc, tirc, rx_hash_fn, mlx5e_rx_hash_fn(rss_params->hfunc));
 +      if (rss_params->hfunc == ETH_RSS_HASH_TOP) {
                void *rss_key = MLX5_ADDR_OF(tirc, tirc,
                                             rx_hash_toeplitz_key);
                size_t len = MLX5_FLD_SZ_BYTES(tirc,
                                               rx_hash_toeplitz_key);
  
                MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
 -              memcpy(rss_key, params->toeplitz_hash_key, len);
 +              memcpy(rss_key, rss_params->toeplitz_hash_key, len);
        }
 +      MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
 +               ttconfig->l3_prot_type);
 +      MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
 +               ttconfig->l4_prot_type);
 +      MLX5_SET(rx_hash_field_select, hfso, selected_fields,
 +               ttconfig->rx_hash_fields);
 +}
  
 -      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;
 +static void mlx5e_update_rx_hash_fields(struct mlx5e_tirc_config *ttconfig,
 +                                      enum mlx5e_traffic_types tt,
 +                                      u32 rx_hash_fields)
 +{
 +      *ttconfig                = tirc_default_config[tt];
 +      ttconfig->rx_hash_fields = rx_hash_fields;
 +}
  
 -      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;
 +void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
 +{
 +      void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
 +      struct mlx5e_rss_params *rss = &priv->rss_params;
 +      struct mlx5_core_dev *mdev = priv->mdev;
 +      int ctxlen = MLX5_ST_SZ_BYTES(tirc);
 +      struct mlx5e_tirc_config ttconfig;
 +      int tt;
  
 -      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;
 +      MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
  
 -      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;
 +      for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
 +              memset(tirc, 0, ctxlen);
 +              mlx5e_update_rx_hash_fields(&ttconfig, tt,
 +                                          rss->rx_hash_fields[tt]);
 +              mlx5e_build_indir_tir_ctx_hash(rss, &ttconfig, tirc, false);
 +              mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
 +      }
  
 -      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;
 +      if (!mlx5e_tunnel_inner_ft_supported(priv->mdev))
 +              return;
  
 -      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__);
 +      for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
 +              memset(tirc, 0, ctxlen);
 +              mlx5e_update_rx_hash_fields(&ttconfig, tt,
 +                                          rss->rx_hash_fields[tt]);
 +              mlx5e_build_indir_tir_ctx_hash(rss, &ttconfig, tirc, true);
 +              mlx5_core_modify_tir(mdev, priv->inner_indir_tir[tt].tirn, in,
 +                                   inlen);
        }
  }
  
@@@ -2788,8 -2778,7 +2786,8 @@@ static void mlx5e_build_inner_indir_tir
        MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
        MLX5_SET(tirc, tirc, tunneled_offload_en, 0x1);
  
 -      mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, true);
 +      mlx5e_build_indir_tir_ctx_hash(&priv->rss_params,
 +                                     &tirc_default_config[tt], tirc, true);
  }
  
  static int mlx5e_set_mtu(struct mlx5_core_dev *mdev,
@@@ -3181,9 -3170,7 +3179,9 @@@ static void mlx5e_build_indir_tir_ctx(s
  
        MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
        MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
 -      mlx5e_build_indir_tir_ctx_hash(&priv->channels.params, tt, tirc, false);
 +
 +      mlx5e_build_indir_tir_ctx_hash(&priv->rss_params,
 +                                     &tirc_default_config[tt], tirc, false);
  }
  
  static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 rqtn, u32 *tirc)
@@@ -3585,7 -3572,6 +3583,7 @@@ static int set_feature_cvlan_filter(str
        return 0;
  }
  
 +#ifdef CONFIG_MLX5_ESWITCH
  static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
  
        return 0;
  }
 +#endif
  
  static int set_feature_rx_all(struct net_device *netdev, bool enable)
  {
@@@ -3697,9 -3682,7 +3695,9 @@@ static int mlx5e_set_features(struct ne
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro);
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER,
                                    set_feature_cvlan_filter);
 +#ifdef CONFIG_MLX5_ESWITCH
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TC, set_feature_tc_num_filters);
 +#endif
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXALL, set_feature_rx_all);
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXFCS, set_feature_rx_fcs);
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan);
@@@ -3770,11 -3753,10 +3768,11 @@@ int mlx5e_change_mtu(struct net_device 
        }
  
        if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
 +              bool is_linear = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, &new_channels.params);
                u8 ppw_old = mlx5e_mpwqe_log_pkts_per_wqe(params);
                u8 ppw_new = mlx5e_mpwqe_log_pkts_per_wqe(&new_channels.params);
  
 -              reset = reset && (ppw_old != ppw_new);
 +              reset = reset && (is_linear || (ppw_old != ppw_new));
        }
  
        if (!reset) {
@@@ -4137,17 -4119,17 +4135,17 @@@ static netdev_features_t mlx5e_features
  static bool mlx5e_tx_timeout_eq_recover(struct net_device *dev,
                                        struct mlx5e_txqsq *sq)
  {
-       struct mlx5_eq *eq = sq->cq.mcq.eq;
+       struct mlx5_eq_comp *eq = sq->cq.mcq.eq;
        u32 eqe_count;
  
        netdev_err(dev, "EQ 0x%x: Cons = 0x%x, irqn = 0x%x\n",
-                  eq->eqn, eq->cons_index, eq->irqn);
+                  eq->core.eqn, eq->core.cons_index, eq->core.irqn);
  
        eqe_count = mlx5_eq_poll_irq_disabled(eq);
        if (!eqe_count)
                return false;
  
-       netdev_err(dev, "Recover %d eqes on EQ 0x%x\n", eqe_count, eq->eqn);
+       netdev_err(dev, "Recover %d eqes on EQ 0x%x\n", eqe_count, eq->core.eqn);
        sq->channel->stats->eq_rearm++;
        return true;
  }
@@@ -4521,23 -4503,15 +4519,23 @@@ void mlx5e_build_rq_params(struct mlx5_
        mlx5e_init_rq_type_params(mdev, params);
  }
  
 -void mlx5e_build_rss_params(struct mlx5e_params *params)
 +void mlx5e_build_rss_params(struct mlx5e_rss_params *rss_params,
 +                          u16 num_channels)
  {
 -      params->rss_hfunc = ETH_RSS_HASH_XOR;
 -      netdev_rss_key_fill(params->toeplitz_hash_key, sizeof(params->toeplitz_hash_key));
 -      mlx5e_build_default_indir_rqt(params->indirection_rqt,
 -                                    MLX5E_INDIR_RQT_SIZE, params->num_channels);
 +      enum mlx5e_traffic_types tt;
 +
 +      rss_params->hfunc = ETH_RSS_HASH_XOR;
 +      netdev_rss_key_fill(rss_params->toeplitz_hash_key,
 +                          sizeof(rss_params->toeplitz_hash_key));
 +      mlx5e_build_default_indir_rqt(rss_params->indirection_rqt,
 +                                    MLX5E_INDIR_RQT_SIZE, num_channels);
 +      for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
 +              rss_params->rx_hash_fields[tt] =
 +                      tirc_default_config[tt].rx_hash_fields;
  }
  
  void mlx5e_build_nic_params(struct mlx5_core_dev *mdev,
 +                          struct mlx5e_rss_params *rss_params,
                            struct mlx5e_params *params,
                            u16 max_channels, u16 mtu)
  {
        params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(mdev);
  
        /* RSS */
 -      mlx5e_build_rss_params(params);
 +      mlx5e_build_rss_params(rss_params, params->num_channels);
  }
  
  static void mlx5e_set_netdev_dev_addr(struct net_device *netdev)
@@@ -4702,9 -4676,7 +4700,9 @@@ static void mlx5e_build_nic_netdev(stru
            FT_CAP(modify_root) &&
            FT_CAP(identified_miss_table_mode) &&
            FT_CAP(flow_table_modify)) {
 +#ifdef CONFIG_MLX5_ESWITCH
                netdev->hw_features      |= NETIF_F_HW_TC;
 +#endif
  #ifdef CONFIG_MLX5_EN_ARFS
                netdev->hw_features      |= NETIF_F_NTUPLE;
  #endif
@@@ -4759,16 -4731,14 +4757,16 @@@ static int mlx5e_nic_init(struct mlx5_c
                          void *ppriv)
  {
        struct mlx5e_priv *priv = netdev_priv(netdev);
 +      struct mlx5e_rss_params *rss = &priv->rss_params;
        int err;
  
        err = mlx5e_netdev_init(netdev, priv, mdev, profile, ppriv);
        if (err)
                return err;
  
 -      mlx5e_build_nic_params(mdev, &priv->channels.params,
 -                             mlx5e_get_netdev_max_channels(netdev), netdev->mtu);
 +      mlx5e_build_nic_params(mdev, rss, &priv->channels.params,
 +                             mlx5e_get_netdev_max_channels(netdev),
 +                             netdev->mtu);
  
        mlx5e_timestamp_init(priv);
  
@@@ -4988,7 -4958,7 +4986,7 @@@ int mlx5e_netdev_init(struct net_devic
        netif_carrier_off(netdev);
  
  #ifdef CONFIG_MLX5_EN_ARFS
-       netdev->rx_cpu_rmap = mdev->rmap;
+       netdev->rx_cpu_rmap =  mlx5_eq_table_get_rmap(mdev);
  #endif
  
        return 0;
@@@ -5032,21 -5002,11 +5030,21 @@@ err_free_netdev
  int mlx5e_attach_netdev(struct mlx5e_priv *priv)
  {
        const struct mlx5e_profile *profile;
 +      int max_nch;
        int err;
  
        profile = priv->profile;
        clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
  
 +      /* max number of channels may have changed */
 +      max_nch = mlx5e_get_max_num_channels(priv->mdev);
 +      if (priv->channels.params.num_channels > max_nch) {
 +              mlx5_core_warn(priv->mdev, "MLX5E: Reducing number of channels to %d\n", max_nch);
 +              priv->channels.params.num_channels = max_nch;
 +              mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
 +                                            MLX5E_INDIR_RQT_SIZE, max_nch);
 +      }
 +
        err = profile->init_tx(priv);
        if (err)
                goto out;
@@@ -5200,21 -5160,12 +5198,12 @@@ static void mlx5e_remove(struct mlx5_co
        kfree(ppriv);
  }
  
- static void *mlx5e_get_netdev(void *vpriv)
- {
-       struct mlx5e_priv *priv = vpriv;
-       return priv->netdev;
- }
  static struct mlx5_interface mlx5e_interface = {
        .add       = mlx5e_add,
        .remove    = mlx5e_remove,
        .attach    = mlx5e_attach,
        .detach    = mlx5e_detach,
-       .event     = mlx5e_async_event,
        .protocol  = MLX5_INTERFACE_PROTOCOL_ETH,
-       .get_dev   = mlx5e_get_netdev,
  };
  
  void mlx5e_init(void)
index 624eed345b5d2b19fa5ed54935667b41090383f8,31956ddd394ee71433b09981877498a39eaaf7d2..a75aad03559368381841f1389a4b0d1f42f90d74
@@@ -554,9 -554,9 +554,9 @@@ static inline void mlx5e_poll_ico_singl
  
        mlx5_cqwq_pop(&cq->wq);
  
-       if (unlikely((cqe->op_own >> 4) != MLX5_CQE_REQ)) {
+       if (unlikely(get_cqe_opcode(cqe) != MLX5_CQE_REQ)) {
                netdev_WARN_ONCE(cq->channel->netdev,
-                                "Bad OP in ICOSQ CQE: 0x%x\n", cqe->op_own);
+                                "Bad OP in ICOSQ CQE: 0x%x\n", get_cqe_opcode(cqe));
                return;
        }
  
@@@ -724,9 -724,9 +724,9 @@@ static u32 mlx5e_get_fcs(const struct s
        return __get_unaligned_cpu32(fcs_bytes);
  }
  
 -static u8 get_ip_proto(struct sk_buff *skb, __be16 proto)
 +static u8 get_ip_proto(struct sk_buff *skb, int network_depth, __be16 proto)
  {
 -      void *ip_p = skb->data + sizeof(struct ethhdr);
 +      void *ip_p = skb->data + network_depth;
  
        return (proto == htons(ETH_P_IP)) ? ((struct iphdr *)ip_p)->protocol :
                                            ((struct ipv6hdr *)ip_p)->nexthdr;
@@@ -755,7 -755,7 +755,7 @@@ static inline void mlx5e_handle_csum(st
                goto csum_unnecessary;
  
        if (likely(is_last_ethertype_ip(skb, &network_depth, &proto))) {
 -              if (unlikely(get_ip_proto(skb, proto) == IPPROTO_SCTP))
 +              if (unlikely(get_ip_proto(skb, network_depth, proto) == IPPROTO_SCTP))
                        goto csum_unnecessary;
  
                skb->ip_summed = CHECKSUM_COMPLETE;
@@@ -898,7 -898,7 +898,7 @@@ mlx5e_skb_from_cqe_linear(struct mlx5e_
        prefetchw(va); /* xdp_frame data area */
        prefetch(data);
  
-       if (unlikely((cqe->op_own >> 4) != MLX5_CQE_RESP_SEND)) {
+       if (unlikely(get_cqe_opcode(cqe) != MLX5_CQE_RESP_SEND)) {
                rq->stats->wqe_err++;
                return NULL;
        }
@@@ -930,7 -930,7 +930,7 @@@ mlx5e_skb_from_cqe_nonlinear(struct mlx
        u16 byte_cnt     = cqe_bcnt - headlen;
        struct sk_buff *skb;
  
-       if (unlikely((cqe->op_own >> 4) != MLX5_CQE_RESP_SEND)) {
+       if (unlikely(get_cqe_opcode(cqe) != MLX5_CQE_RESP_SEND)) {
                rq->stats->wqe_err++;
                return NULL;
        }
@@@ -1104,12 -1104,6 +1104,12 @@@ mlx5e_skb_from_cqe_mpwrq_linear(struct 
        u32 frag_size;
        bool consumed;
  
 +      /* Check packet size. Note LRO doesn't use linear SKB */
 +      if (unlikely(cqe_bcnt > rq->hw_mtu)) {
 +              rq->stats->oversize_pkts_sw_drop++;
 +              return NULL;
 +      }
 +
        va             = page_address(di->page) + head_offset;
        data           = va + rx_headroom;
        frag_size      = MLX5_SKB_FRAG_SZ(rx_headroom + cqe_bcnt32);
@@@ -1154,7 -1148,7 +1154,7 @@@ void mlx5e_handle_rx_cqe_mpwrq(struct m
  
        wi->consumed_strides += cstrides;
  
-       if (unlikely((cqe->op_own >> 4) != MLX5_CQE_RESP_SEND)) {
+       if (unlikely(get_cqe_opcode(cqe) != MLX5_CQE_RESP_SEND)) {
                rq->stats->wqe_err++;
                goto mpwrq_cqe_out;
        }
index 40b60e958cfd9c5a0f1eae5a58d468c605d7587b,881c54c12e1989f6febd0eba1adf2016ff951353..75d30fa637d655640397d9b69e3e69cdf6ddf23c
@@@ -30,6 -30,7 +30,7 @@@
   * SOFTWARE.
   */
  
+ #include "lib/mlx5.h"
  #include "en.h"
  #include "en_accel/ipsec.h"
  #include "en_accel/tls.h"
@@@ -83,7 -84,6 +84,7 @@@ static const struct counter_desc sw_sta
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_wqe_err) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_cqes) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_strides) },
 +      { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_oversize_pkts_sw_drop) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_buff_alloc_err) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_blks) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_pkts) },
@@@ -162,7 -162,6 +163,7 @@@ void mlx5e_grp_sw_update_stats(struct m
                s->rx_wqe_err   += rq_stats->wqe_err;
                s->rx_mpwqe_filler_cqes    += rq_stats->mpwqe_filler_cqes;
                s->rx_mpwqe_filler_strides += rq_stats->mpwqe_filler_strides;
 +              s->rx_oversize_pkts_sw_drop += rq_stats->oversize_pkts_sw_drop;
                s->rx_buff_alloc_err += rq_stats->buff_alloc_err;
                s->rx_cqe_compress_blks += rq_stats->cqe_compress_blks;
                s->rx_cqe_compress_pkts += rq_stats->cqe_compress_pkts;
@@@ -936,7 -935,7 +937,7 @@@ static const struct counter_desc pport_
  };
  
  static const struct counter_desc pport_pfc_stall_stats_desc[] = {
 -      { "tx_pause_storm_warning_events ", PPORT_PER_PRIO_OFF(device_stall_minor_watermark_cnt) },
 +      { "tx_pause_storm_warning_events", PPORT_PER_PRIO_OFF(device_stall_minor_watermark_cnt) },
        { "tx_pause_storm_error_events", PPORT_PER_PRIO_OFF(device_stall_critical_watermark_cnt) },
  };
  
@@@ -1088,13 -1087,13 +1089,13 @@@ static void mlx5e_grp_per_prio_update_s
  }
  
  static const struct counter_desc mlx5e_pme_status_desc[] = {
-       { "module_unplug", 8 },
+       { "module_unplug",       sizeof(u64) * MLX5_MODULE_STATUS_UNPLUGGED },
  };
  
  static const struct counter_desc mlx5e_pme_error_desc[] = {
-       { "module_bus_stuck", 16 },       /* bus stuck (I2C or data shorted) */
-       { "module_high_temp", 48 },       /* high temperature */
-       { "module_bad_shorted", 56 },    /* bad or shorted cable/module */
+       { "module_bus_stuck",    sizeof(u64) * MLX5_MODULE_EVENT_ERROR_BUS_STUCK },
+       { "module_high_temp",    sizeof(u64) * MLX5_MODULE_EVENT_ERROR_HIGH_TEMPERATURE },
+       { "module_bad_shorted",  sizeof(u64) * MLX5_MODULE_EVENT_ERROR_BAD_CABLE },
  };
  
  #define NUM_PME_STATUS_STATS          ARRAY_SIZE(mlx5e_pme_status_desc)
@@@ -1122,15 -1121,17 +1123,17 @@@ static int mlx5e_grp_pme_fill_strings(s
  static int mlx5e_grp_pme_fill_stats(struct mlx5e_priv *priv, u64 *data,
                                    int idx)
  {
-       struct mlx5_priv *mlx5_priv = &priv->mdev->priv;
+       struct mlx5_pme_stats pme_stats;
        int i;
  
+       mlx5_get_pme_stats(priv->mdev, &pme_stats);
        for (i = 0; i < NUM_PME_STATUS_STATS; i++)
-               data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.status_counters,
+               data[idx++] = MLX5E_READ_CTR64_CPU(pme_stats.status_counters,
                                                   mlx5e_pme_status_desc, i);
  
        for (i = 0; i < NUM_PME_ERR_STATS; i++)
-               data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.error_counters,
+               data[idx++] = MLX5E_READ_CTR64_CPU(pme_stats.error_counters,
                                                   mlx5e_pme_error_desc, i);
  
        return idx;
@@@ -1191,7 -1192,6 +1194,7 @@@ static const struct counter_desc rq_sta
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, wqe_err) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_cqes) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_strides) },
 +      { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, oversize_pkts_sw_drop) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, buff_alloc_err) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_blks) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_pkts) },
index 9afdf955f2bc3cf9f60cc8c5db1b8c4cb2d6b5f6,46b5a6914d7174c162681313884394065ad86678..f201965b888f0812991aeb285b48a4b8e8a39e05
@@@ -127,7 -127,7 +127,7 @@@ u16 mlx5e_select_queue(struct net_devic
        else
  #endif
                if (skb_vlan_tag_present(skb))
 -                      up = skb->vlan_tci >> VLAN_PRIO_SHIFT;
 +                      up = skb_vlan_tag_get_prio(skb);
  
        /* channel_ix can be larger than num_channels since
         * dev->num_real_tx_queues = num_channels * num_tc
@@@ -507,7 -507,7 +507,7 @@@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *
  
                wqe_counter = be16_to_cpu(cqe->wqe_counter);
  
-               if (unlikely(cqe->op_own >> 4 == MLX5_CQE_REQ_ERR)) {
+               if (unlikely(get_cqe_opcode(cqe) == MLX5_CQE_REQ_ERR)) {
                        if (!test_and_set_bit(MLX5E_SQ_STATE_RECOVERING,
                                              &sq->state)) {
                                mlx5e_dump_error_cqe(sq,