Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b93f3c18 authored by Sean Hefty's avatar Sean Hefty Committed by Roland Dreier
Browse files

RDMA/uverbs: Export XRC TGT QPs to user space



Allow user space to operate on XRC TGT QPs the same way as other types
of QPs, with one notable exception: since XRC TGT QPs may be shared
among multiple processes, the XRC TGT QP is allowed to exist beyond the
lifetime of the creating process.

The process that creates the QP is allowed to destroy it, but if the
process exits without destroying the QP, then the QP will be left bound
to the lifetime of the XRCD.

TGT QPs are not associated with CQs or a PD.

Signed-off-by: default avatarSean Hefty <sean.hefty@intel.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 9977f4f6
Loading
Loading
Loading
Loading
+67 −38
Original line number Original line Diff line number Diff line
@@ -1370,8 +1370,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
	struct ib_uverbs_create_qp_resp resp;
	struct ib_uverbs_create_qp_resp resp;
	struct ib_udata                 udata;
	struct ib_udata                 udata;
	struct ib_uqp_object           *obj;
	struct ib_uqp_object           *obj;
	struct ib_pd                   *pd;
	struct ib_device	       *device;
	struct ib_cq                   *scq, *rcq = NULL;
	struct ib_pd                   *pd = NULL;
	struct ib_xrcd		       *xrcd = NULL;
	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
	struct ib_cq                   *scq = NULL, *rcq = NULL;
	struct ib_srq                  *srq = NULL;
	struct ib_srq                  *srq = NULL;
	struct ib_qp                   *qp;
	struct ib_qp                   *qp;
	struct ib_qp_init_attr          attr;
	struct ib_qp_init_attr          attr;
@@ -1394,6 +1397,14 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
	down_write(&obj->uevent.uobject.mutex);
	down_write(&obj->uevent.uobject.mutex);


	if (cmd.qp_type == IB_QPT_XRC_TGT) {
		xrcd = idr_read_xrcd(cmd.pd_handle, file->ucontext, &xrcd_uobj);
		if (!xrcd) {
			ret = -EINVAL;
			goto err_put;
		}
		device = xrcd->device;
	} else {
		pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
		pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
		scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
		scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
		if (!pd || !scq) {
		if (!pd || !scq) {
@@ -1418,12 +1429,15 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
				goto err_put;
				goto err_put;
			}
			}
		}
		}
		device = pd->device;
	}


	attr.event_handler = ib_uverbs_qp_event_handler;
	attr.event_handler = ib_uverbs_qp_event_handler;
	attr.qp_context    = file;
	attr.qp_context    = file;
	attr.send_cq       = scq;
	attr.send_cq       = scq;
	attr.recv_cq       = rcq;
	attr.recv_cq       = rcq;
	attr.srq           = srq;
	attr.srq           = srq;
	attr.xrcd	   = xrcd;
	attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
	attr.sq_sig_type   = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
	attr.qp_type       = cmd.qp_type;
	attr.qp_type       = cmd.qp_type;
	attr.create_flags  = 0;
	attr.create_flags  = 0;
@@ -1438,18 +1452,22 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
	INIT_LIST_HEAD(&obj->uevent.event_list);
	INIT_LIST_HEAD(&obj->uevent.event_list);
	INIT_LIST_HEAD(&obj->mcast_list);
	INIT_LIST_HEAD(&obj->mcast_list);


	qp = pd->device->create_qp(pd, &attr, &udata);
	if (cmd.qp_type == IB_QPT_XRC_TGT)
		qp = ib_create_qp(pd, &attr);
	else
		qp = device->create_qp(pd, &attr, &udata);

	if (IS_ERR(qp)) {
	if (IS_ERR(qp)) {
		ret = PTR_ERR(qp);
		ret = PTR_ERR(qp);
		goto err_put;
		goto err_put;
	}
	}


	qp->device     	  = pd->device;
	if (cmd.qp_type != IB_QPT_XRC_TGT) {
		qp->device	  = device;
		qp->pd		  = pd;
		qp->pd		  = pd;
		qp->send_cq	  = attr.send_cq;
		qp->send_cq	  = attr.send_cq;
		qp->recv_cq	  = attr.recv_cq;
		qp->recv_cq	  = attr.recv_cq;
		qp->srq		  = attr.srq;
		qp->srq		  = attr.srq;
	qp->uobject       = &obj->uevent.uobject;
		qp->event_handler = attr.event_handler;
		qp->event_handler = attr.event_handler;
		qp->qp_context	  = attr.qp_context;
		qp->qp_context	  = attr.qp_context;
		qp->qp_type	  = attr.qp_type;
		qp->qp_type	  = attr.qp_type;
@@ -1459,6 +1477,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
			atomic_inc(&attr.recv_cq->usecnt);
			atomic_inc(&attr.recv_cq->usecnt);
		if (attr.srq)
		if (attr.srq)
			atomic_inc(&attr.srq->usecnt);
			atomic_inc(&attr.srq->usecnt);
	}
	qp->uobject = &obj->uevent.uobject;


	obj->uevent.uobject.object = qp;
	obj->uevent.uobject.object = qp;
	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
@@ -1480,7 +1500,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
		goto err_copy;
		goto err_copy;
	}
	}


	if (xrcd)
		put_xrcd_read(xrcd_uobj);
	if (pd)
		put_pd_read(pd);
		put_pd_read(pd);
	if (scq)
		put_cq_read(scq);
		put_cq_read(scq);
	if (rcq && rcq != scq)
	if (rcq && rcq != scq)
		put_cq_read(rcq);
		put_cq_read(rcq);
@@ -1504,6 +1528,8 @@ err_destroy:
	ib_destroy_qp(qp);
	ib_destroy_qp(qp);


err_put:
err_put:
	if (xrcd)
		put_xrcd_read(xrcd_uobj);
	if (pd)
	if (pd)
		put_pd_read(pd);
		put_pd_read(pd);
	if (scq)
	if (scq)
@@ -1623,6 +1649,9 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
	switch (qp_type) {
	switch (qp_type) {
	case IB_QPT_XRC_INI:
	case IB_QPT_XRC_INI:
		return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
		return mask & ~(IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER);
	case IB_QPT_XRC_TGT:
		return mask & ~(IB_QP_MAX_QP_RD_ATOMIC | IB_QP_RETRY_CNT |
				IB_QP_RNR_RETRY);
	default:
	default:
		return mask;
		return mask;
	}
	}
+6 −2
Original line number Original line Diff line number Diff line
@@ -206,8 +206,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
			container_of(uobj, struct ib_uqp_object, uevent.uobject);
			container_of(uobj, struct ib_uqp_object, uevent.uobject);


		idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
		idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
		if (qp->qp_type == IB_QPT_XRC_TGT) {
			ib_release_qp(qp);
		} else {
			ib_uverbs_detach_umcast(qp, uqp);
			ib_uverbs_detach_umcast(qp, uqp);
			ib_destroy_qp(qp);
			ib_destroy_qp(qp);
		}
		ib_uverbs_release_uevent(file, &uqp->uevent);
		ib_uverbs_release_uevent(file, &uqp->uevent);
		kfree(uqp);
		kfree(uqp);
	}
	}