Re: [PATCH rdma-next 3/4] RDMA: Handle AH allocations by IB/core

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 3/26/19 7:56 AM, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro@xxxxxxxxxxxx>
> 
> Simplify drivers by ensuring lifetime of ib_ah object. The changes
> in .create_ah() go hand in hand with relevant update in .destroy_ah().
> 
> We will use this opportunity and convert .destroy_ah() to don't fail, as
> it was suggested a long time ago, because there is nothing to do in case
> of failure during destroy.
> 

vmw_pvrdma conversion looks fine to me.

Acked-by: Adit Ranadive <aditr@xxxxxxxxxx>


> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
> ---
>  drivers/infiniband/core/device.c              |  1 +
>  drivers/infiniband/core/verbs.c               | 39 ++++----
>  drivers/infiniband/hw/bnxt_re/ib_verbs.c      | 44 +++------
>  drivers/infiniband/hw/bnxt_re/ib_verbs.h      | 10 +-
>  drivers/infiniband/hw/bnxt_re/main.c          |  1 +
>  drivers/infiniband/hw/bnxt_re/qplib_sp.c      | 12 +--
>  drivers/infiniband/hw/bnxt_re/qplib_sp.h      |  4 +-
>  drivers/infiniband/hw/hns/hns_roce_ah.c       | 25 ++---
>  drivers/infiniband/hw/hns/hns_roce_device.h   |  7 +-
>  drivers/infiniband/hw/hns/hns_roce_main.c     |  3 +-
>  drivers/infiniband/hw/mlx4/ah.c               | 96 +++++++------------
>  drivers/infiniband/hw/mlx4/mad.c              | 33 ++++---
>  drivers/infiniband/hw/mlx4/main.c             |  3 +-
>  drivers/infiniband/hw/mlx4/mlx4_ib.h          | 11 +--
>  drivers/infiniband/hw/mlx5/ah.c               | 34 +++----
>  drivers/infiniband/hw/mlx5/main.c             |  3 +-
>  drivers/infiniband/hw/mlx5/mlx5_ib.h          |  5 +-
>  drivers/infiniband/hw/mthca/mthca_provider.c  | 29 ++----
>  drivers/infiniband/hw/ocrdma/ocrdma_ah.c      | 25 ++---
>  drivers/infiniband/hw/ocrdma/ocrdma_ah.h      |  6 +-
>  drivers/infiniband/hw/ocrdma/ocrdma_hw.c      |  3 +-
>  drivers/infiniband/hw/ocrdma/ocrdma_hw.h      |  4 +-
>  drivers/infiniband/hw/ocrdma/ocrdma_main.c    |  2 +
>  drivers/infiniband/hw/qedr/main.c             |  2 +
>  drivers/infiniband/hw/qedr/verbs.c            | 16 +---
>  drivers/infiniband/hw/qedr/verbs.h            |  6 +-
>  .../infiniband/hw/vmw_pvrdma/pvrdma_main.c    |  2 +
>  .../infiniband/hw/vmw_pvrdma/pvrdma_verbs.c   | 36 +++----
>  .../infiniband/hw/vmw_pvrdma/pvrdma_verbs.h   |  6 +-
>  drivers/infiniband/sw/rdmavt/ah.c             | 36 +++----
>  drivers/infiniband/sw/rdmavt/ah.h             |  8 +-
>  drivers/infiniband/sw/rdmavt/vt.c             |  2 +
>  drivers/infiniband/sw/rxe/rxe_pool.c          |  2 +-
>  drivers/infiniband/sw/rxe/rxe_verbs.c         | 30 +++---
>  drivers/infiniband/sw/rxe/rxe_verbs.h         |  2 +-
>  include/rdma/ib_verbs.h                       |  8 +-
>  36 files changed, 217 insertions(+), 339 deletions(-)
> 
> diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
> index a26816b2ff01..dad531f2d82a 100644
> --- a/drivers/infiniband/core/device.c
> +++ b/drivers/infiniband/core/device.c
> @@ -2364,6 +2364,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
>  	SET_DEVICE_OP(dev_ops, set_vf_link_state);
>  	SET_DEVICE_OP(dev_ops, unmap_fmr);
>  
> +	SET_OBJ_SIZE(dev_ops, ib_ah);
>  	SET_OBJ_SIZE(dev_ops, ib_pd);
>  	SET_OBJ_SIZE(dev_ops, ib_ucontext);
>  }
> diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
> index 50436922b24f..cd37a13af11f 100644
> --- a/drivers/infiniband/core/verbs.c
> +++ b/drivers/infiniband/core/verbs.c
> @@ -495,25 +495,31 @@ static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
>  				     u32 flags,
>  				     struct ib_udata *udata)
>  {
> +	struct ib_device *device = pd->device;
>  	struct ib_ah *ah;
> +	int ret;
>  
>  	might_sleep_if(flags & RDMA_CREATE_AH_SLEEPABLE);
>  
> -	if (!pd->device->ops.create_ah)
> +	if (!device->ops.create_ah)
>  		return ERR_PTR(-EOPNOTSUPP);
>  
> -	ah = pd->device->ops.create_ah(pd, ah_attr, flags, udata);
> +	ah = rdma_zalloc_drv_obj(device, ib_ah);
> +	if (!ah)
> +		return ERR_PTR(-ENOMEM);
>  
> -	if (!IS_ERR(ah)) {
> -		ah->device  = pd->device;
> -		ah->pd      = pd;
> -		ah->uobject = NULL;
> -		ah->type    = ah_attr->type;
> -		ah->sgid_attr = rdma_update_sgid_attr(ah_attr, NULL);
> +	ah->device = device;
> +	ah->pd = pd;
> +	ah->type = ah_attr->type;
> +	ah->sgid_attr = rdma_update_sgid_attr(ah_attr, NULL);
>  
> -		atomic_inc(&pd->usecnt);
> +	ret = device->ops.create_ah(ah, ah_attr, flags, udata);
> +	if (ret) {
> +		kfree(ah);
> +		return ERR_PTR(ret);
>  	}
>  
> +	atomic_inc(&pd->usecnt);
>  	return ah;
>  }
>  
> @@ -934,21 +940,18 @@ int rdma_destroy_ah(struct ib_ah *ah, u32 flags)
>  {
>  	const struct ib_gid_attr *sgid_attr = ah->sgid_attr;
>  	struct ib_pd *pd;
> -	int ret = 0;
>  
>  	might_sleep_if(flags & RDMA_DESTROY_AH_SLEEPABLE);
>  
>  	pd = ah->pd;
> -
>  	if (ah->device->ops.destroy_ah)
> -		ret = ah->device->ops.destroy_ah(ah, flags);
> -	if (!ret) {
> -		atomic_dec(&pd->usecnt);
> -		if (sgid_attr)
> -			rdma_put_gid_attr(sgid_attr);
> -	}
> +		ah->device->ops.destroy_ah(ah, flags);
> +	atomic_dec(&pd->usecnt);
> +	if (sgid_attr)
> +		rdma_put_gid_attr(sgid_attr);
>  
> -	return ret;
> +	kfree(ah);
> +	return 0;
>  }
>  EXPORT_SYMBOL(rdma_destroy_ah);
>  
> diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> index 071b2fc38b0b..aef84fb73aca 100644
> --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
> @@ -635,20 +635,13 @@ int bnxt_re_alloc_pd(struct ib_pd *ibpd, struct ib_ucontext *ucontext,
>  }
>  
>  /* Address Handles */
> -int bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags)
> +void bnxt_re_destroy_ah(struct ib_ah *ib_ah, u32 flags)
>  {
>  	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
>  	struct bnxt_re_dev *rdev = ah->rdev;
> -	int rc;
>  
> -	rc = bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah,
> -				   !(flags & RDMA_DESTROY_AH_SLEEPABLE));
> -	if (rc) {
> -		dev_err(rdev_to_dev(rdev), "Failed to destroy HW AH");
> -		return rc;
> -	}
> -	kfree(ah);
> -	return 0;
> +	bnxt_qplib_destroy_ah(&rdev->qplib_res, &ah->qplib_ah,
> +			      !(flags & RDMA_DESTROY_AH_SLEEPABLE));
>  }
>  
>  static u8 bnxt_re_stack_to_dev_nw_type(enum rdma_network_type ntype)
> @@ -669,26 +662,22 @@ static u8 bnxt_re_stack_to_dev_nw_type(enum rdma_network_type ntype)
>  	return nw_type;
>  }
>  
> -struct ib_ah *bnxt_re_create_ah(struct ib_pd *ib_pd,
> -				struct rdma_ah_attr *ah_attr,
> -				u32 flags,
> -				struct ib_udata *udata)
> +int bnxt_re_create_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr,
> +		      u32 flags, struct ib_udata *udata)
>  {
> +	struct ib_pd *ib_pd = ib_ah->pd;
>  	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
>  	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
>  	struct bnxt_re_dev *rdev = pd->rdev;
>  	const struct ib_gid_attr *sgid_attr;
> -	struct bnxt_re_ah *ah;
> +	struct bnxt_re_ah *ah = container_of(ib_ah, struct bnxt_re_ah, ib_ah);
>  	u8 nw_type;
>  	int rc;
>  
>  	if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH)) {
>  		dev_err(rdev_to_dev(rdev), "Failed to alloc AH: GRH not set");
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  	}
> -	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
>  
>  	ah->rdev = rdev;
>  	ah->qplib_ah.pd = &pd->qplib_pd;
> @@ -718,7 +707,7 @@ struct ib_ah *bnxt_re_create_ah(struct ib_pd *ib_pd,
>  				  !(flags & RDMA_CREATE_AH_SLEEPABLE));
>  	if (rc) {
>  		dev_err(rdev_to_dev(rdev), "Failed to allocate HW AH");
> -		goto fail;
> +		return rc;
>  	}
>  
>  	/* Write AVID to shared page. */
> @@ -735,11 +724,7 @@ struct ib_ah *bnxt_re_create_ah(struct ib_pd *ib_pd,
>  		spin_unlock_irqrestore(&uctx->sh_lock, flag);
>  	}
>  
> -	return &ah->ib_ah;
> -
> -fail:
> -	kfree(ah);
> -	return ERR_PTR(rc);
> +	return 0;
>  }
>  
>  int bnxt_re_modify_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
> @@ -812,13 +797,8 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp)
>  	bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp);
>  
>  	if (ib_qp->qp_type == IB_QPT_GSI && rdev->qp1_sqp) {
> -		rc = bnxt_qplib_destroy_ah(&rdev->qplib_res,
> -					   &rdev->sqp_ah->qplib_ah, false);
> -		if (rc) {
> -			dev_err(rdev_to_dev(rdev),
> -				"Failed to destroy HW AH for shadow QP");
> -			return rc;
> -		}
> +		bnxt_qplib_destroy_ah(&rdev->qplib_res, &rdev->sqp_ah->qplib_ah,
> +				      false);
>  
>  		bnxt_qplib_clean_qp(&qp->qplib_qp);
>  		rc = bnxt_qplib_destroy_qp(&rdev->qplib_res,
> diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
> index e45465ed4eee..1150cd369588 100644
> --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
> +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
> @@ -63,8 +63,8 @@ struct bnxt_re_pd {
>  };
>  
>  struct bnxt_re_ah {
> -	struct bnxt_re_dev	*rdev;
>  	struct ib_ah		ib_ah;
> +	struct bnxt_re_dev	*rdev;
>  	struct bnxt_qplib_ah	qplib_ah;
>  };
>  
> @@ -166,13 +166,11 @@ enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
>  int bnxt_re_alloc_pd(struct ib_pd *pd, struct ib_ucontext *context,
>  		     struct ib_udata *udata);
>  void bnxt_re_dealloc_pd(struct ib_pd *pd);
> -struct ib_ah *bnxt_re_create_ah(struct ib_pd *pd,
> -				struct rdma_ah_attr *ah_attr,
> -				u32 flags,
> -				struct ib_udata *udata);
> +int bnxt_re_create_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr, u32 flags,
> +		      struct ib_udata *udata);
>  int bnxt_re_modify_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr);
>  int bnxt_re_query_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr);
> -int bnxt_re_destroy_ah(struct ib_ah *ah, u32 flags);
> +void bnxt_re_destroy_ah(struct ib_ah *ah, u32 flags);
>  struct ib_srq *bnxt_re_create_srq(struct ib_pd *pd,
>  				  struct ib_srq_init_attr *srq_init_attr,
>  				  struct ib_udata *udata);
> diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
> index 2bd24ac45ee4..ec22853f8363 100644
> --- a/drivers/infiniband/hw/bnxt_re/main.c
> +++ b/drivers/infiniband/hw/bnxt_re/main.c
> @@ -637,6 +637,7 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
>  	.query_srq = bnxt_re_query_srq,
>  	.reg_user_mr = bnxt_re_reg_user_mr,
>  	.req_notify_cq = bnxt_re_req_notify_cq,
> +	INIT_RDMA_OBJ_SIZE(ib_ah, bnxt_re_ah, ib_ah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, bnxt_re_pd, ib_pd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, bnxt_re_ucontext, ib_uctx),
>  };
> diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
> index e9c53e406404..4197493d5efe 100644
> --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
> +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
> @@ -532,25 +532,21 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
>  	return 0;
>  }
>  
> -int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
> -			  bool block)
> +void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
> +			   bool block)
>  {
>  	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
>  	struct cmdq_destroy_ah req;
>  	struct creq_destroy_ah_resp resp;
>  	u16 cmd_flags = 0;
> -	int rc;
>  
>  	/* Clean up the AH table in the device */
>  	RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags);
>  
>  	req.ah_cid = cpu_to_le32(ah->id);
>  
> -	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
> -					  NULL, block);
> -	if (rc)
> -		return rc;
> -	return 0;
> +	bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL,
> +				     block);
>  }
>  
>  /* MRW */
> diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
> index 39454b3f738d..0ec3b12b0bcd 100644
> --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h
> +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h
> @@ -243,8 +243,8 @@ int bnxt_qplib_set_func_resources(struct bnxt_qplib_res *res,
>  				  struct bnxt_qplib_ctx *ctx);
>  int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
>  			 bool block);
> -int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
> -			  bool block);
> +void bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah,
> +			   bool block);
>  int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res,
>  			 struct bnxt_qplib_mrw *mrw);
>  int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
> diff --git a/drivers/infiniband/hw/hns/hns_roce_ah.c b/drivers/infiniband/hw/hns/hns_roce_ah.c
> index 64e0c69b69c5..913a709d6de5 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_ah.c
> +++ b/drivers/infiniband/hw/hns/hns_roce_ah.c
> @@ -39,23 +39,17 @@
>  #define HNS_ROCE_VLAN_SL_BIT_MASK	7
>  #define HNS_ROCE_VLAN_SL_SHIFT		13
>  
> -struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd,
> -				 struct rdma_ah_attr *ah_attr,
> -				 u32 flags,
> -				 struct ib_udata *udata)
> +int hns_roce_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
> +		       u32 flags, struct ib_udata *udata)
>  {
> -	struct hns_roce_dev *hr_dev = to_hr_dev(ibpd->device);
> +	struct hns_roce_dev *hr_dev = to_hr_dev(ibah->device);
>  	const struct ib_gid_attr *gid_attr;
>  	struct device *dev = hr_dev->dev;
> -	struct hns_roce_ah *ah;
> +	struct hns_roce_ah *ah = to_hr_ah(ibah);
>  	u16 vlan_tag = 0xffff;
>  	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
>  	bool vlan_en = false;
>  
> -	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> -
>  	/* Get mac address */
>  	memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);
>  
> @@ -70,7 +64,7 @@ struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd,
>  			     HNS_ROCE_VLAN_SL_BIT_MASK) <<
>  			     HNS_ROCE_VLAN_SL_SHIFT;
>  
> -	ah->av.port_pd = cpu_to_le32(to_hr_pd(ibpd)->pdn |
> +	ah->av.port_pd = cpu_to_le32(to_hr_pd(ibah->pd)->pdn |
>  				     (rdma_ah_get_port_num(ah_attr) <<
>  				     HNS_ROCE_PORT_NUM_SHIFT));
>  	ah->av.gid_index = grh->sgid_index;
> @@ -86,7 +80,7 @@ struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd,
>  	ah->av.sl_tclass_flowlabel = cpu_to_le32(rdma_ah_get_sl(ah_attr) <<
>  						 HNS_ROCE_SL_SHIFT);
>  
> -	return &ah->ibah;
> +	return 0;
>  }
>  
>  int hns_roce_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
> @@ -110,10 +104,3 @@ int hns_roce_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
>  
>  	return 0;
>  }
> -
> -int hns_roce_destroy_ah(struct ib_ah *ah, u32 flags)
> -{
> -	kfree(to_hr_ah(ah));
> -
> -	return 0;
> -}
> diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
> index 9ee86daf1700..876e88e8fc75 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_device.h
> +++ b/drivers/infiniband/hw/hns/hns_roce_device.h
> @@ -1107,12 +1107,9 @@ void hns_roce_bitmap_free_range(struct hns_roce_bitmap *bitmap,
>  				unsigned long obj, int cnt,
>  				int rr);
>  
> -struct ib_ah *hns_roce_create_ah(struct ib_pd *pd,
> -				 struct rdma_ah_attr *ah_attr,
> -				 u32 flags,
> -				 struct ib_udata *udata);
> +int hns_roce_create_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr,
> +		       u32 flags, struct ib_udata *udata);
>  int hns_roce_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
> -int hns_roce_destroy_ah(struct ib_ah *ah, u32 flags);
>  
>  int hns_roce_alloc_pd(struct ib_pd *pd, struct ib_ucontext *context,
>  		      struct ib_udata *udata);
> diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
> index c929125da84b..ef28215adcbb 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_main.c
> +++ b/drivers/infiniband/hw/hns/hns_roce_main.c
> @@ -452,7 +452,6 @@ static const struct ib_device_ops hns_roce_dev_ops = {
>  	.dealloc_ucontext = hns_roce_dealloc_ucontext,
>  	.del_gid = hns_roce_del_gid,
>  	.dereg_mr = hns_roce_dereg_mr,
> -	.destroy_ah = hns_roce_destroy_ah,
>  	.destroy_cq = hns_roce_ib_destroy_cq,
>  	.disassociate_ucontext = hns_roce_disassociate_ucontext,
>  	.get_dma_mr = hns_roce_get_dma_mr,
> @@ -468,6 +467,8 @@ static const struct ib_device_ops hns_roce_dev_ops = {
>  	.query_pkey = hns_roce_query_pkey,
>  	.query_port = hns_roce_query_port,
>  	.reg_user_mr = hns_roce_reg_user_mr,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, hns_roce_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, hns_roce_pd, ibpd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, hns_roce_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
> index 1672808262ba..9908b74757fe 100644
> --- a/drivers/infiniband/hw/mlx4/ah.c
> +++ b/drivers/infiniband/hw/mlx4/ah.c
> @@ -40,13 +40,12 @@
>  
>  #include "mlx4_ib.h"
>  
> -static struct ib_ah *create_ib_ah(struct ib_pd *pd,
> -				  struct rdma_ah_attr *ah_attr,
> -				  struct mlx4_ib_ah *ah)
> +static void create_ib_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
>  {
> -	struct mlx4_dev *dev = to_mdev(pd->device)->dev;
> +	struct mlx4_ib_ah *ah = to_mah(ib_ah);
> +	struct mlx4_dev *dev = to_mdev(ib_ah->device)->dev;
>  
> -	ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn |
> +	ah->av.ib.port_pd = cpu_to_be32(to_mpd(ib_ah->pd)->pdn |
>  			    (rdma_ah_get_port_num(ah_attr) << 24));
>  	ah->av.ib.g_slid  = rdma_ah_get_path_bits(ah_attr);
>  	ah->av.ib.sl_tclass_flowlabel =
> @@ -73,15 +72,12 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd,
>  			--static_rate;
>  		ah->av.ib.stat_rate = static_rate;
>  	}
> -
> -	return &ah->ibah;
>  }
>  
> -static struct ib_ah *create_iboe_ah(struct ib_pd *pd,
> -				    struct rdma_ah_attr *ah_attr,
> -				    struct mlx4_ib_ah *ah)
> +static int create_iboe_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr)
>  {
> -	struct mlx4_ib_dev *ibdev = to_mdev(pd->device);
> +	struct mlx4_ib_dev *ibdev = to_mdev(ib_ah->device);
> +	struct mlx4_ib_ah *ah = to_mah(ib_ah);
>  	const struct ib_gid_attr *gid_attr;
>  	struct mlx4_dev *dev = ibdev->dev;
>  	int is_mcast = 0;
> @@ -108,7 +104,7 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd,
>  		memcpy(ah->av.eth.s_mac, gid_attr->ndev->dev_addr, ETH_ALEN);
>  		ret = mlx4_ib_gid_index_to_real_index(ibdev, gid_attr);
>  		if (ret < 0)
> -			return ERR_PTR(ret);
> +			return ret;
>  		ah->av.eth.gid_index = ret;
>  	} else {
>  		/* mlx4_ib_create_ah_slave fills in the s_mac and the vlan */
> @@ -117,7 +113,7 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd,
>  
>  	if (vlan_tag < 0x1000)
>  		vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
> -	ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn |
> +	ah->av.eth.port_pd = cpu_to_be32(to_mpd(ib_ah->pd)->pdn |
>  					 (rdma_ah_get_port_num(ah_attr) << 24));
>  	ah->av.eth.vlan = cpu_to_be16(vlan_tag);
>  	ah->av.eth.hop_limit = grh->hop_limit;
> @@ -140,63 +136,45 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd,
>  	memcpy(ah->av.eth.dgid, grh->dgid.raw, 16);
>  	ah->av.eth.sl_tclass_flowlabel |= cpu_to_be32(rdma_ah_get_sl(ah_attr)
>  						      << 29);
> -	return &ah->ibah;
> +	return 0;
>  }
>  
> -struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
> -				u32 flags, struct ib_udata *udata)
> +int mlx4_ib_create_ah(struct ib_ah *ib_ah, struct rdma_ah_attr *ah_attr,
> +		      u32 flags, struct ib_udata *udata)
>  
>  {
> -	struct mlx4_ib_ah *ah;
> -	struct ib_ah *ret;
> -
> -	ah = kzalloc(sizeof *ah, GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> -
>  	if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
> -		if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH)) {
> -			ret = ERR_PTR(-EINVAL);
> -		} else {
> -			/*
> -			 * TBD: need to handle the case when we get
> -			 * called in an atomic context and there we
> -			 * might sleep.  We don't expect this
> -			 * currently since we're working with link
> -			 * local addresses which we can translate
> -			 * without going to sleep.
> -			 */
> -			ret = create_iboe_ah(pd, ah_attr, ah);
> -		}
> -
> -		if (IS_ERR(ret))
> -			kfree(ah);
> +		if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH))
> +			return -EINVAL;
> +		/*
> +		 * TBD: need to handle the case when we get
> +		 * called in an atomic context and there we
> +		 * might sleep.  We don't expect this
> +		 * currently since we're working with link
> +		 * local addresses which we can translate
> +		 * without going to sleep.
> +		 */
> +		return create_iboe_ah(ib_ah, ah_attr);
> +	}
>  
> -		return ret;
> -	} else
> -		return create_ib_ah(pd, ah_attr, ah); /* never fails */
> +	create_ib_ah(ib_ah, ah_attr);
> +	return 0;
>  }
>  
> -/* AH's created via this call must be free'd by mlx4_ib_destroy_ah. */
> -struct ib_ah *mlx4_ib_create_ah_slave(struct ib_pd *pd,
> -				      struct rdma_ah_attr *ah_attr,
> -				      int slave_sgid_index, u8 *s_mac,
> -				      u16 vlan_tag)
> +int mlx4_ib_create_ah_slave(struct ib_ah *ah, struct rdma_ah_attr *ah_attr,
> +			    int slave_sgid_index, u8 *s_mac, u16 vlan_tag)
>  {
>  	struct rdma_ah_attr slave_attr = *ah_attr;
> -	struct mlx4_ib_ah *mah;
> -	struct ib_ah *ah;
> +	struct mlx4_ib_ah *mah = to_mah(ah);
> +	int ret;
>  
>  	slave_attr.grh.sgid_attr = NULL;
>  	slave_attr.grh.sgid_index = slave_sgid_index;
> -	ah = mlx4_ib_create_ah(pd, &slave_attr, 0, NULL);
> -	if (IS_ERR(ah))
> -		return ah;
> +	ret = mlx4_ib_create_ah(ah, &slave_attr, 0, NULL);
> +	if (ret)
> +		return ret;
>  
> -	ah->device = pd->device;
> -	ah->pd = pd;
>  	ah->type = ah_attr->type;
> -	mah = to_mah(ah);
>  
>  	/* get rid of force-loopback bit */
>  	mah->av.ib.port_pd &= cpu_to_be32(0x7FFFFFFF);
> @@ -208,7 +186,7 @@ struct ib_ah *mlx4_ib_create_ah_slave(struct ib_pd *pd,
>  		vlan_tag |= (rdma_ah_get_sl(ah_attr) & 7) << 13;
>  	mah->av.eth.vlan = cpu_to_be16(vlan_tag);
>  
> -	return ah;
> +	return 0;
>  }
>  
>  int mlx4_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
> @@ -249,9 +227,3 @@ int mlx4_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
>  
>  	return 0;
>  }
> -
> -int mlx4_ib_destroy_ah(struct ib_ah *ah, u32 flags)
> -{
> -	kfree(to_mah(ah));
> -	return 0;
> -}
> diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
> index 936ee1314bcd..68c951491a08 100644
> --- a/drivers/infiniband/hw/mlx4/mad.c
> +++ b/drivers/infiniband/hw/mlx4/mad.c
> @@ -1371,9 +1371,9 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
>  	struct ib_ah *ah;
>  	struct ib_qp *send_qp = NULL;
>  	unsigned wire_tx_ix = 0;
> -	int ret = 0;
>  	u16 wire_pkey_ix;
>  	int src_qpnum;
> +	int ret;
>  
>  	sqp_ctx = dev->sriov.sqps[port-1];
>  
> @@ -1393,12 +1393,20 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
>  
>  	send_qp = sqp->qp;
>  
> -	/* create ah */
> -	ah = mlx4_ib_create_ah_slave(sqp_ctx->pd, attr,
> -				     rdma_ah_retrieve_grh(attr)->sgid_index,
> -				     s_mac, vlan_id);
> -	if (IS_ERR(ah))
> +	ah = rdma_zalloc_drv_obj(sqp_ctx->pd->device, ib_ah);
> +	if (!ah)
>  		return -ENOMEM;
> +
> +	ah->device = sqp_ctx->pd->device;
> +	ah->pd = sqp_ctx->pd;
> +
> +	/* create ah */
> +	ret = mlx4_ib_create_ah_slave(ah, attr,
> +				      rdma_ah_retrieve_grh(attr)->sgid_index,
> +				      s_mac, vlan_id);
> +	if (ret)
> +		goto out;
> +
>  	spin_lock(&sqp->tx_lock);
>  	if (sqp->tx_ix_head - sqp->tx_ix_tail >=
>  	    (MLX4_NUM_TUNNEL_BUFS - 1))
> @@ -1410,8 +1418,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
>  		goto out;
>  
>  	sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr);
> -	if (sqp->tx_ring[wire_tx_ix].ah)
> -		mlx4_ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
> +	kfree(sqp->tx_ring[wire_tx_ix].ah);
>  	sqp->tx_ring[wire_tx_ix].ah = ah;
>  	ib_dma_sync_single_for_cpu(&dev->ib_dev,
>  				   sqp->tx_ring[wire_tx_ix].buf.map,
> @@ -1450,7 +1457,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
>  	spin_unlock(&sqp->tx_lock);
>  	sqp->tx_ring[wire_tx_ix].ah = NULL;
>  out:
> -	mlx4_ib_destroy_ah(ah, 0);
> +	kfree(ah);
>  	return ret;
>  }
>  
> @@ -1902,8 +1909,8 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
>  		if (wc.status == IB_WC_SUCCESS) {
>  			switch (wc.opcode) {
>  			case IB_WC_SEND:
> -				mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
> -					      (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
> +				kfree(sqp->tx_ring[wc.wr_id &
> +				      (MLX4_NUM_TUNNEL_BUFS - 1)].ah);
>  				sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
>  					= NULL;
>  				spin_lock(&sqp->tx_lock);
> @@ -1931,8 +1938,8 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
>  				 " status = %d, wrid = 0x%llx\n",
>  				 ctx->slave, wc.status, wc.wr_id);
>  			if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
> -				mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
> -					      (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
> +				kfree(sqp->tx_ring[wc.wr_id &
> +				      (MLX4_NUM_TUNNEL_BUFS - 1)].ah);
>  				sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
>  					= NULL;
>  				spin_lock(&sqp->tx_lock);
> diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
> index 733f7bbd5901..535ec5c2704b 100644
> --- a/drivers/infiniband/hw/mlx4/main.c
> +++ b/drivers/infiniband/hw/mlx4/main.c
> @@ -2524,7 +2524,6 @@ static const struct ib_device_ops mlx4_ib_dev_ops = {
>  	.dealloc_ucontext = mlx4_ib_dealloc_ucontext,
>  	.del_gid = mlx4_ib_del_gid,
>  	.dereg_mr = mlx4_ib_dereg_mr,
> -	.destroy_ah = mlx4_ib_destroy_ah,
>  	.destroy_cq = mlx4_ib_destroy_cq,
>  	.destroy_qp = mlx4_ib_destroy_qp,
>  	.destroy_srq = mlx4_ib_destroy_srq,
> @@ -2560,6 +2559,8 @@ static const struct ib_device_ops mlx4_ib_dev_ops = {
>  	.req_notify_cq = mlx4_ib_arm_cq,
>  	.rereg_user_mr = mlx4_ib_rereg_user_mr,
>  	.resize_cq = mlx4_ib_resize_cq,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, mlx4_ib_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, mlx4_ib_pd, ibpd),
>  	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 60dc1347c5ab..8f1ad2a44573 100644
> --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
> +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
> @@ -754,14 +754,11 @@ int mlx4_ib_arm_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags);
>  void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq);
>  void mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq);
>  
> -struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
> -				u32 flags, struct ib_udata *udata);
> -struct ib_ah *mlx4_ib_create_ah_slave(struct ib_pd *pd,
> -				      struct rdma_ah_attr *ah_attr,
> -				      int slave_sgid_index, u8 *s_mac,
> -				      u16 vlan_tag);
> +int mlx4_ib_create_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr, u32 flags,
> +		      struct ib_udata *udata);
> +int mlx4_ib_create_ah_slave(struct ib_ah *ah, struct rdma_ah_attr *ah_attr,
> +			    int slave_sgid_index, u8 *s_mac, u16 vlan_tag);
>  int mlx4_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
> -int mlx4_ib_destroy_ah(struct ib_ah *ah, u32 flags);
>  
>  struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
>  				  struct ib_srq_init_attr *init_attr,
> diff --git a/drivers/infiniband/hw/mlx5/ah.c b/drivers/infiniband/hw/mlx5/ah.c
> index 420ae0897333..d868f048485f 100644
> --- a/drivers/infiniband/hw/mlx5/ah.c
> +++ b/drivers/infiniband/hw/mlx5/ah.c
> @@ -32,9 +32,8 @@
>  
>  #include "mlx5_ib.h"
>  
> -static struct ib_ah *create_ib_ah(struct mlx5_ib_dev *dev,
> -				  struct mlx5_ib_ah *ah,
> -				  struct rdma_ah_attr *ah_attr)
> +static void create_ib_ah(struct mlx5_ib_dev *dev, struct mlx5_ib_ah *ah,
> +			 struct rdma_ah_attr *ah_attr)
>  {
>  	enum ib_gid_type gid_type;
>  
> @@ -67,21 +66,19 @@ static struct ib_ah *create_ib_ah(struct mlx5_ib_dev *dev,
>  		ah->av.fl_mlid = rdma_ah_get_path_bits(ah_attr) & 0x7f;
>  		ah->av.stat_rate_sl |= (rdma_ah_get_sl(ah_attr) & 0xf);
>  	}
> -
> -	return &ah->ibah;
>  }
>  
> -struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
> -				u32 flags, struct ib_udata *udata)
> +int mlx5_ib_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
> +		      u32 flags, struct ib_udata *udata)
>  
>  {
> -	struct mlx5_ib_ah *ah;
> -	struct mlx5_ib_dev *dev = to_mdev(pd->device);
> +	struct mlx5_ib_ah *ah = to_mah(ibah);
> +	struct mlx5_ib_dev *dev = to_mdev(ibah->device);
>  	enum rdma_ah_attr_type ah_type = ah_attr->type;
>  
>  	if ((ah_type == RDMA_AH_ATTR_TYPE_ROCE) &&
>  	    !(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH))
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  
>  	if (ah_type == RDMA_AH_ATTR_TYPE_ROCE && udata) {
>  		int err;
> @@ -90,21 +87,18 @@ struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
>  				   sizeof(resp.dmac);
>  
>  		if (udata->outlen < min_resp_len)
> -			return ERR_PTR(-EINVAL);
> +			return -EINVAL;
>  
>  		resp.response_length = min_resp_len;
>  
>  		memcpy(resp.dmac, ah_attr->roce.dmac, ETH_ALEN);
>  		err = ib_copy_to_udata(udata, &resp, resp.response_length);
>  		if (err)
> -			return ERR_PTR(err);
> +			return err;
>  	}
>  
> -	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> -
> -	return create_ib_ah(dev, ah, ah_attr); /* never fails */
> +	create_ib_ah(dev, ah, ah_attr);
> +	return 0;
>  }
>  
>  int mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
> @@ -130,9 +124,3 @@ int mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
>  
>  	return 0;
>  }
> -
> -int mlx5_ib_destroy_ah(struct ib_ah *ah, u32 flags)
> -{
> -	kfree(to_mah(ah));
> -	return 0;
> -}
> diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
> index 531ff20b32ad..9a8cf3a9e702 100644
> --- a/drivers/infiniband/hw/mlx5/main.c
> +++ b/drivers/infiniband/hw/mlx5/main.c
> @@ -5945,7 +5945,6 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
>  	.dealloc_ucontext = mlx5_ib_dealloc_ucontext,
>  	.del_gid = mlx5_ib_del_gid,
>  	.dereg_mr = mlx5_ib_dereg_mr,
> -	.destroy_ah = mlx5_ib_destroy_ah,
>  	.destroy_counters = mlx5_ib_destroy_counters,
>  	.destroy_cq = mlx5_ib_destroy_cq,
>  	.destroy_flow = mlx5_ib_destroy_flow,
> @@ -5982,6 +5981,8 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
>  	.req_notify_cq = mlx5_ib_arm_cq,
>  	.rereg_user_mr = mlx5_ib_rereg_user_mr,
>  	.resize_cq = mlx5_ib_resize_cq,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, mlx5_ib_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd),
>  	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 4a617d78eae1..9a55f9853881 100644
> --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
> +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
> @@ -1046,10 +1046,9 @@ void mlx5_ib_db_unmap_user(struct mlx5_ib_ucontext *context, struct mlx5_db *db)
>  void __mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq);
>  void mlx5_ib_cq_clean(struct mlx5_ib_cq *cq, u32 qpn, struct mlx5_ib_srq *srq);
>  void mlx5_ib_free_srq_wqe(struct mlx5_ib_srq *srq, int wqe_index);
> -struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
> -				u32 flags, struct ib_udata *udata);
> +int mlx5_ib_create_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr, u32 flags,
> +		      struct ib_udata *udata);
>  int mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
> -int mlx5_ib_destroy_ah(struct ib_ah *ah, u32 flags);
>  struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
>  				  struct ib_srq_init_attr *init_attr,
>  				  struct ib_udata *udata);
> diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
> index d063d7a37762..ae9b47d438d2 100644
> --- a/drivers/infiniband/hw/mthca/mthca_provider.c
> +++ b/drivers/infiniband/hw/mthca/mthca_provider.c
> @@ -389,34 +389,19 @@ static void mthca_dealloc_pd(struct ib_pd *pd)
>  	mthca_pd_free(to_mdev(pd->device), to_mpd(pd));
>  }
>  
> -static struct ib_ah *mthca_ah_create(struct ib_pd *pd,
> -				     struct rdma_ah_attr *ah_attr,
> -				     u32 flags,
> -				     struct ib_udata *udata)
> +static int mthca_ah_create(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
> +			   u32 flags, struct ib_udata *udata)
>  
>  {
> -	int err;
> -	struct mthca_ah *ah;
> -
> -	ah = kmalloc(sizeof *ah, GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> +	struct mthca_ah *ah = to_mah(ibah);
>  
> -	err = mthca_create_ah(to_mdev(pd->device), to_mpd(pd), ah_attr, ah);
> -	if (err) {
> -		kfree(ah);
> -		return ERR_PTR(err);
> -	}
> -
> -	return &ah->ibah;
> +	return mthca_create_ah(to_mdev(ibah->device), to_mpd(ibah->pd), ah_attr,
> +			       ah);
>  }
>  
> -static int mthca_ah_destroy(struct ib_ah *ah, u32 flags)
> +static void mthca_ah_destroy(struct ib_ah *ah, u32 flags)
>  {
>  	mthca_destroy_ah(to_mdev(ah->device), to_mah(ah));
> -	kfree(ah);
> -
> -	return 0;
>  }
>  
>  static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
> @@ -1200,6 +1185,8 @@ static const struct ib_device_ops mthca_dev_ops = {
>  	.query_qp = mthca_query_qp,
>  	.reg_user_mr = mthca_reg_user_mr,
>  	.resize_cq = mthca_resize_cq,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, mthca_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, mthca_pd, ibpd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, mthca_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
> index a7295322efbc..a17747cb086a 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
> @@ -156,29 +156,25 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
>  	return status;
>  }
>  
> -struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct rdma_ah_attr *attr,
> -			       u32 flags, struct ib_udata *udata)
> +int ocrdma_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr, u32 flags,
> +		     struct ib_udata *udata)
>  {
>  	u32 *ahid_addr;
>  	int status;
> -	struct ocrdma_ah *ah;
> +	struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
>  	bool isvlan = false;
>  	u16 vlan_tag = 0xffff;
>  	const struct ib_gid_attr *sgid_attr;
> -	struct ocrdma_pd *pd = get_ocrdma_pd(ibpd);
> -	struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device);
> +	struct ocrdma_pd *pd = get_ocrdma_pd(ibah->pd);
> +	struct ocrdma_dev *dev = get_ocrdma_dev(ibah->device);
>  
>  	if ((attr->type != RDMA_AH_ATTR_TYPE_ROCE) ||
>  	    !(rdma_ah_get_ah_flags(attr) & IB_AH_GRH))
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  
>  	if (atomic_cmpxchg(&dev->update_sl, 1, 0))
>  		ocrdma_init_service_level(dev);
>  
> -	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> -
>  	status = ocrdma_alloc_av(dev, ah);
>  	if (status)
>  		goto av_err;
> @@ -210,23 +206,20 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct rdma_ah_attr *attr,
>  				       OCRDMA_AH_VLAN_VALID_SHIFT);
>  	}
>  
> -	return &ah->ibah;
> +	return 0;
>  
>  av_conf_err:
>  	ocrdma_free_av(dev, ah);
>  av_err:
> -	kfree(ah);
> -	return ERR_PTR(status);
> +	return status;
>  }
>  
> -int ocrdma_destroy_ah(struct ib_ah *ibah, u32 flags)
> +void ocrdma_destroy_ah(struct ib_ah *ibah, u32 flags)
>  {
>  	struct ocrdma_ah *ah = get_ocrdma_ah(ibah);
>  	struct ocrdma_dev *dev = get_ocrdma_dev(ibah->device);
>  
>  	ocrdma_free_av(dev, ah);
> -	kfree(ah);
> -	return 0;
>  }
>  
>  int ocrdma_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr)
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
> index eb996e14b520..64cb82c08664 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
> @@ -51,9 +51,9 @@ enum {
>  	OCRDMA_AH_L3_TYPE_SHIFT		= 0x1D /* 29 bits */
>  };
>  
> -struct ib_ah *ocrdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
> -			       u32 flags, struct ib_udata *udata);
> -int ocrdma_destroy_ah(struct ib_ah *ah, u32 flags);
> +int ocrdma_create_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr, u32 flags,
> +		     struct ib_udata *udata);
> +void ocrdma_destroy_ah(struct ib_ah *ah, u32 flags);
>  int ocrdma_query_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr);
>  
>  int ocrdma_process_mad(struct ib_device *,
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
> index 097e5ab2a19f..e693eb352959 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
> @@ -3067,13 +3067,12 @@ int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
>  	return status;
>  }
>  
> -int ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
> +void ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah)
>  {
>  	unsigned long flags;
>  	spin_lock_irqsave(&dev->av_tbl.lock, flags);
>  	ah->av->valid = 0;
>  	spin_unlock_irqrestore(&dev->av_tbl.lock, flags);
> -	return 0;
>  }
>  
>  static int ocrdma_create_eqs(struct ocrdma_dev *dev)
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
> index ebc1f442aec3..88d45aa19ded 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
> @@ -139,8 +139,8 @@ int ocrdma_mbx_modify_srq(struct ocrdma_srq *, struct ib_srq_attr *);
>  int ocrdma_mbx_query_srq(struct ocrdma_srq *, struct ib_srq_attr *);
>  int ocrdma_mbx_destroy_srq(struct ocrdma_dev *, struct ocrdma_srq *);
>  
> -int ocrdma_alloc_av(struct ocrdma_dev *, struct ocrdma_ah *);
> -int ocrdma_free_av(struct ocrdma_dev *, struct ocrdma_ah *);
> +int ocrdma_alloc_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah);
> +void ocrdma_free_av(struct ocrdma_dev *dev, struct ocrdma_ah *ah);
>  
>  int ocrdma_qp_state_change(struct ocrdma_qp *, enum ib_qp_state new_state,
>  			    enum ib_qp_state *old_ib_state);
> diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
> index b9e10d55a58e..8642a2e60be7 100644
> --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
> +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
> @@ -179,6 +179,8 @@ static const struct ib_device_ops ocrdma_dev_ops = {
>  	.reg_user_mr = ocrdma_reg_user_mr,
>  	.req_notify_cq = ocrdma_arm_cq,
>  	.resize_cq = ocrdma_resize_cq,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, ocrdma_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, ocrdma_pd, ibpd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, ocrdma_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
> index 996d9ecd93e0..d460a6c02e06 100644
> --- a/drivers/infiniband/hw/qedr/main.c
> +++ b/drivers/infiniband/hw/qedr/main.c
> @@ -239,6 +239,8 @@ static const struct ib_device_ops qedr_dev_ops = {
>  	.reg_user_mr = qedr_reg_user_mr,
>  	.req_notify_cq = qedr_arm_cq,
>  	.resize_cq = qedr_resize_cq,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, qedr_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, qedr_pd, ibpd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, qedr_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
> index 59ad4202422c..fc58f0cc1944 100644
> --- a/drivers/infiniband/hw/qedr/verbs.c
> +++ b/drivers/infiniband/hw/qedr/verbs.c
> @@ -2570,27 +2570,21 @@ int qedr_destroy_qp(struct ib_qp *ibqp)
>  	return rc;
>  }
>  
> -struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct rdma_ah_attr *attr,
> -			     u32 flags, struct ib_udata *udata)
> +int qedr_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr, u32 flags,
> +		   struct ib_udata *udata)
>  {
> -	struct qedr_ah *ah;
> -
> -	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> +	struct qedr_ah *ah = get_qedr_ah(ibah);
>  
>  	rdma_copy_ah_attr(&ah->attr, attr);
>  
> -	return &ah->ibah;
> +	return 0;
>  }
>  
> -int qedr_destroy_ah(struct ib_ah *ibah, u32 flags)
> +void qedr_destroy_ah(struct ib_ah *ibah, u32 flags)
>  {
>  	struct qedr_ah *ah = get_qedr_ah(ibah);
>  
>  	rdma_destroy_ah_attr(&ah->attr);
> -	kfree(ah);
> -	return 0;
>  }
>  
>  static void free_mr_info(struct qedr_dev *dev, struct mr_info *info)
> diff --git a/drivers/infiniband/hw/qedr/verbs.h b/drivers/infiniband/hw/qedr/verbs.h
> index f0c05f4771ac..b2f18667e93e 100644
> --- a/drivers/infiniband/hw/qedr/verbs.h
> +++ b/drivers/infiniband/hw/qedr/verbs.h
> @@ -75,9 +75,9 @@ int qedr_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr);
>  int qedr_destroy_srq(struct ib_srq *ibsrq);
>  int qedr_post_srq_recv(struct ib_srq *ibsrq, const struct ib_recv_wr *wr,
>  		       const struct ib_recv_wr **bad_recv_wr);
> -struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct rdma_ah_attr *attr,
> -			     u32 flags, struct ib_udata *udata);
> -int qedr_destroy_ah(struct ib_ah *ibah, u32 flags);
> +int qedr_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr, u32 flags,
> +		   struct ib_udata *udata);
> +void qedr_destroy_ah(struct ib_ah *ibah, u32 flags);
>  
>  int qedr_dereg_mr(struct ib_mr *);
>  struct ib_mr *qedr_get_dma_mr(struct ib_pd *, int acc);
> diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
> index 6d8b3e0de57a..6cbc271a1b7d 100644
> --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
> +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
> @@ -195,6 +195,8 @@ static const struct ib_device_ops pvrdma_dev_ops = {
>  	.query_qp = pvrdma_query_qp,
>  	.reg_user_mr = pvrdma_reg_user_mr,
>  	.req_notify_cq = pvrdma_req_notify_cq,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, pvrdma_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, pvrdma_pd, ibpd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, pvrdma_ucontext, ibucontext),
>  };
> diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
> index 42fe821f8d58..44766b1d5e45 100644
> --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
> +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
> @@ -507,34 +507,28 @@ void pvrdma_dealloc_pd(struct ib_pd *pd)
>   * @udata: user data blob
>   * @flags: create address handle flags (see enum rdma_create_ah_flags)
>   *
> - * @return: the ib_ah pointer on success, otherwise errno.
> + * @return: 0 on success, otherwise errno.
>   */
> -struct ib_ah *pvrdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
> -			       u32 flags, struct ib_udata *udata)
> +int pvrdma_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
> +		     u32 flags, struct ib_udata *udata)
>  {
> -	struct pvrdma_dev *dev = to_vdev(pd->device);
> -	struct pvrdma_ah *ah;
> +	struct pvrdma_dev *dev = to_vdev(ibah->device);
> +	struct pvrdma_ah *ah = to_vah(ibah);
>  	const struct ib_global_route *grh;
>  	u8 port_num = rdma_ah_get_port_num(ah_attr);
>  
>  	if (!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH))
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  
>  	grh = rdma_ah_read_grh(ah_attr);
>  	if ((ah_attr->type != RDMA_AH_ATTR_TYPE_ROCE)  ||
>  	    rdma_is_multicast_addr((struct in6_addr *)grh->dgid.raw))
> -		return ERR_PTR(-EINVAL);
> +		return -EINVAL;
>  
>  	if (!atomic_add_unless(&dev->num_ahs, 1, dev->dsr->caps.max_ah))
> -		return ERR_PTR(-ENOMEM);
> -
> -	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
> -	if (!ah) {
> -		atomic_dec(&dev->num_ahs);
> -		return ERR_PTR(-ENOMEM);
> -	}
> +		return -ENOMEM;
>  
> -	ah->av.port_pd = to_vpd(pd)->pd_handle | (port_num << 24);
> +	ah->av.port_pd = to_vpd(ibah->pd)->pd_handle | (port_num << 24);
>  	ah->av.src_path_bits = rdma_ah_get_path_bits(ah_attr);
>  	ah->av.src_path_bits |= 0x80;
>  	ah->av.gid_index = grh->sgid_index;
> @@ -544,11 +538,7 @@ struct ib_ah *pvrdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
>  	memcpy(ah->av.dgid, grh->dgid.raw, 16);
>  	memcpy(ah->av.dmac, ah_attr->roce.dmac, ETH_ALEN);
>  
> -	ah->ibah.device = pd->device;
> -	ah->ibah.pd = pd;
> -	ah->ibah.uobject = NULL;
> -
> -	return &ah->ibah;
> +	return 0;
>  }
>  
>  /**
> @@ -556,14 +546,10 @@ struct ib_ah *pvrdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
>   * @ah: the address handle to destroyed
>   * @flags: destroy address handle flags (see enum rdma_destroy_ah_flags)
>   *
> - * @return: 0 on success.
>   */
> -int pvrdma_destroy_ah(struct ib_ah *ah, u32 flags)
> +void pvrdma_destroy_ah(struct ib_ah *ah, u32 flags)
>  {
>  	struct pvrdma_dev *dev = to_vdev(ah->device);
>  
> -	kfree(to_vah(ah));
>  	atomic_dec(&dev->num_ahs);
> -
> -	return 0;
>  }
> diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
> index 607aa131d67c..0d05d8a15225 100644
> --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
> +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
> @@ -417,9 +417,9 @@ struct ib_cq *pvrdma_create_cq(struct ib_device *ibdev,
>  int pvrdma_destroy_cq(struct ib_cq *cq);
>  int pvrdma_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
>  int pvrdma_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags);
> -struct ib_ah *pvrdma_create_ah(struct ib_pd *pd, struct rdma_ah_attr *ah_attr,
> -			       u32 flags, struct ib_udata *udata);
> -int pvrdma_destroy_ah(struct ib_ah *ah, u32 flags);
> +int pvrdma_create_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr, u32 flags,
> +		     struct ib_udata *udata);
> +void pvrdma_destroy_ah(struct ib_ah *ah, u32 flags);
>  
>  struct ib_srq *pvrdma_create_srq(struct ib_pd *pd,
>  				 struct ib_srq_init_attr *init_attr,
> diff --git a/drivers/infiniband/sw/rdmavt/ah.c b/drivers/infiniband/sw/rdmavt/ah.c
> index fc10e4e26ca7..9e85857c3cd9 100644
> --- a/drivers/infiniband/sw/rdmavt/ah.c
> +++ b/drivers/infiniband/sw/rdmavt/ah.c
> @@ -89,36 +89,29 @@ EXPORT_SYMBOL(rvt_check_ah);
>  
>  /**
>   * rvt_create_ah - create an address handle
> - * @pd: the protection domain
> + * @ibah: the IB address handle
>   * @ah_attr: the attributes of the AH
>   * @create_flags: create address handle flags (see enum rdma_create_ah_flags)
>   * @udata: pointer to user's input output buffer information.
>   *
>   * This may be called from interrupt context.
>   *
> - * Return: newly allocated ah
> + * Return: 0 on success
>   */
> -struct ib_ah *rvt_create_ah(struct ib_pd *pd,
> -			    struct rdma_ah_attr *ah_attr,
> -			    u32 create_flags,
> -			    struct ib_udata *udata)
> +int rvt_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr,
> +		  u32 create_flags, struct ib_udata *udata)
>  {
> -	struct rvt_ah *ah;
> -	struct rvt_dev_info *dev = ib_to_rvt(pd->device);
> +	struct rvt_ah *ah = ibah_to_rvtah(ibah);
> +	struct rvt_dev_info *dev = ib_to_rvt(ibah->device);
>  	unsigned long flags;
>  
> -	if (rvt_check_ah(pd->device, ah_attr))
> -		return ERR_PTR(-EINVAL);
> -
> -	ah = kmalloc(sizeof(*ah), GFP_ATOMIC);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> +	if (rvt_check_ah(ibah->device, ah_attr))
> +		return -EINVAL;
>  
>  	spin_lock_irqsave(&dev->n_ahs_lock, flags);
>  	if (dev->n_ahs_allocated == dev->dparms.props.max_ah) {
>  		spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
> -		kfree(ah);
> -		return ERR_PTR(-ENOMEM);
> +		return -ENOMEM;
>  	}
>  
>  	dev->n_ahs_allocated++;
> @@ -129,9 +122,9 @@ struct ib_ah *rvt_create_ah(struct ib_pd *pd,
>  	atomic_set(&ah->refcount, 0);
>  
>  	if (dev->driver_f.notify_new_ah)
> -		dev->driver_f.notify_new_ah(pd->device, ah_attr, ah);
> +		dev->driver_f.notify_new_ah(ibah->device, ah_attr, ah);
>  
> -	return &ah->ibah;
> +	return 0;
>  }
>  
>  /**
> @@ -141,23 +134,20 @@ struct ib_ah *rvt_create_ah(struct ib_pd *pd,
>   *
>   * Return: 0 on success
>   */
> -int rvt_destroy_ah(struct ib_ah *ibah, u32 destroy_flags)
> +void rvt_destroy_ah(struct ib_ah *ibah, u32 destroy_flags)
>  {
>  	struct rvt_dev_info *dev = ib_to_rvt(ibah->device);
>  	struct rvt_ah *ah = ibah_to_rvtah(ibah);
>  	unsigned long flags;
>  
>  	if (atomic_read(&ah->refcount) != 0)
> -		return -EBUSY;
> +		return;
>  
>  	spin_lock_irqsave(&dev->n_ahs_lock, flags);
>  	dev->n_ahs_allocated--;
>  	spin_unlock_irqrestore(&dev->n_ahs_lock, flags);
>  
>  	rdma_destroy_ah_attr(&ah->attr);
> -	kfree(ah);
> -
> -	return 0;
>  }
>  
>  /**
> diff --git a/drivers/infiniband/sw/rdmavt/ah.h b/drivers/infiniband/sw/rdmavt/ah.h
> index 72431a618d5d..bbb4d3bdec4e 100644
> --- a/drivers/infiniband/sw/rdmavt/ah.h
> +++ b/drivers/infiniband/sw/rdmavt/ah.h
> @@ -50,11 +50,9 @@
>  
>  #include <rdma/rdma_vt.h>
>  
> -struct ib_ah *rvt_create_ah(struct ib_pd *pd,
> -			    struct rdma_ah_attr *ah_attr,
> -			    u32 create_flags,
> -			    struct ib_udata *udata);
> -int rvt_destroy_ah(struct ib_ah *ibah, u32 destroy_flags);
> +int rvt_create_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr,
> +		  u32 create_flags, struct ib_udata *udata);
> +void rvt_destroy_ah(struct ib_ah *ibah, u32 destroy_flags);
>  int rvt_modify_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
>  int rvt_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
>  
> diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c
> index 42c9d35f832d..f4b3bb57ab06 100644
> --- a/drivers/infiniband/sw/rdmavt/vt.c
> +++ b/drivers/infiniband/sw/rdmavt/vt.c
> @@ -425,6 +425,8 @@ static const struct ib_device_ops rvt_dev_ops = {
>  	.req_notify_cq = rvt_req_notify_cq,
>  	.resize_cq = rvt_resize_cq,
>  	.unmap_fmr = rvt_unmap_fmr,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, rvt_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, rvt_pd, ibpd),
>  	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 120fa9005954..756bd36fd268 100644
> --- a/drivers/infiniband/sw/rxe/rxe_pool.c
> +++ b/drivers/infiniband/sw/rxe/rxe_pool.c
> @@ -52,7 +52,7 @@ struct rxe_type_info rxe_type_info[RXE_NUM_TYPES] = {
>  	[RXE_TYPE_AH] = {
>  		.name		= "rxe-ah",
>  		.size		= sizeof(struct rxe_ah),
> -		.flags		= RXE_POOL_ATOMIC,
> +		.flags		= RXE_POOL_ATOMIC | RXE_POOL_NO_ALLOC,
>  	},
>  	[RXE_TYPE_SRQ] = {
>  		.name		= "rxe-srq",
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
> index 6ecf28570ff0..c8c8a8a55a32 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.c
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
> @@ -192,30 +192,24 @@ static void rxe_dealloc_pd(struct ib_pd *ibpd)
>  	rxe_drop_ref(pd);
>  }
>  
> -static struct ib_ah *rxe_create_ah(struct ib_pd *ibpd,
> -				   struct rdma_ah_attr *attr,
> -				   u32 flags,
> -				   struct ib_udata *udata)
> +static int rxe_create_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr,
> +			 u32 flags, struct ib_udata *udata)
>  
>  {
>  	int err;
> -	struct rxe_dev *rxe = to_rdev(ibpd->device);
> -	struct rxe_pd *pd = to_rpd(ibpd);
> -	struct rxe_ah *ah;
> +	struct rxe_dev *rxe = to_rdev(ibah->device);
> +	struct rxe_ah *ah = to_rah(ibah);
>  
>  	err = rxe_av_chk_attr(rxe, attr);
>  	if (err)
> -		return ERR_PTR(err);
> -
> -	ah = rxe_alloc(&rxe->ah_pool);
> -	if (!ah)
> -		return ERR_PTR(-ENOMEM);
> +		return err;
>  
> -	rxe_add_ref(pd);
> -	ah->pd = pd;
> +	err = rxe_add_to_pool(&rxe->ah_pool, &ah->pelem);
> +	if (err)
> +		return err;
>  
>  	rxe_init_av(attr, &ah->av);
> -	return &ah->ibah;
> +	return 0;
>  }
>  
>  static int rxe_modify_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr)
> @@ -242,13 +236,11 @@ static int rxe_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *attr)
>  	return 0;
>  }
>  
> -static int rxe_destroy_ah(struct ib_ah *ibah, u32 flags)
> +static void rxe_destroy_ah(struct ib_ah *ibah, u32 flags)
>  {
>  	struct rxe_ah *ah = to_rah(ibah);
>  
> -	rxe_drop_ref(ah->pd);
>  	rxe_drop_ref(ah);
> -	return 0;
>  }
>  
>  static int post_one_recv(struct rxe_rq *rq, const struct ib_recv_wr *ibwr)
> @@ -1176,6 +1168,8 @@ static const struct ib_device_ops rxe_dev_ops = {
>  	.reg_user_mr = rxe_reg_user_mr,
>  	.req_notify_cq = rxe_req_notify_cq,
>  	.resize_cq = rxe_resize_cq,
> +
> +	INIT_RDMA_OBJ_SIZE(ib_ah, rxe_ah, ibah),
>  	INIT_RDMA_OBJ_SIZE(ib_pd, rxe_pd, ibpd),
>  	INIT_RDMA_OBJ_SIZE(ib_ucontext, rxe_ucontext, ibuc),
>  };
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
> index 157e51aeb1e1..23c5002b5134 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.h
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
> @@ -71,8 +71,8 @@ struct rxe_pd {
>  };
>  
>  struct rxe_ah {
> -	struct rxe_pool_entry	pelem;
>  	struct ib_ah		ibah;
> +	struct rxe_pool_entry	pelem;
>  	struct rxe_pd		*pd;
>  	struct rxe_av		av;
>  };
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index a73796581c75..6777c30e796e 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -2400,12 +2400,11 @@ struct ib_device_ops {
>  	int (*alloc_pd)(struct ib_pd *pd, struct ib_ucontext *context,
>  			struct ib_udata *udata);
>  	void (*dealloc_pd)(struct ib_pd *pd);
> -	struct ib_ah *(*create_ah)(struct ib_pd *pd,
> -				   struct rdma_ah_attr *ah_attr, u32 flags,
> -				   struct ib_udata *udata);
> +	int (*create_ah)(struct ib_ah *ah, struct rdma_ah_attr *ah_attr,
> +			 u32 flags, struct ib_udata *udata);
>  	int (*modify_ah)(struct ib_ah *ah, struct rdma_ah_attr *ah_attr);
>  	int (*query_ah)(struct ib_ah *ah, struct rdma_ah_attr *ah_attr);
> -	int (*destroy_ah)(struct ib_ah *ah, u32 flags);
> +	void (*destroy_ah)(struct ib_ah *ah, u32 flags);
>  	struct ib_srq *(*create_srq)(struct ib_pd *pd,
>  				     struct ib_srq_init_attr *srq_init_attr,
>  				     struct ib_udata *udata);
> @@ -2553,6 +2552,7 @@ struct ib_device_ops {
>  	 */
>  	void (*dealloc_driver)(struct ib_device *dev);
>  
> +	DECLARE_RDMA_OBJ_SIZE(ib_ah);
>  	DECLARE_RDMA_OBJ_SIZE(ib_pd);
>  	DECLARE_RDMA_OBJ_SIZE(ib_ucontext);
>  };
> 






[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux