ionic: Add thread domain support for lockless operation Wire up thread domain (TD) to activate the existing lockfree data-path. When a parent domain carries a TD, QP and CQ objects skip spinlocks in post_send, post_recv, and poll_cq. Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
diff --git a/providers/ionic/ionic.h b/providers/ionic/ionic.h index a51d790..7744aee 100644 --- a/providers/ionic/ionic.h +++ b/providers/ionic/ionic.h
@@ -86,9 +86,15 @@ FILE *dbg_file; }; +struct ionic_td { + struct ibv_td ibtd; + atomic_int refcount; +}; + struct ionic_pd { struct ibv_pd ibpd; struct ibv_pd *root_ibpd; + struct ionic_td *td; uint8_t udma_mask; uint8_t sq_cmb; @@ -246,6 +252,16 @@ return container_of(ibpd, struct ionic_pd, ibpd); } +static inline struct ionic_td *to_ionic_td(struct ibv_td *ibtd) +{ + return container_of(ibtd, struct ionic_td, ibtd); +} + +static inline bool ionic_pd_lockfree(struct ibv_pd *ibpd) +{ + return to_ionic_pd(ibpd)->td; +} + static inline struct ibv_pd *ionic_root_ibpd(struct ionic_pd *pd) { return pd->root_ibpd;
diff --git a/providers/ionic/ionic_verbs.c b/providers/ionic/ionic_verbs.c index 6452894..f392a83 100644 --- a/providers/ionic/ionic_verbs.c +++ b/providers/ionic/ionic_verbs.c
@@ -195,6 +195,40 @@ &req, sizeof(req)); } +static struct ibv_td *ionic_alloc_td(struct ibv_context *ibctx, + struct ibv_td_init_attr *init_attr) +{ + struct ionic_td *td; + + if (init_attr->comp_mask) { + errno = EOPNOTSUPP; + return NULL; + } + + td = calloc(1, sizeof(*td)); + if (!td) { + errno = ENOMEM; + return NULL; + } + + td->ibtd.context = ibctx; + atomic_init(&td->refcount, 1); + + return &td->ibtd; +} + +static int ionic_dealloc_td(struct ibv_td *ibtd) +{ + struct ionic_td *td = to_ionic_td(ibtd); + + if (atomic_load(&td->refcount) > 1) + return EBUSY; + + free(td); + + return 0; +} + static struct ibv_pd *ionic_alloc_parent_domain(struct ibv_context *context, struct ibv_parent_domain_init_attr *attr) { @@ -230,6 +264,11 @@ pd->sq_cmb = init_pd->sq_cmb; pd->rq_cmb = init_pd->rq_cmb; + if (attr->td) { + pd->td = to_ionic_td(attr->td); + atomic_fetch_add(&pd->td->refcount, 1); + } + if (attr->comp_mask & IBV_PARENT_DOMAIN_INIT_ATTR_ALLOCATORS) { pd->alloc = attr->alloc; pd->free = attr->free; @@ -295,6 +334,8 @@ rc = ibv_cmd_dealloc_pd(&pd->ibpd); if (rc) return rc; + } else if (pd->td) { + atomic_fetch_sub(&pd->td->refcount, 1); } free(pd); @@ -398,7 +439,7 @@ cq->vcq = vcq; - cq->lockfree = false; + cq->lockfree = pd ? ionic_pd_lockfree(&pd->ibpd) : false; pthread_spin_init(&cq->lock, PTHREAD_PROCESS_PRIVATE); list_head_init(&cq->poll_sq); list_head_init(&cq->poll_rq); @@ -1692,7 +1733,7 @@ qp->vqp.qp.qp_type = ex->qp_type; qp->has_sq = true; qp->has_rq = true; - qp->lockfree = false; + qp->lockfree = ex->pd ? ionic_pd_lockfree(ex->pd) : false; qp->sig_all = ex->sq_sig_all; list_node_init(&qp->cq_poll_sq); @@ -3007,6 +3048,8 @@ static const struct verbs_context_ops ionic_ctx_ops = { .query_device_ex = ionic_query_device_ex, .query_port = ionic_query_port, + .alloc_td = ionic_alloc_td, + .dealloc_td = ionic_dealloc_td, .alloc_parent_domain = ionic_alloc_parent_domain, .alloc_pd = ionic_alloc_pd, .dealloc_pd = ionic_dealloc_pd,