Skip to content

Commit 1a1f460

Browse files
committed
RDMA: Hold the sgid_attr inside the struct ib_ah/qp
If the AH has a GRH then hold a reference to the sgid_attr inside the common struct. If the QP is modified with an AV that includes a GRH then also hold a reference to the sgid_attr inside the common struct. This informs the cache that the sgid_index is in-use so long as the AH or QP using it exists. This also means that all drivers can access the sgid_attr directly from the ah_attr instead of querying the cache during their UD post-send paths. Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
1 parent 7492052 commit 1a1f460

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

drivers/infiniband/core/verbs.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,19 @@ static void rdma_unfill_sgid_attr(struct rdma_ah_attr *ah_attr,
459459
rdma_destroy_ah_attr(ah_attr);
460460
}
461461

462+
static const struct ib_gid_attr *
463+
rdma_update_sgid_attr(struct rdma_ah_attr *ah_attr,
464+
const struct ib_gid_attr *old_attr)
465+
{
466+
if (old_attr)
467+
rdma_put_gid_attr(old_attr);
468+
if (ah_attr->ah_flags & IB_AH_GRH) {
469+
rdma_hold_gid_attr(ah_attr->grh.sgid_attr);
470+
return ah_attr->grh.sgid_attr;
471+
}
472+
return NULL;
473+
}
474+
462475
static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
463476
struct rdma_ah_attr *ah_attr,
464477
struct ib_udata *udata)
@@ -472,6 +485,8 @@ static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
472485
ah->pd = pd;
473486
ah->uobject = NULL;
474487
ah->type = ah_attr->type;
488+
ah->sgid_attr = rdma_update_sgid_attr(ah_attr, NULL);
489+
475490
atomic_inc(&pd->usecnt);
476491
}
477492

@@ -871,6 +886,7 @@ int rdma_modify_ah(struct ib_ah *ah, struct rdma_ah_attr *ah_attr)
871886
ah->device->modify_ah(ah, ah_attr) :
872887
-EOPNOTSUPP;
873888

889+
ah->sgid_attr = rdma_update_sgid_attr(ah_attr, ah->sgid_attr);
874890
rdma_unfill_sgid_attr(ah_attr, old_sgid_attr);
875891
return ret;
876892
}
@@ -888,13 +904,17 @@ EXPORT_SYMBOL(rdma_query_ah);
888904

889905
int rdma_destroy_ah(struct ib_ah *ah)
890906
{
907+
const struct ib_gid_attr *sgid_attr = ah->sgid_attr;
891908
struct ib_pd *pd;
892909
int ret;
893910

894911
pd = ah->pd;
895912
ret = ah->device->destroy_ah(ah);
896-
if (!ret)
913+
if (!ret) {
897914
atomic_dec(&pd->usecnt);
915+
if (sgid_attr)
916+
rdma_put_gid_attr(sgid_attr);
917+
}
898918

899919
return ret;
900920
}
@@ -1573,6 +1593,13 @@ static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
15731593
return ret;
15741594
}
15751595
if (attr_mask & IB_QP_ALT_PATH) {
1596+
/*
1597+
* FIXME: This does not track the migration state, so if the
1598+
* user loads a new alternate path after the HW has migrated
1599+
* from primary->alternate we will keep the wrong
1600+
* references. This is OK for IB because the reference
1601+
* counting does not serve any functional purpose.
1602+
*/
15761603
ret = rdma_fill_sgid_attr(qp->device, &attr->alt_ah_attr,
15771604
&old_sgid_attr_alt_av);
15781605
if (ret)
@@ -1606,8 +1633,17 @@ static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,
16061633
}
16071634

16081635
ret = ib_security_modify_qp(qp, attr, attr_mask, udata);
1609-
if (!ret && (attr_mask & IB_QP_PORT))
1636+
if (ret)
1637+
goto out;
1638+
1639+
if (attr_mask & IB_QP_PORT)
16101640
qp->port = attr->port_num;
1641+
if (attr_mask & IB_QP_AV)
1642+
qp->av_sgid_attr =
1643+
rdma_update_sgid_attr(&attr->ah_attr, qp->av_sgid_attr);
1644+
if (attr_mask & IB_QP_ALT_PATH)
1645+
qp->alt_path_sgid_attr = rdma_update_sgid_attr(
1646+
&attr->alt_ah_attr, qp->alt_path_sgid_attr);
16111647

16121648
out:
16131649
if (attr_mask & IB_QP_ALT_PATH)
@@ -1765,6 +1801,8 @@ static int __ib_destroy_shared_qp(struct ib_qp *qp)
17651801

17661802
int ib_destroy_qp(struct ib_qp *qp)
17671803
{
1804+
const struct ib_gid_attr *alt_path_sgid_attr = qp->alt_path_sgid_attr;
1805+
const struct ib_gid_attr *av_sgid_attr = qp->av_sgid_attr;
17681806
struct ib_pd *pd;
17691807
struct ib_cq *scq, *rcq;
17701808
struct ib_srq *srq;
@@ -1795,6 +1833,10 @@ int ib_destroy_qp(struct ib_qp *qp)
17951833
rdma_restrack_del(&qp->res);
17961834
ret = qp->device->destroy_qp(qp);
17971835
if (!ret) {
1836+
if (alt_path_sgid_attr)
1837+
rdma_put_gid_attr(alt_path_sgid_attr);
1838+
if (av_sgid_attr)
1839+
rdma_put_gid_attr(av_sgid_attr);
17981840
if (pd)
17991841
atomic_dec(&pd->usecnt);
18001842
if (scq)

include/rdma/ib_verbs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,7 @@ struct ib_ah {
15801580
struct ib_device *device;
15811581
struct ib_pd *pd;
15821582
struct ib_uobject *uobject;
1583+
const struct ib_gid_attr *sgid_attr;
15831584
enum rdma_ah_attr_type type;
15841585
};
15851586

@@ -1778,6 +1779,9 @@ struct ib_qp {
17781779
struct ib_uobject *uobject;
17791780
void (*event_handler)(struct ib_event *, void *);
17801781
void *qp_context;
1782+
/* sgid_attrs associated with the AV's */
1783+
const struct ib_gid_attr *av_sgid_attr;
1784+
const struct ib_gid_attr *alt_path_sgid_attr;
17811785
u32 qp_num;
17821786
u32 max_write_sge;
17831787
u32 max_read_sge;

0 commit comments

Comments
 (0)