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); > }; >