linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH rdma-next v1 0/9] QP allocation changes
@ 2021-07-23 11:39 Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 1/9] RDMA/hns: Don't skip IB creation flow for regular RC QP Leon Romanovsky
                   ` (9 more replies)
  0 siblings, 10 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

Changelog:
v1:
 * Added ROB tags
 * Deleted already existed double rwq_ind_tbl assignment
 * Deleted hr_qp->ibqp.qp_type assignment
v0: https://lore.kernel.org/lkml/cover.1626609283.git.leonro@nvidia.com

-----------------------------------------------------------------------------
Hi,

This series convert IB/core to use core allocation scheme for the QP
objects.

Thanks

Leon Romanovsky (9):
  RDMA/hns: Don't skip IB creation flow for regular RC QP
  RDMA/hns: Don't overwrite supplied QP attributes
  RDMA/efa: Remove double QP type assignment
  RDMA/mlx5: Cancel pkey work before destroying device resources
  RDMA/mlx5: Delete device resource mutex that didn't protect anything
  RDMA/mlx5: Rework custom driver QP type creation
  RDMA/rdmavt: Decouple QP and SGE lists allocations
  RDMA: Globally allocate and release QP memory
  RDMA/mlx5: Drop in-driver verbs object creations

 drivers/infiniband/core/core_priv.h           |  28 +++-
 drivers/infiniband/core/device.c              |   2 +
 drivers/infiniband/core/restrack.c            |   2 +-
 drivers/infiniband/core/verbs.c               |  47 +++---
 drivers/infiniband/hw/bnxt_re/ib_verbs.c      |  26 ++--
 drivers/infiniband/hw/bnxt_re/ib_verbs.h      |   7 +-
 drivers/infiniband/hw/bnxt_re/main.c          |   1 +
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h        |   5 +-
 drivers/infiniband/hw/cxgb4/provider.c        |   1 +
 drivers/infiniband/hw/cxgb4/qp.c              |  37 ++---
 drivers/infiniband/hw/efa/efa.h               |   5 +-
 drivers/infiniband/hw/efa/efa_main.c          |   1 +
 drivers/infiniband/hw/efa/efa_verbs.c         |  29 ++--
 drivers/infiniband/hw/hns/hns_roce_device.h   |   5 +-
 drivers/infiniband/hw/hns/hns_roce_hw_v1.c    |   6 +-
 drivers/infiniband/hw/hns/hns_roce_main.c     |   1 +
 drivers/infiniband/hw/hns/hns_roce_qp.c       |  36 ++---
 drivers/infiniband/hw/irdma/utils.c           |   3 -
 drivers/infiniband/hw/irdma/verbs.c           |  31 ++--
 drivers/infiniband/hw/mlx4/main.c             |   1 +
 drivers/infiniband/hw/mlx4/mlx4_ib.h          |   5 +-
 drivers/infiniband/hw/mlx4/qp.c               |  25 ++--
 drivers/infiniband/hw/mlx5/gsi.c              |  51 ++-----
 drivers/infiniband/hw/mlx5/main.c             | 135 ++++++------------
 drivers/infiniband/hw/mlx5/mlx5_ib.h          |   7 +-
 drivers/infiniband/hw/mlx5/qp.c               |  62 +++-----
 drivers/infiniband/hw/mthca/mthca_provider.c  |  77 ++++------
 drivers/infiniband/hw/ocrdma/ocrdma_main.c    |   1 +
 drivers/infiniband/hw/ocrdma/ocrdma_verbs.c   |  25 ++--
 drivers/infiniband/hw/ocrdma/ocrdma_verbs.h   |   5 +-
 drivers/infiniband/hw/qedr/main.c             |   1 +
 drivers/infiniband/hw/qedr/qedr_roce_cm.c     |  13 +-
 drivers/infiniband/hw/qedr/qedr_roce_cm.h     |   5 +-
 drivers/infiniband/hw/qedr/verbs.c            |  49 ++-----
 drivers/infiniband/hw/qedr/verbs.h            |   4 +-
 drivers/infiniband/hw/usnic/usnic_ib_main.c   |   1 +
 drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c |  34 ++---
 drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h |  10 +-
 drivers/infiniband/hw/usnic/usnic_ib_verbs.c  |  69 +++++----
 drivers/infiniband/hw/usnic/usnic_ib_verbs.h  |   5 +-
 .../infiniband/hw/vmw_pvrdma/pvrdma_main.c    |   1 +
 drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c  |  53 +++----
 .../infiniband/hw/vmw_pvrdma/pvrdma_verbs.h   |   5 +-
 drivers/infiniband/sw/rdmavt/qp.c             | 102 ++++++-------
 drivers/infiniband/sw/rdmavt/qp.h             |   5 +-
 drivers/infiniband/sw/rdmavt/vt.c             |   9 ++
 drivers/infiniband/sw/rxe/rxe_pool.c          |   2 +-
 drivers/infiniband/sw/rxe/rxe_verbs.c         |  48 +++----
 drivers/infiniband/sw/rxe/rxe_verbs.h         |   2 +-
 drivers/infiniband/sw/siw/siw_main.c          |   1 +
 drivers/infiniband/sw/siw/siw_qp.c            |   2 -
 drivers/infiniband/sw/siw/siw_verbs.c         |  54 +++----
 drivers/infiniband/sw/siw/siw_verbs.h         |   5 +-
 include/rdma/ib_verbs.h                       |  30 +++-
 include/rdma/rdmavt_qp.h                      |   2 +-
 55 files changed, 480 insertions(+), 699 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 1/9] RDMA/hns: Don't skip IB creation flow for regular RC QP
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 2/9] RDMA/hns: Don't overwrite supplied QP attributes Leon Romanovsky
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

The call to internal QP creation function skips QP creation checks
and misses the addition of such device QPs to the restrack DB.

As a preparation to general allocation scheme, convert hns to use
proper API.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/hw/hns/hns_roce_hw_v1.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
index a3305d196675..e0f59b8d7d5d 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
@@ -758,7 +758,7 @@ static struct hns_roce_qp *hns_roce_v1_create_lp_qp(struct hns_roce_dev *hr_dev,
 	init_attr.cap.max_recv_wr	= HNS_ROCE_MIN_WQE_NUM;
 	init_attr.cap.max_send_wr	= HNS_ROCE_MIN_WQE_NUM;
 
-	qp = hns_roce_create_qp(pd, &init_attr, NULL);
+	qp = ib_create_qp(pd, &init_attr);
 	if (IS_ERR(qp)) {
 		dev_err(dev, "Create loop qp for mr free failed!");
 		return NULL;
@@ -923,7 +923,7 @@ static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
 create_lp_qp_failed:
 	for (i -= 1; i >= 0; i--) {
 		hr_qp = free_mr->mr_free_qp[i];
-		if (hns_roce_v1_destroy_qp(&hr_qp->ibqp, NULL))
+		if (ib_destroy_qp(&hr_qp->ibqp))
 			dev_err(dev, "Destroy qp %d for mr free failed!\n", i);
 	}
 
@@ -953,7 +953,7 @@ static void hns_roce_v1_release_lp_qp(struct hns_roce_dev *hr_dev)
 		if (!hr_qp)
 			continue;
 
-		ret = hns_roce_v1_destroy_qp(&hr_qp->ibqp, NULL);
+		ret = ib_destroy_qp(&hr_qp->ibqp);
 		if (ret)
 			dev_err(dev, "Destroy qp %d for mr free failed(%d)!\n",
 				i, ret);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 2/9] RDMA/hns: Don't overwrite supplied QP attributes
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 1/9] RDMA/hns: Don't skip IB creation flow for regular RC QP Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 3/9] RDMA/efa: Remove double QP type assignment Leon Romanovsky
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

QP attributes that were supplied by IB/core already have all parameters
set when they are passed to the driver. The drivers are not supposed to
change anything in struct ib_qp_init_attr.

Fixes: 66d86e529dd5 ("RDMA/hns: Add UD support for HIP09")
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/hw/hns/hns_roce_qp.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
index b101b7e578f2..c3e2fee16c0e 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -1171,14 +1171,8 @@ struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
 	if (!hr_qp)
 		return ERR_PTR(-ENOMEM);
 
-	if (init_attr->qp_type == IB_QPT_XRC_INI)
-		init_attr->recv_cq = NULL;
-
-	if (init_attr->qp_type == IB_QPT_XRC_TGT) {
+	if (init_attr->qp_type == IB_QPT_XRC_TGT)
 		hr_qp->xrcdn = to_hr_xrcd(init_attr->xrcd)->xrcdn;
-		init_attr->recv_cq = NULL;
-		init_attr->send_cq = NULL;
-	}
 
 	if (init_attr->qp_type == IB_QPT_GSI) {
 		hr_qp->port = init_attr->port_num - 1;
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 3/9] RDMA/efa: Remove double QP type assignment
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 1/9] RDMA/hns: Don't skip IB creation flow for regular RC QP Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 2/9] RDMA/hns: Don't overwrite supplied QP attributes Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 4/9] RDMA/mlx5: Cancel pkey work before destroying device resources Leon Romanovsky
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

The QP type is set by the IB/core and shouldn't be set in the driver.

Fixes: 40909f664d27 ("RDMA/efa: Add EFA verbs implementation")
Acked-by: Gal Pressman <galpress@amazon.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/hw/efa/efa_verbs.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index b4cfb656ddd5..b1c4780e86be 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -727,7 +727,6 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
 
 	qp->qp_handle = create_qp_resp.qp_handle;
 	qp->ibqp.qp_num = create_qp_resp.qp_num;
-	qp->ibqp.qp_type = init_attr->qp_type;
 	qp->max_send_wr = init_attr->cap.max_send_wr;
 	qp->max_recv_wr = init_attr->cap.max_recv_wr;
 	qp->max_send_sge = init_attr->cap.max_send_sge;
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 4/9] RDMA/mlx5: Cancel pkey work before destroying device resources
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
                   ` (2 preceding siblings ...)
  2021-07-23 11:39 ` [PATCH rdma-next v1 3/9] RDMA/efa: Remove double QP type assignment Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 5/9] RDMA/mlx5: Delete device resource mutex that didn't protect anything Leon Romanovsky
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

In the driver release flow, we are ensuring that notifier is disabled
and no new works can be added to pkey_change_handler. It means that
we can cancel that handler before destroying resources to make sure
that our unwind routine is symmetrical to the allocation one.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/hw/mlx5/main.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 9b8dd7a604c9..75d5de14f80b 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -2908,6 +2908,15 @@ static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)
 	struct mlx5_ib_resources *devr = &dev->devr;
 	int port;
 
+	/*
+	 * Make sure no change P_Key work items are still executing.
+	 *
+	 * At this stage, the mlx5_ib_event should be unregistered
+	 * and it ensures that no new works are added.
+	 */
+	for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
+		cancel_work_sync(&devr->ports[port].pkey_change_work);
+
 	mlx5_ib_destroy_srq(devr->s1, NULL);
 	kfree(devr->s1);
 	mlx5_ib_destroy_srq(devr->s0, NULL);
@@ -2918,10 +2927,6 @@ static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)
 	kfree(devr->c0);
 	mlx5_ib_dealloc_pd(devr->p0, NULL);
 	kfree(devr->p0);
-
-	/* Make sure no change P_Key work items are still executing */
-	for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
-		cancel_work_sync(&devr->ports[port].pkey_change_work);
 }
 
 static u32 get_core_cap_flags(struct ib_device *ibdev,
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 5/9] RDMA/mlx5: Delete device resource mutex that didn't protect anything
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
                   ` (3 preceding siblings ...)
  2021-07-23 11:39 ` [PATCH rdma-next v1 4/9] RDMA/mlx5: Cancel pkey work before destroying device resources Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 6/9] RDMA/mlx5: Rework custom driver QP type creation Leon Romanovsky
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

The dev->devr.mutex was intended to protect GSI QP pointer change
in the struct mlx5_ib_port_resources when it is accessed from the
pkey_change_work. However that pointer isn't changed during the
runtime and once IB/core adds MAD, it stays stable.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/hw/mlx5/gsi.c     | 34 ++++++++--------------------
 drivers/infiniband/hw/mlx5/main.c    |  9 ++++++--
 drivers/infiniband/hw/mlx5/mlx5_ib.h |  2 --
 3 files changed, 16 insertions(+), 29 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/gsi.c b/drivers/infiniband/hw/mlx5/gsi.c
index 7fcad9135276..e549d6fa4a41 100644
--- a/drivers/infiniband/hw/mlx5/gsi.c
+++ b/drivers/infiniband/hw/mlx5/gsi.c
@@ -116,8 +116,6 @@ int mlx5_ib_create_gsi(struct ib_pd *pd, struct mlx5_ib_qp *mqp,
 		goto err_free_tx;
 	}
 
-	mutex_lock(&dev->devr.mutex);
-
 	if (dev->devr.ports[port_num - 1].gsi) {
 		mlx5_ib_warn(dev, "GSI QP already exists on port %d\n",
 			     port_num);
@@ -167,15 +165,11 @@ int mlx5_ib_create_gsi(struct ib_pd *pd, struct mlx5_ib_qp *mqp,
 	INIT_LIST_HEAD(&gsi->rx_qp->sig_mrs);
 
 	dev->devr.ports[attr->port_num - 1].gsi = gsi;
-
-	mutex_unlock(&dev->devr.mutex);
-
 	return 0;
 
 err_destroy_cq:
 	ib_free_cq(gsi->cq);
 err_free_wrs:
-	mutex_unlock(&dev->devr.mutex);
 	kfree(gsi->outstanding_wrs);
 err_free_tx:
 	kfree(gsi->tx_qps);
@@ -190,16 +184,13 @@ int mlx5_ib_destroy_gsi(struct mlx5_ib_qp *mqp)
 	int qp_index;
 	int ret;
 
-	mutex_lock(&dev->devr.mutex);
 	ret = mlx5_ib_destroy_qp(gsi->rx_qp, NULL);
 	if (ret) {
 		mlx5_ib_warn(dev, "unable to destroy hardware GSI QP. error %d\n",
 			     ret);
-		mutex_unlock(&dev->devr.mutex);
 		return ret;
 	}
 	dev->devr.ports[port_num - 1].gsi = NULL;
-	mutex_unlock(&dev->devr.mutex);
 	gsi->rx_qp = NULL;
 
 	for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index) {
@@ -339,23 +330,13 @@ static void setup_qp(struct mlx5_ib_gsi_qp *gsi, u16 qp_index)
 	WARN_ON_ONCE(qp);
 }
 
-static void setup_qps(struct mlx5_ib_gsi_qp *gsi)
-{
-	struct mlx5_ib_dev *dev = to_mdev(gsi->rx_qp->device);
-	u16 qp_index;
-
-	mutex_lock(&dev->devr.mutex);
-	for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
-		setup_qp(gsi, qp_index);
-	mutex_unlock(&dev->devr.mutex);
-}
-
 int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
 			  int attr_mask)
 {
 	struct mlx5_ib_dev *dev = to_mdev(qp->device);
 	struct mlx5_ib_qp *mqp = to_mqp(qp);
 	struct mlx5_ib_gsi_qp *gsi = &mqp->gsi;
+	u16 qp_index;
 	int ret;
 
 	mlx5_ib_dbg(dev, "modifying GSI QP to state %d\n", attr->qp_state);
@@ -366,8 +347,11 @@ int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
 		return ret;
 	}
 
-	if (to_mqp(gsi->rx_qp)->state == IB_QPS_RTS)
-		setup_qps(gsi);
+	if (to_mqp(gsi->rx_qp)->state != IB_QPS_RTS)
+		return 0;
+
+	for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
+		setup_qp(gsi, qp_index);
 	return 0;
 }
 
@@ -511,8 +495,8 @@ int mlx5_ib_gsi_post_recv(struct ib_qp *qp, const struct ib_recv_wr *wr,
 
 void mlx5_ib_gsi_pkey_change(struct mlx5_ib_gsi_qp *gsi)
 {
-	if (!gsi)
-		return;
+	u16 qp_index;
 
-	setup_qps(gsi);
+	for (qp_index = 0; qp_index < gsi->num_qps; ++qp_index)
+		setup_qp(gsi, qp_index);
 }
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 75d5de14f80b..cac05bbe14c2 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -2501,6 +2501,13 @@ static void pkey_change_handler(struct work_struct *work)
 		container_of(work, struct mlx5_ib_port_resources,
 			     pkey_change_work);
 
+	if (!ports->gsi)
+		/*
+		 * We got this event before device was fully configured
+		 * and MAD registration code wasn't called/finished yet.
+		 */
+		return;
+
 	mlx5_ib_gsi_pkey_change(ports->gsi);
 }
 
@@ -2795,8 +2802,6 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
 	if (!MLX5_CAP_GEN(dev->mdev, xrc))
 		return -EOPNOTSUPP;
 
-	mutex_init(&devr->mutex);
-
 	devr->p0 = rdma_zalloc_drv_obj(ibdev, ib_pd);
 	if (!devr->p0)
 		return -ENOMEM;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index dbbcb53d2ca2..f2c8a6375b16 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -813,8 +813,6 @@ struct mlx5_ib_resources {
 	struct ib_srq	*s0;
 	struct ib_srq	*s1;
 	struct mlx5_ib_port_resources ports[2];
-	/* Protects changes to the port resources */
-	struct mutex	mutex;
 };
 
 struct mlx5_ib_counters {
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 6/9] RDMA/mlx5: Rework custom driver QP type creation
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
                   ` (4 preceding siblings ...)
  2021-07-23 11:39 ` [PATCH rdma-next v1 5/9] RDMA/mlx5: Delete device resource mutex that didn't protect anything Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 7/9] RDMA/rdmavt: Decouple QP and SGE lists allocations Leon Romanovsky
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

Starting from commit 2b1f747071c5 ("RDMA/core: Allow drivers to disable
restrack DB") the restrack is able to handle non-standard QP types either.

That change allows us to rewrite custom QP calls to their IB/core counterparts,
so we will use general QP creation flow even for the driver QP types.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/hw/mlx5/gsi.c  | 15 ++-------------
 drivers/infiniband/hw/mlx5/main.c | 20 +++++++-------------
 drivers/infiniband/hw/mlx5/qp.c   |  6 +++++-
 3 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/gsi.c b/drivers/infiniband/hw/mlx5/gsi.c
index e549d6fa4a41..541da52470cb 100644
--- a/drivers/infiniband/hw/mlx5/gsi.c
+++ b/drivers/infiniband/hw/mlx5/gsi.c
@@ -145,24 +145,13 @@ int mlx5_ib_create_gsi(struct ib_pd *pd, struct mlx5_ib_qp *mqp,
 		hw_init_attr.cap.max_inline_data = 0;
 	}
 
-	gsi->rx_qp = mlx5_ib_create_qp(pd, &hw_init_attr, NULL);
+	gsi->rx_qp = ib_create_qp(pd, &hw_init_attr);
 	if (IS_ERR(gsi->rx_qp)) {
 		mlx5_ib_warn(dev, "unable to create hardware GSI QP. error %ld\n",
 			     PTR_ERR(gsi->rx_qp));
 		ret = PTR_ERR(gsi->rx_qp);
 		goto err_destroy_cq;
 	}
-	gsi->rx_qp->device = pd->device;
-	gsi->rx_qp->pd = pd;
-	gsi->rx_qp->real_qp = gsi->rx_qp;
-
-	gsi->rx_qp->qp_type = hw_init_attr.qp_type;
-	gsi->rx_qp->send_cq = hw_init_attr.send_cq;
-	gsi->rx_qp->recv_cq = hw_init_attr.recv_cq;
-	gsi->rx_qp->event_handler = hw_init_attr.event_handler;
-	spin_lock_init(&gsi->rx_qp->mr_lock);
-	INIT_LIST_HEAD(&gsi->rx_qp->rdma_mrs);
-	INIT_LIST_HEAD(&gsi->rx_qp->sig_mrs);
 
 	dev->devr.ports[attr->port_num - 1].gsi = gsi;
 	return 0;
@@ -184,7 +173,7 @@ int mlx5_ib_destroy_gsi(struct mlx5_ib_qp *mqp)
 	int qp_index;
 	int ret;
 
-	ret = mlx5_ib_destroy_qp(gsi->rx_qp, NULL);
+	ret = ib_destroy_qp(gsi->rx_qp);
 	if (ret) {
 		mlx5_ib_warn(dev, "unable to destroy hardware GSI QP. error %d\n",
 			     ret);
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index cac05bbe14c2..bcdbc3033b0a 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -4073,7 +4073,7 @@ static void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev)
 		mlx5_ib_warn(dev, "mr cache cleanup failed\n");
 
 	if (dev->umrc.qp)
-		mlx5_ib_destroy_qp(dev->umrc.qp, NULL);
+		ib_destroy_qp(dev->umrc.qp);
 	if (dev->umrc.cq)
 		ib_free_cq(dev->umrc.cq);
 	if (dev->umrc.pd)
@@ -4126,23 +4126,17 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
 	init_attr->cap.max_send_sge = 1;
 	init_attr->qp_type = MLX5_IB_QPT_REG_UMR;
 	init_attr->port_num = 1;
-	qp = mlx5_ib_create_qp(pd, init_attr, NULL);
+	qp = ib_create_qp(pd, init_attr);
 	if (IS_ERR(qp)) {
 		mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
 		ret = PTR_ERR(qp);
 		goto error_3;
 	}
-	qp->device     = &dev->ib_dev;
-	qp->real_qp    = qp;
-	qp->uobject    = NULL;
-	qp->qp_type    = MLX5_IB_QPT_REG_UMR;
-	qp->send_cq    = init_attr->send_cq;
-	qp->recv_cq    = init_attr->recv_cq;
 
 	attr->qp_state = IB_QPS_INIT;
 	attr->port_num = 1;
-	ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_PKEY_INDEX |
-				IB_QP_PORT, NULL);
+	ret = ib_modify_qp(qp, attr,
+			   IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT);
 	if (ret) {
 		mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n");
 		goto error_4;
@@ -4152,7 +4146,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
 	attr->qp_state = IB_QPS_RTR;
 	attr->path_mtu = IB_MTU_256;
 
-	ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
+	ret = ib_modify_qp(qp, attr, IB_QP_STATE);
 	if (ret) {
 		mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n");
 		goto error_4;
@@ -4160,7 +4154,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
 
 	memset(attr, 0, sizeof(*attr));
 	attr->qp_state = IB_QPS_RTS;
-	ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
+	ret = ib_modify_qp(qp, attr, IB_QP_STATE);
 	if (ret) {
 		mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n");
 		goto error_4;
@@ -4183,7 +4177,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
 	return 0;
 
 error_4:
-	mlx5_ib_destroy_qp(qp, NULL);
+	ib_destroy_qp(qp);
 	dev->umrc.qp = NULL;
 
 error_3:
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 3d797be84bfa..d6c6bfe9921a 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -2675,7 +2675,6 @@ static int create_dct(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 	}
 
 	qp->state = IB_QPS_RESET;
-	rdma_restrack_no_track(&qp->ibqp.res);
 	return 0;
 }
 
@@ -3014,6 +3013,7 @@ static int create_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 	switch (qp->type) {
 	case MLX5_IB_QPT_DCT:
 		err = create_dct(dev, pd, qp, params);
+		rdma_restrack_no_track(&qp->ibqp.res);
 		break;
 	case MLX5_IB_QPT_DCI:
 		err = create_dci(dev, pd, qp, params);
@@ -3024,6 +3024,10 @@ static int create_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
 	case IB_QPT_GSI:
 		err = mlx5_ib_create_gsi(pd, qp, params->attr);
 		break;
+	case MLX5_IB_QPT_HW_GSI:
+	case MLX5_IB_QPT_REG_UMR:
+		rdma_restrack_no_track(&qp->ibqp.res);
+		fallthrough;
 	default:
 		if (params->udata)
 			err = create_user_qp(dev, pd, qp, params);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 7/9] RDMA/rdmavt: Decouple QP and SGE lists allocations
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
                   ` (5 preceding siblings ...)
  2021-07-23 11:39 ` [PATCH rdma-next v1 6/9] RDMA/mlx5: Rework custom driver QP type creation Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-23 11:39 ` [PATCH rdma-next v1 8/9] RDMA: Globally allocate and release QP memory Leon Romanovsky
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

The rdmavt QP has fields that are both needed for the control and data
path. Such mixed declaration caused to the very specific allocation flow
with kzalloc_node and SGE list embedded into the struct rvt_qp.

This patch separates QP creation to two: regular memory allocation for
the control path and specific code for the SGE list, while the access to
the later is performed through derefenced pointer.

Such pointer and its context are expected to be in the cache, so
performance difference is expected to be negligible, if any exists.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/sw/rdmavt/qp.c | 13 ++++++++-----
 include/rdma/rdmavt_qp.h          |  2 +-
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
index e9f3d356b361..14900860985c 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -1078,7 +1078,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 	int err;
 	struct rvt_swqe *swq = NULL;
 	size_t sz;
-	size_t sg_list_sz;
+	size_t sg_list_sz = 0;
 	struct ib_qp *ret = ERR_PTR(-ENOMEM);
 	struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device);
 	void *priv = NULL;
@@ -1126,8 +1126,6 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		if (!swq)
 			return ERR_PTR(-ENOMEM);
 
-		sz = sizeof(*qp);
-		sg_list_sz = 0;
 		if (init_attr->srq) {
 			struct rvt_srq *srq = ibsrq_to_rvtsrq(init_attr->srq);
 
@@ -1137,10 +1135,13 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		} else if (init_attr->cap.max_recv_sge > 1)
 			sg_list_sz = sizeof(*qp->r_sg_list) *
 				(init_attr->cap.max_recv_sge - 1);
-		qp = kzalloc_node(sz + sg_list_sz, GFP_KERNEL,
-				  rdi->dparms.node);
+		qp = kzalloc_node(sizeof(*qp), GFP_KERNEL, rdi->dparms.node);
 		if (!qp)
 			goto bail_swq;
+		qp->r_sg_list =
+			kzalloc_node(sg_list_sz, GFP_KERNEL, rdi->dparms.node);
+		if (!qp->r_sg_list)
+			goto bail_qp;
 		qp->allowed_ops = get_allowed_ops(init_attr->qp_type);
 
 		RCU_INIT_POINTER(qp->next, NULL);
@@ -1328,6 +1329,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 
 bail_qp:
 	kfree(qp->s_ack_queue);
+	kfree(qp->r_sg_list);
 	kfree(qp);
 
 bail_swq:
@@ -1762,6 +1764,7 @@ int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 	kvfree(qp->r_rq.kwq);
 	rdi->driver_f.qp_priv_free(rdi, qp);
 	kfree(qp->s_ack_queue);
+	kfree(qp->r_sg_list);
 	rdma_destroy_ah_attr(&qp->remote_ah_attr);
 	rdma_destroy_ah_attr(&qp->alt_ah_attr);
 	free_ud_wq_attr(qp);
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h
index 8275954f5ce6..2e58d5e6ac0e 100644
--- a/include/rdma/rdmavt_qp.h
+++ b/include/rdma/rdmavt_qp.h
@@ -444,7 +444,7 @@ struct rvt_qp {
 	/*
 	 * This sge list MUST be last. Do not add anything below here.
 	 */
-	struct rvt_sge r_sg_list[] /* verified SGEs */
+	struct rvt_sge *r_sg_list /* verified SGEs */
 		____cacheline_aligned_in_smp;
 };
 
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 8/9] RDMA: Globally allocate and release QP memory
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
                   ` (6 preceding siblings ...)
  2021-07-23 11:39 ` [PATCH rdma-next v1 7/9] RDMA/rdmavt: Decouple QP and SGE lists allocations Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-07-29 20:20   ` Nikolova, Tatyana E
  2021-07-23 11:39 ` [PATCH rdma-next v1 9/9] RDMA/mlx5: Drop in-driver verbs object creations Leon Romanovsky
  2021-08-03 17:22 ` [PATCH rdma-next v1 0/9] QP allocation changes Jason Gunthorpe
  9 siblings, 1 reply; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

Convert QP object to follow IB/core general allocation scheme.
That change allows us to make sure that restrack properly kref
the memory.

Reviewed-by: Gal Pressman <galpress@amazon.com> #efa
Tested-by: Gal Pressman <galpress@amazon.com>
Reviewed-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com> #rdma and core
Tested-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/core/core_priv.h           | 28 ++++--
 drivers/infiniband/core/device.c              |  2 +
 drivers/infiniband/core/restrack.c            |  2 +-
 drivers/infiniband/core/verbs.c               | 40 ++++----
 drivers/infiniband/hw/bnxt_re/ib_verbs.c      | 26 ++----
 drivers/infiniband/hw/bnxt_re/ib_verbs.h      |  7 +-
 drivers/infiniband/hw/bnxt_re/main.c          |  1 +
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h        |  5 +-
 drivers/infiniband/hw/cxgb4/provider.c        |  1 +
 drivers/infiniband/hw/cxgb4/qp.c              | 37 +++-----
 drivers/infiniband/hw/efa/efa.h               |  5 +-
 drivers/infiniband/hw/efa/efa_main.c          |  1 +
 drivers/infiniband/hw/efa/efa_verbs.c         | 28 ++----
 drivers/infiniband/hw/hns/hns_roce_device.h   |  5 +-
 drivers/infiniband/hw/hns/hns_roce_main.c     |  1 +
 drivers/infiniband/hw/hns/hns_roce_qp.c       | 28 ++----
 drivers/infiniband/hw/irdma/utils.c           |  3 -
 drivers/infiniband/hw/irdma/verbs.c           | 31 +++----
 drivers/infiniband/hw/mlx4/main.c             |  1 +
 drivers/infiniband/hw/mlx4/mlx4_ib.h          |  5 +-
 drivers/infiniband/hw/mlx4/qp.c               | 25 ++---
 drivers/infiniband/hw/mlx5/gsi.c              |  2 -
 drivers/infiniband/hw/mlx5/main.c             |  1 +
 drivers/infiniband/hw/mlx5/mlx5_ib.h          |  5 +-
 drivers/infiniband/hw/mlx5/qp.c               | 56 ++++--------
 drivers/infiniband/hw/mthca/mthca_provider.c  | 77 ++++++----------
 drivers/infiniband/hw/ocrdma/ocrdma_main.c    |  1 +
 drivers/infiniband/hw/ocrdma/ocrdma_verbs.c   | 25 ++---
 drivers/infiniband/hw/ocrdma/ocrdma_verbs.h   |  5 +-
 drivers/infiniband/hw/qedr/main.c             |  1 +
 drivers/infiniband/hw/qedr/qedr_roce_cm.c     | 13 ++-
 drivers/infiniband/hw/qedr/qedr_roce_cm.h     |  5 +-
 drivers/infiniband/hw/qedr/verbs.c            | 49 +++-------
 drivers/infiniband/hw/qedr/verbs.h            |  4 +-
 drivers/infiniband/hw/usnic/usnic_ib_main.c   |  1 +
 drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c | 34 +++----
 drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h | 10 +-
 drivers/infiniband/hw/usnic/usnic_ib_verbs.c  | 69 +++++++-------
 drivers/infiniband/hw/usnic/usnic_ib_verbs.h  |  5 +-
 .../infiniband/hw/vmw_pvrdma/pvrdma_main.c    |  1 +
 drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c  | 53 +++++------
 .../infiniband/hw/vmw_pvrdma/pvrdma_verbs.h   |  5 +-
 drivers/infiniband/sw/rdmavt/qp.c             | 91 +++++++------------
 drivers/infiniband/sw/rdmavt/qp.h             |  5 +-
 drivers/infiniband/sw/rdmavt/vt.c             |  9 ++
 drivers/infiniband/sw/rxe/rxe_pool.c          |  2 +-
 drivers/infiniband/sw/rxe/rxe_verbs.c         | 48 +++++-----
 drivers/infiniband/sw/rxe/rxe_verbs.h         |  2 +-
 drivers/infiniband/sw/siw/siw_main.c          |  1 +
 drivers/infiniband/sw/siw/siw_qp.c            |  2 -
 drivers/infiniband/sw/siw/siw_verbs.c         | 54 +++++------
 drivers/infiniband/sw/siw/siw_verbs.h         |  5 +-
 include/rdma/ib_verbs.h                       | 30 +++++-
 53 files changed, 404 insertions(+), 549 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 647cca4e0240..fa2e0bbaf8c7 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -322,13 +322,14 @@ _ib_create_qp(struct ib_device *dev, struct ib_pd *pd,
 	      struct ib_uqp_object *uobj, const char *caller)
 {
 	struct ib_qp *qp;
+	int ret;
 
 	if (!dev->ops.create_qp)
 		return ERR_PTR(-EOPNOTSUPP);
 
-	qp = dev->ops.create_qp(pd, attr, udata);
-	if (IS_ERR(qp))
-		return qp;
+	qp = rdma_zalloc_drv_obj_numa(dev, ib_qp);
+	if (!qp)
+		return ERR_PTR(-ENOMEM);
 
 	qp->device = dev;
 	qp->pd = pd;
@@ -337,14 +338,10 @@ _ib_create_qp(struct ib_device *dev, struct ib_pd *pd,
 
 	qp->qp_type = attr->qp_type;
 	qp->rwq_ind_tbl = attr->rwq_ind_tbl;
-	qp->send_cq = attr->send_cq;
-	qp->recv_cq = attr->recv_cq;
 	qp->srq = attr->srq;
-	qp->rwq_ind_tbl = attr->rwq_ind_tbl;
 	qp->event_handler = attr->event_handler;
 	qp->port = attr->port_num;
 
-	atomic_set(&qp->usecnt, 0);
 	spin_lock_init(&qp->mr_lock);
 	INIT_LIST_HEAD(&qp->rdma_mrs);
 	INIT_LIST_HEAD(&qp->sig_mrs);
@@ -352,8 +349,25 @@ _ib_create_qp(struct ib_device *dev, struct ib_pd *pd,
 	rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
 	WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
 	rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
+	ret = dev->ops.create_qp(qp, attr, udata);
+	if (ret)
+		goto err_create;
+
+	/*
+	 * TODO: The mlx4 internally overwrites send_cq and recv_cq.
+	 * Unfortunately, it is not an easy task to fix that driver.
+	 */
+	qp->send_cq = attr->send_cq;
+	qp->recv_cq = attr->recv_cq;
+
 	rdma_restrack_add(&qp->res);
 	return qp;
+
+err_create:
+	rdma_restrack_put(&qp->res);
+	kfree(qp);
+	return ERR_PTR(ret);
+
 }
 
 struct rdma_dev_addr;
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 9056f48bdca6..f4814bb7f082 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -2654,6 +2654,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
 	SET_DEVICE_OP(dev_ops, get_hw_stats);
 	SET_DEVICE_OP(dev_ops, get_link_layer);
 	SET_DEVICE_OP(dev_ops, get_netdev);
+	SET_DEVICE_OP(dev_ops, get_numa_node);
 	SET_DEVICE_OP(dev_ops, get_port_immutable);
 	SET_DEVICE_OP(dev_ops, get_vector_affinity);
 	SET_DEVICE_OP(dev_ops, get_vf_config);
@@ -2710,6 +2711,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
 	SET_OBJ_SIZE(dev_ops, ib_cq);
 	SET_OBJ_SIZE(dev_ops, ib_mw);
 	SET_OBJ_SIZE(dev_ops, ib_pd);
+	SET_OBJ_SIZE(dev_ops, ib_qp);
 	SET_OBJ_SIZE(dev_ops, ib_rwq_ind_table);
 	SET_OBJ_SIZE(dev_ops, ib_srq);
 	SET_OBJ_SIZE(dev_ops, ib_ucontext);
diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
index 033207882c82..1f935d9f6178 100644
--- a/drivers/infiniband/core/restrack.c
+++ b/drivers/infiniband/core/restrack.c
@@ -343,7 +343,7 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)
 	rt = &dev->res[res->type];
 
 	old = xa_erase(&rt->xa, res->id);
-	if (res->type == RDMA_RESTRACK_MR || res->type == RDMA_RESTRACK_QP)
+	if (res->type == RDMA_RESTRACK_MR)
 		return;
 	WARN_ON(old != res);
 
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 7036967e4c0b..a164609c2ee7 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1963,30 +1963,32 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
 		rdma_rw_cleanup_mrs(qp);
 
 	rdma_counter_unbind_qp(qp, true);
-	rdma_restrack_del(&qp->res);
 	ret = qp->device->ops.destroy_qp(qp, udata);
-	if (!ret) {
-		if (alt_path_sgid_attr)
-			rdma_put_gid_attr(alt_path_sgid_attr);
-		if (av_sgid_attr)
-			rdma_put_gid_attr(av_sgid_attr);
-		if (pd)
-			atomic_dec(&pd->usecnt);
-		if (scq)
-			atomic_dec(&scq->usecnt);
-		if (rcq)
-			atomic_dec(&rcq->usecnt);
-		if (srq)
-			atomic_dec(&srq->usecnt);
-		if (ind_tbl)
-			atomic_dec(&ind_tbl->usecnt);
-		if (sec)
-			ib_destroy_qp_security_end(sec);
-	} else {
+	if (ret) {
 		if (sec)
 			ib_destroy_qp_security_abort(sec);
+		return ret;
 	}
 
+	if (alt_path_sgid_attr)
+		rdma_put_gid_attr(alt_path_sgid_attr);
+	if (av_sgid_attr)
+		rdma_put_gid_attr(av_sgid_attr);
+	if (pd)
+		atomic_dec(&pd->usecnt);
+	if (scq)
+		atomic_dec(&scq->usecnt);
+	if (rcq)
+		atomic_dec(&rcq->usecnt);
+	if (srq)
+		atomic_dec(&srq->usecnt);
+	if (ind_tbl)
+		atomic_dec(&ind_tbl->usecnt);
+	if (sec)
+		ib_destroy_qp_security_end(sec);
+
+	rdma_restrack_del(&qp->res);
+	kfree(qp);
 	return ret;
 }
 EXPORT_SYMBOL(ib_destroy_qp_user);
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 283b6b81563c..634d1586a1fa 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -815,7 +815,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
 		rc = bnxt_re_destroy_gsi_sqp(qp);
 		if (rc)
-			goto sh_fail;
+			return rc;
 	}
 
 	mutex_lock(&rdev->qp_lock);
@@ -826,10 +826,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 	ib_umem_release(qp->rumem);
 	ib_umem_release(qp->sumem);
 
-	kfree(qp);
 	return 0;
-sh_fail:
-	return rc;
 }
 
 static u8 __from_ib_qp_type(enum ib_qp_type type)
@@ -1402,27 +1399,22 @@ static bool bnxt_re_test_qp_limits(struct bnxt_re_dev *rdev,
 	return rc;
 }
 
-struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
-				struct ib_qp_init_attr *qp_init_attr,
-				struct ib_udata *udata)
+int bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *qp_init_attr,
+		      struct ib_udata *udata)
 {
+	struct ib_pd *ib_pd = ib_qp->pd;
 	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
 	struct bnxt_re_dev *rdev = pd->rdev;
 	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
-	struct bnxt_re_qp *qp;
+	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
 	int rc;
 
 	rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr);
 	if (!rc) {
 		rc = -EINVAL;
-		goto exit;
+		goto fail;
 	}
 
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp) {
-		rc = -ENOMEM;
-		goto exit;
-	}
 	qp->rdev = rdev;
 	rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata);
 	if (rc)
@@ -1465,16 +1457,14 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
 	mutex_unlock(&rdev->qp_lock);
 	atomic_inc(&rdev->qp_count);
 
-	return &qp->ib_qp;
+	return 0;
 qp_destroy:
 	bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
 free_umem:
 	ib_umem_release(qp->rumem);
 	ib_umem_release(qp->sumem);
 fail:
-	kfree(qp);
-exit:
-	return ERR_PTR(rc);
+	return rc;
 }
 
 static u8 __from_ib_qp_state(enum ib_qp_state state)
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index d68671cc6173..b5c6e0f4f877 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -78,9 +78,9 @@ struct bnxt_re_srq {
 };
 
 struct bnxt_re_qp {
+	struct ib_qp		ib_qp;
 	struct list_head	list;
 	struct bnxt_re_dev	*rdev;
-	struct ib_qp		ib_qp;
 	spinlock_t		sq_lock;	/* protect sq */
 	spinlock_t		rq_lock;	/* protect rq */
 	struct bnxt_qplib_qp	qplib_qp;
@@ -179,9 +179,8 @@ int bnxt_re_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
 int bnxt_re_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
 int bnxt_re_post_srq_recv(struct ib_srq *srq, const struct ib_recv_wr *recv_wr,
 			  const struct ib_recv_wr **bad_recv_wr);
-struct ib_qp *bnxt_re_create_qp(struct ib_pd *pd,
-				struct ib_qp_init_attr *qp_init_attr,
-				struct ib_udata *udata);
+int bnxt_re_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *qp_init_attr,
+		      struct ib_udata *udata);
 int bnxt_re_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
 		      int qp_attr_mask, struct ib_udata *udata);
 int bnxt_re_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index d5674026512a..3edf66818e4b 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -709,6 +709,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, bnxt_re_ah, ib_ah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, bnxt_re_cq, ib_cq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, bnxt_re_pd, ib_pd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, bnxt_re_qp, ib_qp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, bnxt_re_srq, ib_srq),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, bnxt_re_ucontext, ib_uctx),
 };
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 3883af3d2312..6a2a415ec791 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -989,9 +989,8 @@ int c4iw_destroy_srq(struct ib_srq *ib_srq, struct ib_udata *udata);
 int c4iw_create_srq(struct ib_srq *srq, struct ib_srq_init_attr *attrs,
 		    struct ib_udata *udata);
 int c4iw_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata);
-struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
-			     struct ib_qp_init_attr *attrs,
-			     struct ib_udata *udata);
+int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+		   struct ib_udata *udata);
 int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 				 int attr_mask, struct ib_udata *udata);
 int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 881d515eb15a..e7337662aff8 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -499,6 +499,7 @@ static const struct ib_device_ops c4iw_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_cq, c4iw_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_mw, c4iw_mw, ibmw),
 	INIT_RDMA_OBJ_SIZE(ib_pd, c4iw_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, c4iw_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, c4iw_srq, ibsrq),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, c4iw_ucontext, ibucontext),
 };
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index a81fa7a56edb..d20b4ef2c853 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -2103,16 +2103,15 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 		   ucontext ? &ucontext->uctx : &rhp->rdev.uctx, !qhp->srq);
 
 	c4iw_put_wr_wait(qhp->wr_waitp);
-
-	kfree(qhp);
 	return 0;
 }
 
-struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
-			     struct ib_udata *udata)
+int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+		   struct ib_udata *udata)
 {
+	struct ib_pd *pd = qp->pd;
 	struct c4iw_dev *rhp;
-	struct c4iw_qp *qhp;
+	struct c4iw_qp *qhp = to_c4iw_qp(qp);
 	struct c4iw_pd *php;
 	struct c4iw_cq *schp;
 	struct c4iw_cq *rchp;
@@ -2124,44 +2123,36 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
 	struct c4iw_mm_entry *sq_key_mm, *rq_key_mm = NULL, *sq_db_key_mm;
 	struct c4iw_mm_entry *rq_db_key_mm = NULL, *ma_sync_key_mm = NULL;
 
-	pr_debug("ib_pd %p\n", pd);
-
 	if (attrs->qp_type != IB_QPT_RC || attrs->create_flags)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	php = to_c4iw_pd(pd);
 	rhp = php->rhp;
 	schp = get_chp(rhp, ((struct c4iw_cq *)attrs->send_cq)->cq.cqid);
 	rchp = get_chp(rhp, ((struct c4iw_cq *)attrs->recv_cq)->cq.cqid);
 	if (!schp || !rchp)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	if (attrs->cap.max_inline_data > T4_MAX_SEND_INLINE)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	if (!attrs->srq) {
 		if (attrs->cap.max_recv_wr > rhp->rdev.hw_queue.t4_max_rq_size)
-			return ERR_PTR(-E2BIG);
+			return -E2BIG;
 		rqsize = attrs->cap.max_recv_wr + 1;
 		if (rqsize < 8)
 			rqsize = 8;
 	}
 
 	if (attrs->cap.max_send_wr > rhp->rdev.hw_queue.t4_max_sq_size)
-		return ERR_PTR(-E2BIG);
+		return -E2BIG;
 	sqsize = attrs->cap.max_send_wr + 1;
 	if (sqsize < 8)
 		sqsize = 8;
 
-	qhp = kzalloc(sizeof(*qhp), GFP_KERNEL);
-	if (!qhp)
-		return ERR_PTR(-ENOMEM);
-
 	qhp->wr_waitp = c4iw_alloc_wr_wait(GFP_KERNEL);
-	if (!qhp->wr_waitp) {
-		ret = -ENOMEM;
-		goto err_free_qhp;
-	}
+	if (!qhp->wr_waitp)
+		return -ENOMEM;
 
 	qhp->wq.sq.size = sqsize;
 	qhp->wq.sq.memsize =
@@ -2339,7 +2330,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
 		 qhp->wq.sq.qid, qhp->wq.sq.size, qhp->wq.sq.memsize,
 		 attrs->cap.max_send_wr, qhp->wq.rq.qid, qhp->wq.rq.size,
 		 qhp->wq.rq.memsize, attrs->cap.max_recv_wr);
-	return &qhp->ibqp;
+	return 0;
 err_free_ma_sync_key:
 	kfree(ma_sync_key_mm);
 err_free_rq_db_key:
@@ -2359,9 +2350,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
 		   ucontext ? &ucontext->uctx : &rhp->rdev.uctx, !attrs->srq);
 err_free_wr_wait:
 	c4iw_put_wr_wait(qhp->wr_waitp);
-err_free_qhp:
-	kfree(qhp);
-	return ERR_PTR(ret);
+	return ret;
 }
 
 int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/hw/efa/efa.h b/drivers/infiniband/hw/efa/efa.h
index 2b8ca099b381..1a1e60eee1dc 100644
--- a/drivers/infiniband/hw/efa/efa.h
+++ b/drivers/infiniband/hw/efa/efa.h
@@ -132,9 +132,8 @@ int efa_query_pkey(struct ib_device *ibdev, u32 port, u16 index,
 int efa_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
 int efa_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
 int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
-struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
-			    struct ib_qp_init_attr *init_attr,
-			    struct ib_udata *udata);
+int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+		  struct ib_udata *udata);
 int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
 int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
 		  struct ib_udata *udata);
diff --git a/drivers/infiniband/hw/efa/efa_main.c b/drivers/infiniband/hw/efa/efa_main.c
index 203e6ddcacbc..997947d77de6 100644
--- a/drivers/infiniband/hw/efa/efa_main.c
+++ b/drivers/infiniband/hw/efa/efa_main.c
@@ -271,6 +271,7 @@ static const struct ib_device_ops efa_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, efa_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, efa_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, efa_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, efa_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, efa_ucontext, ibucontext),
 };
 
diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c
index b1c4780e86be..e5f9d90aad5e 100644
--- a/drivers/infiniband/hw/efa/efa_verbs.c
+++ b/drivers/infiniband/hw/efa/efa_verbs.c
@@ -450,7 +450,6 @@ int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 				qp->rq_size, DMA_TO_DEVICE);
 	}
 
-	kfree(qp);
 	return 0;
 }
 
@@ -609,17 +608,16 @@ static int efa_qp_validate_attr(struct efa_dev *dev,
 	return 0;
 }
 
-struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
-			    struct ib_qp_init_attr *init_attr,
-			    struct ib_udata *udata)
+int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+		  struct ib_udata *udata)
 {
 	struct efa_com_create_qp_params create_qp_params = {};
 	struct efa_com_create_qp_result create_qp_resp;
-	struct efa_dev *dev = to_edev(ibpd->device);
+	struct efa_dev *dev = to_edev(ibqp->device);
 	struct efa_ibv_create_qp_resp resp = {};
 	struct efa_ibv_create_qp cmd = {};
+	struct efa_qp *qp = to_eqp(ibqp);
 	struct efa_ucontext *ucontext;
-	struct efa_qp *qp;
 	int err;
 
 	ucontext = rdma_udata_to_drv_context(udata, struct efa_ucontext,
@@ -664,14 +662,8 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
 		goto err_out;
 	}
 
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp) {
-		err = -ENOMEM;
-		goto err_out;
-	}
-
 	create_qp_params.uarn = ucontext->uarn;
-	create_qp_params.pd = to_epd(ibpd)->pdn;
+	create_qp_params.pd = to_epd(ibqp->pd)->pdn;
 
 	if (init_attr->qp_type == IB_QPT_UD) {
 		create_qp_params.qp_type = EFA_ADMIN_QP_TYPE_UD;
@@ -682,7 +674,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
 			  "Unsupported qp type %d driver qp type %d\n",
 			  init_attr->qp_type, cmd.driver_qp_type);
 		err = -EOPNOTSUPP;
-		goto err_free_qp;
+		goto err_out;
 	}
 
 	ibdev_dbg(&dev->ibdev, "Create QP: qp type %d driver qp type %#x\n",
@@ -700,7 +692,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
 						    qp->rq_size, DMA_TO_DEVICE);
 		if (!qp->rq_cpu_addr) {
 			err = -ENOMEM;
-			goto err_free_qp;
+			goto err_out;
 		}
 
 		ibdev_dbg(&dev->ibdev,
@@ -746,7 +738,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
 
 	ibdev_dbg(&dev->ibdev, "Created qp[%d]\n", qp->ibqp.qp_num);
 
-	return &qp->ibqp;
+	return 0;
 
 err_remove_mmap_entries:
 	efa_qp_user_mmap_entries_remove(qp);
@@ -756,11 +748,9 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
 	if (qp->rq_size)
 		efa_free_mapped(dev, qp->rq_cpu_addr, qp->rq_dma_addr,
 				qp->rq_size, DMA_TO_DEVICE);
-err_free_qp:
-	kfree(qp);
 err_out:
 	atomic64_inc(&dev->stats.create_qp_err);
-	return ERR_PTR(err);
+	return err;
 }
 
 static const struct {
diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index 991f65269fa6..0c3eb1163977 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -1216,9 +1216,8 @@ int hns_roce_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata);
 int hns_roce_alloc_xrcd(struct ib_xrcd *ib_xrcd, struct ib_udata *udata);
 int hns_roce_dealloc_xrcd(struct ib_xrcd *ib_xrcd, struct ib_udata *udata);
 
-struct ib_qp *hns_roce_create_qp(struct ib_pd *ib_pd,
-				 struct ib_qp_init_attr *init_attr,
-				 struct ib_udata *udata);
+int hns_roce_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr *init_attr,
+		       struct ib_udata *udata);
 int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		       int attr_mask, struct ib_udata *udata);
 void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp);
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
index 078a97193f0e..23b88a5a372f 100644
--- a/drivers/infiniband/hw/hns/hns_roce_main.c
+++ b/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -454,6 +454,7 @@ static const struct ib_device_ops hns_roce_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, hns_roce_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, hns_roce_cq, ib_cq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, hns_roce_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, hns_roce_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, hns_roce_ucontext, ibucontext),
 };
 
diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c
index c3e2fee16c0e..fd0f71acd470 100644
--- a/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -959,8 +959,6 @@ static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
 	struct ib_device *ibdev = &hr_dev->ib_dev;
 	int ret;
 
-	hr_qp->ibqp.qp_type = init_attr->qp_type;
-
 	if (init_attr->cap.max_inline_data > hr_dev->caps.max_sq_inline)
 		init_attr->cap.max_inline_data = hr_dev->caps.max_sq_inline;
 
@@ -1121,8 +1119,6 @@ void hns_roce_qp_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
 	free_qp_buf(hr_dev, hr_qp);
 	free_kernel_wrid(hr_qp);
 	free_qp_db(hr_dev, hr_qp, udata);
-
-	kfree(hr_qp);
 }
 
 static int check_qp_type(struct hns_roce_dev *hr_dev, enum ib_qp_type type,
@@ -1154,22 +1150,18 @@ static int check_qp_type(struct hns_roce_dev *hr_dev, enum ib_qp_type type,
 	return -EOPNOTSUPP;
 }
 
-struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
-				 struct ib_qp_init_attr *init_attr,
-				 struct ib_udata *udata)
+int hns_roce_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+		       struct ib_udata *udata)
 {
-	struct ib_device *ibdev = pd ? pd->device : init_attr->xrcd->device;
+	struct ib_device *ibdev = qp->device;
 	struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
-	struct hns_roce_qp *hr_qp;
+	struct hns_roce_qp *hr_qp = to_hr_qp(qp);
+	struct ib_pd *pd = qp->pd;
 	int ret;
 
 	ret = check_qp_type(hr_dev, init_attr->qp_type, !!udata);
 	if (ret)
-		return ERR_PTR(ret);
-
-	hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL);
-	if (!hr_qp)
-		return ERR_PTR(-ENOMEM);
+		return ret;
 
 	if (init_attr->qp_type == IB_QPT_XRC_TGT)
 		hr_qp->xrcdn = to_hr_xrcd(init_attr->xrcd)->xrcdn;
@@ -1180,15 +1172,11 @@ struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
 	}
 
 	ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata, hr_qp);
-	if (ret) {
+	if (ret)
 		ibdev_err(ibdev, "Create QP type 0x%x failed(%d)\n",
 			  init_attr->qp_type, ret);
 
-		kfree(hr_qp);
-		return ERR_PTR(ret);
-	}
-
-	return &hr_qp->ibqp;
+	return ret;
 }
 
 int to_hr_qp_type(int qp_type)
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index 5bbe44e54f9a..e94470991fe0 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -1141,10 +1141,7 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
 			  iwqp->kqp.dma_mem.va, iwqp->kqp.dma_mem.pa);
 	iwqp->kqp.dma_mem.va = NULL;
 	kfree(iwqp->kqp.sq_wrid_mem);
-	iwqp->kqp.sq_wrid_mem = NULL;
 	kfree(iwqp->kqp.rq_wrid_mem);
-	iwqp->kqp.rq_wrid_mem = NULL;
-	kfree(iwqp);
 }
 
 /**
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 9712f6902ba8..9b8c451e2426 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -792,18 +792,19 @@ static int irdma_validate_qp_attrs(struct ib_qp_init_attr *init_attr,
 
 /**
  * irdma_create_qp - create qp
- * @ibpd: ptr of pd
+ * @ibqp: ptr of qp
  * @init_attr: attributes for qp
  * @udata: user data for create qp
  */
-static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
-				     struct ib_qp_init_attr *init_attr,
-				     struct ib_udata *udata)
+static int irdma_create_qp(struct ib_qp *ibqp,
+			   struct ib_qp_init_attr *init_attr,
+			   struct ib_udata *udata)
 {
+	struct ib_pd *ibpd = ibqp->pd;
 	struct irdma_pd *iwpd = to_iwpd(ibpd);
 	struct irdma_device *iwdev = to_iwdev(ibpd->device);
 	struct irdma_pci_f *rf = iwdev->rf;
-	struct irdma_qp *iwqp;
+	struct irdma_qp *iwqp = to_iwqp(ibqp);
 	struct irdma_create_qp_req req;
 	struct irdma_create_qp_resp uresp = {};
 	u32 qp_num = 0;
@@ -820,7 +821,7 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
 
 	err_code = irdma_validate_qp_attrs(init_attr, iwdev);
 	if (err_code)
-		return ERR_PTR(err_code);
+		return err_code;
 
 	sq_size = init_attr->cap.max_send_wr;
 	rq_size = init_attr->cap.max_recv_wr;
@@ -833,10 +834,6 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
 	init_info.qp_uk_init_info.max_rq_frag_cnt = init_attr->cap.max_recv_sge;
 	init_info.qp_uk_init_info.max_inline_data = init_attr->cap.max_inline_data;
 
-	iwqp = kzalloc(sizeof(*iwqp), GFP_KERNEL);
-	if (!iwqp)
-		return ERR_PTR(-ENOMEM);
-
 	qp = &iwqp->sc_qp;
 	qp->qp_uk.back_qp = iwqp;
 	qp->qp_uk.lock = &iwqp->lock;
@@ -849,10 +846,8 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
 						 iwqp->q2_ctx_mem.size,
 						 &iwqp->q2_ctx_mem.pa,
 						 GFP_KERNEL);
-	if (!iwqp->q2_ctx_mem.va) {
-		err_code = -ENOMEM;
-		goto error;
-	}
+	if (!iwqp->q2_ctx_mem.va)
+		return -ENOMEM;
 
 	init_info.q2 = iwqp->q2_ctx_mem.va;
 	init_info.q2_pa = iwqp->q2_ctx_mem.pa;
@@ -1001,17 +996,16 @@ static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
 		if (err_code) {
 			ibdev_dbg(&iwdev->ibdev, "VERBS: copy_to_udata failed\n");
 			irdma_destroy_qp(&iwqp->ibqp, udata);
-			return ERR_PTR(err_code);
+			return err_code;
 		}
 	}
 
 	init_completion(&iwqp->free_qp);
-	return &iwqp->ibqp;
+	return 0;
 
 error:
 	irdma_free_qp_rsrc(iwqp);
-
-	return ERR_PTR(err_code);
+	return err_code;
 }
 
 static int irdma_get_ib_acc_flags(struct irdma_qp *iwqp)
@@ -4406,6 +4400,7 @@ static const struct ib_device_ops irdma_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, irdma_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, irdma_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_mw, irdma_mr, ibmw),
+	INIT_RDMA_OBJ_SIZE(ib_qp, irdma_qp, ibqp),
 };
 
 /**
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index ae4c91b612ce..f367f4a4abff 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -2577,6 +2577,7 @@ static const struct ib_device_ops mlx4_ib_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, mlx4_ib_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, mlx4_ib_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, mlx4_ib_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, mlx4_ib_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, mlx4_ib_srq, ibsrq),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx4_ib_ucontext, ibucontext),
 };
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index e856cf23a0a1..c60f6e9ac640 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -792,9 +792,8 @@ void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index);
 int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
 			  const struct ib_recv_wr **bad_wr);
 
-struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
-				struct ib_qp_init_attr *init_attr,
-				struct ib_udata *udata);
+int mlx4_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+		      struct ib_udata *udata);
 int mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
 void mlx4_ib_drain_sq(struct ib_qp *qp);
 void mlx4_ib_drain_rq(struct ib_qp *qp);
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 4a2ef7daaded..8662f462e2a5 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1578,24 +1578,19 @@ static int _mlx4_ib_create_qp(struct ib_pd *pd, struct mlx4_ib_qp *qp,
 	return 0;
 }
 
-struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
-				struct ib_qp_init_attr *init_attr,
-				struct ib_udata *udata) {
-	struct ib_device *device = pd ? pd->device : init_attr->xrcd->device;
+int mlx4_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+		      struct ib_udata *udata)
+{
+	struct ib_device *device = ibqp->device;
 	struct mlx4_ib_dev *dev = to_mdev(device);
-	struct mlx4_ib_qp *qp;
+	struct mlx4_ib_qp *qp = to_mqp(ibqp);
+	struct ib_pd *pd = ibqp->pd;
 	int ret;
 
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp)
-		return ERR_PTR(-ENOMEM);
-
 	mutex_init(&qp->mutex);
 	ret = _mlx4_ib_create_qp(pd, qp, init_attr, udata);
-	if (ret) {
-		kfree(qp);
-		return ERR_PTR(ret);
-	}
+	if (ret)
+		return ret;
 
 	if (init_attr->qp_type == IB_QPT_GSI &&
 	    !(init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI)) {
@@ -1618,7 +1613,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 			init_attr->create_flags &= ~MLX4_IB_QP_CREATE_ROCE_V2_GSI;
 		}
 	}
-	return &qp->ibqp;
+	return 0;
 }
 
 static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
@@ -1646,8 +1641,6 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 	}
 
 	kfree(mqp->sqp);
-	kfree(mqp);
-
 	return 0;
 }
 
diff --git a/drivers/infiniband/hw/mlx5/gsi.c b/drivers/infiniband/hw/mlx5/gsi.c
index 541da52470cb..3ad8f637c589 100644
--- a/drivers/infiniband/hw/mlx5/gsi.c
+++ b/drivers/infiniband/hw/mlx5/gsi.c
@@ -193,8 +193,6 @@ int mlx5_ib_destroy_gsi(struct mlx5_ib_qp *mqp)
 
 	kfree(gsi->outstanding_wrs);
 	kfree(gsi->tx_qps);
-	kfree(mqp);
-
 	return 0;
 }
 
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index bcdbc3033b0a..7a6bafc19c9b 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -3805,6 +3805,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs),
 	INIT_RDMA_OBJ_SIZE(ib_cq, mlx5_ib_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, mlx5_ib_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, mlx5_ib_srq, ibsrq),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx5_ib_ucontext, ibucontext),
 };
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index f2c8a6375b16..d662896e7fba 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -1237,9 +1237,8 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
 			  const struct ib_recv_wr **bad_wr);
 int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp);
 void mlx5_ib_disable_lb(struct mlx5_ib_dev *dev, bool td, bool qp);
-struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
-				struct ib_qp_init_attr *init_attr,
-				struct ib_udata *udata);
+int mlx5_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+		      struct ib_udata *udata);
 int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		      int attr_mask, struct ib_udata *udata);
 int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index d6c6bfe9921a..18b018f1db83 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -3116,7 +3116,6 @@ static int mlx5_ib_destroy_dct(struct mlx5_ib_qp *mqp)
 	}
 
 	kfree(mqp->dct.in);
-	kfree(mqp);
 	return 0;
 }
 
@@ -3154,25 +3153,23 @@ static int check_ucmd_data(struct mlx5_ib_dev *dev,
 	return ret ? 0 : -EINVAL;
 }
 
-struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
-				struct ib_udata *udata)
+int mlx5_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
+		      struct ib_udata *udata)
 {
 	struct mlx5_create_qp_params params = {};
-	struct mlx5_ib_dev *dev;
-	struct mlx5_ib_qp *qp;
+	struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
+	struct mlx5_ib_qp *qp = to_mqp(ibqp);
+	struct ib_pd *pd = ibqp->pd;
 	enum ib_qp_type type;
 	int err;
 
-	dev = pd ? to_mdev(pd->device) :
-		   to_mdev(to_mxrcd(attr->xrcd)->ibxrcd.device);
-
 	err = check_qp_type(dev, attr, &type);
 	if (err)
-		return ERR_PTR(err);
+		return err;
 
 	err = check_valid_flow(dev, pd, attr, udata);
 	if (err)
-		return ERR_PTR(err);
+		return err;
 
 	params.udata = udata;
 	params.uidx = MLX5_IB_DEFAULT_UIDX;
@@ -3182,49 +3179,43 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
 	if (udata) {
 		err = process_udata_size(dev, &params);
 		if (err)
-			return ERR_PTR(err);
+			return err;
 
 		err = check_ucmd_data(dev, &params);
 		if (err)
-			return ERR_PTR(err);
+			return err;
 
 		params.ucmd = kzalloc(params.ucmd_size, GFP_KERNEL);
 		if (!params.ucmd)
-			return ERR_PTR(-ENOMEM);
+			return -ENOMEM;
 
 		err = ib_copy_from_udata(params.ucmd, udata, params.inlen);
 		if (err)
 			goto free_ucmd;
 	}
 
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp) {
-		err = -ENOMEM;
-		goto free_ucmd;
-	}
-
 	mutex_init(&qp->mutex);
 	qp->type = type;
 	if (udata) {
 		err = process_vendor_flags(dev, qp, params.ucmd, attr);
 		if (err)
-			goto free_qp;
+			goto free_ucmd;
 
 		err = get_qp_uidx(qp, &params);
 		if (err)
-			goto free_qp;
+			goto free_ucmd;
 	}
 	err = process_create_flags(dev, qp, attr);
 	if (err)
-		goto free_qp;
+		goto free_ucmd;
 
 	err = check_qp_attr(dev, qp, attr);
 	if (err)
-		goto free_qp;
+		goto free_ucmd;
 
 	err = create_qp(dev, pd, qp, &params);
 	if (err)
-		goto free_qp;
+		goto free_ucmd;
 
 	kfree(params.ucmd);
 	params.ucmd = NULL;
@@ -3239,7 +3230,7 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
 	if (err)
 		goto destroy_qp;
 
-	return &qp->ibqp;
+	return 0;
 
 destroy_qp:
 	switch (qp->type) {
@@ -3250,22 +3241,12 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attr,
 		mlx5_ib_destroy_gsi(qp);
 		break;
 	default:
-		/*
-		 * These lines below are temp solution till QP allocation
-		 * will be moved to be under IB/core responsiblity.
-		 */
-		qp->ibqp.send_cq = attr->send_cq;
-		qp->ibqp.recv_cq = attr->recv_cq;
-		qp->ibqp.pd = pd;
 		destroy_qp_common(dev, qp, udata);
 	}
 
-	qp = NULL;
-free_qp:
-	kfree(qp);
 free_ucmd:
 	kfree(params.ucmd);
-	return ERR_PTR(err);
+	return err;
 }
 
 int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
@@ -3280,9 +3261,6 @@ int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 		return mlx5_ib_destroy_dct(mqp);
 
 	destroy_qp_common(dev, mqp, udata);
-
-	kfree(mqp);
-
 	return 0;
 }
 
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index adf4fcf0fee4..ceee23ebc0f2 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -459,52 +459,45 @@ static int mthca_destroy_srq(struct ib_srq *srq, struct ib_udata *udata)
 	return 0;
 }
 
-static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
-				     struct ib_qp_init_attr *init_attr,
-				     struct ib_udata *udata)
+static int mthca_create_qp(struct ib_qp *ibqp,
+			   struct ib_qp_init_attr *init_attr,
+			   struct ib_udata *udata)
 {
 	struct mthca_ucontext *context = rdma_udata_to_drv_context(
 		udata, struct mthca_ucontext, ibucontext);
 	struct mthca_create_qp ucmd;
-	struct mthca_qp *qp;
+	struct mthca_qp *qp = to_mqp(ibqp);
+	struct mthca_dev *dev = to_mdev(ibqp->device);
 	int err;
 
 	if (init_attr->create_flags)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	switch (init_attr->qp_type) {
 	case IB_QPT_RC:
 	case IB_QPT_UC:
 	case IB_QPT_UD:
 	{
-		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-		if (!qp)
-			return ERR_PTR(-ENOMEM);
-
 		if (udata) {
-			if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
-				kfree(qp);
-				return ERR_PTR(-EFAULT);
-			}
+			if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd)))
+				return -EFAULT;
 
-			err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+			err = mthca_map_user_db(dev, &context->uar,
 						context->db_tab,
-						ucmd.sq_db_index, ucmd.sq_db_page);
-			if (err) {
-				kfree(qp);
-				return ERR_PTR(err);
-			}
+						ucmd.sq_db_index,
+						ucmd.sq_db_page);
+			if (err)
+				return err;
 
-			err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
+			err = mthca_map_user_db(dev, &context->uar,
 						context->db_tab,
-						ucmd.rq_db_index, ucmd.rq_db_page);
+						ucmd.rq_db_index,
+						ucmd.rq_db_page);
 			if (err) {
-				mthca_unmap_user_db(to_mdev(pd->device),
-						    &context->uar,
+				mthca_unmap_user_db(dev, &context->uar,
 						    context->db_tab,
 						    ucmd.sq_db_index);
-				kfree(qp);
-				return ERR_PTR(err);
+				return err;
 			}
 
 			qp->mr.ibmr.lkey = ucmd.lkey;
@@ -512,20 +505,16 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
 			qp->rq.db_index  = ucmd.rq_db_index;
 		}
 
-		err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd),
+		err = mthca_alloc_qp(dev, to_mpd(ibqp->pd),
 				     to_mcq(init_attr->send_cq),
 				     to_mcq(init_attr->recv_cq),
 				     init_attr->qp_type, init_attr->sq_sig_type,
 				     &init_attr->cap, qp, udata);
 
 		if (err && udata) {
-			mthca_unmap_user_db(to_mdev(pd->device),
-					    &context->uar,
-					    context->db_tab,
+			mthca_unmap_user_db(dev, &context->uar, context->db_tab,
 					    ucmd.sq_db_index);
-			mthca_unmap_user_db(to_mdev(pd->device),
-					    &context->uar,
-					    context->db_tab,
+			mthca_unmap_user_db(dev, &context->uar, context->db_tab,
 					    ucmd.rq_db_index);
 		}
 
@@ -535,34 +524,28 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:
 	{
-		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-		if (!qp)
-			return ERR_PTR(-ENOMEM);
 		qp->sqp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
-		if (!qp->sqp) {
-			kfree(qp);
-			return ERR_PTR(-ENOMEM);
-		}
+		if (!qp->sqp)
+			return -ENOMEM;
 
 		qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1;
 
-		err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd),
+		err = mthca_alloc_sqp(dev, to_mpd(ibqp->pd),
 				      to_mcq(init_attr->send_cq),
 				      to_mcq(init_attr->recv_cq),
 				      init_attr->sq_sig_type, &init_attr->cap,
-				      qp->ibqp.qp_num, init_attr->port_num,
-				      qp, udata);
+				      qp->ibqp.qp_num, init_attr->port_num, qp,
+				      udata);
 		break;
 	}
 	default:
 		/* Don't support raw QPs */
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 
 	if (err) {
 		kfree(qp->sqp);
-		kfree(qp);
-		return ERR_PTR(err);
+		return err;
 	}
 
 	init_attr->cap.max_send_wr     = qp->sq.max;
@@ -571,7 +554,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
 	init_attr->cap.max_recv_sge    = qp->rq.max_gs;
 	init_attr->cap.max_inline_data = qp->max_inline_data;
 
-	return &qp->ibqp;
+	return 0;
 }
 
 static int mthca_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
@@ -594,7 +577,6 @@ static int mthca_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 	}
 	mthca_free_qp(to_mdev(qp->device), to_mqp(qp));
 	kfree(to_mqp(qp)->sqp);
-	kfree(to_mqp(qp));
 	return 0;
 }
 
@@ -1121,6 +1103,7 @@ static const struct ib_device_ops mthca_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, mthca_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, mthca_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, mthca_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, mthca_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, mthca_ucontext, ibucontext),
 };
 
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index f329db0c591f..7abf6cf1e937 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -185,6 +185,7 @@ static const struct ib_device_ops ocrdma_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, ocrdma_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, ocrdma_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, ocrdma_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, ocrdma_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, ocrdma_ucontext, ibucontext),
 };
 
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 58619ce64d0d..735123d0e9ec 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -1288,19 +1288,19 @@ static void ocrdma_store_gsi_qp_cq(struct ocrdma_dev *dev,
 	}
 }
 
-struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
-			       struct ib_qp_init_attr *attrs,
-			       struct ib_udata *udata)
+int ocrdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
+		     struct ib_udata *udata)
 {
 	int status;
+	struct ib_pd *ibpd = ibqp->pd;
 	struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
-	struct ocrdma_qp *qp;
-	struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device);
+	struct ocrdma_qp *qp = get_ocrdma_qp(ibqp);
+	struct ocrdma_dev *dev = get_ocrdma_dev(ibqp->device);
 	struct ocrdma_create_qp_ureq ureq;
 	u16 dpp_credit_lmt, dpp_offset;
 
 	if (attrs->create_flags)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	status = ocrdma_check_qp_params(ibpd, dev, attrs, udata);
 	if (status)
@@ -1309,12 +1309,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
 	memset(&ureq, 0, sizeof(ureq));
 	if (udata) {
 		if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
-			return ERR_PTR(-EFAULT);
-	}
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp) {
-		status = -ENOMEM;
-		goto gen_err;
+			return -EFAULT;
 	}
 	ocrdma_set_qp_init_params(qp, pd, attrs);
 	if (udata == NULL)
@@ -1349,7 +1344,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
 	ocrdma_store_gsi_qp_cq(dev, attrs);
 	qp->ibqp.qp_num = qp->id;
 	mutex_unlock(&dev->dev_lock);
-	return &qp->ibqp;
+	return 0;
 
 cpy_err:
 	ocrdma_del_qpn_map(dev, qp);
@@ -1359,10 +1354,9 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
 	mutex_unlock(&dev->dev_lock);
 	kfree(qp->wqe_wr_id_tbl);
 	kfree(qp->rqe_wr_id_tbl);
-	kfree(qp);
 	pr_err("%s(%d) error=%d\n", __func__, dev->id, status);
 gen_err:
-	return ERR_PTR(status);
+	return status;
 }
 
 int _ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
@@ -1731,7 +1725,6 @@ int ocrdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 
 	kfree(qp->wqe_wr_id_tbl);
 	kfree(qp->rqe_wr_id_tbl);
-	kfree(qp);
 	return 0;
 }
 
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
index b1c5fad81603..b73d742a520c 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -75,9 +75,8 @@ int ocrdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
 int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
 int ocrdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
 
-struct ib_qp *ocrdma_create_qp(struct ib_pd *,
-			       struct ib_qp_init_attr *attrs,
-			       struct ib_udata *);
+int ocrdma_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+		     struct ib_udata *udata);
 int _ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
 		      int attr_mask);
 int ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
index de98e0604f91..755930be01b8 100644
--- a/drivers/infiniband/hw/qedr/main.c
+++ b/drivers/infiniband/hw/qedr/main.c
@@ -233,6 +233,7 @@ static const struct ib_device_ops qedr_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, qedr_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, qedr_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, qedr_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, qedr_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, qedr_srq, ibsrq),
 	INIT_RDMA_OBJ_SIZE(ib_xrcd, qedr_xrcd, ibxrcd),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, qedr_ucontext, ibucontext),
diff --git a/drivers/infiniband/hw/qedr/qedr_roce_cm.c b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
index 13e5e6bbec99..05307c1488b8 100644
--- a/drivers/infiniband/hw/qedr/qedr_roce_cm.c
+++ b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
@@ -319,20 +319,19 @@ static int qedr_ll2_start(struct qedr_dev *dev,
 	return rc;
 }
 
-struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
-				 struct ib_qp_init_attr *attrs,
-				 struct qedr_qp *qp)
+int qedr_create_gsi_qp(struct qedr_dev *dev, struct ib_qp_init_attr *attrs,
+		       struct qedr_qp *qp)
 {
 	int rc;
 
 	rc = qedr_check_gsi_qp_attrs(dev, attrs);
 	if (rc)
-		return ERR_PTR(rc);
+		return rc;
 
 	rc = qedr_ll2_start(dev, attrs, qp);
 	if (rc) {
 		DP_ERR(dev, "create gsi qp: failed on ll2 start. rc=%d\n", rc);
-		return ERR_PTR(rc);
+		return rc;
 	}
 
 	/* create QP */
@@ -359,7 +358,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
 
 	DP_DEBUG(dev, QEDR_MSG_GSI, "created GSI QP %p\n", qp);
 
-	return &qp->ibqp;
+	return 0;
 
 err:
 	kfree(qp->rqe_wr_id);
@@ -368,7 +367,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
 	if (rc)
 		DP_ERR(dev, "create gsi qp: failed destroy on create\n");
 
-	return ERR_PTR(-ENOMEM);
+	return -ENOMEM;
 }
 
 int qedr_destroy_gsi_qp(struct qedr_dev *dev)
diff --git a/drivers/infiniband/hw/qedr/qedr_roce_cm.h b/drivers/infiniband/hw/qedr/qedr_roce_cm.h
index d46dcd3f6424..f3432f035ec6 100644
--- a/drivers/infiniband/hw/qedr/qedr_roce_cm.h
+++ b/drivers/infiniband/hw/qedr/qedr_roce_cm.h
@@ -50,9 +50,8 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
 		       const struct ib_recv_wr **bad_wr);
 int qedr_gsi_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
 		       const struct ib_send_wr **bad_wr);
-struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
-				 struct ib_qp_init_attr *attrs,
-				 struct qedr_qp *qp);
+int qedr_create_gsi_qp(struct qedr_dev *dev, struct ib_qp_init_attr *attrs,
+		       struct qedr_qp *qp);
 void qedr_store_gsi_qp_cq(struct qedr_dev *dev,
 			  struct qedr_qp *qp, struct ib_qp_init_attr *attrs);
 int qedr_destroy_gsi_qp(struct qedr_dev *dev);
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index fdc47ef7d861..9cf94dc768ec 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -2239,34 +2239,30 @@ static int qedr_free_qp_resources(struct qedr_dev *dev, struct qedr_qp *qp,
 	return 0;
 }
 
-struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
-			     struct ib_qp_init_attr *attrs,
-			     struct ib_udata *udata)
+int qedr_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
+		   struct ib_udata *udata)
 {
 	struct qedr_xrcd *xrcd = NULL;
-	struct qedr_pd *pd = NULL;
-	struct qedr_dev *dev;
-	struct qedr_qp *qp;
-	struct ib_qp *ibqp;
+	struct ib_pd *ibpd = ibqp->pd;
+	struct qedr_pd *pd = get_qedr_pd(ibpd);
+	struct qedr_dev *dev = get_qedr_dev(ibqp->device);
+	struct qedr_qp *qp = get_qedr_qp(ibqp);
 	int rc = 0;
 
 	if (attrs->create_flags)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
-	if (attrs->qp_type == IB_QPT_XRC_TGT) {
+	if (attrs->qp_type == IB_QPT_XRC_TGT)
 		xrcd = get_qedr_xrcd(attrs->xrcd);
-		dev = get_qedr_dev(xrcd->ibxrcd.device);
-	} else {
+	else
 		pd = get_qedr_pd(ibpd);
-		dev = get_qedr_dev(ibpd->device);
-	}
 
 	DP_DEBUG(dev, QEDR_MSG_QP, "create qp: called from %s, pd=%p\n",
 		 udata ? "user library" : "kernel", pd);
 
 	rc = qedr_check_qp_attrs(ibpd, dev, attrs, udata);
 	if (rc)
-		return ERR_PTR(rc);
+		return rc;
 
 	DP_DEBUG(dev, QEDR_MSG_QP,
 		 "create qp: called from %s, event_handler=%p, eepd=%p sq_cq=%p, sq_icid=%d, rq_cq=%p, rq_icid=%d\n",
@@ -2276,20 +2272,10 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
 		 get_qedr_cq(attrs->recv_cq),
 		 attrs->recv_cq ? get_qedr_cq(attrs->recv_cq)->icid : 0);
 
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp) {
-		DP_ERR(dev, "create qp: failed allocating memory\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
 	qedr_set_common_qp_params(dev, qp, pd, attrs);
 
-	if (attrs->qp_type == IB_QPT_GSI) {
-		ibqp = qedr_create_gsi_qp(dev, attrs, qp);
-		if (IS_ERR(ibqp))
-			kfree(qp);
-		return ibqp;
-	}
+	if (attrs->qp_type == IB_QPT_GSI)
+		return qedr_create_gsi_qp(dev, attrs, qp);
 
 	if (udata || xrcd)
 		rc = qedr_create_user_qp(dev, qp, ibpd, udata, attrs);
@@ -2297,7 +2283,7 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
 		rc = qedr_create_kernel_qp(dev, qp, ibpd, attrs);
 
 	if (rc)
-		goto out_free_qp;
+		return rc;
 
 	qp->ibqp.qp_num = qp->qp_id;
 
@@ -2307,14 +2293,11 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
 			goto out_free_qp_resources;
 	}
 
-	return &qp->ibqp;
+	return 0;
 
 out_free_qp_resources:
 	qedr_free_qp_resources(dev, qp, udata);
-out_free_qp:
-	kfree(qp);
-
-	return ERR_PTR(-EFAULT);
+	return -EFAULT;
 }
 
 static enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state qp_state)
@@ -2874,8 +2857,6 @@ int qedr_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 
 	if (rdma_protocol_iwarp(&dev->ibdev, 1))
 		qedr_iw_qp_rem_ref(&qp->ibqp);
-	else
-		kfree(qp);
 
 	return 0;
 }
diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h
index 34ad47515861..031687dafc61 100644
--- a/drivers/infiniband/hw/qedr/verbs.h
+++ b/drivers/infiniband/hw/qedr/verbs.h
@@ -56,8 +56,8 @@ int qedr_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
 int qedr_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
 int qedr_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
 int qedr_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
-struct ib_qp *qedr_create_qp(struct ib_pd *, struct ib_qp_init_attr *attrs,
-			     struct ib_udata *);
+int qedr_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
+		   struct ib_udata *udata);
 int qedr_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
 		   int attr_mask, struct ib_udata *udata);
 int qedr_query_qp(struct ib_qp *, struct ib_qp_attr *qp_attr,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index c49f9e19d926..228e9a36dad0 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -360,6 +360,7 @@ static const struct ib_device_ops usnic_dev_ops = {
 	.reg_user_mr = usnic_ib_reg_mr,
 	INIT_RDMA_OBJ_SIZE(ib_pd, usnic_ib_pd, ibpd),
 	INIT_RDMA_OBJ_SIZE(ib_cq, usnic_ib_cq, ibcq),
+	INIT_RDMA_OBJ_SIZE(ib_qp, usnic_ib_qp_grp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, usnic_ib_ucontext, ibucontext),
 };
 
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
index 0cdb156e165e..3b60fa9cb58d 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
@@ -665,13 +665,12 @@ static int qp_grp_id_from_flow(struct usnic_ib_qp_grp_flow *qp_flow,
 	return 0;
 }
 
-struct usnic_ib_qp_grp *
-usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
-			struct usnic_ib_pd *pd,
-			struct usnic_vnic_res_spec *res_spec,
-			struct usnic_transport_spec *transport_spec)
+int usnic_ib_qp_grp_create(struct usnic_ib_qp_grp *qp_grp,
+			   struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
+			   struct usnic_ib_pd *pd,
+			   struct usnic_vnic_res_spec *res_spec,
+			   struct usnic_transport_spec *transport_spec)
 {
-	struct usnic_ib_qp_grp *qp_grp;
 	int err;
 	enum usnic_transport_type transport = transport_spec->trans_type;
 	struct usnic_ib_qp_grp_flow *qp_flow;
@@ -684,20 +683,15 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
 		usnic_err("Spec does not meet minimum req for transport %d\n",
 				transport);
 		log_spec(res_spec);
-		return ERR_PTR(err);
+		return err;
 	}
 
-	qp_grp = kzalloc(sizeof(*qp_grp), GFP_ATOMIC);
-	if (!qp_grp)
-		return NULL;
-
 	qp_grp->res_chunk_list = alloc_res_chunk_list(vf->vnic, res_spec,
 							qp_grp);
-	if (IS_ERR_OR_NULL(qp_grp->res_chunk_list)) {
-		err = qp_grp->res_chunk_list ?
-				PTR_ERR(qp_grp->res_chunk_list) : -ENOMEM;
-		goto out_free_qp_grp;
-	}
+	if (IS_ERR_OR_NULL(qp_grp->res_chunk_list))
+		return qp_grp->res_chunk_list ?
+				     PTR_ERR(qp_grp->res_chunk_list) :
+				     -ENOMEM;
 
 	err = qp_grp_and_vf_bind(vf, pd, qp_grp);
 	if (err)
@@ -724,7 +718,7 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
 
 	usnic_ib_sysfs_qpn_add(qp_grp);
 
-	return qp_grp;
+	return 0;
 
 out_release_flow:
 	release_and_remove_flow(qp_flow);
@@ -732,10 +726,7 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
 	qp_grp_and_vf_unbind(qp_grp);
 out_free_res:
 	free_qp_grp_res(qp_grp->res_chunk_list);
-out_free_qp_grp:
-	kfree(qp_grp);
-
-	return ERR_PTR(err);
+	return err;
 }
 
 void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
@@ -748,7 +739,6 @@ void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
 	usnic_ib_sysfs_qpn_remove(qp_grp);
 	qp_grp_and_vf_unbind(qp_grp);
 	free_qp_grp_res(qp_grp->res_chunk_list);
-	kfree(qp_grp);
 }
 
 struct usnic_vnic_res_chunk*
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
index a8a2314c9531..62e732be6736 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
@@ -89,11 +89,11 @@ extern const struct usnic_vnic_res_spec min_transport_spec[USNIC_TRANSPORT_MAX];
 const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state);
 int usnic_ib_qp_grp_dump_hdr(char *buf, int buf_sz);
 int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz);
-struct usnic_ib_qp_grp *
-usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
-			struct usnic_ib_pd *pd,
-			struct usnic_vnic_res_spec *res_spec,
-			struct usnic_transport_spec *trans_spec);
+int usnic_ib_qp_grp_create(struct usnic_ib_qp_grp *qp,
+			   struct usnic_fwd_dev *ufdev, struct usnic_ib_vf *vf,
+			   struct usnic_ib_pd *pd,
+			   struct usnic_vnic_res_spec *res_spec,
+			   struct usnic_transport_spec *trans_spec);
 void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp);
 int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
 				enum ib_qp_state new_state,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 57d210ca855a..06a4e9d4545d 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -168,30 +168,31 @@ static int usnic_ib_fill_create_qp_resp(struct usnic_ib_qp_grp *qp_grp,
 	return 0;
 }
 
-static struct usnic_ib_qp_grp*
-find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
-				struct usnic_ib_pd *pd,
-				struct usnic_transport_spec *trans_spec,
-				struct usnic_vnic_res_spec *res_spec)
+static int
+find_free_vf_and_create_qp_grp(struct ib_qp *qp,
+			       struct usnic_transport_spec *trans_spec,
+			       struct usnic_vnic_res_spec *res_spec)
 {
+	struct usnic_ib_dev *us_ibdev = to_usdev(qp->device);
+	struct usnic_ib_pd *pd = to_upd(qp->pd);
 	struct usnic_ib_vf *vf;
 	struct usnic_vnic *vnic;
-	struct usnic_ib_qp_grp *qp_grp;
+	struct usnic_ib_qp_grp *qp_grp = to_uqp_grp(qp);
 	struct device *dev, **dev_list;
-	int i;
+	int i, ret;
 
 	BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));
 
 	if (list_empty(&us_ibdev->vf_dev_list)) {
 		usnic_info("No vfs to allocate\n");
-		return NULL;
+		return -ENOMEM;
 	}
 
 	if (usnic_ib_share_vf) {
 		/* Try to find resouces on a used vf which is in pd */
 		dev_list = usnic_uiom_get_dev_list(pd->umem_pd);
 		if (IS_ERR(dev_list))
-			return ERR_CAST(dev_list);
+			return PTR_ERR(dev_list);
 		for (i = 0; dev_list[i]; i++) {
 			dev = dev_list[i];
 			vf = dev_get_drvdata(dev);
@@ -202,10 +203,10 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
 						dev_name(&us_ibdev->ib_dev.dev),
 						pci_name(usnic_vnic_get_pdev(
 									vnic)));
-				qp_grp = usnic_ib_qp_grp_create(us_ibdev->ufdev,
-								vf, pd,
-								res_spec,
-								trans_spec);
+				ret = usnic_ib_qp_grp_create(qp_grp,
+							     us_ibdev->ufdev,
+							     vf, pd, res_spec,
+							     trans_spec);
 
 				spin_unlock(&vf->lock);
 				goto qp_grp_check;
@@ -223,9 +224,9 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
 		vnic = vf->vnic;
 		if (vf->qp_grp_ref_cnt == 0 &&
 		    usnic_vnic_check_room(vnic, res_spec) == 0) {
-			qp_grp = usnic_ib_qp_grp_create(us_ibdev->ufdev, vf,
-							pd, res_spec,
-							trans_spec);
+			ret = usnic_ib_qp_grp_create(qp_grp, us_ibdev->ufdev,
+						     vf, pd, res_spec,
+						     trans_spec);
 
 			spin_unlock(&vf->lock);
 			goto qp_grp_check;
@@ -235,16 +236,15 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
 
 	usnic_info("No free qp grp found on %s\n",
 		   dev_name(&us_ibdev->ib_dev.dev));
-	return ERR_PTR(-ENOMEM);
+	return -ENOMEM;
 
 qp_grp_check:
-	if (IS_ERR_OR_NULL(qp_grp)) {
+	if (ret) {
 		usnic_err("Failed to allocate qp_grp\n");
 		if (usnic_ib_share_vf)
 			usnic_uiom_free_dev_list(dev_list);
-		return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
 	}
-	return qp_grp;
+	return ret;
 }
 
 static void qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
@@ -458,13 +458,12 @@ int usnic_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata)
 	return 0;
 }
 
-struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
-					struct ib_qp_init_attr *init_attr,
-					struct ib_udata *udata)
+int usnic_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+		       struct ib_udata *udata)
 {
 	int err;
 	struct usnic_ib_dev *us_ibdev;
-	struct usnic_ib_qp_grp *qp_grp;
+	struct usnic_ib_qp_grp *qp_grp = to_uqp_grp(ibqp);
 	struct usnic_ib_ucontext *ucontext = rdma_udata_to_drv_context(
 		udata, struct usnic_ib_ucontext, ibucontext);
 	int cq_cnt;
@@ -474,29 +473,29 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
 
 	usnic_dbg("\n");
 
-	us_ibdev = to_usdev(pd->device);
+	us_ibdev = to_usdev(ibqp->device);
 
 	if (init_attr->create_flags)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	err = ib_copy_from_udata(&cmd, udata, sizeof(cmd));
 	if (err) {
 		usnic_err("%s: cannot copy udata for create_qp\n",
 			  dev_name(&us_ibdev->ib_dev.dev));
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
 	err = create_qp_validate_user_data(cmd);
 	if (err) {
 		usnic_err("%s: Failed to validate user data\n",
 			  dev_name(&us_ibdev->ib_dev.dev));
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (init_attr->qp_type != IB_QPT_UD) {
 		usnic_err("%s asked to make a non-UD QP: %d\n",
 			  dev_name(&us_ibdev->ib_dev.dev), init_attr->qp_type);
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 
 	trans_spec = cmd.spec;
@@ -504,13 +503,9 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
 	cq_cnt = (init_attr->send_cq == init_attr->recv_cq) ? 1 : 2;
 	res_spec = min_transport_spec[trans_spec.trans_type];
 	usnic_vnic_res_spec_update(&res_spec, USNIC_VNIC_RES_TYPE_CQ, cq_cnt);
-	qp_grp = find_free_vf_and_create_qp_grp(us_ibdev, to_upd(pd),
-						&trans_spec,
-						&res_spec);
-	if (IS_ERR_OR_NULL(qp_grp)) {
-		err = qp_grp ? PTR_ERR(qp_grp) : -ENOMEM;
+	err = find_free_vf_and_create_qp_grp(ibqp, &trans_spec, &res_spec);
+	if (err)
 		goto out_release_mutex;
-	}
 
 	err = usnic_ib_fill_create_qp_resp(qp_grp, udata);
 	if (err) {
@@ -522,13 +517,13 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
 	list_add_tail(&qp_grp->link, &ucontext->qp_grp_list);
 	usnic_ib_log_vf(qp_grp->vf);
 	mutex_unlock(&us_ibdev->usdev_lock);
-	return &qp_grp->ibqp;
+	return 0;
 
 out_release_qp_grp:
 	qp_grp_destroy(qp_grp);
 out_release_mutex:
 	mutex_unlock(&us_ibdev->usdev_lock);
-	return ERR_PTR(err);
+	return err;
 }
 
 int usnic_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
index 6b82d0f2d184..6ca9ee0dddbe 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
@@ -50,9 +50,8 @@ int usnic_ib_query_gid(struct ib_device *ibdev, u32 port, int index,
 				union ib_gid *gid);
 int usnic_ib_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
 int usnic_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);
-struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
-					struct ib_qp_init_attr *init_attr,
-					struct ib_udata *udata);
+int usnic_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+		       struct ib_udata *udata);
 int usnic_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
 int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 				int attr_mask, struct ib_udata *udata);
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
index 8ed8bc24c69f..b39175837d58 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
@@ -185,6 +185,7 @@ static const struct ib_device_ops pvrdma_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, pvrdma_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, pvrdma_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, pvrdma_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, pvrdma_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, pvrdma_ucontext, ibucontext),
 };
 
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
index 67769b715126..f83cd4a9d992 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
@@ -182,18 +182,17 @@ static int pvrdma_set_sq_size(struct pvrdma_dev *dev, struct ib_qp_cap *req_cap,
 
 /**
  * pvrdma_create_qp - create queue pair
- * @pd: protection domain
+ * @ibqp: queue pair
  * @init_attr: queue pair attributes
  * @udata: user data
  *
- * @return: the ib_qp pointer on success, otherwise returns an errno.
+ * @return: the 0 on success, otherwise returns an errno.
  */
-struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
-			       struct ib_qp_init_attr *init_attr,
-			       struct ib_udata *udata)
+int pvrdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+		     struct ib_udata *udata)
 {
-	struct pvrdma_qp *qp = NULL;
-	struct pvrdma_dev *dev = to_vdev(pd->device);
+	struct pvrdma_qp *qp = to_vqp(ibqp);
+	struct pvrdma_dev *dev = to_vdev(ibqp->device);
 	union pvrdma_cmd_req req;
 	union pvrdma_cmd_resp rsp;
 	struct pvrdma_cmd_create_qp *cmd = &req.create_qp;
@@ -209,7 +208,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 		dev_warn(&dev->pdev->dev,
 			 "invalid create queuepair flags %#x\n",
 			 init_attr->create_flags);
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 
 	if (init_attr->qp_type != IB_QPT_RC &&
@@ -217,22 +216,22 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 	    init_attr->qp_type != IB_QPT_GSI) {
 		dev_warn(&dev->pdev->dev, "queuepair type %d not supported\n",
 			 init_attr->qp_type);
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 
 	if (is_srq && !dev->dsr->caps.max_srq) {
 		dev_warn(&dev->pdev->dev,
 			 "SRQs not supported by device\n");
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
 	if (!atomic_add_unless(&dev->num_qps, 1, dev->dsr->caps.max_qp))
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	switch (init_attr->qp_type) {
 	case IB_QPT_GSI:
 		if (init_attr->port_num == 0 ||
-		    init_attr->port_num > pd->device->phys_port_cnt) {
+		    init_attr->port_num > ibqp->device->phys_port_cnt) {
 			dev_warn(&dev->pdev->dev, "invalid queuepair attrs\n");
 			ret = -EINVAL;
 			goto err_qp;
@@ -240,12 +239,6 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 		fallthrough;
 	case IB_QPT_RC:
 	case IB_QPT_UD:
-		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-		if (!qp) {
-			ret = -ENOMEM;
-			goto err_qp;
-		}
-
 		spin_lock_init(&qp->sq.lock);
 		spin_lock_init(&qp->rq.lock);
 		mutex_init(&qp->mutex);
@@ -275,9 +268,9 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 
 			if (!is_srq) {
 				/* set qp->sq.wqe_cnt, shift, buf_size.. */
-				qp->rumem =
-					ib_umem_get(pd->device, ucmd.rbuf_addr,
-						    ucmd.rbuf_size, 0);
+				qp->rumem = ib_umem_get(ibqp->device,
+							ucmd.rbuf_addr,
+							ucmd.rbuf_size, 0);
 				if (IS_ERR(qp->rumem)) {
 					ret = PTR_ERR(qp->rumem);
 					goto err_qp;
@@ -288,7 +281,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 				qp->srq = to_vsrq(init_attr->srq);
 			}
 
-			qp->sumem = ib_umem_get(pd->device, ucmd.sbuf_addr,
+			qp->sumem = ib_umem_get(ibqp->device, ucmd.sbuf_addr,
 						ucmd.sbuf_size, 0);
 			if (IS_ERR(qp->sumem)) {
 				if (!is_srq)
@@ -306,12 +299,12 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 				qp->npages_recv = 0;
 			qp->npages = qp->npages_send + qp->npages_recv;
 		} else {
-			ret = pvrdma_set_sq_size(to_vdev(pd->device),
+			ret = pvrdma_set_sq_size(to_vdev(ibqp->device),
 						 &init_attr->cap, qp);
 			if (ret)
 				goto err_qp;
 
-			ret = pvrdma_set_rq_size(to_vdev(pd->device),
+			ret = pvrdma_set_rq_size(to_vdev(ibqp->device),
 						 &init_attr->cap, qp);
 			if (ret)
 				goto err_qp;
@@ -362,7 +355,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 
 	memset(cmd, 0, sizeof(*cmd));
 	cmd->hdr.cmd = PVRDMA_CMD_CREATE_QP;
-	cmd->pd_handle = to_vpd(pd)->pd_handle;
+	cmd->pd_handle = to_vpd(ibqp->pd)->pd_handle;
 	cmd->send_cq_handle = to_vcq(init_attr->send_cq)->cq_handle;
 	cmd->recv_cq_handle = to_vcq(init_attr->recv_cq)->cq_handle;
 	if (is_srq)
@@ -418,11 +411,11 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 			dev_warn(&dev->pdev->dev,
 				 "failed to copy back udata\n");
 			__pvrdma_destroy_qp(dev, qp);
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 		}
 	}
 
-	return &qp->ibqp;
+	return 0;
 
 err_pdir:
 	pvrdma_page_dir_cleanup(dev, &qp->pdir);
@@ -430,10 +423,8 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
 	ib_umem_release(qp->rumem);
 	ib_umem_release(qp->sumem);
 err_qp:
-	kfree(qp);
 	atomic_dec(&dev->num_qps);
-
-	return ERR_PTR(ret);
+	return ret;
 }
 
 static void _pvrdma_free_qp(struct pvrdma_qp *qp)
@@ -454,8 +445,6 @@ static void _pvrdma_free_qp(struct pvrdma_qp *qp)
 
 	pvrdma_page_dir_cleanup(dev, &qp->pdir);
 
-	kfree(qp);
-
 	atomic_dec(&dev->num_qps);
 }
 
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
index 544b94d97c3a..78807b23d831 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
@@ -390,9 +390,8 @@ int pvrdma_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 int pvrdma_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
 int pvrdma_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
 
-struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
-			       struct ib_qp_init_attr *init_attr,
-			       struct ib_udata *udata);
+int pvrdma_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
+		     struct ib_udata *udata);
 int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		     int attr_mask, struct ib_udata *udata);
 int pvrdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
index 14900860985c..da2d94a5a9c2 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -1058,7 +1058,7 @@ static int alloc_ud_wq_attr(struct rvt_qp *qp, int node)
 
 /**
  * rvt_create_qp - create a queue pair for a device
- * @ibpd: the protection domain who's device we create the queue pair for
+ * @ibqp: the queue pair
  * @init_attr: the attributes of the queue pair
  * @udata: user data for libibverbs.so
  *
@@ -1066,47 +1066,45 @@ static int alloc_ud_wq_attr(struct rvt_qp *qp, int node)
  * unique idea of what queue pair numbers mean. For instance there is a reserved
  * range for PSM.
  *
- * Return: the queue pair on success, otherwise returns an errno.
+ * Return: 0 on success, otherwise returns an errno.
  *
  * Called by the ib_create_qp() core verbs function.
  */
-struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
-			    struct ib_qp_init_attr *init_attr,
-			    struct ib_udata *udata)
+int rvt_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+		  struct ib_udata *udata)
 {
-	struct rvt_qp *qp;
-	int err;
+	struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);
+	int ret = -ENOMEM;
 	struct rvt_swqe *swq = NULL;
 	size_t sz;
 	size_t sg_list_sz = 0;
-	struct ib_qp *ret = ERR_PTR(-ENOMEM);
-	struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device);
+	struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device);
 	void *priv = NULL;
 	size_t sqsize;
 	u8 exclude_prefix = 0;
 
 	if (!rdi)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	if (init_attr->create_flags & ~IB_QP_CREATE_NETDEV_USE)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	if (init_attr->cap.max_send_sge > rdi->dparms.props.max_send_sge ||
 	    init_attr->cap.max_send_wr > rdi->dparms.props.max_qp_wr)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	/* Check receive queue parameters if no SRQ is specified. */
 	if (!init_attr->srq) {
 		if (init_attr->cap.max_recv_sge >
 		    rdi->dparms.props.max_recv_sge ||
 		    init_attr->cap.max_recv_wr > rdi->dparms.props.max_qp_wr)
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 
 		if (init_attr->cap.max_send_sge +
 		    init_attr->cap.max_send_wr +
 		    init_attr->cap.max_recv_sge +
 		    init_attr->cap.max_recv_wr == 0)
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 	}
 	sqsize =
 		init_attr->cap.max_send_wr + 1 +
@@ -1115,8 +1113,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:
 		if (init_attr->port_num == 0 ||
-		    init_attr->port_num > ibpd->device->phys_port_cnt)
-			return ERR_PTR(-EINVAL);
+		    init_attr->port_num > ibqp->device->phys_port_cnt)
+			return -EINVAL;
 		fallthrough;
 	case IB_QPT_UC:
 	case IB_QPT_RC:
@@ -1124,7 +1122,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		sz = struct_size(swq, sg_list, init_attr->cap.max_send_sge);
 		swq = vzalloc_node(array_size(sz, sqsize), rdi->dparms.node);
 		if (!swq)
-			return ERR_PTR(-ENOMEM);
+			return -ENOMEM;
 
 		if (init_attr->srq) {
 			struct rvt_srq *srq = ibsrq_to_rvtsrq(init_attr->srq);
@@ -1135,9 +1133,6 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		} else if (init_attr->cap.max_recv_sge > 1)
 			sg_list_sz = sizeof(*qp->r_sg_list) *
 				(init_attr->cap.max_recv_sge - 1);
-		qp = kzalloc_node(sizeof(*qp), GFP_KERNEL, rdi->dparms.node);
-		if (!qp)
-			goto bail_swq;
 		qp->r_sg_list =
 			kzalloc_node(sg_list_sz, GFP_KERNEL, rdi->dparms.node);
 		if (!qp->r_sg_list)
@@ -1166,7 +1161,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		 */
 		priv = rdi->driver_f.qp_priv_alloc(rdi, qp);
 		if (IS_ERR(priv)) {
-			ret = priv;
+			ret = PTR_ERR(priv);
 			goto bail_qp;
 		}
 		qp->priv = priv;
@@ -1180,12 +1175,10 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 			qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
 			sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) +
 				sizeof(struct rvt_rwqe);
-			err = rvt_alloc_rq(&qp->r_rq, qp->r_rq.size * sz,
+			ret = rvt_alloc_rq(&qp->r_rq, qp->r_rq.size * sz,
 					   rdi->dparms.node, udata);
-			if (err) {
-				ret = ERR_PTR(err);
+			if (ret)
 				goto bail_driver_priv;
-			}
 		}
 
 		/*
@@ -1206,40 +1199,35 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		qp->s_max_sge = init_attr->cap.max_send_sge;
 		if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR)
 			qp->s_flags = RVT_S_SIGNAL_REQ_WR;
-		err = alloc_ud_wq_attr(qp, rdi->dparms.node);
-		if (err) {
-			ret = (ERR_PTR(err));
+		ret = alloc_ud_wq_attr(qp, rdi->dparms.node);
+		if (ret)
 			goto bail_rq_rvt;
-		}
 
 		if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
 			exclude_prefix = RVT_AIP_QP_PREFIX;
 
-		err = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
+		ret = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
 				init_attr->qp_type,
 				init_attr->port_num,
 				exclude_prefix);
-		if (err < 0) {
-			ret = ERR_PTR(err);
+		if (ret < 0)
 			goto bail_rq_wq;
-		}
-		qp->ibqp.qp_num = err;
+
+		qp->ibqp.qp_num = ret;
 		if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
 			qp->ibqp.qp_num |= RVT_AIP_QP_BASE;
 		qp->port_num = init_attr->port_num;
 		rvt_init_qp(rdi, qp, init_attr->qp_type);
 		if (rdi->driver_f.qp_priv_init) {
-			err = rdi->driver_f.qp_priv_init(rdi, qp, init_attr);
-			if (err) {
-				ret = ERR_PTR(err);
+			ret = rdi->driver_f.qp_priv_init(rdi, qp, init_attr);
+			if (ret)
 				goto bail_rq_wq;
-			}
 		}
 		break;
 
 	default:
 		/* Don't support raw QPs */
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 	}
 
 	init_attr->cap.max_inline_data = 0;
@@ -1252,28 +1240,24 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		if (!qp->r_rq.wq) {
 			__u64 offset = 0;
 
-			err = ib_copy_to_udata(udata, &offset,
+			ret = ib_copy_to_udata(udata, &offset,
 					       sizeof(offset));
-			if (err) {
-				ret = ERR_PTR(err);
+			if (ret)
 				goto bail_qpn;
-			}
 		} else {
 			u32 s = sizeof(struct rvt_rwq) + qp->r_rq.size * sz;
 
 			qp->ip = rvt_create_mmap_info(rdi, s, udata,
 						      qp->r_rq.wq);
 			if (IS_ERR(qp->ip)) {
-				ret = ERR_CAST(qp->ip);
+				ret = PTR_ERR(qp->ip);
 				goto bail_qpn;
 			}
 
-			err = ib_copy_to_udata(udata, &qp->ip->offset,
+			ret = ib_copy_to_udata(udata, &qp->ip->offset,
 					       sizeof(qp->ip->offset));
-			if (err) {
-				ret = ERR_PTR(err);
+			if (ret)
 				goto bail_ip;
-			}
 		}
 		qp->pid = current->pid;
 	}
@@ -1281,7 +1265,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 	spin_lock(&rdi->n_qps_lock);
 	if (rdi->n_qps_allocated == rdi->dparms.props.max_qp) {
 		spin_unlock(&rdi->n_qps_lock);
-		ret = ERR_PTR(-ENOMEM);
+		ret = ENOMEM;
 		goto bail_ip;
 	}
 
@@ -1307,9 +1291,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 		spin_unlock_irq(&rdi->pending_lock);
 	}
 
-	ret = &qp->ibqp;
-
-	return ret;
+	return 0;
 
 bail_ip:
 	if (qp->ip)
@@ -1330,11 +1312,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
 bail_qp:
 	kfree(qp->s_ack_queue);
 	kfree(qp->r_sg_list);
-	kfree(qp);
-
-bail_swq:
 	vfree(swq);
-
 	return ret;
 }
 
@@ -1769,7 +1747,6 @@ int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 	rdma_destroy_ah_attr(&qp->alt_ah_attr);
 	free_ud_wq_attr(qp);
 	vfree(qp->s_wq);
-	kfree(qp);
 	return 0;
 }
 
diff --git a/drivers/infiniband/sw/rdmavt/qp.h b/drivers/infiniband/sw/rdmavt/qp.h
index 2cdba1283bf6..bceb77c28c71 100644
--- a/drivers/infiniband/sw/rdmavt/qp.h
+++ b/drivers/infiniband/sw/rdmavt/qp.h
@@ -52,9 +52,8 @@
 
 int rvt_driver_qp_init(struct rvt_dev_info *rdi);
 void rvt_qp_exit(struct rvt_dev_info *rdi);
-struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
-			    struct ib_qp_init_attr *init_attr,
-			    struct ib_udata *udata);
+int rvt_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
+		  struct ib_udata *udata);
 int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		  int attr_mask, struct ib_udata *udata);
 int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c
index ac17209816cd..d4526f38427e 100644
--- a/drivers/infiniband/sw/rdmavt/vt.c
+++ b/drivers/infiniband/sw/rdmavt/vt.c
@@ -131,6 +131,13 @@ static int rvt_query_device(struct ib_device *ibdev,
 	return 0;
 }
 
+static int rvt_get_numa_node(struct ib_device *ibdev)
+{
+	struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
+
+	return rdi->dparms.node;
+}
+
 static int rvt_modify_device(struct ib_device *device,
 			     int device_modify_mask,
 			     struct ib_device_modify *device_modify)
@@ -380,6 +387,7 @@ static const struct ib_device_ops rvt_dev_ops = {
 	.destroy_srq = rvt_destroy_srq,
 	.detach_mcast = rvt_detach_mcast,
 	.get_dma_mr = rvt_get_dma_mr,
+	.get_numa_node = rvt_get_numa_node,
 	.get_port_immutable = rvt_get_port_immutable,
 	.map_mr_sg = rvt_map_mr_sg,
 	.mmap = rvt_mmap,
@@ -406,6 +414,7 @@ static const struct ib_device_ops rvt_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, rvt_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, rvt_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, rvt_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, rvt_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, rvt_srq, ibsrq),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, rvt_ucontext, ibucontext),
 };
diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c
index 0b8e7c6255a2..ffa8420b4765 100644
--- a/drivers/infiniband/sw/rxe/rxe_pool.c
+++ b/drivers/infiniband/sw/rxe/rxe_pool.c
@@ -41,7 +41,7 @@ struct rxe_type_info rxe_type_info[RXE_NUM_TYPES] = {
 		.size		= sizeof(struct rxe_qp),
 		.elem_offset	= offsetof(struct rxe_qp, pelem),
 		.cleanup	= rxe_qp_cleanup,
-		.flags		= RXE_POOL_INDEX,
+		.flags		= RXE_POOL_INDEX | RXE_POOL_NO_ALLOC,
 		.min_index	= RXE_MIN_QP_INDEX,
 		.max_index	= RXE_MAX_QP_INDEX,
 	},
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index f7b1a1f64c13..267b5a9c345d 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -391,59 +391,52 @@ static int rxe_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
 	return err;
 }
 
-static struct ib_qp *rxe_create_qp(struct ib_pd *ibpd,
-				   struct ib_qp_init_attr *init,
-				   struct ib_udata *udata)
+static int rxe_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init,
+			 struct ib_udata *udata)
 {
 	int err;
-	struct rxe_dev *rxe = to_rdev(ibpd->device);
-	struct rxe_pd *pd = to_rpd(ibpd);
-	struct rxe_qp *qp;
+	struct rxe_dev *rxe = to_rdev(ibqp->device);
+	struct rxe_pd *pd = to_rpd(ibqp->pd);
+	struct rxe_qp *qp = to_rqp(ibqp);
 	struct rxe_create_qp_resp __user *uresp = NULL;
 
 	if (udata) {
 		if (udata->outlen < sizeof(*uresp))
-			return ERR_PTR(-EINVAL);
+			return -EINVAL;
 		uresp = udata->outbuf;
 	}
 
 	if (init->create_flags)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	err = rxe_qp_chk_init(rxe, init);
 	if (err)
-		goto err1;
-
-	qp = rxe_alloc(&rxe->qp_pool);
-	if (!qp) {
-		err = -ENOMEM;
-		goto err1;
-	}
+		return err;
 
 	if (udata) {
-		if (udata->inlen) {
-			err = -EINVAL;
-			goto err2;
-		}
+		if (udata->inlen)
+			return -EINVAL;
+
 		qp->is_user = true;
 	} else {
 		qp->is_user = false;
 	}
 
-	rxe_add_index(qp);
+	err = rxe_add_to_pool(&rxe->qp_pool, qp);
+	if (err)
+		return err;
 
-	err = rxe_qp_from_init(rxe, qp, pd, init, uresp, ibpd, udata);
+	rxe_add_index(qp);
+	err = rxe_qp_from_init(rxe, qp, pd, init, uresp, ibqp->pd, udata);
 	if (err)
-		goto err3;
+		goto qp_init;
 
-	return &qp->ibqp;
+	return 0;
 
-err3:
+qp_init:
 	rxe_drop_index(qp);
-err2:
 	rxe_drop_ref(qp);
-err1:
-	return ERR_PTR(err);
+	return err;
 }
 
 static int rxe_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
@@ -1145,6 +1138,7 @@ static const struct ib_device_ops rxe_dev_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_ah, rxe_ah, ibah),
 	INIT_RDMA_OBJ_SIZE(ib_cq, rxe_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, rxe_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, rxe_qp, ibqp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, rxe_srq, ibsrq),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, rxe_ucontext, ibuc),
 	INIT_RDMA_OBJ_SIZE(ib_mw, rxe_mw, ibmw),
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
index 959a3260fcab..ac2a2148027f 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.h
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -210,8 +210,8 @@ struct rxe_resp_info {
 };
 
 struct rxe_qp {
-	struct rxe_pool_entry	pelem;
 	struct ib_qp		ibqp;
+	struct rxe_pool_entry	pelem;
 	struct ib_qp_attr	attr;
 	unsigned int		valid;
 	unsigned int		mtu;
diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c
index cf55326f2ab4..9093e6a80b26 100644
--- a/drivers/infiniband/sw/siw/siw_main.c
+++ b/drivers/infiniband/sw/siw/siw_main.c
@@ -297,6 +297,7 @@ static const struct ib_device_ops siw_device_ops = {
 
 	INIT_RDMA_OBJ_SIZE(ib_cq, siw_cq, base_cq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, siw_pd, base_pd),
+	INIT_RDMA_OBJ_SIZE(ib_qp, siw_qp, base_qp),
 	INIT_RDMA_OBJ_SIZE(ib_srq, siw_srq, base_srq),
 	INIT_RDMA_OBJ_SIZE(ib_ucontext, siw_ucontext, base_ucontext),
 };
diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c
index ddb2e66f9f13..7e01f2438afc 100644
--- a/drivers/infiniband/sw/siw/siw_qp.c
+++ b/drivers/infiniband/sw/siw/siw_qp.c
@@ -1344,6 +1344,4 @@ void siw_free_qp(struct kref *ref)
 	siw_put_tx_cpu(qp->tx_cpu);
 
 	atomic_dec(&sdev->num_qp);
-	siw_dbg_qp(qp, "free QP\n");
-	kfree_rcu(qp, rcu);
 }
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
index 3f175f220a22..1b36350601fa 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -285,16 +285,16 @@ siw_mmap_entry_insert(struct siw_ucontext *uctx,
  *
  * Create QP of requested size on given device.
  *
- * @pd:		Protection Domain
+ * @qp:		Queue pait
  * @attrs:	Initial QP attributes.
  * @udata:	used to provide QP ID, SQ and RQ size back to user.
  */
 
-struct ib_qp *siw_create_qp(struct ib_pd *pd,
-			    struct ib_qp_init_attr *attrs,
-			    struct ib_udata *udata)
+int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
+		  struct ib_udata *udata)
 {
-	struct siw_qp *qp = NULL;
+	struct ib_pd *pd = ibqp->pd;
+	struct siw_qp *qp = to_siw_qp(ibqp);
 	struct ib_device *base_dev = pd->device;
 	struct siw_device *sdev = to_siw_dev(base_dev);
 	struct siw_ucontext *uctx =
@@ -307,17 +307,16 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
 	siw_dbg(base_dev, "create new QP\n");
 
 	if (attrs->create_flags)
-		return ERR_PTR(-EOPNOTSUPP);
+		return -EOPNOTSUPP;
 
 	if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) {
 		siw_dbg(base_dev, "too many QP's\n");
-		rv = -ENOMEM;
-		goto err_out;
+		return -ENOMEM;
 	}
 	if (attrs->qp_type != IB_QPT_RC) {
 		siw_dbg(base_dev, "only RC QP's supported\n");
 		rv = -EOPNOTSUPP;
-		goto err_out;
+		goto err_atomic;
 	}
 	if ((attrs->cap.max_send_wr > SIW_MAX_QP_WR) ||
 	    (attrs->cap.max_recv_wr > SIW_MAX_QP_WR) ||
@@ -325,13 +324,13 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
 	    (attrs->cap.max_recv_sge > SIW_MAX_SGE)) {
 		siw_dbg(base_dev, "QP size error\n");
 		rv = -EINVAL;
-		goto err_out;
+		goto err_atomic;
 	}
 	if (attrs->cap.max_inline_data > SIW_MAX_INLINE) {
 		siw_dbg(base_dev, "max inline send: %d > %d\n",
 			attrs->cap.max_inline_data, (int)SIW_MAX_INLINE);
 		rv = -EINVAL;
-		goto err_out;
+		goto err_atomic;
 	}
 	/*
 	 * NOTE: we allow for zero element SQ and RQ WQE's SGL's
@@ -340,19 +339,15 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
 	if (attrs->cap.max_send_wr + attrs->cap.max_recv_wr == 0) {
 		siw_dbg(base_dev, "QP must have send or receive queue\n");
 		rv = -EINVAL;
-		goto err_out;
+		goto err_atomic;
 	}
 
 	if (!attrs->send_cq || (!attrs->recv_cq && !attrs->srq)) {
 		siw_dbg(base_dev, "send CQ or receive CQ invalid\n");
 		rv = -EINVAL;
-		goto err_out;
-	}
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp) {
-		rv = -ENOMEM;
-		goto err_out;
+		goto err_atomic;
 	}
+
 	init_rwsem(&qp->state_lock);
 	spin_lock_init(&qp->sq_lock);
 	spin_lock_init(&qp->rq_lock);
@@ -360,7 +355,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
 
 	rv = siw_qp_add(sdev, qp);
 	if (rv)
-		goto err_out;
+		goto err_atomic;
 
 	num_sqe = attrs->cap.max_send_wr;
 	num_rqe = attrs->cap.max_recv_wr;
@@ -482,23 +477,20 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
 	list_add_tail(&qp->devq, &sdev->qp_list);
 	spin_unlock_irqrestore(&sdev->lock, flags);
 
-	return &qp->base_qp;
+	return 0;
 
 err_out_xa:
 	xa_erase(&sdev->qp_xa, qp_id(qp));
-err_out:
-	if (qp) {
-		if (uctx) {
-			rdma_user_mmap_entry_remove(qp->sq_entry);
-			rdma_user_mmap_entry_remove(qp->rq_entry);
-		}
-		vfree(qp->sendq);
-		vfree(qp->recvq);
-		kfree(qp);
+	if (uctx) {
+		rdma_user_mmap_entry_remove(qp->sq_entry);
+		rdma_user_mmap_entry_remove(qp->rq_entry);
 	}
-	atomic_dec(&sdev->num_qp);
+	vfree(qp->sendq);
+	vfree(qp->recvq);
 
-	return ERR_PTR(rv);
+err_atomic:
+	atomic_dec(&sdev->num_qp);
+	return rv;
 }
 
 /*
diff --git a/drivers/infiniband/sw/siw/siw_verbs.h b/drivers/infiniband/sw/siw/siw_verbs.h
index 67ac08886a70..09964234f8d3 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.h
+++ b/drivers/infiniband/sw/siw/siw_verbs.h
@@ -50,9 +50,8 @@ int siw_query_gid(struct ib_device *base_dev, u32 port, int idx,
 		  union ib_gid *gid);
 int siw_alloc_pd(struct ib_pd *base_pd, struct ib_udata *udata);
 int siw_dealloc_pd(struct ib_pd *base_pd, struct ib_udata *udata);
-struct ib_qp *siw_create_qp(struct ib_pd *base_pd,
-			    struct ib_qp_init_attr *attr,
-			    struct ib_udata *udata);
+int siw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attr,
+		  struct ib_udata *udata);
 int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr,
 		 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
 int siw_verbs_modify_qp(struct ib_qp *base_qp, struct ib_qp_attr *attr,
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 2dba30849731..8cd7d1fc719f 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2268,8 +2268,13 @@ struct iw_cm_conn_param;
 			 !__same_type(((struct drv_struct *)NULL)->member,     \
 				      struct ib_struct)))
 
-#define rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, gfp)                         \
-	((struct ib_type *)kzalloc(ib_dev->ops.size_##ib_type, gfp))
+#define rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, gfp)                          \
+	((struct ib_type *)rdma_zalloc_obj(ib_dev, ib_dev->ops.size_##ib_type, \
+					   gfp, false))
+
+#define rdma_zalloc_drv_obj_numa(ib_dev, ib_type)                              \
+	((struct ib_type *)rdma_zalloc_obj(ib_dev, ib_dev->ops.size_##ib_type, \
+					   GFP_KERNEL, true))
 
 #define rdma_zalloc_drv_obj(ib_dev, ib_type)                                   \
 	rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, GFP_KERNEL)
@@ -2435,9 +2440,8 @@ struct ib_device_ops {
 			  struct ib_udata *udata);
 	int (*query_srq)(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
 	int (*destroy_srq)(struct ib_srq *srq, struct ib_udata *udata);
-	struct ib_qp *(*create_qp)(struct ib_pd *pd,
-				   struct ib_qp_init_attr *qp_init_attr,
-				   struct ib_udata *udata);
+	int (*create_qp)(struct ib_qp *qp, struct ib_qp_init_attr *qp_init_attr,
+			 struct ib_udata *udata);
 	int (*modify_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
 			 int qp_attr_mask, struct ib_udata *udata);
 	int (*query_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
@@ -2635,11 +2639,18 @@ struct ib_device_ops {
 	int (*query_ucontext)(struct ib_ucontext *context,
 			      struct uverbs_attr_bundle *attrs);
 
+	/*
+	 * Provide NUMA node. This API exists for rdmavt/hfi1 only.
+	 * Everyone else relies on Linux memory management model.
+	 */
+	int (*get_numa_node)(struct ib_device *dev);
+
 	DECLARE_RDMA_OBJ_SIZE(ib_ah);
 	DECLARE_RDMA_OBJ_SIZE(ib_counters);
 	DECLARE_RDMA_OBJ_SIZE(ib_cq);
 	DECLARE_RDMA_OBJ_SIZE(ib_mw);
 	DECLARE_RDMA_OBJ_SIZE(ib_pd);
+	DECLARE_RDMA_OBJ_SIZE(ib_qp);
 	DECLARE_RDMA_OBJ_SIZE(ib_rwq_ind_table);
 	DECLARE_RDMA_OBJ_SIZE(ib_srq);
 	DECLARE_RDMA_OBJ_SIZE(ib_ucontext);
@@ -2746,6 +2757,15 @@ struct ib_device {
 	u32 lag_flags;
 };
 
+static inline void *rdma_zalloc_obj(struct ib_device *dev, size_t size,
+				    gfp_t gfp, bool is_numa_aware)
+{
+	if (is_numa_aware && dev->ops.get_numa_node)
+		return kzalloc_node(size, gfp, dev->ops.get_numa_node(dev));
+
+	return kzalloc(size, gfp);
+}
+
 struct ib_client_nl_info;
 struct ib_client {
 	const char *name;
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH rdma-next v1 9/9] RDMA/mlx5: Drop in-driver verbs object creations
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
                   ` (7 preceding siblings ...)
  2021-07-23 11:39 ` [PATCH rdma-next v1 8/9] RDMA: Globally allocate and release QP memory Leon Romanovsky
@ 2021-07-23 11:39 ` Leon Romanovsky
  2021-08-03 17:22 ` [PATCH rdma-next v1 0/9] QP allocation changes Jason Gunthorpe
  9 siblings, 0 replies; 12+ messages in thread
From: Leon Romanovsky @ 2021-07-23 11:39 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Mustafa Ismail, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Shiraz Saleem, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun

From: Leon Romanovsky <leonro@nvidia.com>

There is no real value in bypassing IB/core APIs for creating standard
objects with standard types. The open-coded variant didn't have any
restrack task management calls and caused to such objects to be not
present when running rdmatoool.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
 drivers/infiniband/core/verbs.c   |  7 ++-
 drivers/infiniband/hw/mlx5/main.c | 92 +++++++------------------------
 2 files changed, 25 insertions(+), 74 deletions(-)

diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index a164609c2ee7..89c6987cb5eb 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1035,7 +1035,8 @@ struct ib_srq *ib_create_srq_user(struct ib_pd *pd,
 	}
 	if (srq->srq_type == IB_SRQT_XRC) {
 		srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
-		atomic_inc(&srq->ext.xrc.xrcd->usecnt);
+		if (srq->ext.xrc.xrcd)
+			atomic_inc(&srq->ext.xrc.xrcd->usecnt);
 	}
 	atomic_inc(&pd->usecnt);
 
@@ -1046,7 +1047,7 @@ struct ib_srq *ib_create_srq_user(struct ib_pd *pd,
 	if (ret) {
 		rdma_restrack_put(&srq->res);
 		atomic_dec(&srq->pd->usecnt);
-		if (srq->srq_type == IB_SRQT_XRC)
+		if (srq->srq_type == IB_SRQT_XRC && srq->ext.xrc.xrcd)
 			atomic_dec(&srq->ext.xrc.xrcd->usecnt);
 		if (ib_srq_has_cq(srq->srq_type))
 			atomic_dec(&srq->ext.cq->usecnt);
@@ -1090,7 +1091,7 @@ int ib_destroy_srq_user(struct ib_srq *srq, struct ib_udata *udata)
 		return ret;
 
 	atomic_dec(&srq->pd->usecnt);
-	if (srq->srq_type == IB_SRQT_XRC)
+	if (srq->srq_type == IB_SRQT_XRC && srq->ext.xrc.xrcd)
 		atomic_dec(&srq->ext.xrc.xrcd->usecnt);
 	if (ib_srq_has_cq(srq->srq_type))
 		atomic_dec(&srq->ext.cq->usecnt);
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 7a6bafc19c9b..fbed9e4241e1 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -2802,31 +2802,16 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
 	if (!MLX5_CAP_GEN(dev->mdev, xrc))
 		return -EOPNOTSUPP;
 
-	devr->p0 = rdma_zalloc_drv_obj(ibdev, ib_pd);
-	if (!devr->p0)
-		return -ENOMEM;
-
-	devr->p0->device  = ibdev;
-	devr->p0->uobject = NULL;
-	atomic_set(&devr->p0->usecnt, 0);
+	devr->p0 = ib_alloc_pd(ibdev, 0);
+	if (IS_ERR(devr->p0))
+		return PTR_ERR(devr->p0);
 
-	ret = mlx5_ib_alloc_pd(devr->p0, NULL);
-	if (ret)
-		goto error0;
-
-	devr->c0 = rdma_zalloc_drv_obj(ibdev, ib_cq);
-	if (!devr->c0) {
-		ret = -ENOMEM;
+	devr->c0 = ib_create_cq(ibdev, NULL, NULL, NULL, &cq_attr);
+	if (IS_ERR(devr->c0)) {
+		ret = PTR_ERR(devr->c0);
 		goto error1;
 	}
 
-	devr->c0->device = &dev->ib_dev;
-	atomic_set(&devr->c0->usecnt, 0);
-
-	ret = mlx5_ib_create_cq(devr->c0, &cq_attr, NULL);
-	if (ret)
-		goto err_create_cq;
-
 	ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn0, 0);
 	if (ret)
 		goto error2;
@@ -2841,45 +2826,22 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
 	attr.srq_type = IB_SRQT_XRC;
 	attr.ext.cq = devr->c0;
 
-	devr->s0 = rdma_zalloc_drv_obj(ibdev, ib_srq);
-	if (!devr->s0) {
-		ret = -ENOMEM;
-		goto error4;
-	}
-
-	devr->s0->device	= &dev->ib_dev;
-	devr->s0->pd		= devr->p0;
-	devr->s0->srq_type      = IB_SRQT_XRC;
-	devr->s0->ext.cq	= devr->c0;
-	ret = mlx5_ib_create_srq(devr->s0, &attr, NULL);
-	if (ret)
+	devr->s0 = ib_create_srq(devr->p0, &attr);
+	if (IS_ERR(devr->s0)) {
+		ret = PTR_ERR(devr->s0);
 		goto err_create;
-
-	atomic_inc(&devr->s0->ext.cq->usecnt);
-	atomic_inc(&devr->p0->usecnt);
-	atomic_set(&devr->s0->usecnt, 0);
+	}
 
 	memset(&attr, 0, sizeof(attr));
 	attr.attr.max_sge = 1;
 	attr.attr.max_wr = 1;
 	attr.srq_type = IB_SRQT_BASIC;
-	devr->s1 = rdma_zalloc_drv_obj(ibdev, ib_srq);
-	if (!devr->s1) {
-		ret = -ENOMEM;
-		goto error5;
-	}
-
-	devr->s1->device	= &dev->ib_dev;
-	devr->s1->pd		= devr->p0;
-	devr->s1->srq_type      = IB_SRQT_BASIC;
-	devr->s1->ext.cq	= devr->c0;
 
-	ret = mlx5_ib_create_srq(devr->s1, &attr, NULL);
-	if (ret)
+	devr->s1 = ib_create_srq(devr->p0, &attr);
+	if (IS_ERR(devr->s1)) {
+		ret = PTR_ERR(devr->s1);
 		goto error6;
-
-	atomic_inc(&devr->p0->usecnt);
-	atomic_set(&devr->s1->usecnt, 0);
+	}
 
 	for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
 		INIT_WORK(&devr->ports[port].pkey_change_work,
@@ -2888,23 +2850,15 @@ static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)
 	return 0;
 
 error6:
-	kfree(devr->s1);
-error5:
-	mlx5_ib_destroy_srq(devr->s0, NULL);
+	ib_destroy_srq(devr->s0);
 err_create:
-	kfree(devr->s0);
-error4:
 	mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);
 error3:
 	mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
 error2:
-	mlx5_ib_destroy_cq(devr->c0, NULL);
-err_create_cq:
-	kfree(devr->c0);
+	ib_destroy_cq(devr->c0);
 error1:
-	mlx5_ib_dealloc_pd(devr->p0, NULL);
-error0:
-	kfree(devr->p0);
+	ib_dealloc_pd(devr->p0);
 	return ret;
 }
 
@@ -2922,16 +2876,12 @@ static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)
 	for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)
 		cancel_work_sync(&devr->ports[port].pkey_change_work);
 
-	mlx5_ib_destroy_srq(devr->s1, NULL);
-	kfree(devr->s1);
-	mlx5_ib_destroy_srq(devr->s0, NULL);
-	kfree(devr->s0);
+	ib_destroy_srq(devr->s1);
+	ib_destroy_srq(devr->s0);
 	mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);
 	mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);
-	mlx5_ib_destroy_cq(devr->c0, NULL);
-	kfree(devr->c0);
-	mlx5_ib_dealloc_pd(devr->p0, NULL);
-	kfree(devr->p0);
+	ib_destroy_cq(devr->c0);
+	ib_dealloc_pd(devr->p0);
 }
 
 static u32 get_core_cap_flags(struct ib_device *ibdev,
-- 
2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH rdma-next v1 8/9] RDMA: Globally allocate and release QP memory
  2021-07-23 11:39 ` [PATCH rdma-next v1 8/9] RDMA: Globally allocate and release QP memory Leon Romanovsky
@ 2021-07-29 20:20   ` Nikolova, Tatyana E
  0 siblings, 0 replies; 12+ messages in thread
From: Nikolova, Tatyana E @ 2021-07-29 20:20 UTC (permalink / raw)
  To: Leon Romanovsky, Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, Adit Ranadive, Ariel Elior, Bernard Metzler,
	Christian Benvenuti, Dennis Dalessandro, Gal Pressman,
	linux-kernel, linux-rdma, Michal Kalderon, Mike Marciniszyn,
	Ismail, Mustafa, Naresh Kumar PBS, Nelson Escobar,
	Potnuri Bharat Teja, Selvin Xavier, Saleem, Shiraz, Steve Wise,
	VMware PV-Drivers, Weihang Li, Wenpeng Liang, Yishai Hadas,
	Zhu Yanjun



> -----Original Message-----
> From: Leon Romanovsky <leon@kernel.org>
> Sent: Friday, July 23, 2021 6:40 AM
> To: Doug Ledford <dledford@redhat.com>; Jason Gunthorpe
> <jgg@nvidia.com>
> Cc: Leon Romanovsky <leonro@nvidia.com>; Adit Ranadive
> <aditr@vmware.com>; Ariel Elior <aelior@marvell.com>; Bernard Metzler
> <bmt@zurich.ibm.com>; Christian Benvenuti <benve@cisco.com>; Dennis
> Dalessandro <dennis.dalessandro@cornelisnetworks.com>; Gal Pressman
> <galpress@amazon.com>; linux-kernel@vger.kernel.org; linux-
> rdma@vger.kernel.org; Michal Kalderon <mkalderon@marvell.com>; Mike
> Marciniszyn <mike.marciniszyn@cornelisnetworks.com>; Ismail, Mustafa
> <mustafa.ismail@intel.com>; Naresh Kumar PBS
> <nareshkumar.pbs@broadcom.com>; Nelson Escobar
> <neescoba@cisco.com>; Potnuri Bharat Teja <bharat@chelsio.com>; Selvin
> Xavier <selvin.xavier@broadcom.com>; Saleem, Shiraz
> <shiraz.saleem@intel.com>; Steve Wise <larrystevenwise@gmail.com>;
> VMware PV-Drivers <pv-drivers@vmware.com>; Weihang Li
> <liweihang@huawei.com>; Wenpeng Liang <liangwenpeng@huawei.com>;
> Yishai Hadas <yishaih@nvidia.com>; Zhu Yanjun <zyjzyj2000@gmail.com>
> Subject: [PATCH rdma-next v1 8/9] RDMA: Globally allocate and release QP
> memory
> 
> From: Leon Romanovsky <leonro@nvidia.com>
> 
> Convert QP object to follow IB/core general allocation scheme.
> That change allows us to make sure that restrack properly kref
> the memory.
> 
> Reviewed-by: Gal Pressman <galpress@amazon.com> #efa
> Tested-by: Gal Pressman <galpress@amazon.com>
> Reviewed-by: Dennis Dalessandro
> <dennis.dalessandro@cornelisnetworks.com> #rdma and core
> Tested-by: Dennis Dalessandro
> <dennis.dalessandro@cornelisnetworks.com>
> Signed-off-by: Leon Romanovsky <leonro@nvidia.com

Hi Leon,

I tested your changes with the irdma driver.

Tested-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>



> ---
>  drivers/infiniband/core/core_priv.h           | 28 ++++--
>  drivers/infiniband/core/device.c              |  2 +
>  drivers/infiniband/core/restrack.c            |  2 +-
>  drivers/infiniband/core/verbs.c               | 40 ++++----
>  drivers/infiniband/hw/bnxt_re/ib_verbs.c      | 26 ++----
>  drivers/infiniband/hw/bnxt_re/ib_verbs.h      |  7 +-
>  drivers/infiniband/hw/bnxt_re/main.c          |  1 +
>  drivers/infiniband/hw/cxgb4/iw_cxgb4.h        |  5 +-
>  drivers/infiniband/hw/cxgb4/provider.c        |  1 +
>  drivers/infiniband/hw/cxgb4/qp.c              | 37 +++-----
>  drivers/infiniband/hw/efa/efa.h               |  5 +-
>  drivers/infiniband/hw/efa/efa_main.c          |  1 +
>  drivers/infiniband/hw/efa/efa_verbs.c         | 28 ++----
>  drivers/infiniband/hw/hns/hns_roce_device.h   |  5 +-
>  drivers/infiniband/hw/hns/hns_roce_main.c     |  1 +
>  drivers/infiniband/hw/hns/hns_roce_qp.c       | 28 ++----
>  drivers/infiniband/hw/irdma/utils.c           |  3 -
>  drivers/infiniband/hw/irdma/verbs.c           | 31 +++----
>  drivers/infiniband/hw/mlx4/main.c             |  1 +
>  drivers/infiniband/hw/mlx4/mlx4_ib.h          |  5 +-
>  drivers/infiniband/hw/mlx4/qp.c               | 25 ++---
>  drivers/infiniband/hw/mlx5/gsi.c              |  2 -
>  drivers/infiniband/hw/mlx5/main.c             |  1 +
>  drivers/infiniband/hw/mlx5/mlx5_ib.h          |  5 +-
>  drivers/infiniband/hw/mlx5/qp.c               | 56 ++++--------
>  drivers/infiniband/hw/mthca/mthca_provider.c  | 77 ++++++----------
>  drivers/infiniband/hw/ocrdma/ocrdma_main.c    |  1 +
>  drivers/infiniband/hw/ocrdma/ocrdma_verbs.c   | 25 ++---
>  drivers/infiniband/hw/ocrdma/ocrdma_verbs.h   |  5 +-
>  drivers/infiniband/hw/qedr/main.c             |  1 +
>  drivers/infiniband/hw/qedr/qedr_roce_cm.c     | 13 ++-
>  drivers/infiniband/hw/qedr/qedr_roce_cm.h     |  5 +-
>  drivers/infiniband/hw/qedr/verbs.c            | 49 +++-------
>  drivers/infiniband/hw/qedr/verbs.h            |  4 +-
>  drivers/infiniband/hw/usnic/usnic_ib_main.c   |  1 +
>  drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c | 34 +++----
>  drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h | 10 +-
>  drivers/infiniband/hw/usnic/usnic_ib_verbs.c  | 69 +++++++-------
>  drivers/infiniband/hw/usnic/usnic_ib_verbs.h  |  5 +-
>  .../infiniband/hw/vmw_pvrdma/pvrdma_main.c    |  1 +
>  drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c  | 53 +++++------
>  .../infiniband/hw/vmw_pvrdma/pvrdma_verbs.h   |  5 +-
>  drivers/infiniband/sw/rdmavt/qp.c             | 91 +++++++------------
>  drivers/infiniband/sw/rdmavt/qp.h             |  5 +-
>  drivers/infiniband/sw/rdmavt/vt.c             |  9 ++
>  drivers/infiniband/sw/rxe/rxe_pool.c          |  2 +-
>  drivers/infiniband/sw/rxe/rxe_verbs.c         | 48 +++++-----
>  drivers/infiniband/sw/rxe/rxe_verbs.h         |  2 +-
>  drivers/infiniband/sw/siw/siw_main.c          |  1 +
>  drivers/infiniband/sw/siw/siw_qp.c            |  2 -
>  drivers/infiniband/sw/siw/siw_verbs.c         | 54 +++++------
>  drivers/infiniband/sw/siw/siw_verbs.h         |  5 +-
>  include/rdma/ib_verbs.h                       | 30 +++++-
>  53 files changed, 404 insertions(+), 549 deletions(-)
> 
> diff --git a/drivers/infiniband/core/core_priv.h
> b/drivers/infiniband/core/core_priv.h
> index 647cca4e0240..fa2e0bbaf8c7 100644
> --- a/drivers/infiniband/core/core_priv.h
> +++ b/drivers/infiniband/core/core_priv.h
> @@ -322,13 +322,14 @@ _ib_create_qp(struct ib_device *dev, struct ib_pd
> *pd,
>  	      struct ib_uqp_object *uobj, const char *caller)
>  {
>  	struct ib_qp *qp;
> +	int ret;
> 
>  	if (!dev->ops.create_qp)
>  		return ERR_PTR(-EOPNOTSUPP);
> 
> -	qp = dev->ops.create_qp(pd, attr, udata);
> -	if (IS_ERR(qp))
> -		return qp;
> +	qp = rdma_zalloc_drv_obj_numa(dev, ib_qp);
> +	if (!qp)
> +		return ERR_PTR(-ENOMEM);
> 
>  	qp->device = dev;
>  	qp->pd = pd;
> @@ -337,14 +338,10 @@ _ib_create_qp(struct ib_device *dev, struct ib_pd
> *pd,
> 
>  	qp->qp_type = attr->qp_type;
>  	qp->rwq_ind_tbl = attr->rwq_ind_tbl;
> -	qp->send_cq = attr->send_cq;
> -	qp->recv_cq = attr->recv_cq;
>  	qp->srq = attr->srq;
> -	qp->rwq_ind_tbl = attr->rwq_ind_tbl;
>  	qp->event_handler = attr->event_handler;
>  	qp->port = attr->port_num;
> 
> -	atomic_set(&qp->usecnt, 0);
>  	spin_lock_init(&qp->mr_lock);
>  	INIT_LIST_HEAD(&qp->rdma_mrs);
>  	INIT_LIST_HEAD(&qp->sig_mrs);
> @@ -352,8 +349,25 @@ _ib_create_qp(struct ib_device *dev, struct ib_pd
> *pd,
>  	rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
>  	WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
>  	rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
> +	ret = dev->ops.create_qp(qp, attr, udata);
> +	if (ret)
> +		goto err_create;
> +
> +	/*
> +	 * TODO: The mlx4 internally overwrites send_cq and recv_cq.
> +	 * Unfortunately, it is not an easy task to fix that driver.
> +	 */
> +	qp->send_cq = attr->send_cq;
> +	qp->recv_cq = attr->recv_cq;
> +
>  	rdma_restrack_add(&qp->res);
>  	return qp;
> +
> +err_create:
> +	rdma_restrack_put(&qp->res);
> +	kfree(qp);
> +	return ERR_PTR(ret);
> +
>  }
> 
>  struct rdma_dev_addr;
> diff --git a/drivers/infiniband/core/device.c
> b/drivers/infiniband/core/device.c
> index 9056f48bdca6..f4814bb7f082 100644
> --- a/drivers/infiniband/core/device.c
> +++ b/drivers/infiniband/core/device.c
> @@ -2654,6 +2654,7 @@ void ib_set_device_ops(struct ib_device *dev,
> const struct ib_device_ops *ops)
>  	SET_DEVICE_OP(dev_ops, get_hw_stats);
>  	SET_DEVICE_OP(dev_ops, get_link_layer);
>  	SET_DEVICE_OP(dev_ops, get_netdev);
> +	SET_DEVICE_OP(dev_ops, get_numa_node);
>  	SET_DEVICE_OP(dev_ops, get_port_immutable);
>  	SET_DEVICE_OP(dev_ops, get_vector_affinity);
>  	SET_DEVICE_OP(dev_ops, get_vf_config);
> @@ -2710,6 +2711,7 @@ void ib_set_device_ops(struct ib_device *dev,
> const struct ib_device_ops *ops)
>  	SET_OBJ_SIZE(dev_ops, ib_cq);
>  	SET_OBJ_SIZE(dev_ops, ib_mw);
>  	SET_OBJ_SIZE(dev_ops, ib_pd);
> +	SET_OBJ_SIZE(dev_ops, ib_qp);
>  	SET_OBJ_SIZE(dev_ops, ib_rwq_ind_table);
>  	SET_OBJ_SIZE(dev_ops, ib_srq);
>  	SET_OBJ_SIZE(dev_ops, ib_ucontext);
> diff --git a/drivers/infiniband/core/restrack.c
> b/drivers/infiniband/core/restrack.c
> index 033207882c82..1f935d9f6178 100644
> --- a/drivers/infiniband/core/restrack.c
> +++ b/drivers/infiniband/core/restrack.c
> @@ -343,7 +343,7 @@ void rdma_restrack_del(struct rdma_restrack_entry
> *res)
>  	rt = &dev->res[res->type];
> 
>  	old = xa_erase(&rt->xa, res->id);
> -	if (res->type == RDMA_RESTRACK_MR || res->type ==
> RDMA_RESTRACK_QP)
> +	if (res->type == RDMA_RESTRACK_MR)
>  		return;
>  	WARN_ON(old != res);
> 
> diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
> index 7036967e4c0b..a164609c2ee7 100644
> --- a/drivers/infiniband/core/verbs.c
> +++ b/drivers/infiniband/core/verbs.c
> @@ -1963,30 +1963,32 @@ int ib_destroy_qp_user(struct ib_qp *qp, struct
> ib_udata *udata)
>  		rdma_rw_cleanup_mrs(qp);
> 
>  	rdma_counter_unbind_qp(qp, true);
> -	rdma_restrack_del(&qp->res);
>  	ret = qp->device->ops.destroy_qp(qp, udata);
> -	if (!ret) {
> -		if (alt_path_sgid_attr)
> -			rdma_put_gid_attr(alt_path_sgid_attr);
> -		if (av_sgid_attr)
> -			rdma_put_gid_attr(av_sgid_attr);
> -		if (pd)
> -			atomic_dec(&pd->usecnt);
> -		if (scq)
> -			atomic_dec(&scq->usecnt);
> -		if (rcq)
> -			atomic_dec(&rcq->usecnt);
> -		if (srq)
> -			atomic_dec(&srq->usecnt);
> -		if (ind_tbl)
> -			atomic_dec(&ind_tbl->usecnt);
> -		if (sec)
> -			ib_destroy_qp_security_end(sec);
> -	} else {
> +	if (ret) {
>  		if (sec)
>  			ib_destroy_qp_security_abort(sec);
> +		return ret;
>  	}
> 
> +	if (alt_path_sgid_attr)
> +		rdma_put_gid_attr(alt_path_sgid_attr);
> +	if (av_sgid_attr)
> +		rdma_put_gid_attr(av_sgid_attr);
> +	if (pd)
> +		atomic_dec(&pd->usecnt);
> +	if (scq)
> +		atomic_dec(&scq->usecnt);
> +	if (rcq)
> +		atomic_dec(&rcq->usecnt);
> +	if (srq)
> +		atomic_dec(&srq->usecnt);
> +	if (ind_tbl)
> +		atomic_dec(&ind_tbl->usecnt);
> +	if (sec)
> +		ib_destroy_qp_security_end(sec);
> +
> +	rdma_restrack_del(&qp->res);
> +	kfree(qp);
>  	return ret;
>  }
>  EXPORT_SYMBOL(ib_destroy_qp_user);
> diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> index 283b6b81563c..634d1586a1fa 100644
> --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> @@ -815,7 +815,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct
> ib_udata *udata)
>  	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
>  		rc = bnxt_re_destroy_gsi_sqp(qp);
>  		if (rc)
> -			goto sh_fail;
> +			return rc;
>  	}
> 
>  	mutex_lock(&rdev->qp_lock);
> @@ -826,10 +826,7 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct
> ib_udata *udata)
>  	ib_umem_release(qp->rumem);
>  	ib_umem_release(qp->sumem);
> 
> -	kfree(qp);
>  	return 0;
> -sh_fail:
> -	return rc;
>  }
> 
>  static u8 __from_ib_qp_type(enum ib_qp_type type)
> @@ -1402,27 +1399,22 @@ static bool bnxt_re_test_qp_limits(struct
> bnxt_re_dev *rdev,
>  	return rc;
>  }
> 
> -struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
> -				struct ib_qp_init_attr *qp_init_attr,
> -				struct ib_udata *udata)
> +int bnxt_re_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr
> *qp_init_attr,
> +		      struct ib_udata *udata)
>  {
> +	struct ib_pd *ib_pd = ib_qp->pd;
>  	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd,
> ib_pd);
>  	struct bnxt_re_dev *rdev = pd->rdev;
>  	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
> -	struct bnxt_re_qp *qp;
> +	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp,
> ib_qp);
>  	int rc;
> 
>  	rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr);
>  	if (!rc) {
>  		rc = -EINVAL;
> -		goto exit;
> +		goto fail;
>  	}
> 
> -	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -	if (!qp) {
> -		rc = -ENOMEM;
> -		goto exit;
> -	}
>  	qp->rdev = rdev;
>  	rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata);
>  	if (rc)
> @@ -1465,16 +1457,14 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd
> *ib_pd,
>  	mutex_unlock(&rdev->qp_lock);
>  	atomic_inc(&rdev->qp_count);
> 
> -	return &qp->ib_qp;
> +	return 0;
>  qp_destroy:
>  	bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
>  free_umem:
>  	ib_umem_release(qp->rumem);
>  	ib_umem_release(qp->sumem);
>  fail:
> -	kfree(qp);
> -exit:
> -	return ERR_PTR(rc);
> +	return rc;
>  }
> 
>  static u8 __from_ib_qp_state(enum ib_qp_state state)
> diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
> b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
> index d68671cc6173..b5c6e0f4f877 100644
> --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
> +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
> @@ -78,9 +78,9 @@ struct bnxt_re_srq {
>  };
> 
>  struct bnxt_re_qp {
> +	struct ib_qp		ib_qp;
>  	struct list_head	list;
>  	struct bnxt_re_dev	*rdev;
> -	struct ib_qp		ib_qp;
>  	spinlock_t		sq_lock;	/* protect sq */
>  	spinlock_t		rq_lock;	/* protect rq */
>  	struct bnxt_qplib_qp	qplib_qp;
> @@ -179,9 +179,8 @@ int bnxt_re_query_srq(struct ib_srq *srq, struct
> ib_srq_attr *srq_attr);
>  int bnxt_re_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
>  int bnxt_re_post_srq_recv(struct ib_srq *srq, const struct ib_recv_wr
> *recv_wr,
>  			  const struct ib_recv_wr **bad_recv_wr);
> -struct ib_qp *bnxt_re_create_qp(struct ib_pd *pd,
> -				struct ib_qp_init_attr *qp_init_attr,
> -				struct ib_udata *udata);
> +int bnxt_re_create_qp(struct ib_qp *qp, struct ib_qp_init_attr
> *qp_init_attr,
> +		      struct ib_udata *udata);
>  int bnxt_re_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
>  		      int qp_attr_mask, struct ib_udata *udata);
>  int bnxt_re_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
> diff --git a/drivers/infiniband/hw/bnxt_re/main.c
> b/drivers/infiniband/hw/bnxt_re/main.c
> index d5674026512a..3edf66818e4b 100644
> --- a/drivers/infiniband/hw/bnxt_re/main.c
> +++ b/drivers/infiniband/hw/bnxt_re/main.c
> @@ -709,6 +709,7 @@ static const struct ib_device_ops bnxt_re_dev_ops =
> {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, bnxt_re_ah, ib_ah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, bnxt_re_cq, ib_cq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, bnxt_re_pd, ib_pd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, bnxt_re_qp, ib_qp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, bnxt_re_srq, ib_srq),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, bnxt_re_ucontext, ib_uctx),
>  };
> diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
> b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
> index 3883af3d2312..6a2a415ec791 100644
> --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
> +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
> @@ -989,9 +989,8 @@ int c4iw_destroy_srq(struct ib_srq *ib_srq, struct
> ib_udata *udata);
>  int c4iw_create_srq(struct ib_srq *srq, struct ib_srq_init_attr *attrs,
>  		    struct ib_udata *udata);
>  int c4iw_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata);
> -struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
> -			     struct ib_qp_init_attr *attrs,
> -			     struct ib_udata *udata);
> +int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
> +		   struct ib_udata *udata);
>  int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
>  				 int attr_mask, struct ib_udata *udata);
>  int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
> diff --git a/drivers/infiniband/hw/cxgb4/provider.c
> b/drivers/infiniband/hw/cxgb4/provider.c
> index 881d515eb15a..e7337662aff8 100644
> --- a/drivers/infiniband/hw/cxgb4/provider.c
> +++ b/drivers/infiniband/hw/cxgb4/provider.c
> @@ -499,6 +499,7 @@ static const struct ib_device_ops c4iw_dev_ops = {
>  	INIT_RDMA_OBJ_SIZE(ib_cq, c4iw_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_mw, c4iw_mw, ibmw),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, c4iw_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, c4iw_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, c4iw_srq, ibsrq),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, c4iw_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/cxgb4/qp.c
> b/drivers/infiniband/hw/cxgb4/qp.c
> index a81fa7a56edb..d20b4ef2c853 100644
> --- a/drivers/infiniband/hw/cxgb4/qp.c
> +++ b/drivers/infiniband/hw/cxgb4/qp.c
> @@ -2103,16 +2103,15 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp, struct
> ib_udata *udata)
>  		   ucontext ? &ucontext->uctx : &rhp->rdev.uctx, !qhp->srq);
> 
>  	c4iw_put_wr_wait(qhp->wr_waitp);
> -
> -	kfree(qhp);
>  	return 0;
>  }
> 
> -struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr
> *attrs,
> -			     struct ib_udata *udata)
> +int c4iw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
> +		   struct ib_udata *udata)
>  {
> +	struct ib_pd *pd = qp->pd;
>  	struct c4iw_dev *rhp;
> -	struct c4iw_qp *qhp;
> +	struct c4iw_qp *qhp = to_c4iw_qp(qp);
>  	struct c4iw_pd *php;
>  	struct c4iw_cq *schp;
>  	struct c4iw_cq *rchp;
> @@ -2124,44 +2123,36 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
> struct ib_qp_init_attr *attrs,
>  	struct c4iw_mm_entry *sq_key_mm, *rq_key_mm = NULL,
> *sq_db_key_mm;
>  	struct c4iw_mm_entry *rq_db_key_mm = NULL,
> *ma_sync_key_mm = NULL;
> 
> -	pr_debug("ib_pd %p\n", pd);
> -
>  	if (attrs->qp_type != IB_QPT_RC || attrs->create_flags)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
>  	php = to_c4iw_pd(pd);
>  	rhp = php->rhp;
>  	schp = get_chp(rhp, ((struct c4iw_cq *)attrs->send_cq)->cq.cqid);
>  	rchp = get_chp(rhp, ((struct c4iw_cq *)attrs->recv_cq)->cq.cqid);
>  	if (!schp || !rchp)
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
> 
>  	if (attrs->cap.max_inline_data > T4_MAX_SEND_INLINE)
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
> 
>  	if (!attrs->srq) {
>  		if (attrs->cap.max_recv_wr > rhp-
> >rdev.hw_queue.t4_max_rq_size)
> -			return ERR_PTR(-E2BIG);
> +			return -E2BIG;
>  		rqsize = attrs->cap.max_recv_wr + 1;
>  		if (rqsize < 8)
>  			rqsize = 8;
>  	}
> 
>  	if (attrs->cap.max_send_wr > rhp-
> >rdev.hw_queue.t4_max_sq_size)
> -		return ERR_PTR(-E2BIG);
> +		return -E2BIG;
>  	sqsize = attrs->cap.max_send_wr + 1;
>  	if (sqsize < 8)
>  		sqsize = 8;
> 
> -	qhp = kzalloc(sizeof(*qhp), GFP_KERNEL);
> -	if (!qhp)
> -		return ERR_PTR(-ENOMEM);
> -
>  	qhp->wr_waitp = c4iw_alloc_wr_wait(GFP_KERNEL);
> -	if (!qhp->wr_waitp) {
> -		ret = -ENOMEM;
> -		goto err_free_qhp;
> -	}
> +	if (!qhp->wr_waitp)
> +		return -ENOMEM;
> 
>  	qhp->wq.sq.size = sqsize;
>  	qhp->wq.sq.memsize =
> @@ -2339,7 +2330,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
> struct ib_qp_init_attr *attrs,
>  		 qhp->wq.sq.qid, qhp->wq.sq.size, qhp->wq.sq.memsize,
>  		 attrs->cap.max_send_wr, qhp->wq.rq.qid, qhp->wq.rq.size,
>  		 qhp->wq.rq.memsize, attrs->cap.max_recv_wr);
> -	return &qhp->ibqp;
> +	return 0;
>  err_free_ma_sync_key:
>  	kfree(ma_sync_key_mm);
>  err_free_rq_db_key:
> @@ -2359,9 +2350,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
> struct ib_qp_init_attr *attrs,
>  		   ucontext ? &ucontext->uctx : &rhp->rdev.uctx, !attrs->srq);
>  err_free_wr_wait:
>  	c4iw_put_wr_wait(qhp->wr_waitp);
> -err_free_qhp:
> -	kfree(qhp);
> -	return ERR_PTR(ret);
> +	return ret;
>  }
> 
>  int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
> diff --git a/drivers/infiniband/hw/efa/efa.h
> b/drivers/infiniband/hw/efa/efa.h
> index 2b8ca099b381..1a1e60eee1dc 100644
> --- a/drivers/infiniband/hw/efa/efa.h
> +++ b/drivers/infiniband/hw/efa/efa.h
> @@ -132,9 +132,8 @@ int efa_query_pkey(struct ib_device *ibdev, u32
> port, u16 index,
>  int efa_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
>  int efa_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
>  int efa_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
> -struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
> -			    struct ib_qp_init_attr *init_attr,
> -			    struct ib_udata *udata);
> +int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
> +		  struct ib_udata *udata);
>  int efa_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
>  int efa_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
>  		  struct ib_udata *udata);
> diff --git a/drivers/infiniband/hw/efa/efa_main.c
> b/drivers/infiniband/hw/efa/efa_main.c
> index 203e6ddcacbc..997947d77de6 100644
> --- a/drivers/infiniband/hw/efa/efa_main.c
> +++ b/drivers/infiniband/hw/efa/efa_main.c
> @@ -271,6 +271,7 @@ static const struct ib_device_ops efa_dev_ops = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, efa_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, efa_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, efa_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, efa_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, efa_ucontext, ibucontext),
>  };
> 
> diff --git a/drivers/infiniband/hw/efa/efa_verbs.c
> b/drivers/infiniband/hw/efa/efa_verbs.c
> index b1c4780e86be..e5f9d90aad5e 100644
> --- a/drivers/infiniband/hw/efa/efa_verbs.c
> +++ b/drivers/infiniband/hw/efa/efa_verbs.c
> @@ -450,7 +450,6 @@ int efa_destroy_qp(struct ib_qp *ibqp, struct
> ib_udata *udata)
>  				qp->rq_size, DMA_TO_DEVICE);
>  	}
> 
> -	kfree(qp);
>  	return 0;
>  }
> 
> @@ -609,17 +608,16 @@ static int efa_qp_validate_attr(struct efa_dev
> *dev,
>  	return 0;
>  }
> 
> -struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
> -			    struct ib_qp_init_attr *init_attr,
> -			    struct ib_udata *udata)
> +int efa_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
> +		  struct ib_udata *udata)
>  {
>  	struct efa_com_create_qp_params create_qp_params = {};
>  	struct efa_com_create_qp_result create_qp_resp;
> -	struct efa_dev *dev = to_edev(ibpd->device);
> +	struct efa_dev *dev = to_edev(ibqp->device);
>  	struct efa_ibv_create_qp_resp resp = {};
>  	struct efa_ibv_create_qp cmd = {};
> +	struct efa_qp *qp = to_eqp(ibqp);
>  	struct efa_ucontext *ucontext;
> -	struct efa_qp *qp;
>  	int err;
> 
>  	ucontext = rdma_udata_to_drv_context(udata, struct efa_ucontext,
> @@ -664,14 +662,8 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
>  		goto err_out;
>  	}
> 
> -	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -	if (!qp) {
> -		err = -ENOMEM;
> -		goto err_out;
> -	}
> -
>  	create_qp_params.uarn = ucontext->uarn;
> -	create_qp_params.pd = to_epd(ibpd)->pdn;
> +	create_qp_params.pd = to_epd(ibqp->pd)->pdn;
> 
>  	if (init_attr->qp_type == IB_QPT_UD) {
>  		create_qp_params.qp_type = EFA_ADMIN_QP_TYPE_UD;
> @@ -682,7 +674,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
>  			  "Unsupported qp type %d driver qp type %d\n",
>  			  init_attr->qp_type, cmd.driver_qp_type);
>  		err = -EOPNOTSUPP;
> -		goto err_free_qp;
> +		goto err_out;
>  	}
> 
>  	ibdev_dbg(&dev->ibdev, "Create QP: qp type %d driver qp type
> %#x\n",
> @@ -700,7 +692,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
>  						    qp->rq_size,
> DMA_TO_DEVICE);
>  		if (!qp->rq_cpu_addr) {
>  			err = -ENOMEM;
> -			goto err_free_qp;
> +			goto err_out;
>  		}
> 
>  		ibdev_dbg(&dev->ibdev,
> @@ -746,7 +738,7 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
> 
>  	ibdev_dbg(&dev->ibdev, "Created qp[%d]\n", qp->ibqp.qp_num);
> 
> -	return &qp->ibqp;
> +	return 0;
> 
>  err_remove_mmap_entries:
>  	efa_qp_user_mmap_entries_remove(qp);
> @@ -756,11 +748,9 @@ struct ib_qp *efa_create_qp(struct ib_pd *ibpd,
>  	if (qp->rq_size)
>  		efa_free_mapped(dev, qp->rq_cpu_addr, qp-
> >rq_dma_addr,
>  				qp->rq_size, DMA_TO_DEVICE);
> -err_free_qp:
> -	kfree(qp);
>  err_out:
>  	atomic64_inc(&dev->stats.create_qp_err);
> -	return ERR_PTR(err);
> +	return err;
>  }
> 
>  static const struct {
> diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h
> b/drivers/infiniband/hw/hns/hns_roce_device.h
> index 991f65269fa6..0c3eb1163977 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_device.h
> +++ b/drivers/infiniband/hw/hns/hns_roce_device.h
> @@ -1216,9 +1216,8 @@ int hns_roce_destroy_srq(struct ib_srq *ibsrq,
> struct ib_udata *udata);
>  int hns_roce_alloc_xrcd(struct ib_xrcd *ib_xrcd, struct ib_udata *udata);
>  int hns_roce_dealloc_xrcd(struct ib_xrcd *ib_xrcd, struct ib_udata *udata);
> 
> -struct ib_qp *hns_roce_create_qp(struct ib_pd *ib_pd,
> -				 struct ib_qp_init_attr *init_attr,
> -				 struct ib_udata *udata);
> +int hns_roce_create_qp(struct ib_qp *ib_qp, struct ib_qp_init_attr
> *init_attr,
> +		       struct ib_udata *udata);
>  int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
>  		       int attr_mask, struct ib_udata *udata);
>  void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp
> *hr_qp);
> diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c
> b/drivers/infiniband/hw/hns/hns_roce_main.c
> index 078a97193f0e..23b88a5a372f 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_main.c
> +++ b/drivers/infiniband/hw/hns/hns_roce_main.c
> @@ -454,6 +454,7 @@ static const struct ib_device_ops hns_roce_dev_ops
> = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, hns_roce_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, hns_roce_cq, ib_cq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, hns_roce_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, hns_roce_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, hns_roce_ucontext,
> ibucontext),
>  };
> 
> diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c
> b/drivers/infiniband/hw/hns/hns_roce_qp.c
> index c3e2fee16c0e..fd0f71acd470 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_qp.c
> +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c
> @@ -959,8 +959,6 @@ static int set_qp_param(struct hns_roce_dev
> *hr_dev, struct hns_roce_qp *hr_qp,
>  	struct ib_device *ibdev = &hr_dev->ib_dev;
>  	int ret;
> 
> -	hr_qp->ibqp.qp_type = init_attr->qp_type;
> -
>  	if (init_attr->cap.max_inline_data > hr_dev->caps.max_sq_inline)
>  		init_attr->cap.max_inline_data = hr_dev-
> >caps.max_sq_inline;
> 
> @@ -1121,8 +1119,6 @@ void hns_roce_qp_destroy(struct hns_roce_dev
> *hr_dev, struct hns_roce_qp *hr_qp,
>  	free_qp_buf(hr_dev, hr_qp);
>  	free_kernel_wrid(hr_qp);
>  	free_qp_db(hr_dev, hr_qp, udata);
> -
> -	kfree(hr_qp);
>  }
> 
>  static int check_qp_type(struct hns_roce_dev *hr_dev, enum ib_qp_type
> type,
> @@ -1154,22 +1150,18 @@ static int check_qp_type(struct hns_roce_dev
> *hr_dev, enum ib_qp_type type,
>  	return -EOPNOTSUPP;
>  }
> 
> -struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
> -				 struct ib_qp_init_attr *init_attr,
> -				 struct ib_udata *udata)
> +int hns_roce_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
> +		       struct ib_udata *udata)
>  {
> -	struct ib_device *ibdev = pd ? pd->device : init_attr->xrcd->device;
> +	struct ib_device *ibdev = qp->device;
>  	struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
> -	struct hns_roce_qp *hr_qp;
> +	struct hns_roce_qp *hr_qp = to_hr_qp(qp);
> +	struct ib_pd *pd = qp->pd;
>  	int ret;
> 
>  	ret = check_qp_type(hr_dev, init_attr->qp_type, !!udata);
>  	if (ret)
> -		return ERR_PTR(ret);
> -
> -	hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL);
> -	if (!hr_qp)
> -		return ERR_PTR(-ENOMEM);
> +		return ret;
> 
>  	if (init_attr->qp_type == IB_QPT_XRC_TGT)
>  		hr_qp->xrcdn = to_hr_xrcd(init_attr->xrcd)->xrcdn;
> @@ -1180,15 +1172,11 @@ struct ib_qp *hns_roce_create_qp(struct ib_pd
> *pd,
>  	}
> 
>  	ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata,
> hr_qp);
> -	if (ret) {
> +	if (ret)
>  		ibdev_err(ibdev, "Create QP type 0x%x failed(%d)\n",
>  			  init_attr->qp_type, ret);
> 
> -		kfree(hr_qp);
> -		return ERR_PTR(ret);
> -	}
> -
> -	return &hr_qp->ibqp;
> +	return ret;
>  }
> 
>  int to_hr_qp_type(int qp_type)
> diff --git a/drivers/infiniband/hw/irdma/utils.c
> b/drivers/infiniband/hw/irdma/utils.c
> index 5bbe44e54f9a..e94470991fe0 100644
> --- a/drivers/infiniband/hw/irdma/utils.c
> +++ b/drivers/infiniband/hw/irdma/utils.c
> @@ -1141,10 +1141,7 @@ void irdma_free_qp_rsrc(struct irdma_qp *iwqp)
>  			  iwqp->kqp.dma_mem.va, iwqp-
> >kqp.dma_mem.pa);
>  	iwqp->kqp.dma_mem.va = NULL;
>  	kfree(iwqp->kqp.sq_wrid_mem);
> -	iwqp->kqp.sq_wrid_mem = NULL;
>  	kfree(iwqp->kqp.rq_wrid_mem);
> -	iwqp->kqp.rq_wrid_mem = NULL;
> -	kfree(iwqp);
>  }
> 
>  /**
> diff --git a/drivers/infiniband/hw/irdma/verbs.c
> b/drivers/infiniband/hw/irdma/verbs.c
> index 9712f6902ba8..9b8c451e2426 100644
> --- a/drivers/infiniband/hw/irdma/verbs.c
> +++ b/drivers/infiniband/hw/irdma/verbs.c
> @@ -792,18 +792,19 @@ static int irdma_validate_qp_attrs(struct
> ib_qp_init_attr *init_attr,
> 
>  /**
>   * irdma_create_qp - create qp
> - * @ibpd: ptr of pd
> + * @ibqp: ptr of qp
>   * @init_attr: attributes for qp
>   * @udata: user data for create qp
>   */
> -static struct ib_qp *irdma_create_qp(struct ib_pd *ibpd,
> -				     struct ib_qp_init_attr *init_attr,
> -				     struct ib_udata *udata)
> +static int irdma_create_qp(struct ib_qp *ibqp,
> +			   struct ib_qp_init_attr *init_attr,
> +			   struct ib_udata *udata)
>  {
> +	struct ib_pd *ibpd = ibqp->pd;
>  	struct irdma_pd *iwpd = to_iwpd(ibpd);
>  	struct irdma_device *iwdev = to_iwdev(ibpd->device);
>  	struct irdma_pci_f *rf = iwdev->rf;
> -	struct irdma_qp *iwqp;
> +	struct irdma_qp *iwqp = to_iwqp(ibqp);
>  	struct irdma_create_qp_req req;
>  	struct irdma_create_qp_resp uresp = {};
>  	u32 qp_num = 0;
> @@ -820,7 +821,7 @@ static struct ib_qp *irdma_create_qp(struct ib_pd
> *ibpd,
> 
>  	err_code = irdma_validate_qp_attrs(init_attr, iwdev);
>  	if (err_code)
> -		return ERR_PTR(err_code);
> +		return err_code;
> 
>  	sq_size = init_attr->cap.max_send_wr;
>  	rq_size = init_attr->cap.max_recv_wr;
> @@ -833,10 +834,6 @@ static struct ib_qp *irdma_create_qp(struct ib_pd
> *ibpd,
>  	init_info.qp_uk_init_info.max_rq_frag_cnt = init_attr-
> >cap.max_recv_sge;
>  	init_info.qp_uk_init_info.max_inline_data = init_attr-
> >cap.max_inline_data;
> 
> -	iwqp = kzalloc(sizeof(*iwqp), GFP_KERNEL);
> -	if (!iwqp)
> -		return ERR_PTR(-ENOMEM);
> -
>  	qp = &iwqp->sc_qp;
>  	qp->qp_uk.back_qp = iwqp;
>  	qp->qp_uk.lock = &iwqp->lock;
> @@ -849,10 +846,8 @@ static struct ib_qp *irdma_create_qp(struct ib_pd
> *ibpd,
>  						 iwqp->q2_ctx_mem.size,
>  						 &iwqp->q2_ctx_mem.pa,
>  						 GFP_KERNEL);
> -	if (!iwqp->q2_ctx_mem.va) {
> -		err_code = -ENOMEM;
> -		goto error;
> -	}
> +	if (!iwqp->q2_ctx_mem.va)
> +		return -ENOMEM;
> 
>  	init_info.q2 = iwqp->q2_ctx_mem.va;
>  	init_info.q2_pa = iwqp->q2_ctx_mem.pa;
> @@ -1001,17 +996,16 @@ static struct ib_qp *irdma_create_qp(struct ib_pd
> *ibpd,
>  		if (err_code) {
>  			ibdev_dbg(&iwdev->ibdev, "VERBS: copy_to_udata
> failed\n");
>  			irdma_destroy_qp(&iwqp->ibqp, udata);
> -			return ERR_PTR(err_code);
> +			return err_code;
>  		}
>  	}
> 
>  	init_completion(&iwqp->free_qp);
> -	return &iwqp->ibqp;
> +	return 0;
> 
>  error:
>  	irdma_free_qp_rsrc(iwqp);
> -
> -	return ERR_PTR(err_code);
> +	return err_code;
>  }
> 
>  static int irdma_get_ib_acc_flags(struct irdma_qp *iwqp)
> @@ -4406,6 +4400,7 @@ static const struct ib_device_ops irdma_dev_ops =
> {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, irdma_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, irdma_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_mw, irdma_mr, ibmw),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, irdma_qp, ibqp),
>  };
> 
>  /**
> diff --git a/drivers/infiniband/hw/mlx4/main.c
> b/drivers/infiniband/hw/mlx4/main.c
> index ae4c91b612ce..f367f4a4abff 100644
> --- a/drivers/infiniband/hw/mlx4/main.c
> +++ b/drivers/infiniband/hw/mlx4/main.c
> @@ -2577,6 +2577,7 @@ static const struct ib_device_ops mlx4_ib_dev_ops
> = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, mlx4_ib_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, mlx4_ib_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, mlx4_ib_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, mlx4_ib_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, mlx4_ib_srq, ibsrq),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx4_ib_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h
> b/drivers/infiniband/hw/mlx4/mlx4_ib.h
> index e856cf23a0a1..c60f6e9ac640 100644
> --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
> +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
> @@ -792,9 +792,8 @@ void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq,
> int wqe_index);
>  int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
>  			  const struct ib_recv_wr **bad_wr);
> 
> -struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
> -				struct ib_qp_init_attr *init_attr,
> -				struct ib_udata *udata);
> +int mlx4_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
> +		      struct ib_udata *udata);
>  int mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
>  void mlx4_ib_drain_sq(struct ib_qp *qp);
>  void mlx4_ib_drain_rq(struct ib_qp *qp);
> diff --git a/drivers/infiniband/hw/mlx4/qp.c
> b/drivers/infiniband/hw/mlx4/qp.c
> index 4a2ef7daaded..8662f462e2a5 100644
> --- a/drivers/infiniband/hw/mlx4/qp.c
> +++ b/drivers/infiniband/hw/mlx4/qp.c
> @@ -1578,24 +1578,19 @@ static int _mlx4_ib_create_qp(struct ib_pd *pd,
> struct mlx4_ib_qp *qp,
>  	return 0;
>  }
> 
> -struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
> -				struct ib_qp_init_attr *init_attr,
> -				struct ib_udata *udata) {
> -	struct ib_device *device = pd ? pd->device : init_attr->xrcd->device;
> +int mlx4_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
> +		      struct ib_udata *udata)
> +{
> +	struct ib_device *device = ibqp->device;
>  	struct mlx4_ib_dev *dev = to_mdev(device);
> -	struct mlx4_ib_qp *qp;
> +	struct mlx4_ib_qp *qp = to_mqp(ibqp);
> +	struct ib_pd *pd = ibqp->pd;
>  	int ret;
> 
> -	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -	if (!qp)
> -		return ERR_PTR(-ENOMEM);
> -
>  	mutex_init(&qp->mutex);
>  	ret = _mlx4_ib_create_qp(pd, qp, init_attr, udata);
> -	if (ret) {
> -		kfree(qp);
> -		return ERR_PTR(ret);
> -	}
> +	if (ret)
> +		return ret;
> 
>  	if (init_attr->qp_type == IB_QPT_GSI &&
>  	    !(init_attr->create_flags & MLX4_IB_QP_CREATE_ROCE_V2_GSI)) {
> @@ -1618,7 +1613,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
>  			init_attr->create_flags &=
> ~MLX4_IB_QP_CREATE_ROCE_V2_GSI;
>  		}
>  	}
> -	return &qp->ibqp;
> +	return 0;
>  }
> 
>  static int _mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
> @@ -1646,8 +1641,6 @@ static int _mlx4_ib_destroy_qp(struct ib_qp *qp,
> struct ib_udata *udata)
>  	}
> 
>  	kfree(mqp->sqp);
> -	kfree(mqp);
> -
>  	return 0;
>  }
> 
> diff --git a/drivers/infiniband/hw/mlx5/gsi.c
> b/drivers/infiniband/hw/mlx5/gsi.c
> index 541da52470cb..3ad8f637c589 100644
> --- a/drivers/infiniband/hw/mlx5/gsi.c
> +++ b/drivers/infiniband/hw/mlx5/gsi.c
> @@ -193,8 +193,6 @@ int mlx5_ib_destroy_gsi(struct mlx5_ib_qp *mqp)
> 
>  	kfree(gsi->outstanding_wrs);
>  	kfree(gsi->tx_qps);
> -	kfree(mqp);
> -
>  	return 0;
>  }
> 
> diff --git a/drivers/infiniband/hw/mlx5/main.c
> b/drivers/infiniband/hw/mlx5/main.c
> index bcdbc3033b0a..7a6bafc19c9b 100644
> --- a/drivers/infiniband/hw/mlx5/main.c
> +++ b/drivers/infiniband/hw/mlx5/main.c
> @@ -3805,6 +3805,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops
> = {
>  	INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, mlx5_ib_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, mlx5_ib_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, mlx5_ib_srq, ibsrq),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx5_ib_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h
> b/drivers/infiniband/hw/mlx5/mlx5_ib.h
> index f2c8a6375b16..d662896e7fba 100644
> --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
> +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
> @@ -1237,9 +1237,8 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq,
> const struct ib_recv_wr *wr,
>  			  const struct ib_recv_wr **bad_wr);
>  int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp);
>  void mlx5_ib_disable_lb(struct mlx5_ib_dev *dev, bool td, bool qp);
> -struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
> -				struct ib_qp_init_attr *init_attr,
> -				struct ib_udata *udata);
> +int mlx5_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
> +		      struct ib_udata *udata);
>  int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
>  		      int attr_mask, struct ib_udata *udata);
>  int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int
> qp_attr_mask,
> diff --git a/drivers/infiniband/hw/mlx5/qp.c
> b/drivers/infiniband/hw/mlx5/qp.c
> index d6c6bfe9921a..18b018f1db83 100644
> --- a/drivers/infiniband/hw/mlx5/qp.c
> +++ b/drivers/infiniband/hw/mlx5/qp.c
> @@ -3116,7 +3116,6 @@ static int mlx5_ib_destroy_dct(struct mlx5_ib_qp
> *mqp)
>  	}
> 
>  	kfree(mqp->dct.in);
> -	kfree(mqp);
>  	return 0;
>  }
> 
> @@ -3154,25 +3153,23 @@ static int check_ucmd_data(struct mlx5_ib_dev
> *dev,
>  	return ret ? 0 : -EINVAL;
>  }
> 
> -struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd, struct ib_qp_init_attr
> *attr,
> -				struct ib_udata *udata)
> +int mlx5_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attr,
> +		      struct ib_udata *udata)
>  {
>  	struct mlx5_create_qp_params params = {};
> -	struct mlx5_ib_dev *dev;
> -	struct mlx5_ib_qp *qp;
> +	struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
> +	struct mlx5_ib_qp *qp = to_mqp(ibqp);
> +	struct ib_pd *pd = ibqp->pd;
>  	enum ib_qp_type type;
>  	int err;
> 
> -	dev = pd ? to_mdev(pd->device) :
> -		   to_mdev(to_mxrcd(attr->xrcd)->ibxrcd.device);
> -
>  	err = check_qp_type(dev, attr, &type);
>  	if (err)
> -		return ERR_PTR(err);
> +		return err;
> 
>  	err = check_valid_flow(dev, pd, attr, udata);
>  	if (err)
> -		return ERR_PTR(err);
> +		return err;
> 
>  	params.udata = udata;
>  	params.uidx = MLX5_IB_DEFAULT_UIDX;
> @@ -3182,49 +3179,43 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd
> *pd, struct ib_qp_init_attr *attr,
>  	if (udata) {
>  		err = process_udata_size(dev, &params);
>  		if (err)
> -			return ERR_PTR(err);
> +			return err;
> 
>  		err = check_ucmd_data(dev, &params);
>  		if (err)
> -			return ERR_PTR(err);
> +			return err;
> 
>  		params.ucmd = kzalloc(params.ucmd_size, GFP_KERNEL);
>  		if (!params.ucmd)
> -			return ERR_PTR(-ENOMEM);
> +			return -ENOMEM;
> 
>  		err = ib_copy_from_udata(params.ucmd, udata,
> params.inlen);
>  		if (err)
>  			goto free_ucmd;
>  	}
> 
> -	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -	if (!qp) {
> -		err = -ENOMEM;
> -		goto free_ucmd;
> -	}
> -
>  	mutex_init(&qp->mutex);
>  	qp->type = type;
>  	if (udata) {
>  		err = process_vendor_flags(dev, qp, params.ucmd, attr);
>  		if (err)
> -			goto free_qp;
> +			goto free_ucmd;
> 
>  		err = get_qp_uidx(qp, &params);
>  		if (err)
> -			goto free_qp;
> +			goto free_ucmd;
>  	}
>  	err = process_create_flags(dev, qp, attr);
>  	if (err)
> -		goto free_qp;
> +		goto free_ucmd;
> 
>  	err = check_qp_attr(dev, qp, attr);
>  	if (err)
> -		goto free_qp;
> +		goto free_ucmd;
> 
>  	err = create_qp(dev, pd, qp, &params);
>  	if (err)
> -		goto free_qp;
> +		goto free_ucmd;
> 
>  	kfree(params.ucmd);
>  	params.ucmd = NULL;
> @@ -3239,7 +3230,7 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
> struct ib_qp_init_attr *attr,
>  	if (err)
>  		goto destroy_qp;
> 
> -	return &qp->ibqp;
> +	return 0;
> 
>  destroy_qp:
>  	switch (qp->type) {
> @@ -3250,22 +3241,12 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd
> *pd, struct ib_qp_init_attr *attr,
>  		mlx5_ib_destroy_gsi(qp);
>  		break;
>  	default:
> -		/*
> -		 * These lines below are temp solution till QP allocation
> -		 * will be moved to be under IB/core responsiblity.
> -		 */
> -		qp->ibqp.send_cq = attr->send_cq;
> -		qp->ibqp.recv_cq = attr->recv_cq;
> -		qp->ibqp.pd = pd;
>  		destroy_qp_common(dev, qp, udata);
>  	}
> 
> -	qp = NULL;
> -free_qp:
> -	kfree(qp);
>  free_ucmd:
>  	kfree(params.ucmd);
> -	return ERR_PTR(err);
> +	return err;
>  }
> 
>  int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
> @@ -3280,9 +3261,6 @@ int mlx5_ib_destroy_qp(struct ib_qp *qp, struct
> ib_udata *udata)
>  		return mlx5_ib_destroy_dct(mqp);
> 
>  	destroy_qp_common(dev, mqp, udata);
> -
> -	kfree(mqp);
> -
>  	return 0;
>  }
> 
> diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c
> b/drivers/infiniband/hw/mthca/mthca_provider.c
> index adf4fcf0fee4..ceee23ebc0f2 100644
> --- a/drivers/infiniband/hw/mthca/mthca_provider.c
> +++ b/drivers/infiniband/hw/mthca/mthca_provider.c
> @@ -459,52 +459,45 @@ static int mthca_destroy_srq(struct ib_srq *srq,
> struct ib_udata *udata)
>  	return 0;
>  }
> 
> -static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
> -				     struct ib_qp_init_attr *init_attr,
> -				     struct ib_udata *udata)
> +static int mthca_create_qp(struct ib_qp *ibqp,
> +			   struct ib_qp_init_attr *init_attr,
> +			   struct ib_udata *udata)
>  {
>  	struct mthca_ucontext *context = rdma_udata_to_drv_context(
>  		udata, struct mthca_ucontext, ibucontext);
>  	struct mthca_create_qp ucmd;
> -	struct mthca_qp *qp;
> +	struct mthca_qp *qp = to_mqp(ibqp);
> +	struct mthca_dev *dev = to_mdev(ibqp->device);
>  	int err;
> 
>  	if (init_attr->create_flags)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
>  	switch (init_attr->qp_type) {
>  	case IB_QPT_RC:
>  	case IB_QPT_UC:
>  	case IB_QPT_UD:
>  	{
> -		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -		if (!qp)
> -			return ERR_PTR(-ENOMEM);
> -
>  		if (udata) {
> -			if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
> {
> -				kfree(qp);
> -				return ERR_PTR(-EFAULT);
> -			}
> +			if (ib_copy_from_udata(&ucmd, udata,
> sizeof(ucmd)))
> +				return -EFAULT;
> 
> -			err = mthca_map_user_db(to_mdev(pd->device),
> &context->uar,
> +			err = mthca_map_user_db(dev, &context->uar,
>  						context->db_tab,
> -						ucmd.sq_db_index,
> ucmd.sq_db_page);
> -			if (err) {
> -				kfree(qp);
> -				return ERR_PTR(err);
> -			}
> +						ucmd.sq_db_index,
> +						ucmd.sq_db_page);
> +			if (err)
> +				return err;
> 
> -			err = mthca_map_user_db(to_mdev(pd->device),
> &context->uar,
> +			err = mthca_map_user_db(dev, &context->uar,
>  						context->db_tab,
> -						ucmd.rq_db_index,
> ucmd.rq_db_page);
> +						ucmd.rq_db_index,
> +						ucmd.rq_db_page);
>  			if (err) {
> -				mthca_unmap_user_db(to_mdev(pd-
> >device),
> -						    &context->uar,
> +				mthca_unmap_user_db(dev, &context->uar,
>  						    context->db_tab,
>  						    ucmd.sq_db_index);
> -				kfree(qp);
> -				return ERR_PTR(err);
> +				return err;
>  			}
> 
>  			qp->mr.ibmr.lkey = ucmd.lkey;
> @@ -512,20 +505,16 @@ static struct ib_qp *mthca_create_qp(struct ib_pd
> *pd,
>  			qp->rq.db_index  = ucmd.rq_db_index;
>  		}
> 
> -		err = mthca_alloc_qp(to_mdev(pd->device), to_mpd(pd),
> +		err = mthca_alloc_qp(dev, to_mpd(ibqp->pd),
>  				     to_mcq(init_attr->send_cq),
>  				     to_mcq(init_attr->recv_cq),
>  				     init_attr->qp_type, init_attr->sq_sig_type,
>  				     &init_attr->cap, qp, udata);
> 
>  		if (err && udata) {
> -			mthca_unmap_user_db(to_mdev(pd->device),
> -					    &context->uar,
> -					    context->db_tab,
> +			mthca_unmap_user_db(dev, &context->uar,
> context->db_tab,
>  					    ucmd.sq_db_index);
> -			mthca_unmap_user_db(to_mdev(pd->device),
> -					    &context->uar,
> -					    context->db_tab,
> +			mthca_unmap_user_db(dev, &context->uar,
> context->db_tab,
>  					    ucmd.rq_db_index);
>  		}
> 
> @@ -535,34 +524,28 @@ static struct ib_qp *mthca_create_qp(struct ib_pd
> *pd,
>  	case IB_QPT_SMI:
>  	case IB_QPT_GSI:
>  	{
> -		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -		if (!qp)
> -			return ERR_PTR(-ENOMEM);
>  		qp->sqp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
> -		if (!qp->sqp) {
> -			kfree(qp);
> -			return ERR_PTR(-ENOMEM);
> -		}
> +		if (!qp->sqp)
> +			return -ENOMEM;
> 
>  		qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 :
> 1;
> 
> -		err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd),
> +		err = mthca_alloc_sqp(dev, to_mpd(ibqp->pd),
>  				      to_mcq(init_attr->send_cq),
>  				      to_mcq(init_attr->recv_cq),
>  				      init_attr->sq_sig_type, &init_attr->cap,
> -				      qp->ibqp.qp_num, init_attr->port_num,
> -				      qp, udata);
> +				      qp->ibqp.qp_num, init_attr->port_num,
> qp,
> +				      udata);
>  		break;
>  	}
>  	default:
>  		/* Don't support raw QPs */
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
>  	}
> 
>  	if (err) {
>  		kfree(qp->sqp);
> -		kfree(qp);
> -		return ERR_PTR(err);
> +		return err;
>  	}
> 
>  	init_attr->cap.max_send_wr     = qp->sq.max;
> @@ -571,7 +554,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd
> *pd,
>  	init_attr->cap.max_recv_sge    = qp->rq.max_gs;
>  	init_attr->cap.max_inline_data = qp->max_inline_data;
> 
> -	return &qp->ibqp;
> +	return 0;
>  }
> 
>  static int mthca_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
> @@ -594,7 +577,6 @@ static int mthca_destroy_qp(struct ib_qp *qp, struct
> ib_udata *udata)
>  	}
>  	mthca_free_qp(to_mdev(qp->device), to_mqp(qp));
>  	kfree(to_mqp(qp)->sqp);
> -	kfree(to_mqp(qp));
>  	return 0;
>  }
> 
> @@ -1121,6 +1103,7 @@ static const struct ib_device_ops mthca_dev_ops =
> {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, mthca_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, mthca_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, mthca_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, mthca_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, mthca_ucontext, ibucontext),
>  };
> 
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
> b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
> index f329db0c591f..7abf6cf1e937 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
> @@ -185,6 +185,7 @@ static const struct ib_device_ops ocrdma_dev_ops = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, ocrdma_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, ocrdma_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, ocrdma_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, ocrdma_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, ocrdma_ucontext, ibucontext),
>  };
> 
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
> b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
> index 58619ce64d0d..735123d0e9ec 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
> @@ -1288,19 +1288,19 @@ static void ocrdma_store_gsi_qp_cq(struct
> ocrdma_dev *dev,
>  	}
>  }
> 
> -struct ib_qp *ocrdma_create_qp(struct ib_pd *ibpd,
> -			       struct ib_qp_init_attr *attrs,
> -			       struct ib_udata *udata)
> +int ocrdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
> +		     struct ib_udata *udata)
>  {
>  	int status;
> +	struct ib_pd *ibpd = ibqp->pd;
>  	struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
> -	struct ocrdma_qp *qp;
> -	struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device);
> +	struct ocrdma_qp *qp = get_ocrdma_qp(ibqp);
> +	struct ocrdma_dev *dev = get_ocrdma_dev(ibqp->device);
>  	struct ocrdma_create_qp_ureq ureq;
>  	u16 dpp_credit_lmt, dpp_offset;
> 
>  	if (attrs->create_flags)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
>  	status = ocrdma_check_qp_params(ibpd, dev, attrs, udata);
>  	if (status)
> @@ -1309,12 +1309,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd
> *ibpd,
>  	memset(&ureq, 0, sizeof(ureq));
>  	if (udata) {
>  		if (ib_copy_from_udata(&ureq, udata, sizeof(ureq)))
> -			return ERR_PTR(-EFAULT);
> -	}
> -	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -	if (!qp) {
> -		status = -ENOMEM;
> -		goto gen_err;
> +			return -EFAULT;
>  	}
>  	ocrdma_set_qp_init_params(qp, pd, attrs);
>  	if (udata == NULL)
> @@ -1349,7 +1344,7 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd
> *ibpd,
>  	ocrdma_store_gsi_qp_cq(dev, attrs);
>  	qp->ibqp.qp_num = qp->id;
>  	mutex_unlock(&dev->dev_lock);
> -	return &qp->ibqp;
> +	return 0;
> 
>  cpy_err:
>  	ocrdma_del_qpn_map(dev, qp);
> @@ -1359,10 +1354,9 @@ struct ib_qp *ocrdma_create_qp(struct ib_pd
> *ibpd,
>  	mutex_unlock(&dev->dev_lock);
>  	kfree(qp->wqe_wr_id_tbl);
>  	kfree(qp->rqe_wr_id_tbl);
> -	kfree(qp);
>  	pr_err("%s(%d) error=%d\n", __func__, dev->id, status);
>  gen_err:
> -	return ERR_PTR(status);
> +	return status;
>  }
> 
>  int _ocrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
> @@ -1731,7 +1725,6 @@ int ocrdma_destroy_qp(struct ib_qp *ibqp, struct
> ib_udata *udata)
> 
>  	kfree(qp->wqe_wr_id_tbl);
>  	kfree(qp->rqe_wr_id_tbl);
> -	kfree(qp);
>  	return 0;
>  }
> 
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
> b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
> index b1c5fad81603..b73d742a520c 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
> @@ -75,9 +75,8 @@ int ocrdma_create_cq(struct ib_cq *ibcq, const struct
> ib_cq_init_attr *attr,
>  int ocrdma_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
>  int ocrdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
> 
> -struct ib_qp *ocrdma_create_qp(struct ib_pd *,
> -			       struct ib_qp_init_attr *attrs,
> -			       struct ib_udata *);
> +int ocrdma_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
> +		     struct ib_udata *udata);
>  int _ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
>  		      int attr_mask);
>  int ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
> diff --git a/drivers/infiniband/hw/qedr/main.c
> b/drivers/infiniband/hw/qedr/main.c
> index de98e0604f91..755930be01b8 100644
> --- a/drivers/infiniband/hw/qedr/main.c
> +++ b/drivers/infiniband/hw/qedr/main.c
> @@ -233,6 +233,7 @@ static const struct ib_device_ops qedr_dev_ops = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, qedr_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, qedr_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, qedr_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, qedr_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, qedr_srq, ibsrq),
>  	INIT_RDMA_OBJ_SIZE(ib_xrcd, qedr_xrcd, ibxrcd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, qedr_ucontext, ibucontext),
> diff --git a/drivers/infiniband/hw/qedr/qedr_roce_cm.c
> b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
> index 13e5e6bbec99..05307c1488b8 100644
> --- a/drivers/infiniband/hw/qedr/qedr_roce_cm.c
> +++ b/drivers/infiniband/hw/qedr/qedr_roce_cm.c
> @@ -319,20 +319,19 @@ static int qedr_ll2_start(struct qedr_dev *dev,
>  	return rc;
>  }
> 
> -struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
> -				 struct ib_qp_init_attr *attrs,
> -				 struct qedr_qp *qp)
> +int qedr_create_gsi_qp(struct qedr_dev *dev, struct ib_qp_init_attr *attrs,
> +		       struct qedr_qp *qp)
>  {
>  	int rc;
> 
>  	rc = qedr_check_gsi_qp_attrs(dev, attrs);
>  	if (rc)
> -		return ERR_PTR(rc);
> +		return rc;
> 
>  	rc = qedr_ll2_start(dev, attrs, qp);
>  	if (rc) {
>  		DP_ERR(dev, "create gsi qp: failed on ll2 start. rc=%d\n", rc);
> -		return ERR_PTR(rc);
> +		return rc;
>  	}
> 
>  	/* create QP */
> @@ -359,7 +358,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev
> *dev,
> 
>  	DP_DEBUG(dev, QEDR_MSG_GSI, "created GSI QP %p\n", qp);
> 
> -	return &qp->ibqp;
> +	return 0;
> 
>  err:
>  	kfree(qp->rqe_wr_id);
> @@ -368,7 +367,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev
> *dev,
>  	if (rc)
>  		DP_ERR(dev, "create gsi qp: failed destroy on create\n");
> 
> -	return ERR_PTR(-ENOMEM);
> +	return -ENOMEM;
>  }
> 
>  int qedr_destroy_gsi_qp(struct qedr_dev *dev)
> diff --git a/drivers/infiniband/hw/qedr/qedr_roce_cm.h
> b/drivers/infiniband/hw/qedr/qedr_roce_cm.h
> index d46dcd3f6424..f3432f035ec6 100644
> --- a/drivers/infiniband/hw/qedr/qedr_roce_cm.h
> +++ b/drivers/infiniband/hw/qedr/qedr_roce_cm.h
> @@ -50,9 +50,8 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, const struct
> ib_recv_wr *wr,
>  		       const struct ib_recv_wr **bad_wr);
>  int qedr_gsi_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
>  		       const struct ib_send_wr **bad_wr);
> -struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
> -				 struct ib_qp_init_attr *attrs,
> -				 struct qedr_qp *qp);
> +int qedr_create_gsi_qp(struct qedr_dev *dev, struct ib_qp_init_attr *attrs,
> +		       struct qedr_qp *qp);
>  void qedr_store_gsi_qp_cq(struct qedr_dev *dev,
>  			  struct qedr_qp *qp, struct ib_qp_init_attr *attrs);
>  int qedr_destroy_gsi_qp(struct qedr_dev *dev);
> diff --git a/drivers/infiniband/hw/qedr/verbs.c
> b/drivers/infiniband/hw/qedr/verbs.c
> index fdc47ef7d861..9cf94dc768ec 100644
> --- a/drivers/infiniband/hw/qedr/verbs.c
> +++ b/drivers/infiniband/hw/qedr/verbs.c
> @@ -2239,34 +2239,30 @@ static int qedr_free_qp_resources(struct
> qedr_dev *dev, struct qedr_qp *qp,
>  	return 0;
>  }
> 
> -struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
> -			     struct ib_qp_init_attr *attrs,
> -			     struct ib_udata *udata)
> +int qedr_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
> +		   struct ib_udata *udata)
>  {
>  	struct qedr_xrcd *xrcd = NULL;
> -	struct qedr_pd *pd = NULL;
> -	struct qedr_dev *dev;
> -	struct qedr_qp *qp;
> -	struct ib_qp *ibqp;
> +	struct ib_pd *ibpd = ibqp->pd;
> +	struct qedr_pd *pd = get_qedr_pd(ibpd);
> +	struct qedr_dev *dev = get_qedr_dev(ibqp->device);
> +	struct qedr_qp *qp = get_qedr_qp(ibqp);
>  	int rc = 0;
> 
>  	if (attrs->create_flags)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
> -	if (attrs->qp_type == IB_QPT_XRC_TGT) {
> +	if (attrs->qp_type == IB_QPT_XRC_TGT)
>  		xrcd = get_qedr_xrcd(attrs->xrcd);
> -		dev = get_qedr_dev(xrcd->ibxrcd.device);
> -	} else {
> +	else
>  		pd = get_qedr_pd(ibpd);
> -		dev = get_qedr_dev(ibpd->device);
> -	}
> 
>  	DP_DEBUG(dev, QEDR_MSG_QP, "create qp: called from %s,
> pd=%p\n",
>  		 udata ? "user library" : "kernel", pd);
> 
>  	rc = qedr_check_qp_attrs(ibpd, dev, attrs, udata);
>  	if (rc)
> -		return ERR_PTR(rc);
> +		return rc;
> 
>  	DP_DEBUG(dev, QEDR_MSG_QP,
>  		 "create qp: called from %s, event_handler=%p, eepd=%p
> sq_cq=%p, sq_icid=%d, rq_cq=%p, rq_icid=%d\n",
> @@ -2276,20 +2272,10 @@ struct ib_qp *qedr_create_qp(struct ib_pd
> *ibpd,
>  		 get_qedr_cq(attrs->recv_cq),
>  		 attrs->recv_cq ? get_qedr_cq(attrs->recv_cq)->icid : 0);
> 
> -	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -	if (!qp) {
> -		DP_ERR(dev, "create qp: failed allocating memory\n");
> -		return ERR_PTR(-ENOMEM);
> -	}
> -
>  	qedr_set_common_qp_params(dev, qp, pd, attrs);
> 
> -	if (attrs->qp_type == IB_QPT_GSI) {
> -		ibqp = qedr_create_gsi_qp(dev, attrs, qp);
> -		if (IS_ERR(ibqp))
> -			kfree(qp);
> -		return ibqp;
> -	}
> +	if (attrs->qp_type == IB_QPT_GSI)
> +		return qedr_create_gsi_qp(dev, attrs, qp);
> 
>  	if (udata || xrcd)
>  		rc = qedr_create_user_qp(dev, qp, ibpd, udata, attrs);
> @@ -2297,7 +2283,7 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd,
>  		rc = qedr_create_kernel_qp(dev, qp, ibpd, attrs);
> 
>  	if (rc)
> -		goto out_free_qp;
> +		return rc;
> 
>  	qp->ibqp.qp_num = qp->qp_id;
> 
> @@ -2307,14 +2293,11 @@ struct ib_qp *qedr_create_qp(struct ib_pd
> *ibpd,
>  			goto out_free_qp_resources;
>  	}
> 
> -	return &qp->ibqp;
> +	return 0;
> 
>  out_free_qp_resources:
>  	qedr_free_qp_resources(dev, qp, udata);
> -out_free_qp:
> -	kfree(qp);
> -
> -	return ERR_PTR(-EFAULT);
> +	return -EFAULT;
>  }
> 
>  static enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state
> qp_state)
> @@ -2874,8 +2857,6 @@ int qedr_destroy_qp(struct ib_qp *ibqp, struct
> ib_udata *udata)
> 
>  	if (rdma_protocol_iwarp(&dev->ibdev, 1))
>  		qedr_iw_qp_rem_ref(&qp->ibqp);
> -	else
> -		kfree(qp);
> 
>  	return 0;
>  }
> diff --git a/drivers/infiniband/hw/qedr/verbs.h
> b/drivers/infiniband/hw/qedr/verbs.h
> index 34ad47515861..031687dafc61 100644
> --- a/drivers/infiniband/hw/qedr/verbs.h
> +++ b/drivers/infiniband/hw/qedr/verbs.h
> @@ -56,8 +56,8 @@ int qedr_create_cq(struct ib_cq *ibcq, const struct
> ib_cq_init_attr *attr,
>  int qedr_resize_cq(struct ib_cq *, int cqe, struct ib_udata *);
>  int qedr_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
>  int qedr_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
> -struct ib_qp *qedr_create_qp(struct ib_pd *, struct ib_qp_init_attr *attrs,
> -			     struct ib_udata *);
> +int qedr_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attrs,
> +		   struct ib_udata *udata);
>  int qedr_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
>  		   int attr_mask, struct ib_udata *udata);
>  int qedr_query_qp(struct ib_qp *, struct ib_qp_attr *qp_attr,
> diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c
> b/drivers/infiniband/hw/usnic/usnic_ib_main.c
> index c49f9e19d926..228e9a36dad0 100644
> --- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
> +++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
> @@ -360,6 +360,7 @@ static const struct ib_device_ops usnic_dev_ops = {
>  	.reg_user_mr = usnic_ib_reg_mr,
>  	INIT_RDMA_OBJ_SIZE(ib_pd, usnic_ib_pd, ibpd),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, usnic_ib_cq, ibcq),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, usnic_ib_qp_grp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, usnic_ib_ucontext, ibucontext),
>  };
> 
> diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
> b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
> index 0cdb156e165e..3b60fa9cb58d 100644
> --- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
> +++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
> @@ -665,13 +665,12 @@ static int qp_grp_id_from_flow(struct
> usnic_ib_qp_grp_flow *qp_flow,
>  	return 0;
>  }
> 
> -struct usnic_ib_qp_grp *
> -usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf
> *vf,
> -			struct usnic_ib_pd *pd,
> -			struct usnic_vnic_res_spec *res_spec,
> -			struct usnic_transport_spec *transport_spec)
> +int usnic_ib_qp_grp_create(struct usnic_ib_qp_grp *qp_grp,
> +			   struct usnic_fwd_dev *ufdev, struct usnic_ib_vf
> *vf,
> +			   struct usnic_ib_pd *pd,
> +			   struct usnic_vnic_res_spec *res_spec,
> +			   struct usnic_transport_spec *transport_spec)
>  {
> -	struct usnic_ib_qp_grp *qp_grp;
>  	int err;
>  	enum usnic_transport_type transport = transport_spec->trans_type;
>  	struct usnic_ib_qp_grp_flow *qp_flow;
> @@ -684,20 +683,15 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev
> *ufdev, struct usnic_ib_vf *vf,
>  		usnic_err("Spec does not meet minimum req for transport
> %d\n",
>  				transport);
>  		log_spec(res_spec);
> -		return ERR_PTR(err);
> +		return err;
>  	}
> 
> -	qp_grp = kzalloc(sizeof(*qp_grp), GFP_ATOMIC);
> -	if (!qp_grp)
> -		return NULL;
> -
>  	qp_grp->res_chunk_list = alloc_res_chunk_list(vf->vnic, res_spec,
>  							qp_grp);
> -	if (IS_ERR_OR_NULL(qp_grp->res_chunk_list)) {
> -		err = qp_grp->res_chunk_list ?
> -				PTR_ERR(qp_grp->res_chunk_list) : -
> ENOMEM;
> -		goto out_free_qp_grp;
> -	}
> +	if (IS_ERR_OR_NULL(qp_grp->res_chunk_list))
> +		return qp_grp->res_chunk_list ?
> +				     PTR_ERR(qp_grp->res_chunk_list) :
> +				     -ENOMEM;
> 
>  	err = qp_grp_and_vf_bind(vf, pd, qp_grp);
>  	if (err)
> @@ -724,7 +718,7 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev
> *ufdev, struct usnic_ib_vf *vf,
> 
>  	usnic_ib_sysfs_qpn_add(qp_grp);
> 
> -	return qp_grp;
> +	return 0;
> 
>  out_release_flow:
>  	release_and_remove_flow(qp_flow);
> @@ -732,10 +726,7 @@ usnic_ib_qp_grp_create(struct usnic_fwd_dev
> *ufdev, struct usnic_ib_vf *vf,
>  	qp_grp_and_vf_unbind(qp_grp);
>  out_free_res:
>  	free_qp_grp_res(qp_grp->res_chunk_list);
> -out_free_qp_grp:
> -	kfree(qp_grp);
> -
> -	return ERR_PTR(err);
> +	return err;
>  }
> 
>  void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
> @@ -748,7 +739,6 @@ void usnic_ib_qp_grp_destroy(struct
> usnic_ib_qp_grp *qp_grp)
>  	usnic_ib_sysfs_qpn_remove(qp_grp);
>  	qp_grp_and_vf_unbind(qp_grp);
>  	free_qp_grp_res(qp_grp->res_chunk_list);
> -	kfree(qp_grp);
>  }
> 
>  struct usnic_vnic_res_chunk*
> diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
> b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
> index a8a2314c9531..62e732be6736 100644
> --- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
> +++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
> @@ -89,11 +89,11 @@ extern const struct usnic_vnic_res_spec
> min_transport_spec[USNIC_TRANSPORT_MAX];
>  const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state);
>  int usnic_ib_qp_grp_dump_hdr(char *buf, int buf_sz);
>  int usnic_ib_qp_grp_dump_rows(void *obj, char *buf, int buf_sz);
> -struct usnic_ib_qp_grp *
> -usnic_ib_qp_grp_create(struct usnic_fwd_dev *ufdev, struct usnic_ib_vf
> *vf,
> -			struct usnic_ib_pd *pd,
> -			struct usnic_vnic_res_spec *res_spec,
> -			struct usnic_transport_spec *trans_spec);
> +int usnic_ib_qp_grp_create(struct usnic_ib_qp_grp *qp,
> +			   struct usnic_fwd_dev *ufdev, struct usnic_ib_vf
> *vf,
> +			   struct usnic_ib_pd *pd,
> +			   struct usnic_vnic_res_spec *res_spec,
> +			   struct usnic_transport_spec *trans_spec);
>  void usnic_ib_qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp);
>  int usnic_ib_qp_grp_modify(struct usnic_ib_qp_grp *qp_grp,
>  				enum ib_qp_state new_state,
> diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
> b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
> index 57d210ca855a..06a4e9d4545d 100644
> --- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
> +++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
> @@ -168,30 +168,31 @@ static int usnic_ib_fill_create_qp_resp(struct
> usnic_ib_qp_grp *qp_grp,
>  	return 0;
>  }
> 
> -static struct usnic_ib_qp_grp*
> -find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev,
> -				struct usnic_ib_pd *pd,
> -				struct usnic_transport_spec *trans_spec,
> -				struct usnic_vnic_res_spec *res_spec)
> +static int
> +find_free_vf_and_create_qp_grp(struct ib_qp *qp,
> +			       struct usnic_transport_spec *trans_spec,
> +			       struct usnic_vnic_res_spec *res_spec)
>  {
> +	struct usnic_ib_dev *us_ibdev = to_usdev(qp->device);
> +	struct usnic_ib_pd *pd = to_upd(qp->pd);
>  	struct usnic_ib_vf *vf;
>  	struct usnic_vnic *vnic;
> -	struct usnic_ib_qp_grp *qp_grp;
> +	struct usnic_ib_qp_grp *qp_grp = to_uqp_grp(qp);
>  	struct device *dev, **dev_list;
> -	int i;
> +	int i, ret;
> 
>  	BUG_ON(!mutex_is_locked(&us_ibdev->usdev_lock));
> 
>  	if (list_empty(&us_ibdev->vf_dev_list)) {
>  		usnic_info("No vfs to allocate\n");
> -		return NULL;
> +		return -ENOMEM;
>  	}
> 
>  	if (usnic_ib_share_vf) {
>  		/* Try to find resouces on a used vf which is in pd */
>  		dev_list = usnic_uiom_get_dev_list(pd->umem_pd);
>  		if (IS_ERR(dev_list))
> -			return ERR_CAST(dev_list);
> +			return PTR_ERR(dev_list);
>  		for (i = 0; dev_list[i]; i++) {
>  			dev = dev_list[i];
>  			vf = dev_get_drvdata(dev);
> @@ -202,10 +203,10 @@ find_free_vf_and_create_qp_grp(struct
> usnic_ib_dev *us_ibdev,
>  						dev_name(&us_ibdev-
> >ib_dev.dev),
> 
> 	pci_name(usnic_vnic_get_pdev(
> 
> 	vnic)));
> -				qp_grp = usnic_ib_qp_grp_create(us_ibdev-
> >ufdev,
> -								vf, pd,
> -								res_spec,
> -								trans_spec);
> +				ret = usnic_ib_qp_grp_create(qp_grp,
> +							     us_ibdev->ufdev,
> +							     vf, pd, res_spec,
> +							     trans_spec);
> 
>  				spin_unlock(&vf->lock);
>  				goto qp_grp_check;
> @@ -223,9 +224,9 @@ find_free_vf_and_create_qp_grp(struct
> usnic_ib_dev *us_ibdev,
>  		vnic = vf->vnic;
>  		if (vf->qp_grp_ref_cnt == 0 &&
>  		    usnic_vnic_check_room(vnic, res_spec) == 0) {
> -			qp_grp = usnic_ib_qp_grp_create(us_ibdev->ufdev,
> vf,
> -							pd, res_spec,
> -							trans_spec);
> +			ret = usnic_ib_qp_grp_create(qp_grp, us_ibdev-
> >ufdev,
> +						     vf, pd, res_spec,
> +						     trans_spec);
> 
>  			spin_unlock(&vf->lock);
>  			goto qp_grp_check;
> @@ -235,16 +236,15 @@ find_free_vf_and_create_qp_grp(struct
> usnic_ib_dev *us_ibdev,
> 
>  	usnic_info("No free qp grp found on %s\n",
>  		   dev_name(&us_ibdev->ib_dev.dev));
> -	return ERR_PTR(-ENOMEM);
> +	return -ENOMEM;
> 
>  qp_grp_check:
> -	if (IS_ERR_OR_NULL(qp_grp)) {
> +	if (ret) {
>  		usnic_err("Failed to allocate qp_grp\n");
>  		if (usnic_ib_share_vf)
>  			usnic_uiom_free_dev_list(dev_list);
> -		return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
>  	}
> -	return qp_grp;
> +	return ret;
>  }
> 
>  static void qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp)
> @@ -458,13 +458,12 @@ int usnic_ib_dealloc_pd(struct ib_pd *pd, struct
> ib_udata *udata)
>  	return 0;
>  }
> 
> -struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
> -					struct ib_qp_init_attr *init_attr,
> -					struct ib_udata *udata)
> +int usnic_ib_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
> +		       struct ib_udata *udata)
>  {
>  	int err;
>  	struct usnic_ib_dev *us_ibdev;
> -	struct usnic_ib_qp_grp *qp_grp;
> +	struct usnic_ib_qp_grp *qp_grp = to_uqp_grp(ibqp);
>  	struct usnic_ib_ucontext *ucontext = rdma_udata_to_drv_context(
>  		udata, struct usnic_ib_ucontext, ibucontext);
>  	int cq_cnt;
> @@ -474,29 +473,29 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
> 
>  	usnic_dbg("\n");
> 
> -	us_ibdev = to_usdev(pd->device);
> +	us_ibdev = to_usdev(ibqp->device);
> 
>  	if (init_attr->create_flags)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
>  	err = ib_copy_from_udata(&cmd, udata, sizeof(cmd));
>  	if (err) {
>  		usnic_err("%s: cannot copy udata for create_qp\n",
>  			  dev_name(&us_ibdev->ib_dev.dev));
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  	}
> 
>  	err = create_qp_validate_user_data(cmd);
>  	if (err) {
>  		usnic_err("%s: Failed to validate user data\n",
>  			  dev_name(&us_ibdev->ib_dev.dev));
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  	}
> 
>  	if (init_attr->qp_type != IB_QPT_UD) {
>  		usnic_err("%s asked to make a non-UD QP: %d\n",
>  			  dev_name(&us_ibdev->ib_dev.dev), init_attr-
> >qp_type);
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
>  	}
> 
>  	trans_spec = cmd.spec;
> @@ -504,13 +503,9 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
>  	cq_cnt = (init_attr->send_cq == init_attr->recv_cq) ? 1 : 2;
>  	res_spec = min_transport_spec[trans_spec.trans_type];
>  	usnic_vnic_res_spec_update(&res_spec,
> USNIC_VNIC_RES_TYPE_CQ, cq_cnt);
> -	qp_grp = find_free_vf_and_create_qp_grp(us_ibdev, to_upd(pd),
> -						&trans_spec,
> -						&res_spec);
> -	if (IS_ERR_OR_NULL(qp_grp)) {
> -		err = qp_grp ? PTR_ERR(qp_grp) : -ENOMEM;
> +	err = find_free_vf_and_create_qp_grp(ibqp, &trans_spec,
> &res_spec);
> +	if (err)
>  		goto out_release_mutex;
> -	}
> 
>  	err = usnic_ib_fill_create_qp_resp(qp_grp, udata);
>  	if (err) {
> @@ -522,13 +517,13 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
>  	list_add_tail(&qp_grp->link, &ucontext->qp_grp_list);
>  	usnic_ib_log_vf(qp_grp->vf);
>  	mutex_unlock(&us_ibdev->usdev_lock);
> -	return &qp_grp->ibqp;
> +	return 0;
> 
>  out_release_qp_grp:
>  	qp_grp_destroy(qp_grp);
>  out_release_mutex:
>  	mutex_unlock(&us_ibdev->usdev_lock);
> -	return ERR_PTR(err);
> +	return err;
>  }
> 
>  int usnic_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
> diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
> b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
> index 6b82d0f2d184..6ca9ee0dddbe 100644
> --- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
> +++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
> @@ -50,9 +50,8 @@ int usnic_ib_query_gid(struct ib_device *ibdev, u32
> port, int index,
>  				union ib_gid *gid);
>  int usnic_ib_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata);
>  int usnic_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);
> -struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
> -					struct ib_qp_init_attr *init_attr,
> -					struct ib_udata *udata);
> +int usnic_ib_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
> +		       struct ib_udata *udata);
>  int usnic_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
>  int usnic_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
>  				int attr_mask, struct ib_udata *udata);
> diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
> b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
> index 8ed8bc24c69f..b39175837d58 100644
> --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
> +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
> @@ -185,6 +185,7 @@ static const struct ib_device_ops pvrdma_dev_ops = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, pvrdma_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, pvrdma_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, pvrdma_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, pvrdma_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, pvrdma_ucontext, ibucontext),
>  };
> 
> diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
> b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
> index 67769b715126..f83cd4a9d992 100644
> --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
> +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
> @@ -182,18 +182,17 @@ static int pvrdma_set_sq_size(struct pvrdma_dev
> *dev, struct ib_qp_cap *req_cap,
> 
>  /**
>   * pvrdma_create_qp - create queue pair
> - * @pd: protection domain
> + * @ibqp: queue pair
>   * @init_attr: queue pair attributes
>   * @udata: user data
>   *
> - * @return: the ib_qp pointer on success, otherwise returns an errno.
> + * @return: the 0 on success, otherwise returns an errno.
>   */
> -struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
> -			       struct ib_qp_init_attr *init_attr,
> -			       struct ib_udata *udata)
> +int pvrdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
> +		     struct ib_udata *udata)
>  {
> -	struct pvrdma_qp *qp = NULL;
> -	struct pvrdma_dev *dev = to_vdev(pd->device);
> +	struct pvrdma_qp *qp = to_vqp(ibqp);
> +	struct pvrdma_dev *dev = to_vdev(ibqp->device);
>  	union pvrdma_cmd_req req;
>  	union pvrdma_cmd_resp rsp;
>  	struct pvrdma_cmd_create_qp *cmd = &req.create_qp;
> @@ -209,7 +208,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
>  		dev_warn(&dev->pdev->dev,
>  			 "invalid create queuepair flags %#x\n",
>  			 init_attr->create_flags);
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
>  	}
> 
>  	if (init_attr->qp_type != IB_QPT_RC &&
> @@ -217,22 +216,22 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
>  	    init_attr->qp_type != IB_QPT_GSI) {
>  		dev_warn(&dev->pdev->dev, "queuepair type %d not
> supported\n",
>  			 init_attr->qp_type);
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
>  	}
> 
>  	if (is_srq && !dev->dsr->caps.max_srq) {
>  		dev_warn(&dev->pdev->dev,
>  			 "SRQs not supported by device\n");
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  	}
> 
>  	if (!atomic_add_unless(&dev->num_qps, 1, dev->dsr-
> >caps.max_qp))
> -		return ERR_PTR(-ENOMEM);
> +		return -ENOMEM;
> 
>  	switch (init_attr->qp_type) {
>  	case IB_QPT_GSI:
>  		if (init_attr->port_num == 0 ||
> -		    init_attr->port_num > pd->device->phys_port_cnt) {
> +		    init_attr->port_num > ibqp->device->phys_port_cnt) {
>  			dev_warn(&dev->pdev->dev, "invalid queuepair
> attrs\n");
>  			ret = -EINVAL;
>  			goto err_qp;
> @@ -240,12 +239,6 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
>  		fallthrough;
>  	case IB_QPT_RC:
>  	case IB_QPT_UD:
> -		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -		if (!qp) {
> -			ret = -ENOMEM;
> -			goto err_qp;
> -		}
> -
>  		spin_lock_init(&qp->sq.lock);
>  		spin_lock_init(&qp->rq.lock);
>  		mutex_init(&qp->mutex);
> @@ -275,9 +268,9 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
> 
>  			if (!is_srq) {
>  				/* set qp->sq.wqe_cnt, shift, buf_size.. */
> -				qp->rumem =
> -					ib_umem_get(pd->device,
> ucmd.rbuf_addr,
> -						    ucmd.rbuf_size, 0);
> +				qp->rumem = ib_umem_get(ibqp->device,
> +							ucmd.rbuf_addr,
> +							ucmd.rbuf_size, 0);
>  				if (IS_ERR(qp->rumem)) {
>  					ret = PTR_ERR(qp->rumem);
>  					goto err_qp;
> @@ -288,7 +281,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
>  				qp->srq = to_vsrq(init_attr->srq);
>  			}
> 
> -			qp->sumem = ib_umem_get(pd->device,
> ucmd.sbuf_addr,
> +			qp->sumem = ib_umem_get(ibqp->device,
> ucmd.sbuf_addr,
>  						ucmd.sbuf_size, 0);
>  			if (IS_ERR(qp->sumem)) {
>  				if (!is_srq)
> @@ -306,12 +299,12 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
>  				qp->npages_recv = 0;
>  			qp->npages = qp->npages_send + qp->npages_recv;
>  		} else {
> -			ret = pvrdma_set_sq_size(to_vdev(pd->device),
> +			ret = pvrdma_set_sq_size(to_vdev(ibqp->device),
>  						 &init_attr->cap, qp);
>  			if (ret)
>  				goto err_qp;
> 
> -			ret = pvrdma_set_rq_size(to_vdev(pd->device),
> +			ret = pvrdma_set_rq_size(to_vdev(ibqp->device),
>  						 &init_attr->cap, qp);
>  			if (ret)
>  				goto err_qp;
> @@ -362,7 +355,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
> 
>  	memset(cmd, 0, sizeof(*cmd));
>  	cmd->hdr.cmd = PVRDMA_CMD_CREATE_QP;
> -	cmd->pd_handle = to_vpd(pd)->pd_handle;
> +	cmd->pd_handle = to_vpd(ibqp->pd)->pd_handle;
>  	cmd->send_cq_handle = to_vcq(init_attr->send_cq)->cq_handle;
>  	cmd->recv_cq_handle = to_vcq(init_attr->recv_cq)->cq_handle;
>  	if (is_srq)
> @@ -418,11 +411,11 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
>  			dev_warn(&dev->pdev->dev,
>  				 "failed to copy back udata\n");
>  			__pvrdma_destroy_qp(dev, qp);
> -			return ERR_PTR(-EINVAL);
> +			return -EINVAL;
>  		}
>  	}
> 
> -	return &qp->ibqp;
> +	return 0;
> 
>  err_pdir:
>  	pvrdma_page_dir_cleanup(dev, &qp->pdir);
> @@ -430,10 +423,8 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
>  	ib_umem_release(qp->rumem);
>  	ib_umem_release(qp->sumem);
>  err_qp:
> -	kfree(qp);
>  	atomic_dec(&dev->num_qps);
> -
> -	return ERR_PTR(ret);
> +	return ret;
>  }
> 
>  static void _pvrdma_free_qp(struct pvrdma_qp *qp)
> @@ -454,8 +445,6 @@ static void _pvrdma_free_qp(struct pvrdma_qp *qp)
> 
>  	pvrdma_page_dir_cleanup(dev, &qp->pdir);
> 
> -	kfree(qp);
> -
>  	atomic_dec(&dev->num_qps);
>  }
> 
> diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
> b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
> index 544b94d97c3a..78807b23d831 100644
> --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
> +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
> @@ -390,9 +390,8 @@ int pvrdma_modify_srq(struct ib_srq *ibsrq, struct
> ib_srq_attr *attr,
>  int pvrdma_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
>  int pvrdma_destroy_srq(struct ib_srq *srq, struct ib_udata *udata);
> 
> -struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
> -			       struct ib_qp_init_attr *init_attr,
> -			       struct ib_udata *udata);
> +int pvrdma_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *init_attr,
> +		     struct ib_udata *udata);
>  int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
>  		     int attr_mask, struct ib_udata *udata);
>  int pvrdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
> diff --git a/drivers/infiniband/sw/rdmavt/qp.c
> b/drivers/infiniband/sw/rdmavt/qp.c
> index 14900860985c..da2d94a5a9c2 100644
> --- a/drivers/infiniband/sw/rdmavt/qp.c
> +++ b/drivers/infiniband/sw/rdmavt/qp.c
> @@ -1058,7 +1058,7 @@ static int alloc_ud_wq_attr(struct rvt_qp *qp, int
> node)
> 
>  /**
>   * rvt_create_qp - create a queue pair for a device
> - * @ibpd: the protection domain who's device we create the queue pair for
> + * @ibqp: the queue pair
>   * @init_attr: the attributes of the queue pair
>   * @udata: user data for libibverbs.so
>   *
> @@ -1066,47 +1066,45 @@ static int alloc_ud_wq_attr(struct rvt_qp *qp, int
> node)
>   * unique idea of what queue pair numbers mean. For instance there is a
> reserved
>   * range for PSM.
>   *
> - * Return: the queue pair on success, otherwise returns an errno.
> + * Return: 0 on success, otherwise returns an errno.
>   *
>   * Called by the ib_create_qp() core verbs function.
>   */
> -struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
> -			    struct ib_qp_init_attr *init_attr,
> -			    struct ib_udata *udata)
> +int rvt_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
> +		  struct ib_udata *udata)
>  {
> -	struct rvt_qp *qp;
> -	int err;
> +	struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);
> +	int ret = -ENOMEM;
>  	struct rvt_swqe *swq = NULL;
>  	size_t sz;
>  	size_t sg_list_sz = 0;
> -	struct ib_qp *ret = ERR_PTR(-ENOMEM);
> -	struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device);
> +	struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device);
>  	void *priv = NULL;
>  	size_t sqsize;
>  	u8 exclude_prefix = 0;
> 
>  	if (!rdi)
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
> 
>  	if (init_attr->create_flags & ~IB_QP_CREATE_NETDEV_USE)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
>  	if (init_attr->cap.max_send_sge > rdi->dparms.props.max_send_sge
> ||
>  	    init_attr->cap.max_send_wr > rdi->dparms.props.max_qp_wr)
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
> 
>  	/* Check receive queue parameters if no SRQ is specified. */
>  	if (!init_attr->srq) {
>  		if (init_attr->cap.max_recv_sge >
>  		    rdi->dparms.props.max_recv_sge ||
>  		    init_attr->cap.max_recv_wr > rdi-
> >dparms.props.max_qp_wr)
> -			return ERR_PTR(-EINVAL);
> +			return -EINVAL;
> 
>  		if (init_attr->cap.max_send_sge +
>  		    init_attr->cap.max_send_wr +
>  		    init_attr->cap.max_recv_sge +
>  		    init_attr->cap.max_recv_wr == 0)
> -			return ERR_PTR(-EINVAL);
> +			return -EINVAL;
>  	}
>  	sqsize =
>  		init_attr->cap.max_send_wr + 1 +
> @@ -1115,8 +1113,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  	case IB_QPT_SMI:
>  	case IB_QPT_GSI:
>  		if (init_attr->port_num == 0 ||
> -		    init_attr->port_num > ibpd->device->phys_port_cnt)
> -			return ERR_PTR(-EINVAL);
> +		    init_attr->port_num > ibqp->device->phys_port_cnt)
> +			return -EINVAL;
>  		fallthrough;
>  	case IB_QPT_UC:
>  	case IB_QPT_RC:
> @@ -1124,7 +1122,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  		sz = struct_size(swq, sg_list, init_attr->cap.max_send_sge);
>  		swq = vzalloc_node(array_size(sz, sqsize), rdi-
> >dparms.node);
>  		if (!swq)
> -			return ERR_PTR(-ENOMEM);
> +			return -ENOMEM;
> 
>  		if (init_attr->srq) {
>  			struct rvt_srq *srq = ibsrq_to_rvtsrq(init_attr->srq);
> @@ -1135,9 +1133,6 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  		} else if (init_attr->cap.max_recv_sge > 1)
>  			sg_list_sz = sizeof(*qp->r_sg_list) *
>  				(init_attr->cap.max_recv_sge - 1);
> -		qp = kzalloc_node(sizeof(*qp), GFP_KERNEL, rdi-
> >dparms.node);
> -		if (!qp)
> -			goto bail_swq;
>  		qp->r_sg_list =
>  			kzalloc_node(sg_list_sz, GFP_KERNEL, rdi-
> >dparms.node);
>  		if (!qp->r_sg_list)
> @@ -1166,7 +1161,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  		 */
>  		priv = rdi->driver_f.qp_priv_alloc(rdi, qp);
>  		if (IS_ERR(priv)) {
> -			ret = priv;
> +			ret = PTR_ERR(priv);
>  			goto bail_qp;
>  		}
>  		qp->priv = priv;
> @@ -1180,12 +1175,10 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  			qp->r_rq.max_sge = init_attr->cap.max_recv_sge;
>  			sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) +
>  				sizeof(struct rvt_rwqe);
> -			err = rvt_alloc_rq(&qp->r_rq, qp->r_rq.size * sz,
> +			ret = rvt_alloc_rq(&qp->r_rq, qp->r_rq.size * sz,
>  					   rdi->dparms.node, udata);
> -			if (err) {
> -				ret = ERR_PTR(err);
> +			if (ret)
>  				goto bail_driver_priv;
> -			}
>  		}
> 
>  		/*
> @@ -1206,40 +1199,35 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  		qp->s_max_sge = init_attr->cap.max_send_sge;
>  		if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR)
>  			qp->s_flags = RVT_S_SIGNAL_REQ_WR;
> -		err = alloc_ud_wq_attr(qp, rdi->dparms.node);
> -		if (err) {
> -			ret = (ERR_PTR(err));
> +		ret = alloc_ud_wq_attr(qp, rdi->dparms.node);
> +		if (ret)
>  			goto bail_rq_rvt;
> -		}
> 
>  		if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
>  			exclude_prefix = RVT_AIP_QP_PREFIX;
> 
> -		err = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
> +		ret = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
>  				init_attr->qp_type,
>  				init_attr->port_num,
>  				exclude_prefix);
> -		if (err < 0) {
> -			ret = ERR_PTR(err);
> +		if (ret < 0)
>  			goto bail_rq_wq;
> -		}
> -		qp->ibqp.qp_num = err;
> +
> +		qp->ibqp.qp_num = ret;
>  		if (init_attr->create_flags & IB_QP_CREATE_NETDEV_USE)
>  			qp->ibqp.qp_num |= RVT_AIP_QP_BASE;
>  		qp->port_num = init_attr->port_num;
>  		rvt_init_qp(rdi, qp, init_attr->qp_type);
>  		if (rdi->driver_f.qp_priv_init) {
> -			err = rdi->driver_f.qp_priv_init(rdi, qp, init_attr);
> -			if (err) {
> -				ret = ERR_PTR(err);
> +			ret = rdi->driver_f.qp_priv_init(rdi, qp, init_attr);
> +			if (ret)
>  				goto bail_rq_wq;
> -			}
>  		}
>  		break;
> 
>  	default:
>  		/* Don't support raw QPs */
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
>  	}
> 
>  	init_attr->cap.max_inline_data = 0;
> @@ -1252,28 +1240,24 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  		if (!qp->r_rq.wq) {
>  			__u64 offset = 0;
> 
> -			err = ib_copy_to_udata(udata, &offset,
> +			ret = ib_copy_to_udata(udata, &offset,
>  					       sizeof(offset));
> -			if (err) {
> -				ret = ERR_PTR(err);
> +			if (ret)
>  				goto bail_qpn;
> -			}
>  		} else {
>  			u32 s = sizeof(struct rvt_rwq) + qp->r_rq.size * sz;
> 
>  			qp->ip = rvt_create_mmap_info(rdi, s, udata,
>  						      qp->r_rq.wq);
>  			if (IS_ERR(qp->ip)) {
> -				ret = ERR_CAST(qp->ip);
> +				ret = PTR_ERR(qp->ip);
>  				goto bail_qpn;
>  			}
> 
> -			err = ib_copy_to_udata(udata, &qp->ip->offset,
> +			ret = ib_copy_to_udata(udata, &qp->ip->offset,
>  					       sizeof(qp->ip->offset));
> -			if (err) {
> -				ret = ERR_PTR(err);
> +			if (ret)
>  				goto bail_ip;
> -			}
>  		}
>  		qp->pid = current->pid;
>  	}
> @@ -1281,7 +1265,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  	spin_lock(&rdi->n_qps_lock);
>  	if (rdi->n_qps_allocated == rdi->dparms.props.max_qp) {
>  		spin_unlock(&rdi->n_qps_lock);
> -		ret = ERR_PTR(-ENOMEM);
> +		ret = ENOMEM;
>  		goto bail_ip;
>  	}
> 
> @@ -1307,9 +1291,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  		spin_unlock_irq(&rdi->pending_lock);
>  	}
> 
> -	ret = &qp->ibqp;
> -
> -	return ret;
> +	return 0;
> 
>  bail_ip:
>  	if (qp->ip)
> @@ -1330,11 +1312,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
>  bail_qp:
>  	kfree(qp->s_ack_queue);
>  	kfree(qp->r_sg_list);
> -	kfree(qp);
> -
> -bail_swq:
>  	vfree(swq);
> -
>  	return ret;
>  }
> 
> @@ -1769,7 +1747,6 @@ int rvt_destroy_qp(struct ib_qp *ibqp, struct
> ib_udata *udata)
>  	rdma_destroy_ah_attr(&qp->alt_ah_attr);
>  	free_ud_wq_attr(qp);
>  	vfree(qp->s_wq);
> -	kfree(qp);
>  	return 0;
>  }
> 
> diff --git a/drivers/infiniband/sw/rdmavt/qp.h
> b/drivers/infiniband/sw/rdmavt/qp.h
> index 2cdba1283bf6..bceb77c28c71 100644
> --- a/drivers/infiniband/sw/rdmavt/qp.h
> +++ b/drivers/infiniband/sw/rdmavt/qp.h
> @@ -52,9 +52,8 @@
> 
>  int rvt_driver_qp_init(struct rvt_dev_info *rdi);
>  void rvt_qp_exit(struct rvt_dev_info *rdi);
> -struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
> -			    struct ib_qp_init_attr *init_attr,
> -			    struct ib_udata *udata);
> +int rvt_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init_attr,
> +		  struct ib_udata *udata);
>  int rvt_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
>  		  int attr_mask, struct ib_udata *udata);
>  int rvt_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
> diff --git a/drivers/infiniband/sw/rdmavt/vt.c
> b/drivers/infiniband/sw/rdmavt/vt.c
> index ac17209816cd..d4526f38427e 100644
> --- a/drivers/infiniband/sw/rdmavt/vt.c
> +++ b/drivers/infiniband/sw/rdmavt/vt.c
> @@ -131,6 +131,13 @@ static int rvt_query_device(struct ib_device *ibdev,
>  	return 0;
>  }
> 
> +static int rvt_get_numa_node(struct ib_device *ibdev)
> +{
> +	struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
> +
> +	return rdi->dparms.node;
> +}
> +
>  static int rvt_modify_device(struct ib_device *device,
>  			     int device_modify_mask,
>  			     struct ib_device_modify *device_modify)
> @@ -380,6 +387,7 @@ static const struct ib_device_ops rvt_dev_ops = {
>  	.destroy_srq = rvt_destroy_srq,
>  	.detach_mcast = rvt_detach_mcast,
>  	.get_dma_mr = rvt_get_dma_mr,
> +	.get_numa_node = rvt_get_numa_node,
>  	.get_port_immutable = rvt_get_port_immutable,
>  	.map_mr_sg = rvt_map_mr_sg,
>  	.mmap = rvt_mmap,
> @@ -406,6 +414,7 @@ static const struct ib_device_ops rvt_dev_ops = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, rvt_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, rvt_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, rvt_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, rvt_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, rvt_srq, ibsrq),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, rvt_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c
> b/drivers/infiniband/sw/rxe/rxe_pool.c
> index 0b8e7c6255a2..ffa8420b4765 100644
> --- a/drivers/infiniband/sw/rxe/rxe_pool.c
> +++ b/drivers/infiniband/sw/rxe/rxe_pool.c
> @@ -41,7 +41,7 @@ struct rxe_type_info rxe_type_info[RXE_NUM_TYPES]
> = {
>  		.size		= sizeof(struct rxe_qp),
>  		.elem_offset	= offsetof(struct rxe_qp, pelem),
>  		.cleanup	= rxe_qp_cleanup,
> -		.flags		= RXE_POOL_INDEX,
> +		.flags		= RXE_POOL_INDEX |
> RXE_POOL_NO_ALLOC,
>  		.min_index	= RXE_MIN_QP_INDEX,
>  		.max_index	= RXE_MAX_QP_INDEX,
>  	},
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c
> b/drivers/infiniband/sw/rxe/rxe_verbs.c
> index f7b1a1f64c13..267b5a9c345d 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.c
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
> @@ -391,59 +391,52 @@ static int rxe_post_srq_recv(struct ib_srq *ibsrq,
> const struct ib_recv_wr *wr,
>  	return err;
>  }
> 
> -static struct ib_qp *rxe_create_qp(struct ib_pd *ibpd,
> -				   struct ib_qp_init_attr *init,
> -				   struct ib_udata *udata)
> +static int rxe_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init,
> +			 struct ib_udata *udata)
>  {
>  	int err;
> -	struct rxe_dev *rxe = to_rdev(ibpd->device);
> -	struct rxe_pd *pd = to_rpd(ibpd);
> -	struct rxe_qp *qp;
> +	struct rxe_dev *rxe = to_rdev(ibqp->device);
> +	struct rxe_pd *pd = to_rpd(ibqp->pd);
> +	struct rxe_qp *qp = to_rqp(ibqp);
>  	struct rxe_create_qp_resp __user *uresp = NULL;
> 
>  	if (udata) {
>  		if (udata->outlen < sizeof(*uresp))
> -			return ERR_PTR(-EINVAL);
> +			return -EINVAL;
>  		uresp = udata->outbuf;
>  	}
> 
>  	if (init->create_flags)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
>  	err = rxe_qp_chk_init(rxe, init);
>  	if (err)
> -		goto err1;
> -
> -	qp = rxe_alloc(&rxe->qp_pool);
> -	if (!qp) {
> -		err = -ENOMEM;
> -		goto err1;
> -	}
> +		return err;
> 
>  	if (udata) {
> -		if (udata->inlen) {
> -			err = -EINVAL;
> -			goto err2;
> -		}
> +		if (udata->inlen)
> +			return -EINVAL;
> +
>  		qp->is_user = true;
>  	} else {
>  		qp->is_user = false;
>  	}
> 
> -	rxe_add_index(qp);
> +	err = rxe_add_to_pool(&rxe->qp_pool, qp);
> +	if (err)
> +		return err;
> 
> -	err = rxe_qp_from_init(rxe, qp, pd, init, uresp, ibpd, udata);
> +	rxe_add_index(qp);
> +	err = rxe_qp_from_init(rxe, qp, pd, init, uresp, ibqp->pd, udata);
>  	if (err)
> -		goto err3;
> +		goto qp_init;
> 
> -	return &qp->ibqp;
> +	return 0;
> 
> -err3:
> +qp_init:
>  	rxe_drop_index(qp);
> -err2:
>  	rxe_drop_ref(qp);
> -err1:
> -	return ERR_PTR(err);
> +	return err;
>  }
> 
>  static int rxe_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
> @@ -1145,6 +1138,7 @@ static const struct ib_device_ops rxe_dev_ops = {
>  	INIT_RDMA_OBJ_SIZE(ib_ah, rxe_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_cq, rxe_cq, ibcq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, rxe_pd, ibpd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, rxe_qp, ibqp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, rxe_srq, ibsrq),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, rxe_ucontext, ibuc),
>  	INIT_RDMA_OBJ_SIZE(ib_mw, rxe_mw, ibmw),
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h
> b/drivers/infiniband/sw/rxe/rxe_verbs.h
> index 959a3260fcab..ac2a2148027f 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.h
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
> @@ -210,8 +210,8 @@ struct rxe_resp_info {
>  };
> 
>  struct rxe_qp {
> -	struct rxe_pool_entry	pelem;
>  	struct ib_qp		ibqp;
> +	struct rxe_pool_entry	pelem;
>  	struct ib_qp_attr	attr;
>  	unsigned int		valid;
>  	unsigned int		mtu;
> diff --git a/drivers/infiniband/sw/siw/siw_main.c
> b/drivers/infiniband/sw/siw/siw_main.c
> index cf55326f2ab4..9093e6a80b26 100644
> --- a/drivers/infiniband/sw/siw/siw_main.c
> +++ b/drivers/infiniband/sw/siw/siw_main.c
> @@ -297,6 +297,7 @@ static const struct ib_device_ops siw_device_ops = {
> 
>  	INIT_RDMA_OBJ_SIZE(ib_cq, siw_cq, base_cq),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, siw_pd, base_pd),
> +	INIT_RDMA_OBJ_SIZE(ib_qp, siw_qp, base_qp),
>  	INIT_RDMA_OBJ_SIZE(ib_srq, siw_srq, base_srq),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, siw_ucontext, base_ucontext),
>  };
> diff --git a/drivers/infiniband/sw/siw/siw_qp.c
> b/drivers/infiniband/sw/siw/siw_qp.c
> index ddb2e66f9f13..7e01f2438afc 100644
> --- a/drivers/infiniband/sw/siw/siw_qp.c
> +++ b/drivers/infiniband/sw/siw/siw_qp.c
> @@ -1344,6 +1344,4 @@ void siw_free_qp(struct kref *ref)
>  	siw_put_tx_cpu(qp->tx_cpu);
> 
>  	atomic_dec(&sdev->num_qp);
> -	siw_dbg_qp(qp, "free QP\n");
> -	kfree_rcu(qp, rcu);
>  }
> diff --git a/drivers/infiniband/sw/siw/siw_verbs.c
> b/drivers/infiniband/sw/siw/siw_verbs.c
> index 3f175f220a22..1b36350601fa 100644
> --- a/drivers/infiniband/sw/siw/siw_verbs.c
> +++ b/drivers/infiniband/sw/siw/siw_verbs.c
> @@ -285,16 +285,16 @@ siw_mmap_entry_insert(struct siw_ucontext
> *uctx,
>   *
>   * Create QP of requested size on given device.
>   *
> - * @pd:		Protection Domain
> + * @qp:		Queue pait
>   * @attrs:	Initial QP attributes.
>   * @udata:	used to provide QP ID, SQ and RQ size back to user.
>   */
> 
> -struct ib_qp *siw_create_qp(struct ib_pd *pd,
> -			    struct ib_qp_init_attr *attrs,
> -			    struct ib_udata *udata)
> +int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
> +		  struct ib_udata *udata)
>  {
> -	struct siw_qp *qp = NULL;
> +	struct ib_pd *pd = ibqp->pd;
> +	struct siw_qp *qp = to_siw_qp(ibqp);
>  	struct ib_device *base_dev = pd->device;
>  	struct siw_device *sdev = to_siw_dev(base_dev);
>  	struct siw_ucontext *uctx =
> @@ -307,17 +307,16 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
>  	siw_dbg(base_dev, "create new QP\n");
> 
>  	if (attrs->create_flags)
> -		return ERR_PTR(-EOPNOTSUPP);
> +		return -EOPNOTSUPP;
> 
>  	if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) {
>  		siw_dbg(base_dev, "too many QP's\n");
> -		rv = -ENOMEM;
> -		goto err_out;
> +		return -ENOMEM;
>  	}
>  	if (attrs->qp_type != IB_QPT_RC) {
>  		siw_dbg(base_dev, "only RC QP's supported\n");
>  		rv = -EOPNOTSUPP;
> -		goto err_out;
> +		goto err_atomic;
>  	}
>  	if ((attrs->cap.max_send_wr > SIW_MAX_QP_WR) ||
>  	    (attrs->cap.max_recv_wr > SIW_MAX_QP_WR) ||
> @@ -325,13 +324,13 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
>  	    (attrs->cap.max_recv_sge > SIW_MAX_SGE)) {
>  		siw_dbg(base_dev, "QP size error\n");
>  		rv = -EINVAL;
> -		goto err_out;
> +		goto err_atomic;
>  	}
>  	if (attrs->cap.max_inline_data > SIW_MAX_INLINE) {
>  		siw_dbg(base_dev, "max inline send: %d > %d\n",
>  			attrs->cap.max_inline_data, (int)SIW_MAX_INLINE);
>  		rv = -EINVAL;
> -		goto err_out;
> +		goto err_atomic;
>  	}
>  	/*
>  	 * NOTE: we allow for zero element SQ and RQ WQE's SGL's
> @@ -340,19 +339,15 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
>  	if (attrs->cap.max_send_wr + attrs->cap.max_recv_wr == 0) {
>  		siw_dbg(base_dev, "QP must have send or receive
> queue\n");
>  		rv = -EINVAL;
> -		goto err_out;
> +		goto err_atomic;
>  	}
> 
>  	if (!attrs->send_cq || (!attrs->recv_cq && !attrs->srq)) {
>  		siw_dbg(base_dev, "send CQ or receive CQ invalid\n");
>  		rv = -EINVAL;
> -		goto err_out;
> -	}
> -	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> -	if (!qp) {
> -		rv = -ENOMEM;
> -		goto err_out;
> +		goto err_atomic;
>  	}
> +
>  	init_rwsem(&qp->state_lock);
>  	spin_lock_init(&qp->sq_lock);
>  	spin_lock_init(&qp->rq_lock);
> @@ -360,7 +355,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
> 
>  	rv = siw_qp_add(sdev, qp);
>  	if (rv)
> -		goto err_out;
> +		goto err_atomic;
> 
>  	num_sqe = attrs->cap.max_send_wr;
>  	num_rqe = attrs->cap.max_recv_wr;
> @@ -482,23 +477,20 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
>  	list_add_tail(&qp->devq, &sdev->qp_list);
>  	spin_unlock_irqrestore(&sdev->lock, flags);
> 
> -	return &qp->base_qp;
> +	return 0;
> 
>  err_out_xa:
>  	xa_erase(&sdev->qp_xa, qp_id(qp));
> -err_out:
> -	if (qp) {
> -		if (uctx) {
> -			rdma_user_mmap_entry_remove(qp->sq_entry);
> -			rdma_user_mmap_entry_remove(qp->rq_entry);
> -		}
> -		vfree(qp->sendq);
> -		vfree(qp->recvq);
> -		kfree(qp);
> +	if (uctx) {
> +		rdma_user_mmap_entry_remove(qp->sq_entry);
> +		rdma_user_mmap_entry_remove(qp->rq_entry);
>  	}
> -	atomic_dec(&sdev->num_qp);
> +	vfree(qp->sendq);
> +	vfree(qp->recvq);
> 
> -	return ERR_PTR(rv);
> +err_atomic:
> +	atomic_dec(&sdev->num_qp);
> +	return rv;
>  }
> 
>  /*
> diff --git a/drivers/infiniband/sw/siw/siw_verbs.h
> b/drivers/infiniband/sw/siw/siw_verbs.h
> index 67ac08886a70..09964234f8d3 100644
> --- a/drivers/infiniband/sw/siw/siw_verbs.h
> +++ b/drivers/infiniband/sw/siw/siw_verbs.h
> @@ -50,9 +50,8 @@ int siw_query_gid(struct ib_device *base_dev, u32
> port, int idx,
>  		  union ib_gid *gid);
>  int siw_alloc_pd(struct ib_pd *base_pd, struct ib_udata *udata);
>  int siw_dealloc_pd(struct ib_pd *base_pd, struct ib_udata *udata);
> -struct ib_qp *siw_create_qp(struct ib_pd *base_pd,
> -			    struct ib_qp_init_attr *attr,
> -			    struct ib_udata *udata);
> +int siw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attr,
> +		  struct ib_udata *udata);
>  int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr,
>  		 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
>  int siw_verbs_modify_qp(struct ib_qp *base_qp, struct ib_qp_attr *attr,
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index 2dba30849731..8cd7d1fc719f 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -2268,8 +2268,13 @@ struct iw_cm_conn_param;
>  			 !__same_type(((struct drv_struct *)NULL)-
> >member,     \
>  				      struct ib_struct)))
> 
> -#define rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, gfp)                         \
> -	((struct ib_type *)kzalloc(ib_dev->ops.size_##ib_type, gfp))
> +#define rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, gfp)                          \
> +	((struct ib_type *)rdma_zalloc_obj(ib_dev, ib_dev-
> >ops.size_##ib_type, \
> +					   gfp, false))
> +
> +#define rdma_zalloc_drv_obj_numa(ib_dev, ib_type)                              \
> +	((struct ib_type *)rdma_zalloc_obj(ib_dev, ib_dev-
> >ops.size_##ib_type, \
> +					   GFP_KERNEL, true))
> 
>  #define rdma_zalloc_drv_obj(ib_dev, ib_type)                                   \
>  	rdma_zalloc_drv_obj_gfp(ib_dev, ib_type, GFP_KERNEL)
> @@ -2435,9 +2440,8 @@ struct ib_device_ops {
>  			  struct ib_udata *udata);
>  	int (*query_srq)(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
>  	int (*destroy_srq)(struct ib_srq *srq, struct ib_udata *udata);
> -	struct ib_qp *(*create_qp)(struct ib_pd *pd,
> -				   struct ib_qp_init_attr *qp_init_attr,
> -				   struct ib_udata *udata);
> +	int (*create_qp)(struct ib_qp *qp, struct ib_qp_init_attr
> *qp_init_attr,
> +			 struct ib_udata *udata);
>  	int (*modify_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
>  			 int qp_attr_mask, struct ib_udata *udata);
>  	int (*query_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
> @@ -2635,11 +2639,18 @@ struct ib_device_ops {
>  	int (*query_ucontext)(struct ib_ucontext *context,
>  			      struct uverbs_attr_bundle *attrs);
> 
> +	/*
> +	 * Provide NUMA node. This API exists for rdmavt/hfi1 only.
> +	 * Everyone else relies on Linux memory management model.
> +	 */
> +	int (*get_numa_node)(struct ib_device *dev);
> +
>  	DECLARE_RDMA_OBJ_SIZE(ib_ah);
>  	DECLARE_RDMA_OBJ_SIZE(ib_counters);
>  	DECLARE_RDMA_OBJ_SIZE(ib_cq);
>  	DECLARE_RDMA_OBJ_SIZE(ib_mw);
>  	DECLARE_RDMA_OBJ_SIZE(ib_pd);
> +	DECLARE_RDMA_OBJ_SIZE(ib_qp);
>  	DECLARE_RDMA_OBJ_SIZE(ib_rwq_ind_table);
>  	DECLARE_RDMA_OBJ_SIZE(ib_srq);
>  	DECLARE_RDMA_OBJ_SIZE(ib_ucontext);
> @@ -2746,6 +2757,15 @@ struct ib_device {
>  	u32 lag_flags;
>  };
> 
> +static inline void *rdma_zalloc_obj(struct ib_device *dev, size_t size,
> +				    gfp_t gfp, bool is_numa_aware)
> +{
> +	if (is_numa_aware && dev->ops.get_numa_node)
> +		return kzalloc_node(size, gfp, dev-
> >ops.get_numa_node(dev));
> +
> +	return kzalloc(size, gfp);
> +}
> +
>  struct ib_client_nl_info;
>  struct ib_client {
>  	const char *name;
> --
> 2.31.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH rdma-next v1 0/9] QP allocation changes
  2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
                   ` (8 preceding siblings ...)
  2021-07-23 11:39 ` [PATCH rdma-next v1 9/9] RDMA/mlx5: Drop in-driver verbs object creations Leon Romanovsky
@ 2021-08-03 17:22 ` Jason Gunthorpe
  9 siblings, 0 replies; 12+ messages in thread
From: Jason Gunthorpe @ 2021-08-03 17:22 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Doug Ledford, Leon Romanovsky, Adit Ranadive, Ariel Elior,
	Bernard Metzler, Christian Benvenuti, Dennis Dalessandro,
	Gal Pressman, linux-kernel, linux-rdma, Michal Kalderon,
	Mike Marciniszyn, Mustafa Ismail, Naresh Kumar PBS,
	Nelson Escobar, Potnuri Bharat Teja, Selvin Xavier,
	Shiraz Saleem, Steve Wise, VMware PV-Drivers, Weihang Li,
	Wenpeng Liang, Yishai Hadas, Zhu Yanjun

On Fri, Jul 23, 2021 at 02:39:42PM +0300, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro@nvidia.com>
> 
> Changelog:
> v1:
>  * Added ROB tags
>  * Deleted already existed double rwq_ind_tbl assignment
>  * Deleted hr_qp->ibqp.qp_type assignment
> v0: https://lore.kernel.org/lkml/cover.1626609283.git.leonro@nvidia.com
> 
> -----------------------------------------------------------------------------
> Hi,
> 
> This series convert IB/core to use core allocation scheme for the QP
> objects.
> 
> Thanks
> 
> Leon Romanovsky (9):
>   RDMA/hns: Don't skip IB creation flow for regular RC QP
>   RDMA/hns: Don't overwrite supplied QP attributes
>   RDMA/efa: Remove double QP type assignment
>   RDMA/mlx5: Cancel pkey work before destroying device resources
>   RDMA/mlx5: Delete device resource mutex that didn't protect anything
>   RDMA/mlx5: Rework custom driver QP type creation
>   RDMA/rdmavt: Decouple QP and SGE lists allocations
>   RDMA: Globally allocate and release QP memory
>   RDMA/mlx5: Drop in-driver verbs object creations

Applied to for-next, thanks

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-08-03 17:22 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-23 11:39 [PATCH rdma-next v1 0/9] QP allocation changes Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 1/9] RDMA/hns: Don't skip IB creation flow for regular RC QP Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 2/9] RDMA/hns: Don't overwrite supplied QP attributes Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 3/9] RDMA/efa: Remove double QP type assignment Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 4/9] RDMA/mlx5: Cancel pkey work before destroying device resources Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 5/9] RDMA/mlx5: Delete device resource mutex that didn't protect anything Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 6/9] RDMA/mlx5: Rework custom driver QP type creation Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 7/9] RDMA/rdmavt: Decouple QP and SGE lists allocations Leon Romanovsky
2021-07-23 11:39 ` [PATCH rdma-next v1 8/9] RDMA: Globally allocate and release QP memory Leon Romanovsky
2021-07-29 20:20   ` Nikolova, Tatyana E
2021-07-23 11:39 ` [PATCH rdma-next v1 9/9] RDMA/mlx5: Drop in-driver verbs object creations Leon Romanovsky
2021-08-03 17:22 ` [PATCH rdma-next v1 0/9] QP allocation changes Jason Gunthorpe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).