Merge pull request #1763 from abhijitG-xlnx/manpage

ionic: Add man pages for ionic direct verbs API
diff --git a/providers/efa/efa.c b/providers/efa/efa.c
index e4ca24c..539bcb5 100644
--- a/providers/efa/efa.c
+++ b/providers/efa/efa.c
@@ -23,6 +23,7 @@
 	VERBS_PCI_MATCH(PCI_VENDOR_ID_AMAZON, 0xefa1, NULL),
 	VERBS_PCI_MATCH(PCI_VENDOR_ID_AMAZON, 0xefa2, NULL),
 	VERBS_PCI_MATCH(PCI_VENDOR_ID_AMAZON, 0xefa3, NULL),
+	VERBS_PCI_MATCH(PCI_VENDOR_ID_AMAZON, 0xefa4, NULL),
 	{}
 };
 
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,