diff mbox series

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

Message ID 20181014061118.14889-6-shamir.rabinovitch@oracle.com (mailing list archive)
State Superseded
Headers show
Series convey ib_ucontext via ib_udata | expand

Commit Message

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

Some flows in the code that involve dereg_mr 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_std_types_mr.c   | 13 +++++++++++--
 drivers/infiniband/core/verbs.c                 | 17 ++++++++++++++---
 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     |  4 ++--
 drivers/infiniband/hw/cxgb4/iw_cxgb4.h          |  2 +-
 drivers/infiniband/hw/cxgb4/mem.c               |  2 +-
 drivers/infiniband/hw/i40iw/i40iw_cm.c          |  4 +++-
 drivers/infiniband/hw/i40iw/i40iw_verbs.c       |  2 +-
 drivers/infiniband/hw/mlx4/mlx4_ib.h            |  2 +-
 drivers/infiniband/hw/mlx4/mr.c                 |  2 +-
 drivers/infiniband/hw/mlx5/mlx5_ib.h            |  2 +-
 drivers/infiniband/hw/mlx5/mr.c                 |  2 +-
 drivers/infiniband/hw/mthca/mthca_provider.c    |  2 +-
 drivers/infiniband/hw/nes/nes_cm.c              |  4 +++-
 drivers/infiniband/hw/nes/nes_verbs.c           |  6 +++---
 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_mr.c    |  2 +-
 drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h |  2 +-
 drivers/infiniband/sw/rxe/rxe_verbs.c           |  2 +-
 include/rdma/ib_verbs.h                         | 13 ++++++++++++-
 26 files changed, 67 insertions(+), 32 deletions(-)

Comments

kernel test robot Oct. 14, 2018, 6:51 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-013324
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git for-next
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 8.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=8.1.0 make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   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 to 'int (*)(struct ib_pd *, struct ib_udata *)' from incompatible pointer type 'int (*)(struct ib_pd *)' [-Werror=incompatible-pointer-types]
     ib_dev->dealloc_pd  = hns_roce_dealloc_pd;
                         ^
>> drivers/infiniband//hw/hns/hns_roce_main.c:523:20: error: assignment to 'int (*)(struct ib_mr *, struct ib_udata *)' from incompatible pointer type 'int (*)(struct ib_mr *)' [-Werror=incompatible-pointer-types]
     ib_dev->dereg_mr  = hns_roce_dereg_mr;
                       ^
   cc1: some warnings being treated as errors

vim +523 drivers/infiniband//hw/hns/hns_roce_main.c

9a4435375 oulijun         2016-07-21  442  
9a4435375 oulijun         2016-07-21  443  static int hns_roce_register_device(struct hns_roce_dev *hr_dev)
9a4435375 oulijun         2016-07-21  444  {
9a4435375 oulijun         2016-07-21  445  	int ret;
9a4435375 oulijun         2016-07-21  446  	struct hns_roce_ib_iboe *iboe = NULL;
9a4435375 oulijun         2016-07-21  447  	struct ib_device *ib_dev = NULL;
13ca970e3 Wei Hu(Xavier   2017-08-30  448) 	struct device *dev = hr_dev->dev;
9a4435375 oulijun         2016-07-21  449  
9a4435375 oulijun         2016-07-21  450  	iboe = &hr_dev->iboe;
49fdf6bb0 Lijun Ou        2016-09-20  451  	spin_lock_init(&iboe->lock);
9a4435375 oulijun         2016-07-21  452  
9a4435375 oulijun         2016-07-21  453  	ib_dev = &hr_dev->ib_dev;
9a4435375 oulijun         2016-07-21  454  
9a4435375 oulijun         2016-07-21  455  	ib_dev->owner			= THIS_MODULE;
9a4435375 oulijun         2016-07-21  456  	ib_dev->node_type		= RDMA_NODE_IB_CA;
fecd02eb2 Bart Van Assche 2017-01-20  457  	ib_dev->dev.parent		= dev;
9a4435375 oulijun         2016-07-21  458  
9a4435375 oulijun         2016-07-21  459  	ib_dev->phys_port_cnt		= hr_dev->caps.num_ports;
9a4435375 oulijun         2016-07-21  460  	ib_dev->local_dma_lkey		= hr_dev->caps.reserved_lkey;
9a4435375 oulijun         2016-07-21  461  	ib_dev->num_comp_vectors	= hr_dev->caps.num_comp_vectors;
9a4435375 oulijun         2016-07-21  462  	ib_dev->uverbs_abi_ver		= 1;
9a4435375 oulijun         2016-07-21  463  	ib_dev->uverbs_cmd_mask		=
9a4435375 oulijun         2016-07-21  464  		(1ULL << IB_USER_VERBS_CMD_GET_CONTEXT) |
9a4435375 oulijun         2016-07-21  465  		(1ULL << IB_USER_VERBS_CMD_QUERY_DEVICE) |
9a4435375 oulijun         2016-07-21  466  		(1ULL << IB_USER_VERBS_CMD_QUERY_PORT) |
9a4435375 oulijun         2016-07-21  467  		(1ULL << IB_USER_VERBS_CMD_ALLOC_PD) |
9a4435375 oulijun         2016-07-21  468  		(1ULL << IB_USER_VERBS_CMD_DEALLOC_PD) |
9a4435375 oulijun         2016-07-21  469  		(1ULL << IB_USER_VERBS_CMD_REG_MR) |
9a4435375 oulijun         2016-07-21  470  		(1ULL << IB_USER_VERBS_CMD_DEREG_MR) |
9a4435375 oulijun         2016-07-21  471  		(1ULL << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
9a4435375 oulijun         2016-07-21  472  		(1ULL << IB_USER_VERBS_CMD_CREATE_CQ) |
9a4435375 oulijun         2016-07-21  473  		(1ULL << IB_USER_VERBS_CMD_DESTROY_CQ) |
9a4435375 oulijun         2016-07-21  474  		(1ULL << IB_USER_VERBS_CMD_CREATE_QP) |
9a4435375 oulijun         2016-07-21  475  		(1ULL << IB_USER_VERBS_CMD_MODIFY_QP) |
9a4435375 oulijun         2016-07-21  476  		(1ULL << IB_USER_VERBS_CMD_QUERY_QP) |
9a4435375 oulijun         2016-07-21  477  		(1ULL << IB_USER_VERBS_CMD_DESTROY_QP);
9a4435375 oulijun         2016-07-21  478  
df0651079 Lijun Ou        2018-07-25  479  	ib_dev->uverbs_ex_cmd_mask |=
df0651079 Lijun Ou        2018-07-25  480  		(1ULL << IB_USER_VERBS_EX_CMD_MODIFY_CQ);
df0651079 Lijun Ou        2018-07-25  481  
9a4435375 oulijun         2016-07-21  482  	/* HCA||device||port */
9a4435375 oulijun         2016-07-21  483  	ib_dev->modify_device		= hns_roce_modify_device;
9a4435375 oulijun         2016-07-21  484  	ib_dev->query_device		= hns_roce_query_device;
9a4435375 oulijun         2016-07-21  485  	ib_dev->query_port		= hns_roce_query_port;
9a4435375 oulijun         2016-07-21  486  	ib_dev->modify_port		= hns_roce_modify_port;
9a4435375 oulijun         2016-07-21  487  	ib_dev->get_link_layer		= hns_roce_get_link_layer;
2eefca272 Lijun Ou        2016-09-15  488  	ib_dev->get_netdev		= hns_roce_get_netdev;
825474697 Shaobo Xu       2016-11-23  489  	ib_dev->add_gid			= hns_roce_add_gid;
825474697 Shaobo Xu       2016-11-23  490  	ib_dev->del_gid			= hns_roce_del_gid;
9a4435375 oulijun         2016-07-21  491  	ib_dev->query_pkey		= hns_roce_query_pkey;
9a4435375 oulijun         2016-07-21  492  	ib_dev->alloc_ucontext		= hns_roce_alloc_ucontext;
9a4435375 oulijun         2016-07-21  493  	ib_dev->dealloc_ucontext	= hns_roce_dealloc_ucontext;
9a4435375 oulijun         2016-07-21  494  	ib_dev->mmap			= hns_roce_mmap;
9a4435375 oulijun         2016-07-21  495  
9a4435375 oulijun         2016-07-21  496  	/* PD */
9a4435375 oulijun         2016-07-21  497  	ib_dev->alloc_pd		= hns_roce_alloc_pd;
9a4435375 oulijun         2016-07-21 @498  	ib_dev->dealloc_pd		= hns_roce_dealloc_pd;
9a4435375 oulijun         2016-07-21  499  
9a4435375 oulijun         2016-07-21  500  	/* AH */
9a4435375 oulijun         2016-07-21  501  	ib_dev->create_ah		= hns_roce_create_ah;
9a4435375 oulijun         2016-07-21  502  	ib_dev->query_ah		= hns_roce_query_ah;
9a4435375 oulijun         2016-07-21  503  	ib_dev->destroy_ah		= hns_roce_destroy_ah;
9a4435375 oulijun         2016-07-21  504  
9a4435375 oulijun         2016-07-21  505  	/* QP */
9a4435375 oulijun         2016-07-21  506  	ib_dev->create_qp		= hns_roce_create_qp;
9a4435375 oulijun         2016-07-21  507  	ib_dev->modify_qp		= hns_roce_modify_qp;
9a4435375 oulijun         2016-07-21  508  	ib_dev->query_qp		= hr_dev->hw->query_qp;
9a4435375 oulijun         2016-07-21  509  	ib_dev->destroy_qp		= hr_dev->hw->destroy_qp;
9a4435375 oulijun         2016-07-21  510  	ib_dev->post_send		= hr_dev->hw->post_send;
9a4435375 oulijun         2016-07-21  511  	ib_dev->post_recv		= hr_dev->hw->post_recv;
9a4435375 oulijun         2016-07-21  512  
9a4435375 oulijun         2016-07-21  513  	/* CQ */
9a4435375 oulijun         2016-07-21  514  	ib_dev->create_cq		= hns_roce_ib_create_cq;
b156269d8 oulijun         2017-10-19  515  	ib_dev->modify_cq		= hr_dev->hw->modify_cq;
9a4435375 oulijun         2016-07-21  516  	ib_dev->destroy_cq		= hns_roce_ib_destroy_cq;
9a4435375 oulijun         2016-07-21  517  	ib_dev->req_notify_cq		= hr_dev->hw->req_notify_cq;
9a4435375 oulijun         2016-07-21  518  	ib_dev->poll_cq			= hr_dev->hw->poll_cq;
9a4435375 oulijun         2016-07-21  519  
9a4435375 oulijun         2016-07-21  520  	/* MR */
9a4435375 oulijun         2016-07-21  521  	ib_dev->get_dma_mr		= hns_roce_get_dma_mr;
9a4435375 oulijun         2016-07-21  522  	ib_dev->reg_user_mr		= hns_roce_reg_user_mr;
9a4435375 oulijun         2016-07-21 @523  	ib_dev->dereg_mr		= hns_roce_dereg_mr;
a2c80b7b4 Wei Hu(Xavier   2017-10-26  524) 	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_REREG_MR) {
a2c80b7b4 Wei Hu(Xavier   2017-10-26  525) 		ib_dev->rereg_user_mr	= hns_roce_rereg_user_mr;
a2c80b7b4 Wei Hu(Xavier   2017-10-26  526) 		ib_dev->uverbs_cmd_mask |= (1ULL << IB_USER_VERBS_CMD_REREG_MR);
a2c80b7b4 Wei Hu(Xavier   2017-10-26  527) 	}
9a4435375 oulijun         2016-07-21  528  
c7c281914 Yixian Liu      2018-09-23  529  	/* MW */
c7c281914 Yixian Liu      2018-09-23  530  	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_MW) {
c7c281914 Yixian Liu      2018-09-23  531  		ib_dev->alloc_mw = hns_roce_alloc_mw;
c7c281914 Yixian Liu      2018-09-23  532  		ib_dev->dealloc_mw = hns_roce_dealloc_mw;
c7c281914 Yixian Liu      2018-09-23  533  		ib_dev->uverbs_cmd_mask |=
c7c281914 Yixian Liu      2018-09-23  534  					(1ULL << IB_USER_VERBS_CMD_ALLOC_MW) |
c7c281914 Yixian Liu      2018-09-23  535  					(1ULL << IB_USER_VERBS_CMD_DEALLOC_MW);
c7c281914 Yixian Liu      2018-09-23  536  	}
c7c281914 Yixian Liu      2018-09-23  537  
9a4435375 oulijun         2016-07-21  538  	/* OTHERS */
9a4435375 oulijun         2016-07-21  539  	ib_dev->get_port_immutable	= hns_roce_port_immutable;
fedc3abe7 Wei Hu(Xavier   2018-05-28  540) 	ib_dev->disassociate_ucontext	= hns_roce_disassociate_ucontext;
9a4435375 oulijun         2016-07-21  541  
0ede73bc0 Matan Barak     2018-03-19  542  	ib_dev->driver_id = RDMA_DRIVER_HNS;
e349f858d Jason Gunthorpe 2018-09-25  543  	ret = ib_register_device(ib_dev, "hns_%d", NULL);
9a4435375 oulijun         2016-07-21  544  	if (ret) {
9a4435375 oulijun         2016-07-21  545  		dev_err(dev, "ib_register_device failed!\n");
9a4435375 oulijun         2016-07-21  546  		return ret;
9a4435375 oulijun         2016-07-21  547  	}
9a4435375 oulijun         2016-07-21  548  
825474697 Shaobo Xu       2016-11-23  549  	ret = hns_roce_setup_mtu_mac(hr_dev);
9a4435375 oulijun         2016-07-21  550  	if (ret) {
825474697 Shaobo Xu       2016-11-23  551  		dev_err(dev, "setup_mtu_mac failed!\n");
825474697 Shaobo Xu       2016-11-23  552  		goto error_failed_setup_mtu_mac;
9a4435375 oulijun         2016-07-21  553  	}
9a4435375 oulijun         2016-07-21  554  
9a4435375 oulijun         2016-07-21  555  	iboe->nb.notifier_call = hns_roce_netdev_event;
9a4435375 oulijun         2016-07-21  556  	ret = register_netdevice_notifier(&iboe->nb);
9a4435375 oulijun         2016-07-21  557  	if (ret) {
9a4435375 oulijun         2016-07-21  558  		dev_err(dev, "register_netdevice_notifier failed!\n");
825474697 Shaobo Xu       2016-11-23  559  		goto error_failed_setup_mtu_mac;
9a4435375 oulijun         2016-07-21  560  	}
9a4435375 oulijun         2016-07-21  561  
cb7a94c9c Wei Hu(Xavier   2018-05-28  562) 	hr_dev->active = true;
9a4435375 oulijun         2016-07-21  563  	return 0;
9a4435375 oulijun         2016-07-21  564  
825474697 Shaobo Xu       2016-11-23  565  error_failed_setup_mtu_mac:
9a4435375 oulijun         2016-07-21  566  	ib_unregister_device(ib_dev);
9a4435375 oulijun         2016-07-21  567  
9a4435375 oulijun         2016-07-21  568  	return ret;
9a4435375 oulijun         2016-07-21  569  }
9a4435375 oulijun         2016-07-21  570  

:::::: The code at line 523 was first introduced by commit
:::::: 9a4435375cd151e07c0c38fa601b00115986091b IB/hns: Add driver files for hns RoCE driver

:::::: TO: oulijun <oulijun@huawei.com>
:::::: CC: Doug Ledford <dledford@redhat.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Jason Gunthorpe Oct. 14, 2018, 7:27 p.m. UTC | #2
On Sun, Oct 14, 2018 at 09:11:16AM +0300, Shamir Rabinovitch wrote:

> diff --git a/drivers/infiniband/core/uverbs_std_types_mr.c b/drivers/infiniband/core/uverbs_std_types_mr.c
> index cf02e774303e..afdf2ab74883 100644
> +++ b/drivers/infiniband/core/uverbs_std_types_mr.c
> @@ -36,7 +36,12 @@
>  static int uverbs_free_mr(struct ib_uobject *uobject,
>  			  enum rdma_remove_reason why)
>  {
> -	return ib_dereg_mr((struct ib_mr *)uobject->object);
> +	struct ib_udata udata = {0};

The ={} is not needed if we call init:

> +	ib_uverbs_init_udata_buf_or_null(&udata, NULL, NULL, 0, 0,
> +					 uobject->context);
> +
> +	return ib_dereg_mr_user((struct ib_mr *)uobject->object, &udata);
>  }

> -int ib_dereg_mr(struct ib_mr *mr)
> +int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata)
>  {
>  	struct ib_pd *pd = mr->pd;
>  	struct ib_dm *dm = mr->dm;
>  	int ret;
>  
>  	rdma_restrack_del(&mr->res);
> -	ret = mr->device->dereg_mr(mr);
> +	ret = mr->device->dereg_mr(mr, NULL);

Should the NULL be udata??

Jason
diff mbox series

Patch

diff --git a/drivers/infiniband/core/uverbs_std_types_mr.c b/drivers/infiniband/core/uverbs_std_types_mr.c
index cf02e774303e..afdf2ab74883 100644
--- a/drivers/infiniband/core/uverbs_std_types_mr.c
+++ b/drivers/infiniband/core/uverbs_std_types_mr.c
@@ -36,7 +36,12 @@ 
 static int uverbs_free_mr(struct ib_uobject *uobject,
 			  enum rdma_remove_reason why)
 {
-	return ib_dereg_mr((struct ib_mr *)uobject->object);
+	struct ib_udata udata = {0};
+
+	ib_uverbs_init_udata_buf_or_null(&udata, NULL, NULL, 0, 0,
+					 uobject->context);
+
+	return ib_dereg_mr_user((struct ib_mr *)uobject->object, &udata);
 }
 
 static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(
@@ -50,6 +55,7 @@  static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(
 	struct ib_pd *pd =
 		uverbs_attr_get_obj(attrs, UVERBS_ATTR_REG_DM_MR_PD_HANDLE);
 	struct ib_device *ib_dev = pd->device;
+	struct ib_udata udata = {0};
 
 	struct ib_mr *mr;
 	int ret;
@@ -109,7 +115,10 @@  static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(
 	return 0;
 
 err_dereg:
-	ib_dereg_mr(mr);
+	ib_uverbs_init_udata_buf_or_null(&udata, NULL, NULL, 0, 0,
+					 file->ucontext);
+
+	ib_dereg_mr_user(mr, &udata);
 
 	return ret;
 }
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index cfb08547a1db..7991470de40e 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -308,7 +308,7 @@  void ib_dealloc_pd_user(struct ib_pd *pd, struct ib_udata *udata)
 	int ret;
 
 	if (pd->__internal_mr) {
-		ret = pd->device->dereg_mr(pd->__internal_mr);
+		ret = pd->device->dereg_mr(pd->__internal_mr, udata);
 		WARN_ON(ret);
 		pd->__internal_mr = NULL;
 	}
@@ -1941,14 +1941,14 @@  EXPORT_SYMBOL(ib_resize_cq);
 
 /* Memory regions */
 
-int ib_dereg_mr(struct ib_mr *mr)
+int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata)
 {
 	struct ib_pd *pd = mr->pd;
 	struct ib_dm *dm = mr->dm;
 	int ret;
 
 	rdma_restrack_del(&mr->res);
-	ret = mr->device->dereg_mr(mr);
+	ret = mr->device->dereg_mr(mr, NULL);
 	if (!ret) {
 		atomic_dec(&pd->usecnt);
 		if (dm)
@@ -1957,6 +1957,17 @@  int ib_dereg_mr(struct ib_mr *mr)
 
 	return ret;
 }
+EXPORT_SYMBOL(ib_dereg_mr_user);
+
+/* NOTE: Never call this function from uverbs! */
+
+int ib_dereg_mr(struct ib_mr *mr)
+{
+	if (WARN_ON(rdma_is_user_pd(mr->pd)))
+		return -EINVAL;
+
+	return ib_dereg_mr_user(mr, NULL);
+}
 EXPORT_SYMBOL(ib_dereg_mr);
 
 /**
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 1e9a7aa89d7e..a2982a160123 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -3360,7 +3360,7 @@  struct ib_mr *bnxt_re_get_dma_mr(struct ib_pd *ib_pd, int mr_access_flags)
 	return ERR_PTR(rc);
 }
 
-int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
+int bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 {
 	struct bnxt_re_mr *mr = container_of(ib_mr, struct bnxt_re_mr, ib_mr);
 	struct bnxt_re_dev *rdev = mr->rdev;
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index 6ea70e2980b4..d73a5c74c85d 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -208,7 +208,7 @@  int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
 		      unsigned int *sg_offset);
 struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type mr_type,
 			       u32 max_num_sg, struct ib_udata *udata);
-int bnxt_re_dereg_mr(struct ib_mr *mr);
+int bnxt_re_dereg_mr(struct ib_mr *mr, struct ib_udata *udata);
 struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
 			       struct ib_udata *udata);
 int bnxt_re_dealloc_mw(struct ib_mw *mw);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 07b7d261e952..059280fc1eab 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -415,7 +415,7 @@  static struct ib_pd *iwch_allocate_pd(struct ib_device *ibdev,
 	return &php->ibpd;
 }
 
-static int iwch_dereg_mr(struct ib_mr *ib_mr)
+static int iwch_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 {
 	struct iwch_dev *rhp;
 	struct iwch_mr *mhp;
@@ -604,7 +604,7 @@  static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 			 uresp.pbl_addr);
 
 		if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
-			iwch_dereg_mr(&mhp->ibmr);
+			iwch_dereg_mr(&mhp->ibmr, udata);
 			err = -EFAULT;
 			goto err;
 		}
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 22966787ae42..79016715720b 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -1062,7 +1062,7 @@  struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start,
 					   u64 length, u64 virt, int acc,
 					   struct ib_udata *udata);
 struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc);
-int c4iw_dereg_mr(struct ib_mr *ib_mr);
+int c4iw_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata);
 int c4iw_destroy_cq(struct ib_cq *ib_cq);
 struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
 			     const struct ib_cq_init_attr *attr,
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index df8ade89a3c9..30d5521c5c21 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -793,7 +793,7 @@  int c4iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
 	return ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, c4iw_set_page);
 }
 
-int c4iw_dereg_mr(struct ib_mr *ib_mr)
+int c4iw_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 {
 	struct c4iw_dev *rhp;
 	struct c4iw_mr *mhp;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c
index 771eb6bd0785..ef79e9831dfb 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -3457,6 +3457,8 @@  void i40iw_cm_disconn(struct i40iw_qp *iwqp)
 /**
  * i40iw_qp_disconnect - free qp and close cm
  * @iwqp: associate qp for the connection
+ *
+ * NOTE: never call this function from uverbs!
  */
 static void i40iw_qp_disconnect(struct i40iw_qp *iwqp)
 {
@@ -3478,7 +3480,7 @@  static void i40iw_qp_disconnect(struct i40iw_qp *iwqp)
 		/* Need to free the Last Streaming Mode Message */
 		if (iwqp->ietf_mem.va) {
 			if (iwqp->lsmm_mr)
-				iwibdev->ibdev.dereg_mr(iwqp->lsmm_mr);
+				iwibdev->ibdev.dereg_mr(iwqp->lsmm_mr, NULL);
 			i40iw_free_dma_mem(iwdev->sc_dev.hw, &iwqp->ietf_mem);
 		}
 	}
diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
index c270bb1035fa..201c030acd50 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
@@ -2073,7 +2073,7 @@  static void i40iw_del_memlist(struct i40iw_mr *iwmr,
  * i40iw_dereg_mr - deregister mr
  * @ib_mr: mr ptr for dereg
  */
-static int i40iw_dereg_mr(struct ib_mr *ib_mr)
+static int i40iw_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 {
 	struct ib_pd *ibpd = ib_mr->pd;
 	struct i40iw_pd *iwpd = to_iwpd(ibpd);
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index e99fd3dac030..7a66decf37ec 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -731,7 +731,7 @@  int mlx4_ib_umem_write_mtt(struct mlx4_ib_dev *dev, struct mlx4_mtt *mtt,
 struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 				  u64 virt_addr, int access_flags,
 				  struct ib_udata *udata);
-int mlx4_ib_dereg_mr(struct ib_mr *mr);
+int mlx4_ib_dereg_mr(struct ib_mr *mr, struct ib_udata *udata);
 struct ib_mw *mlx4_ib_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
 			       struct ib_udata *udata);
 int mlx4_ib_dealloc_mw(struct ib_mw *mw);
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index 16f868bd91dc..dfd5eee13dbe 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -596,7 +596,7 @@  mlx4_free_priv_pages(struct mlx4_ib_mr *mr)
 	}
 }
 
-int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
+int mlx4_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
 {
 	struct mlx4_ib_mr *mr = to_mmr(ibmr);
 	int ret;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 8d8937222e00..168a464e7069 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -1080,7 +1080,7 @@  void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *mr);
 int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
 			  u64 length, u64 virt_addr, int access_flags,
 			  struct ib_pd *pd, struct ib_udata *udata);
-int mlx5_ib_dereg_mr(struct ib_mr *ibmr);
+int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata);
 struct ib_mr *mlx5_ib_alloc_mr(struct ib_pd *pd,
 			       enum ib_mr_type mr_type,
 			       u32 max_num_sg,
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 571c16eb4197..a91c47ac2948 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1663,7 +1663,7 @@  static void dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
 		mlx5_mr_cache_free(dev, mr);
 }
 
-int mlx5_ib_dereg_mr(struct ib_mr *ibmr)
+int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
 {
 	dereg_mr(to_mdev(ibmr->device), to_mmr(ibmr));
 	return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 9763484716b5..303de9955ad6 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1001,7 +1001,7 @@  static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 	return ERR_PTR(err);
 }
 
-static int mthca_dereg_mr(struct ib_mr *mr)
+static int mthca_dereg_mr(struct ib_mr *mr, struct ib_udata *udata)
 {
 	struct mthca_mr *mmr = to_mmr(mr);
 
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 2b67ace5b614..51d86136f562 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -3007,6 +3007,8 @@  static int nes_cm_disconn_true(struct nes_qp *nesqp)
 
 /**
  * nes_disconnect
+ *
+ * NOTE: never call this function from uverbs!
  */
 static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
 {
@@ -3033,7 +3035,7 @@  static int nes_disconnect(struct nes_qp *nesqp, int abrupt)
 		/* Need to free the Last Streaming Mode Message */
 		if (nesqp->ietf_frame) {
 			if (nesqp->lsmm_mr)
-				nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr);
+				nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr, NULL);
 			pci_free_consistent(nesdev->pcidev,
 					    nesqp->private_data_len + nesqp->ietf_frame_size,
 					    nesqp->ietf_frame, nesqp->ietf_frame_pbase);
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index d27c65d50721..5f69d076b742 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -51,7 +51,7 @@  atomic_t qps_created;
 atomic_t sw_qps_destroyed;
 
 static void nes_unregister_ofa_device(struct nes_ib_device *nesibdev);
-static int nes_dereg_mr(struct ib_mr *ib_mr);
+static int nes_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata);
 
 /**
  * nes_alloc_mw
@@ -386,7 +386,7 @@  static struct ib_mr *nes_alloc_mr(struct ib_pd *ibpd,
 	return ibmr;
 
 err:
-	nes_dereg_mr(ibmr);
+	nes_dereg_mr(ibmr, udata);
 
 	return ERR_PTR(-ENOMEM);
 }
@@ -2455,7 +2455,7 @@  static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 /**
  * nes_dereg_mr
  */
-static int nes_dereg_mr(struct ib_mr *ib_mr)
+static int nes_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 {
 	struct nes_mr *nesmr = to_nesmr(ib_mr);
 	struct nes_vnic *nesvnic = to_nesvnic(ib_mr->device);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index bb36f0eec897..84a815277788 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -967,7 +967,7 @@  struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
 	return ERR_PTR(status);
 }
 
-int ocrdma_dereg_mr(struct ib_mr *ib_mr)
+int ocrdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 {
 	struct ocrdma_mr *mr = get_ocrdma_mr(ib_mr);
 	struct ocrdma_dev *dev = get_ocrdma_dev(ib_mr->device);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
index 8616b295271d..8bc96aaf0972 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -103,7 +103,7 @@  int ocrdma_destroy_srq(struct ib_srq *);
 int ocrdma_post_srq_recv(struct ib_srq *, const struct ib_recv_wr *,
 			 const struct ib_recv_wr **bad_recv_wr);
 
-int ocrdma_dereg_mr(struct ib_mr *);
+int ocrdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata);
 struct ib_mr *ocrdma_get_dma_mr(struct ib_pd *, int acc);
 struct ib_mr *ocrdma_reg_user_mr(struct ib_pd *, u64 start, u64 length,
 				 u64 virt, int acc, struct ib_udata *);
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 6f189f49dabe..6e364b801f33 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -2794,7 +2794,7 @@  struct ib_mr *qedr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
 	return ERR_PTR(rc);
 }
 
-int qedr_dereg_mr(struct ib_mr *ib_mr)
+int qedr_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 {
 	struct qedr_mr *mr = get_qedr_mr(ib_mr);
 	struct qedr_dev *dev = get_qedr_dev(ib_mr->device);
diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h
index cf5fd18f5349..16a8c7494447 100644
--- a/drivers/infiniband/hw/qedr/verbs.h
+++ b/drivers/infiniband/hw/qedr/verbs.h
@@ -79,7 +79,7 @@  struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct rdma_ah_attr *attr,
 			     struct ib_udata *udata);
 int qedr_destroy_ah(struct ib_ah *ibah);
 
-int qedr_dereg_mr(struct ib_mr *);
+int qedr_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata);
 struct ib_mr *qedr_get_dma_mr(struct ib_pd *, int acc);
 
 struct ib_mr *qedr_reg_user_mr(struct ib_pd *, u64 start, u64 length,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 67343791e054..120cfd522aba 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -662,7 +662,7 @@  struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length,
 	return ERR_PTR(err);
 }
 
-int usnic_ib_dereg_mr(struct ib_mr *ibmr)
+int usnic_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
 {
 	struct usnic_ib_mr *mr = to_umr(ibmr);
 
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
index 0e5de8876c50..32cd4363b190 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
@@ -69,7 +69,7 @@  int usnic_ib_destroy_cq(struct ib_cq *cq);
 struct ib_mr *usnic_ib_reg_mr(struct ib_pd *pd, u64 start, u64 length,
 				u64 virt_addr, int access_flags,
 				struct ib_udata *udata);
-int usnic_ib_dereg_mr(struct ib_mr *ibmr);
+int usnic_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata);
 struct ib_ucontext *usnic_ib_alloc_ucontext(struct ib_device *ibdev,
 						struct ib_udata *udata);
 int usnic_ib_dealloc_ucontext(struct ib_ucontext *ibcontext);
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c
index 84f3cff92d93..adf0478b4756 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c
@@ -273,7 +273,7 @@  struct ib_mr *pvrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
  *
  * @return: 0 on success.
  */
-int pvrdma_dereg_mr(struct ib_mr *ibmr)
+int pvrdma_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
 {
 	struct pvrdma_user_mr *mr = to_vmr(ibmr);
 	struct pvrdma_dev *dev = to_vdev(ibmr->device);
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
index c3c9450dcc3a..64c8f778c53a 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
@@ -407,7 +407,7 @@  struct ib_mr *pvrdma_get_dma_mr(struct ib_pd *pd, int acc);
 struct ib_mr *pvrdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 				 u64 virt_addr, int access_flags,
 				 struct ib_udata *udata);
-int pvrdma_dereg_mr(struct ib_mr *mr);
+int pvrdma_dereg_mr(struct ib_mr *mr, struct ib_udata *udata);
 struct ib_mr *pvrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
 			      u32 max_num_sg, struct ib_udata *udata);
 int pvrdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index fd0a9727f8e2..d396f889eb10 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -1025,7 +1025,7 @@  static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd,
 	return ERR_PTR(err);
 }
 
-static int rxe_dereg_mr(struct ib_mr *ibmr)
+static int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
 {
 	struct rxe_mem *mr = to_rmr(ibmr);
 
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 41570f7b6d84..43d69f54a6e4 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2464,7 +2464,8 @@  struct ib_device {
 						    int mr_access_flags,
 						    struct ib_pd *pd,
 						    struct ib_udata *udata);
-	int                        (*dereg_mr)(struct ib_mr *mr);
+	int                        (*dereg_mr)(struct ib_mr *mr,
+					       struct ib_udata *udata);
 	struct ib_mr *		   (*alloc_mr)(struct ib_pd *pd,
 					       enum ib_mr_type mr_type,
 					       u32 max_num_sg,
@@ -3795,6 +3796,16 @@  static inline void ib_dma_free_coherent(struct ib_device *dev,
 	dma_free_coherent(dev->dma_device, size, cpu_addr, dma_handle);
 }
 
+/**
+ * ib_dereg_mr_user - Deregisters a memory region and removes it from the
+ *   HCA translation table.
+ * @mr: The memory region to deregister.
+ * @udata: User data (if any)
+ *
+ * This function can fail, if the memory region has memory windows bound to it.
+ */
+int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata);
+
 /**
  * ib_dereg_mr - Deregisters a memory region and removes it from the
  *   HCA translation table.