#include "cmd.h"
 
-int mlx5_cmd_dump_fill_mkey(struct mlx5_core_dev *dev, u32 *mkey)
+int mlx5r_cmd_query_special_mkeys(struct mlx5_ib_dev *dev)
 {
        u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {};
        u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {};
+       bool is_terminate, is_dump, is_null;
        int err;
 
-       MLX5_SET(query_special_contexts_in, in, opcode,
-                MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
-       err = mlx5_cmd_exec_inout(dev, query_special_contexts, in, out);
-       if (!err)
-               *mkey = MLX5_GET(query_special_contexts_out, out,
-                                dump_fill_mkey);
-       return err;
-}
+       is_terminate = MLX5_CAP_GEN(dev->mdev, terminate_scatter_list_mkey);
+       is_dump = MLX5_CAP_GEN(dev->mdev, dump_fill_mkey);
+       is_null = MLX5_CAP_GEN(dev->mdev, null_mkey);
 
-int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey)
-{
-       u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {};
-       u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {};
-       int err;
+       dev->mkeys.terminate_scatter_list_mkey = MLX5_TERMINATE_SCATTER_LIST_LKEY;
+       if (!is_terminate && !is_dump && !is_null)
+               return 0;
 
        MLX5_SET(query_special_contexts_in, in, opcode,
                 MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
-       err = mlx5_cmd_exec_inout(dev, query_special_contexts, in, out);
-       if (!err)
-               *null_mkey = MLX5_GET(query_special_contexts_out, out,
-                                     null_mkey);
-       return err;
+       err = mlx5_cmd_exec_inout(dev->mdev, query_special_contexts, in, out);
+       if (err)
+               return err;
+
+       if (is_dump)
+               dev->mkeys.dump_fill_mkey = MLX5_GET(query_special_contexts_out,
+                                                    out, dump_fill_mkey);
+
+       if (is_null)
+               dev->mkeys.null_mkey = cpu_to_be32(
+                       MLX5_GET(query_special_contexts_out, out, null_mkey));
+
+       if (is_terminate)
+               dev->mkeys.terminate_scatter_list_mkey =
+                       cpu_to_be32(MLX5_GET(query_special_contexts_out, out,
+                                            terminate_scatter_list_mkey));
+
+       return 0;
 }
 
 int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point,
 
 #include <linux/kernel.h>
 #include <linux/mlx5/driver.h>
 
-int mlx5_cmd_dump_fill_mkey(struct mlx5_core_dev *dev, u32 *mkey);
-int mlx5_cmd_null_mkey(struct mlx5_core_dev *dev, u32 *null_mkey);
+int mlx5r_cmd_query_special_mkeys(struct mlx5_ib_dev *dev);
 int mlx5_cmd_query_cong_params(struct mlx5_core_dev *dev, int cong_point,
                               void *out);
 int mlx5_cmd_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn, u16 uid);
 
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
        struct mlx5_ib_ucontext *context = to_mucontext(uctx);
        struct mlx5_bfreg_info *bfregi = &context->bfregi;
-       int err;
 
        if (MLX5_CAP_GEN(dev->mdev, dump_fill_mkey)) {
-               err = mlx5_cmd_dump_fill_mkey(dev->mdev,
-                                             &resp->dump_fill_mkey);
-               if (err)
-                       return err;
+               resp->dump_fill_mkey = dev->mkeys.dump_fill_mkey;
                resp->comp_mask |=
                        MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY;
        }
                dev->port[i].roce.last_port_state = IB_PORT_DOWN;
        }
 
+       err = mlx5r_cmd_query_special_mkeys(dev);
+       if (err)
+               return err;
+
        err = mlx5_ib_init_multiport_master(dev);
        if (err)
                return err;
 
        u8 ext_port_cap;
 };
 
+
+struct mlx5_special_mkeys {
+       u32 dump_fill_mkey;
+       __be32 null_mkey;
+       __be32 terminate_scatter_list_mkey;
+};
+
 struct mlx5_ib_dev {
        struct ib_device                ib_dev;
        struct mlx5_core_dev            *mdev;
 
        struct xarray           odp_mkeys;
 
-       u32                     null_mkey;
        struct mlx5_ib_flow_db  *flow_db;
        /* protect resources needed as part of reset flow */
        spinlock_t              reset_flow_resource_lock;
        struct mlx5_port_caps port_caps[MLX5_MAX_PORTS];
        u16 pkey_table_len;
        u8 lag_ports;
+       struct mlx5_special_mkeys mkeys;
 };
 
 static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
 
        if (flags & MLX5_IB_UPD_XLT_ZAP) {
                for (; pklm != end; pklm++, idx++) {
                        pklm->bcount = cpu_to_be32(MLX5_IMR_MTT_SIZE);
-                       pklm->key = cpu_to_be32(mr_to_mdev(imr)->null_mkey);
+                       pklm->key = mr_to_mdev(imr)->mkeys.null_mkey;
                        pklm->va = 0;
                }
                return;
                        pklm->key = cpu_to_be32(mtt->ibmr.lkey);
                        pklm->va = cpu_to_be64(idx * MLX5_IMR_MTT_SIZE);
                } else {
-                       pklm->key = cpu_to_be32(mr_to_mdev(imr)->null_mkey);
+                       pklm->key = mr_to_mdev(imr)->mkeys.null_mkey;
                        pklm->va = 0;
                }
        }
 
                /* receive WQE end of sg list. */
                if (receive_queue && bcnt == 0 &&
-                   key == MLX5_TERMINATE_SCATTER_LIST_LKEY && io_virt == 0)
+                   key == dev->mkeys.terminate_scatter_list_mkey &&
+                   io_virt == 0)
                        break;
 
                if (!inline_segment && total_wqe_bytes) {
 
 int mlx5_ib_odp_init_one(struct mlx5_ib_dev *dev)
 {
-       int ret = 0;
-
        internal_fill_odp_caps(dev);
 
        if (!(dev->odp_caps.general_caps & IB_ODP_SUPPORT))
-               return ret;
+               return 0;
 
        ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_odp_ops);
 
-       if (dev->odp_caps.general_caps & IB_ODP_SUPPORT_IMPLICIT) {
-               ret = mlx5_cmd_null_mkey(dev->mdev, &dev->null_mkey);
-               if (ret) {
-                       mlx5_ib_err(dev, "Error getting null_mkey %d\n", ret);
-                       return ret;
-               }
-       }
-
        mutex_init(&dev->odp_eq_mutex);
-       return ret;
+       return 0;
 }
 
 void mlx5_ib_odp_cleanup_one(struct mlx5_ib_dev *dev)
 
 
                if (i < srq->msrq.max_avail_gather) {
                        scat[i].byte_count = 0;
-                       scat[i].lkey = MLX5_TERMINATE_SCATTER_LIST_LKEY;
+                       scat[i].lkey = dev->mkeys.terminate_scatter_list_mkey;
                        scat[i].addr       = 0;
                }
        }
 
 
                if (i < qp->rq.max_gs) {
                        scat[i].byte_count = 0;
-                       scat[i].lkey = MLX5_TERMINATE_SCATTER_LIST_LKEY;
+                       scat[i].lkey = dev->mkeys.terminate_scatter_list_mkey;
                        scat[i].addr       = 0;
                }