diff mbox series

[v2,7/7] IB/verbs: destroy_qp verb need ib_udata

Message ID 20181014070445.4130-8-shamir.rabinovitch@oracle.com (mailing list archive)
State Changes Requested
Headers show
Series convey ib_ucontext via ib_udata | expand

Commit Message

Shamir Rabinovitch Oct. 14, 2018, 7:04 a.m. UTC
Prepare the code for shared ib_x model.

Some flows in the code that involve destroy_qp verb rely on ucontext
from the ib_pd. Future patch will remove the information from ib_pd.
Convey the ib_ucontext via ib_udata.

Signed-off-by: Shamir Rabinovitch <shamir.rabinovitch@oracle.com>
---
 drivers/infiniband/core/uverbs_cmd.c          |  2 +-
 drivers/infiniband/core/uverbs_std_types.c    |  6 ++-
 drivers/infiniband/core/verbs.c               | 37 +++++++++++++++----
 drivers/infiniband/hw/bnxt_re/ib_verbs.c      |  2 +-
 drivers/infiniband/hw/bnxt_re/ib_verbs.h      |  2 +-
 drivers/infiniband/hw/cxgb3/iwch_provider.c   |  8 ++--
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h        |  2 +-
 drivers/infiniband/hw/cxgb4/qp.c              |  2 +-
 drivers/infiniband/hw/i40iw/i40iw_verbs.c     |  5 ++-
 drivers/infiniband/hw/mlx4/mlx4_ib.h          |  2 +-
 drivers/infiniband/hw/mlx4/qp.c               |  5 ++-
 drivers/infiniband/hw/mlx5/gsi.c              |  5 ++-
 drivers/infiniband/hw/mlx5/main.c             |  4 +-
 drivers/infiniband/hw/mlx5/mlx5_ib.h          |  5 ++-
 drivers/infiniband/hw/mlx5/qp.c               |  4 +-
 drivers/infiniband/hw/mthca/mthca_provider.c  |  2 +-
 drivers/infiniband/hw/nes/nes_verbs.c         |  2 +-
 drivers/infiniband/hw/ocrdma/ocrdma_verbs.c   |  2 +-
 drivers/infiniband/hw/ocrdma/ocrdma_verbs.h   |  2 +-
 drivers/infiniband/hw/qedr/verbs.c            |  2 +-
 drivers/infiniband/hw/qedr/verbs.h            |  2 +-
 drivers/infiniband/hw/usnic/usnic_ib_verbs.c  |  2 +-
 drivers/infiniband/hw/usnic/usnic_ib_verbs.h  |  2 +-
 drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c  |  2 +-
 .../infiniband/hw/vmw_pvrdma/pvrdma_verbs.h   |  2 +-
 drivers/infiniband/sw/rxe/rxe_verbs.c         |  2 +-
 include/rdma/ib_verbs.h                       | 27 +++++++++++++-
 27 files changed, 98 insertions(+), 42 deletions(-)

Comments

kernel test robot Oct. 14, 2018, 11:55 p.m. UTC | #1
Hi Shamir,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on rdma/for-next]
[also build test ERROR on v4.19-rc7 next-20181012]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Shamir-Rabinovitch/convey-ib_ucontext-via-ib_udata/20181015-021539
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git for-next
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

>> drivers/infiniband/core/uverbs_std_types.c:79:34: warning: Using plain integer as NULL pointer
   drivers/infiniband/core/uverbs_std_types.c:131:34: warning: Using plain integer as NULL pointer
   drivers/infiniband/core/uverbs_std_types.c:192:34: warning: Using plain integer as NULL pointer
--
>> drivers/infiniband/core/uverbs_std_types_mr.c:39:34: warning: Using plain integer as NULL pointer
   drivers/infiniband/core/uverbs_std_types_mr.c:58:34: warning: Using plain integer as NULL pointer
--
>> drivers/infiniband/core/verbs.c:340:9: error: undefined identifier 'rdma_is_user_pd'
   drivers/infiniband/core/verbs.c:1228:13: error: undefined identifier 'rdma_is_user_pd'
   drivers/infiniband/core/verbs.c:1905:13: error: undefined identifier 'rdma_is_user_pd'
   drivers/infiniband/core/verbs.c:1989:13: error: undefined identifier 'rdma_is_user_pd'
   drivers/infiniband/core/verbs.c:2015:13: error: undefined identifier 'rdma_is_user_pd'
   In file included from arch/x86/include/asm/bug.h:83:0,
                    from include/linux/bug.h:5,
                    from include/linux/mmdebug.h:5,
                    from include/linux/gfp.h:5,
                    from include/linux/slab.h:15,
                    from drivers/infiniband/core/verbs.c:43:
   drivers/infiniband/core/verbs.c: In function 'ib_dealloc_pd':
   drivers/infiniband/core/verbs.c:340:10: error: implicit declaration of function 'rdma_is_user_pd'; did you mean 'rdma_is_zero_gid'? [-Werror=implicit-function-declaration]
     WARN_ON(rdma_is_user_pd(pd));
             ^
   include/asm-generic/bug.h:122:25: note: in definition of macro 'WARN_ON'
     int __ret_warn_on = !!(condition);    \
                            ^~~~~~~~~
   cc1: some warnings being treated as errors
--
>> drivers/infiniband/hw/hns/hns_roce_main.c:498:41: warning: incorrect type in assignment (different argument counts)
   drivers/infiniband/hw/hns/hns_roce_main.c:498:41:    expected int ( *dealloc_pd )( ... )
   drivers/infiniband/hw/hns/hns_roce_main.c:498:41:    got int ( *<noident> )( ... )
   drivers/infiniband/hw/hns/hns_roce_main.c:509:41: warning: incorrect type in assignment (different argument counts)
   drivers/infiniband/hw/hns/hns_roce_main.c:509:41:    expected int ( *destroy_qp )( ... )
   drivers/infiniband/hw/hns/hns_roce_main.c:509:41:    got int ( *const destroy_qp )( ... )
   drivers/infiniband/hw/hns/hns_roce_main.c:523:41: warning: incorrect type in assignment (different argument counts)
   drivers/infiniband/hw/hns/hns_roce_main.c:523:41:    expected int ( *dereg_mr )( ... )
   drivers/infiniband/hw/hns/hns_roce_main.c:523:41:    got int ( *<noident> )( ... )
   drivers/infiniband/hw/hns/hns_roce_main.c: In function 'hns_roce_register_device':
   drivers/infiniband/hw/hns/hns_roce_main.c:498:22: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     ib_dev->dealloc_pd  = hns_roce_dealloc_pd;
                         ^
   drivers/infiniband/hw/hns/hns_roce_main.c:509:22: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     ib_dev->destroy_qp  = hr_dev->hw->destroy_qp;
                         ^
   drivers/infiniband/hw/hns/hns_roce_main.c:523:20: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     ib_dev->dereg_mr  = hns_roce_dereg_mr;
                       ^
   cc1: some warnings being treated as errors

vim +/rdma_is_user_pd +340 drivers/infiniband/core/verbs.c

eda5b925 Shamir Rabinovitch 2018-10-14  327  
eda5b925 Shamir Rabinovitch 2018-10-14  328  /**
eda5b925 Shamir Rabinovitch 2018-10-14  329   * ib_dealloc_pd - Deallocates a protection domain.
eda5b925 Shamir Rabinovitch 2018-10-14  330   * @pd: The protection domain to deallocate.
eda5b925 Shamir Rabinovitch 2018-10-14  331   *
eda5b925 Shamir Rabinovitch 2018-10-14  332   * It is an error to call this function while any resources in the pd still
eda5b925 Shamir Rabinovitch 2018-10-14  333   * exist.  The caller is responsible to synchronously destroy them and
eda5b925 Shamir Rabinovitch 2018-10-14  334   * guarantee no new allocations will happen.
eda5b925 Shamir Rabinovitch 2018-10-14  335   *
eda5b925 Shamir Rabinovitch 2018-10-14  336   * NOTE: Never call this function from uverbs!
eda5b925 Shamir Rabinovitch 2018-10-14  337   */
eda5b925 Shamir Rabinovitch 2018-10-14  338  void ib_dealloc_pd(struct ib_pd *pd)
eda5b925 Shamir Rabinovitch 2018-10-14  339  {
eda5b925 Shamir Rabinovitch 2018-10-14 @340  	WARN_ON(rdma_is_user_pd(pd));
eda5b925 Shamir Rabinovitch 2018-10-14  341  	ib_dealloc_pd_user(pd, NULL);
eda5b925 Shamir Rabinovitch 2018-10-14  342  }
^1da177e Linus Torvalds     2005-04-16  343  EXPORT_SYMBOL(ib_dealloc_pd);
^1da177e Linus Torvalds     2005-04-16  344  

:::::: The code at line 340 was first introduced by commit
:::::: eda5b92561d6d57782b4f6097b71886b85e3ca08 IB/verbs: dealloc_pd verb need ib_udata

:::::: TO: Shamir Rabinovitch <shamir.rabinovitch@oracle.com>
:::::: CC: 0day robot <lkp@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Doug Ledford Oct. 17, 2018, 3:36 p.m. UTC | #2
On Mon, 2018-10-15 at 07:55 +0800, kbuild test robot wrote:
> Hi Shamir,
> 
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on rdma/for-next]
> [also build test ERROR on v4.19-rc7 next-20181012]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Shamir-Rabinovitch/convey-ib_ucontext-via-ib_udata/20181015-021539
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git for-next
> config: x86_64-allmodconfig (attached as .config)
> compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=x86_64 
> 
> All error/warnings (new ones prefixed by >>):
> 
> > > drivers/infiniband/core/uverbs_std_types.c:79:34: warning: Using plain integer as NULL pointer
> 
>    drivers/infiniband/core/uverbs_std_types.c:131:34: warning: Using plain integer as NULL pointer
>    drivers/infiniband/core/uverbs_std_types.c:192:34: warning: Using plain integer as NULL pointer
> --
> > > drivers/infiniband/core/uverbs_std_types_mr.c:39:34: warning: Using plain integer as NULL pointer
> 
>    drivers/infiniband/core/uverbs_std_types_mr.c:58:34: warning: Using plain integer as NULL pointer
> --
> > > drivers/infiniband/core/verbs.c:340:9: error: undefined identifier 'rdma_is_user_pd'
> 
>    drivers/infiniband/core/verbs.c:1228:13: error: undefined identifier 'rdma_is_user_pd'
>    drivers/infiniband/core/verbs.c:1905:13: error: undefined identifier 'rdma_is_user_pd'
>    drivers/infiniband/core/verbs.c:1989:13: error: undefined identifier 'rdma_is_user_pd'
>    drivers/infiniband/core/verbs.c:2015:13: error: undefined identifier 'rdma_is_user_pd'
>    In file included from arch/x86/include/asm/bug.h:83:0,
>                     from include/linux/bug.h:5,
>                     from include/linux/mmdebug.h:5,
>                     from include/linux/gfp.h:5,
>                     from include/linux/slab.h:15,
>                     from drivers/infiniband/core/verbs.c:43:
>    drivers/infiniband/core/verbs.c: In function 'ib_dealloc_pd':
>    drivers/infiniband/core/verbs.c:340:10: error: implicit declaration of function 'rdma_is_user_pd'; did you mean 'rdma_is_zero_gid'? [-Werror=implicit-function-declaration]
>      WARN_ON(rdma_is_user_pd(pd));
>              ^
>    include/asm-generic/bug.h:122:25: note: in definition of macro 'WARN_ON'
>      int __ret_warn_on = !!(condition);    \
>                             ^~~~~~~~~
>    cc1: some warnings being treated as errors

Are you even building this locally before submitting it?  Just so you
know, I ignore anything with kbuild errors.  Please fix those up and
resubmit.
Shamir Rabinovitch Oct. 18, 2018, 7:31 a.m. UTC | #3
On Wed, Oct 17, 2018 at 11:36:56AM -0400, Doug Ledford wrote:
> On Mon, 2018-10-15 at 07:55 +0800, kbuild test robot wrote:

[...]

> >    drivers/infiniband/core/verbs.c: In function 'ib_dealloc_pd':
> >    drivers/infiniband/core/verbs.c:340:10: error: implicit declaration of function 'rdma_is_user_pd'; did you mean 'rdma_is_zero_gid'? [-Werror=implicit-function-declaration]
> >      WARN_ON(rdma_is_user_pd(pd));
> >              ^
> >    include/asm-generic/bug.h:122:25: note: in definition of macro 'WARN_ON'
> >      int __ret_warn_on = !!(condition);    \
> >                             ^~~~~~~~~
> >    cc1: some warnings being treated as errors
> 
> Are you even building this locally before submitting it?  Just so you
> know, I ignore anything with kbuild errors.  Please fix those up and
> resubmit.
> 

Sure. It was built and tested. But Jason asked me to split the (long)
series of patches to 3 series. This patch is part of series #2. Series
#1 has this commit that add the (assumed) missing function: 
[PATCH v2 2/4] IB/verbs: Add rdma_is_user_pd function

We have 3 patch sets that kbuild test need to apply them all by order:
1: [PATCH v2 0/4] figure uverbs/kernel ib_pd w/o using ib_pd uobject
2: [PATCH v2 0/7] convey ib_ucontext via ib_udata
3: [PATCH v2 0/4] remove ib_pd uobject pointer

Any way to still split those and not have the kbuild assuming that it
can apply each of those independently?

Thanks, Shamir

> -- 
> Doug Ledford <dledford@redhat.com>
>     GPG KeyID: B826A3330E572FDD
>     Key fingerprint = AE6B 1BDA 122B 23B4 265B  1274 B826 A333 0E57 2FDD
Doug Ledford Oct. 18, 2018, 12:25 p.m. UTC | #4
On 10/18/2018 3:31 AM, Shamir Rabinovitch wrote:
> On Wed, Oct 17, 2018 at 11:36:56AM -0400, Doug Ledford wrote:
>> On Mon, 2018-10-15 at 07:55 +0800, kbuild test robot wrote:
> 
> [...]
> 
>>>    drivers/infiniband/core/verbs.c: In function 'ib_dealloc_pd':
>>>    drivers/infiniband/core/verbs.c:340:10: error: implicit declaration of function 'rdma_is_user_pd'; did you mean 'rdma_is_zero_gid'? [-Werror=implicit-function-declaration]
>>>      WARN_ON(rdma_is_user_pd(pd));
>>>              ^
>>>    include/asm-generic/bug.h:122:25: note: in definition of macro 'WARN_ON'
>>>      int __ret_warn_on = !!(condition);    \
>>>                             ^~~~~~~~~
>>>    cc1: some warnings being treated as errors
>>
>> Are you even building this locally before submitting it?  Just so you
>> know, I ignore anything with kbuild errors.  Please fix those up and
>> resubmit.
>>
> 
> Sure. It was built and tested. But Jason asked me to split the (long)
> series of patches to 3 series. This patch is part of series #2. Series
> #1 has this commit that add the (assumed) missing function: 
> [PATCH v2 2/4] IB/verbs: Add rdma_is_user_pd function
> 
> We have 3 patch sets that kbuild test need to apply them all by order:
> 1: [PATCH v2 0/4] figure uverbs/kernel ib_pd w/o using ib_pd uobject
> 2: [PATCH v2 0/7] convey ib_ucontext via ib_udata
> 3: [PATCH v2 0/4] remove ib_pd uobject pointer
> 
> Any way to still split those and not have the kbuild assuming that it
> can apply each of those independently?

Not that I know of.  And in this particular case it looked like there
were some resends or something that added to the confusion.  Plus some
of the series had already been removed from patchworks.  Jason knows
what he requested on this series, I may punt to him on it ;-)
diff mbox series

Patch

diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index afa3a6ebb4e0..f2bb0ebbad69 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1789,7 +1789,7 @@  ssize_t ib_uverbs_open_qp(struct ib_uverbs_file *file,
 	return uobj_alloc_commit(&obj->uevent.uobject, in_len);
 
 err_destroy:
-	ib_destroy_qp(qp);
+	ib_destroy_qp_user(qp, &udata);
 err_xrcd:
 	uobj_put_read(xrcd_uobj);
 err_put:
diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c
index 302aa5261cda..59e527a6ffc1 100644
--- a/drivers/infiniband/core/uverbs_std_types.c
+++ b/drivers/infiniband/core/uverbs_std_types.c
@@ -76,6 +76,7 @@  static int uverbs_free_qp(struct ib_uobject *uobject,
 	struct ib_qp *qp = uobject->object;
 	struct ib_uqp_object *uqp =
 		container_of(uobject, struct ib_uqp_object, uevent.uobject);
+	struct ib_udata udata = {0};
 	int ret;
 
 	/*
@@ -92,7 +93,10 @@  static int uverbs_free_qp(struct ib_uobject *uobject,
 		ib_uverbs_detach_umcast(qp, uqp);
 	}
 
-	ret = ib_destroy_qp(qp);
+	ib_uverbs_init_udata_buf_or_null(&udata, NULL, NULL, 0, 0,
+					 uobject->context);
+
+	ret = ib_destroy_qp_user(qp, &udata);
 	if (ib_is_destroy_retryable(ret, why, uobject))
 		return ret;
 
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index e59372af72ac..d972f1dbf8fd 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1106,7 +1106,8 @@  struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
 EXPORT_SYMBOL(ib_open_qp);
 
 static struct ib_qp *ib_create_xrc_qp(struct ib_qp *qp,
-		struct ib_qp_init_attr *qp_init_attr)
+		struct ib_qp_init_attr *qp_init_attr,
+		struct ib_udata *udata)
 {
 	struct ib_qp *real_qp = qp;
 
@@ -1124,12 +1125,13 @@  static struct ib_qp *ib_create_xrc_qp(struct ib_qp *qp,
 	if (!IS_ERR(qp))
 		__ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
 	else
-		real_qp->device->destroy_qp(real_qp);
+		real_qp->device->destroy_qp(real_qp, udata);
 	return qp;
 }
 
-struct ib_qp *ib_create_qp(struct ib_pd *pd,
-			   struct ib_qp_init_attr *qp_init_attr)
+struct ib_qp *ib_create_qp_user(struct ib_pd *pd,
+				struct ib_qp_init_attr *qp_init_attr,
+				struct ib_udata *udata)
 {
 	struct ib_device *device = pd ? pd->device : qp_init_attr->xrcd->device;
 	struct ib_qp *qp;
@@ -1172,7 +1174,7 @@  struct ib_qp *ib_create_qp(struct ib_pd *pd,
 	qp->port = 0;
 
 	if (qp_init_attr->qp_type == IB_QPT_XRC_TGT)
-		return ib_create_xrc_qp(qp, qp_init_attr);
+		return ib_create_xrc_qp(qp, qp_init_attr, udata);
 
 	qp->event_handler = qp_init_attr->event_handler;
 	qp->qp_context = qp_init_attr->qp_context;
@@ -1217,6 +1219,17 @@  struct ib_qp *ib_create_qp(struct ib_pd *pd,
 
 	return qp;
 }
+EXPORT_SYMBOL(ib_create_qp_user);
+
+/* NOTE: Never call this function from uverbs! */
+struct ib_qp *ib_create_qp(struct ib_pd *pd,
+			   struct ib_qp_init_attr *qp_init_attr)
+{
+	if (WARN_ON(rdma_is_user_pd(pd)))
+		return ERR_PTR(-EINVAL);
+
+	return ib_create_qp_user(pd, qp_init_attr, NULL);
+}
 EXPORT_SYMBOL(ib_create_qp);
 
 static const struct {
@@ -1827,7 +1840,7 @@  static int __ib_destroy_shared_qp(struct ib_qp *qp)
 	return 0;
 }
 
-int ib_destroy_qp(struct ib_qp *qp)
+int ib_destroy_qp_user(struct ib_qp *qp, struct ib_udata *udata)
 {
 	const struct ib_gid_attr *alt_path_sgid_attr = qp->alt_path_sgid_attr;
 	const struct ib_gid_attr *av_sgid_attr = qp->av_sgid_attr;
@@ -1859,7 +1872,7 @@  int ib_destroy_qp(struct ib_qp *qp)
 		rdma_rw_cleanup_mrs(qp);
 
 	rdma_restrack_del(&qp->res);
-	ret = qp->device->destroy_qp(qp);
+	ret = qp->device->destroy_qp(qp, udata);
 	if (!ret) {
 		if (alt_path_sgid_attr)
 			rdma_put_gid_attr(alt_path_sgid_attr);
@@ -1884,6 +1897,16 @@  int ib_destroy_qp(struct ib_qp *qp)
 
 	return ret;
 }
+EXPORT_SYMBOL(ib_destroy_qp_user);
+
+/* NOTE: Never call this function from uverbs! */
+int ib_destroy_qp(struct ib_qp *qp)
+{
+	if (WARN_ON(rdma_is_user_pd(qp->pd)))
+		return -EINVAL;
+
+	return ib_destroy_qp_user(qp, NULL);
+}
 EXPORT_SYMBOL(ib_destroy_qp);
 
 /* Completion queues */
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index a2982a160123..cceaa6133903 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -797,7 +797,7 @@  void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp,
 }
 
 /* Queue Pairs */
-int bnxt_re_destroy_qp(struct ib_qp *ib_qp)
+int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 {
 	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
 	struct bnxt_re_dev *rdev = qp->rdev;
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index d73a5c74c85d..14b853249d59 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -190,7 +190,7 @@  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,
 		     int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
-int bnxt_re_destroy_qp(struct ib_qp *qp);
+int bnxt_re_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
 int bnxt_re_post_send(struct ib_qp *qp, const struct ib_send_wr *send_wr,
 		      const struct ib_send_wr **bad_send_wr);
 int bnxt_re_post_recv(struct ib_qp *qp, const struct ib_recv_wr *recv_wr,
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 059280fc1eab..4d1a86999a2a 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -757,7 +757,7 @@  static int iwch_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
 	return ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, iwch_set_page);
 }
 
-static int iwch_destroy_qp(struct ib_qp *ib_qp)
+static int iwch_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 {
 	struct iwch_dev *rhp;
 	struct iwch_qp *qhp;
@@ -899,14 +899,14 @@  static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
 
 		mm1 = kmalloc(sizeof *mm1, GFP_KERNEL);
 		if (!mm1) {
-			iwch_destroy_qp(&qhp->ibqp);
+			iwch_destroy_qp(&qhp->ibqp, udata);
 			return ERR_PTR(-ENOMEM);
 		}
 
 		mm2 = kmalloc(sizeof *mm2, GFP_KERNEL);
 		if (!mm2) {
 			kfree(mm1);
-			iwch_destroy_qp(&qhp->ibqp);
+			iwch_destroy_qp(&qhp->ibqp, udata);
 			return ERR_PTR(-ENOMEM);
 		}
 
@@ -923,7 +923,7 @@  static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
 		if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
 			kfree(mm1);
 			kfree(mm2);
-			iwch_destroy_qp(&qhp->ibqp);
+			iwch_destroy_qp(&qhp->ibqp, udata);
 			return ERR_PTR(-EFAULT);
 		}
 		mm1->key = uresp.key;
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 79016715720b..0d64e72b2303 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -1076,7 +1076,7 @@  int c4iw_destroy_srq(struct ib_srq *ib_srq);
 struct ib_srq *c4iw_create_srq(struct ib_pd *pd,
 			       struct ib_srq_init_attr *attrs,
 			       struct ib_udata *udata);
-int c4iw_destroy_qp(struct ib_qp *ib_qp);
+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);
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 74eb70300fdf..6103c1a6caec 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -2089,7 +2089,7 @@  int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 	return ret;
 }
 
-int c4iw_destroy_qp(struct ib_qp *ib_qp)
+int c4iw_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 {
 	struct c4iw_dev *rhp;
 	struct c4iw_qp *qhp;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
index 201c030acd50..408a65fc00b3 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
@@ -443,8 +443,9 @@  static void i40iw_clean_cqes(struct i40iw_qp *iwqp, struct i40iw_cq *iwcq)
 /**
  * i40iw_destroy_qp - destroy qp
  * @ibqp: qp's ib pointer also to get to device's qp address
+ * @udata: user data (if any)
  */
-static int i40iw_destroy_qp(struct ib_qp *ibqp)
+static int i40iw_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
 	struct i40iw_qp *iwqp = to_iwqp(ibqp);
 
@@ -775,7 +776,7 @@  static struct ib_qp *i40iw_create_qp(struct ib_pd *ibpd,
 		err_code = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
 		if (err_code) {
 			i40iw_pr_err("copy_to_udata failed\n");
-			i40iw_destroy_qp(&iwqp->ibqp);
+			i40iw_destroy_qp(&iwqp->ibqp, udata);
 			   /* let the completion of the qp destroy free the qp */
 			return ERR_PTR(err_code);
 		}
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index d4c45fdfd0c9..4662e39caecd 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -776,7 +776,7 @@  int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *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_destroy_qp(struct ib_qp *qp);
+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);
 int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 227f419df222..78e0a430e6be 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1572,7 +1572,8 @@  struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 		if (is_eth &&
 		    dev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ROCE_V1_V2) {
 			init_attr->create_flags |= MLX4_IB_QP_CREATE_ROCE_V2_GSI;
-			sqp->roce_v2_gsi = ib_create_qp(pd, init_attr);
+			sqp->roce_v2_gsi = ib_create_qp_user(pd, init_attr,
+							     udata);
 
 			if (IS_ERR(sqp->roce_v2_gsi)) {
 				pr_err("Failed to create GSI QP for RoCEv2 (%ld)\n", PTR_ERR(sqp->roce_v2_gsi));
@@ -1624,7 +1625,7 @@  static int _mlx4_ib_destroy_qp(struct ib_qp *qp)
 	return 0;
 }
 
-int mlx4_ib_destroy_qp(struct ib_qp *qp)
+int mlx4_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 {
 	struct mlx4_ib_qp *mqp = to_mqp(qp);
 
diff --git a/drivers/infiniband/hw/mlx5/gsi.c b/drivers/infiniband/hw/mlx5/gsi.c
index 4950df3f71b6..8bdd35286ead 100644
--- a/drivers/infiniband/hw/mlx5/gsi.c
+++ b/drivers/infiniband/hw/mlx5/gsi.c
@@ -113,7 +113,8 @@  static void handle_single_completion(struct ib_cq *cq, struct ib_wc *wc)
 }
 
 struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd,
-				    struct ib_qp_init_attr *init_attr)
+				    struct ib_qp_init_attr *init_attr,
+				    struct ib_udata *udata)
 {
 	struct mlx5_ib_dev *dev = to_mdev(pd->device);
 	struct mlx5_ib_gsi_qp *gsi;
@@ -184,7 +185,7 @@  struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd,
 		hw_init_attr.cap.max_send_sge = 0;
 		hw_init_attr.cap.max_inline_data = 0;
 	}
-	gsi->rx_qp = ib_create_qp(pd, &hw_init_attr);
+	gsi->rx_qp = ib_create_qp_user(pd, &hw_init_attr, udata);
 	if (IS_ERR(gsi->rx_qp)) {
 		mlx5_ib_warn(dev, "unable to create hardware GSI QP. error %ld\n",
 			     PTR_ERR(gsi->rx_qp));
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 09a298a5043f..885129678837 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -4415,7 +4415,7 @@  static void destroy_umrc_res(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);
+		mlx5_ib_destroy_qp(dev->umrc.qp, NULL);
 	if (dev->umrc.cq)
 		ib_free_cq(dev->umrc.cq);
 	if (dev->umrc.pd)
@@ -4520,7 +4520,7 @@  static int create_umr_res(struct mlx5_ib_dev *dev)
 	return 0;
 
 error_4:
-	mlx5_ib_destroy_qp(qp);
+	mlx5_ib_destroy_qp(qp, NULL);
 	dev->umrc.qp = NULL;
 
 error_3:
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 2561594df671..fe1032ced752 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -1045,7 +1045,7 @@  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,
 		     struct ib_qp_init_attr *qp_init_attr);
-int mlx5_ib_destroy_qp(struct ib_qp *qp);
+int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
 void mlx5_ib_drain_sq(struct ib_qp *qp);
 void mlx5_ib_drain_rq(struct ib_qp *qp);
 int mlx5_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
@@ -1226,7 +1226,8 @@  int mlx5_ib_init_cong_debugfs(struct mlx5_ib_dev *dev, u8 port_num);
 
 /* GSI QP helper functions */
 struct ib_qp *mlx5_ib_gsi_create_qp(struct ib_pd *pd,
-				    struct ib_qp_init_attr *init_attr);
+				    struct ib_qp_init_attr *init_attr,
+				    struct ib_udata *udata);
 int mlx5_ib_gsi_destroy_qp(struct ib_qp *qp);
 int mlx5_ib_gsi_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
 			  int attr_mask);
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index f13447cfba12..edfbcfa90555 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -2452,7 +2452,7 @@  struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
 		break;
 
 	case IB_QPT_GSI:
-		return mlx5_ib_gsi_create_qp(pd, init_attr);
+		return mlx5_ib_gsi_create_qp(pd, init_attr, udata);
 
 	case IB_QPT_RAW_IPV6:
 	case IB_QPT_RAW_ETHERTYPE:
@@ -2489,7 +2489,7 @@  static int mlx5_ib_destroy_dct(struct mlx5_ib_qp *mqp)
 	return 0;
 }
 
-int mlx5_ib_destroy_qp(struct ib_qp *qp)
+int mlx5_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 {
 	struct mlx5_ib_dev *dev = to_mdev(qp->device);
 	struct mlx5_ib_qp *mqp = to_mqp(qp);
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 303de9955ad6..e0536325de81 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -632,7 +632,7 @@  static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
 	return &qp->ibqp;
 }
 
-static int mthca_destroy_qp(struct ib_qp *qp)
+static int mthca_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 {
 	if (qp->uobject) {
 		mthca_unmap_user_db(to_mdev(qp->device),
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 5f69d076b742..185ad94b0daf 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1334,7 +1334,7 @@  static void nes_clean_cq(struct nes_qp *nesqp, struct nes_cq *nescq)
 /**
  * nes_destroy_qp
  */
-static int nes_destroy_qp(struct ib_qp *ibqp)
+static int nes_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
 	struct nes_qp *nesqp = to_nesqp(ibqp);
 	struct nes_ucontext *nes_ucontext;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 84a815277788..b04b42bf9a24 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -1741,7 +1741,7 @@  void ocrdma_del_flush_qp(struct ocrdma_qp *qp)
 	spin_unlock_irqrestore(&dev->flush_q_lock, flags);
 }
 
-int ocrdma_destroy_qp(struct ib_qp *ibqp)
+int ocrdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
 	struct ocrdma_pd *pd;
 	struct ocrdma_qp *qp;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
index 8bc96aaf0972..176dabd22714 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -91,7 +91,7 @@  int ocrdma_modify_qp(struct ib_qp *, struct ib_qp_attr *attr,
 int ocrdma_query_qp(struct ib_qp *,
 		    struct ib_qp_attr *qp_attr,
 		    int qp_attr_mask, struct ib_qp_init_attr *);
-int ocrdma_destroy_qp(struct ib_qp *);
+int ocrdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
 void ocrdma_del_flush_qp(struct ocrdma_qp *qp);
 
 struct ib_srq *ocrdma_create_srq(struct ib_pd *, struct ib_srq_init_attr *,
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 6e364b801f33..b9c5ca03fbe9 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -2571,7 +2571,7 @@  static int qedr_free_qp_resources(struct qedr_dev *dev, struct qedr_qp *qp)
 	return 0;
 }
 
-int qedr_destroy_qp(struct ib_qp *ibqp)
+int qedr_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
 	struct qedr_qp *qp = get_qedr_qp(ibqp);
 	struct qedr_dev *dev = qp->dev;
diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h
index 16a8c7494447..3aca0c0164d1 100644
--- a/drivers/infiniband/hw/qedr/verbs.h
+++ b/drivers/infiniband/hw/qedr/verbs.h
@@ -64,7 +64,7 @@  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,
 		  int qp_attr_mask, struct ib_qp_init_attr *);
-int qedr_destroy_qp(struct ib_qp *ibqp);
+int qedr_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
 
 struct ib_srq *qedr_create_srq(struct ib_pd *ibpd,
 			       struct ib_srq_init_attr *attr,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 120cfd522aba..11945372fee0 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -559,7 +559,7 @@  struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
 	return ERR_PTR(err);
 }
 
-int usnic_ib_destroy_qp(struct ib_qp *qp)
+int usnic_ib_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 {
 	struct usnic_ib_qp_grp *qp_grp;
 	struct usnic_ib_vf *vf;
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
index 32cd4363b190..a6feb1d975a9 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
@@ -58,7 +58,7 @@  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_destroy_qp(struct ib_qp *qp);
+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);
 struct ib_cq *usnic_ib_create_cq(struct ib_device *ibdev,
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
index 1a013e2d7399..36d9ce00527d 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
@@ -451,7 +451,7 @@  static void pvrdma_free_qp(struct pvrdma_qp *qp)
  *
  * @return: 0 on success.
  */
-int pvrdma_destroy_qp(struct ib_qp *qp)
+int pvrdma_destroy_qp(struct ib_qp *qp, struct ib_udata *udata)
 {
 	struct pvrdma_qp *vqp = to_vqp(qp);
 	union pvrdma_cmd_req req;
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
index 64c8f778c53a..8a3c25ce6d41 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
@@ -438,7 +438,7 @@  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,
 		    int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
-int pvrdma_destroy_qp(struct ib_qp *qp);
+int pvrdma_destroy_qp(struct ib_qp *qp, struct ib_udata *udata);
 int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
 		     const struct ib_send_wr **bad_wr);
 int pvrdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr,
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index d396f889eb10..581e6261b9d0 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -544,7 +544,7 @@  static int rxe_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	return 0;
 }
 
-static int rxe_destroy_qp(struct ib_qp *ibqp)
+static int rxe_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
 	struct rxe_qp *qp = to_rqp(ibqp);
 
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 1886b50e630a..f88838988f4d 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2427,7 +2427,8 @@  struct ib_device {
 					       struct ib_qp_attr *qp_attr,
 					       int qp_attr_mask,
 					       struct ib_qp_init_attr *qp_init_attr);
-	int                        (*destroy_qp)(struct ib_qp *qp);
+	int                        (*destroy_qp)(struct ib_qp *qp,
+						 struct ib_udata *udata);
 	int                        (*post_send)(struct ib_qp *qp,
 						const struct ib_send_wr *send_wr,
 						const struct ib_send_wr **bad_send_wr);
@@ -3357,6 +3358,18 @@  static inline int ib_post_srq_recv(struct ib_srq *srq,
 	return srq->device->post_srq_recv(srq, recv_wr, bad_recv_wr ? : &dummy);
 }
 
+/**
+ * ib_create_qp_user - Creates a QP associated with the specified protection
+ *   domain.
+ * @pd: The protection domain associated with the QP.
+ * @qp_init_attr: A list of initial attributes required to create the
+ *   QP.  If QP creation succeeds, then the attributes are updated to
+ *   the actual capabilities of the created QP.
+ * @udata: User data (if any)
+ */
+struct ib_qp *ib_create_qp_user(struct ib_pd *pd,
+				struct ib_qp_init_attr *qp_init_attr,
+				struct ib_udata *udata);
 /**
  * ib_create_qp - Creates a QP associated with the specified protection
  *   domain.
@@ -3364,6 +3377,8 @@  static inline int ib_post_srq_recv(struct ib_srq *srq,
  * @qp_init_attr: A list of initial attributes required to create the
  *   QP.  If QP creation succeeds, then the attributes are updated to
  *   the actual capabilities of the created QP.
+ *
+ *   NOTE: Never call this function from uverbs!
  */
 struct ib_qp *ib_create_qp(struct ib_pd *pd,
 			   struct ib_qp_init_attr *qp_init_attr);
@@ -3413,9 +3428,19 @@  int ib_query_qp(struct ib_qp *qp,
 		int qp_attr_mask,
 		struct ib_qp_init_attr *qp_init_attr);
 
+/**
+ * ib_destroy_qp_user - Destroys the specified QP.
+ * @qp: The QP to destroy.
+ * @udata: User data (if any)
+ */
+int ib_destroy_qp_user(struct ib_qp *qp,
+		       struct ib_udata *udata);
+
 /**
  * ib_destroy_qp - Destroys the specified QP.
  * @qp: The QP to destroy.
+ *
+ * NOTE: Never call this function from uverbs!
  */
 int ib_destroy_qp(struct ib_qp *qp);