|
@@ -1370,8 +1370,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
struct ib_uverbs_create_qp_resp resp;
|
|
|
struct ib_udata udata;
|
|
|
struct ib_uqp_object *obj;
|
|
|
- struct ib_pd *pd;
|
|
|
- struct ib_cq *scq, *rcq = NULL;
|
|
|
+ struct ib_device *device;
|
|
|
+ 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_qp *qp;
|
|
|
struct ib_qp_init_attr attr;
|
|
@@ -1394,29 +1397,39 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext, &qp_lock_key);
|
|
|
down_write(&obj->uevent.uobject.mutex);
|
|
|
|
|
|
- pd = idr_read_pd(cmd.pd_handle, file->ucontext);
|
|
|
- scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
|
|
|
- if (!pd || !scq) {
|
|
|
- ret = -EINVAL;
|
|
|
- goto err_put;
|
|
|
- }
|
|
|
-
|
|
|
- if (cmd.qp_type == IB_QPT_XRC_INI) {
|
|
|
- cmd.max_recv_wr = cmd.max_recv_sge = 0;
|
|
|
+ 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 {
|
|
|
- if (cmd.is_srq) {
|
|
|
- srq = idr_read_srq(cmd.srq_handle, file->ucontext);
|
|
|
- if (!srq || srq->srq_type != IB_SRQT_BASIC) {
|
|
|
+ pd = idr_read_pd(cmd.pd_handle, file->ucontext);
|
|
|
+ scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
|
|
|
+ if (!pd || !scq) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err_put;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmd.qp_type == IB_QPT_XRC_INI) {
|
|
|
+ cmd.max_recv_wr = cmd.max_recv_sge = 0;
|
|
|
+ } else {
|
|
|
+ if (cmd.is_srq) {
|
|
|
+ srq = idr_read_srq(cmd.srq_handle, file->ucontext);
|
|
|
+ if (!srq || srq->srq_type != IB_SRQT_BASIC) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto err_put;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
|
|
|
+ scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
|
|
|
+ if (!rcq) {
|
|
|
ret = -EINVAL;
|
|
|
goto err_put;
|
|
|
}
|
|
|
}
|
|
|
- rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ?
|
|
|
- scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
|
|
|
- if (!rcq) {
|
|
|
- ret = -EINVAL;
|
|
|
- goto err_put;
|
|
|
- }
|
|
|
+ device = pd->device;
|
|
|
}
|
|
|
|
|
|
attr.event_handler = ib_uverbs_qp_event_handler;
|
|
@@ -1424,6 +1437,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
attr.send_cq = scq;
|
|
|
attr.recv_cq = rcq;
|
|
|
attr.srq = srq;
|
|
|
+ attr.xrcd = xrcd;
|
|
|
attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
|
|
|
attr.qp_type = cmd.qp_type;
|
|
|
attr.create_flags = 0;
|
|
@@ -1438,27 +1452,33 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
INIT_LIST_HEAD(&obj->uevent.event_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)) {
|
|
|
ret = PTR_ERR(qp);
|
|
|
goto err_put;
|
|
|
}
|
|
|
|
|
|
- qp->device = pd->device;
|
|
|
- qp->pd = pd;
|
|
|
- qp->send_cq = attr.send_cq;
|
|
|
- qp->recv_cq = attr.recv_cq;
|
|
|
- qp->srq = attr.srq;
|
|
|
- qp->uobject = &obj->uevent.uobject;
|
|
|
- qp->event_handler = attr.event_handler;
|
|
|
- qp->qp_context = attr.qp_context;
|
|
|
- qp->qp_type = attr.qp_type;
|
|
|
- atomic_inc(&pd->usecnt);
|
|
|
- atomic_inc(&attr.send_cq->usecnt);
|
|
|
- if (attr.recv_cq)
|
|
|
- atomic_inc(&attr.recv_cq->usecnt);
|
|
|
- if (attr.srq)
|
|
|
- atomic_inc(&attr.srq->usecnt);
|
|
|
+ if (cmd.qp_type != IB_QPT_XRC_TGT) {
|
|
|
+ qp->device = device;
|
|
|
+ qp->pd = pd;
|
|
|
+ qp->send_cq = attr.send_cq;
|
|
|
+ qp->recv_cq = attr.recv_cq;
|
|
|
+ qp->srq = attr.srq;
|
|
|
+ qp->event_handler = attr.event_handler;
|
|
|
+ qp->qp_context = attr.qp_context;
|
|
|
+ qp->qp_type = attr.qp_type;
|
|
|
+ atomic_inc(&pd->usecnt);
|
|
|
+ atomic_inc(&attr.send_cq->usecnt);
|
|
|
+ if (attr.recv_cq)
|
|
|
+ atomic_inc(&attr.recv_cq->usecnt);
|
|
|
+ if (attr.srq)
|
|
|
+ atomic_inc(&attr.srq->usecnt);
|
|
|
+ }
|
|
|
+ qp->uobject = &obj->uevent.uobject;
|
|
|
|
|
|
obj->uevent.uobject.object = qp;
|
|
|
ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
|
|
@@ -1480,8 +1500,12 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
goto err_copy;
|
|
|
}
|
|
|
|
|
|
- put_pd_read(pd);
|
|
|
- put_cq_read(scq);
|
|
|
+ if (xrcd)
|
|
|
+ put_xrcd_read(xrcd_uobj);
|
|
|
+ if (pd)
|
|
|
+ put_pd_read(pd);
|
|
|
+ if (scq)
|
|
|
+ put_cq_read(scq);
|
|
|
if (rcq && rcq != scq)
|
|
|
put_cq_read(rcq);
|
|
|
if (srq)
|
|
@@ -1504,6 +1528,8 @@ err_destroy:
|
|
|
ib_destroy_qp(qp);
|
|
|
|
|
|
err_put:
|
|
|
+ if (xrcd)
|
|
|
+ put_xrcd_read(xrcd_uobj);
|
|
|
if (pd)
|
|
|
put_pd_read(pd);
|
|
|
if (scq)
|
|
@@ -1623,6 +1649,9 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
|
|
|
switch (qp_type) {
|
|
|
case IB_QPT_XRC_INI:
|
|
|
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:
|
|
|
return mask;
|
|
|
}
|