|
@@ -1371,8 +1371,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
struct ib_udata udata;
|
|
|
struct ib_uqp_object *obj;
|
|
|
struct ib_pd *pd;
|
|
|
- struct ib_cq *scq, *rcq;
|
|
|
- struct ib_srq *srq;
|
|
|
+ struct ib_cq *scq, *rcq = NULL;
|
|
|
+ struct ib_srq *srq = NULL;
|
|
|
struct ib_qp *qp;
|
|
|
struct ib_qp_init_attr attr;
|
|
|
int ret;
|
|
@@ -1394,18 +1394,31 @@ 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);
|
|
|
|
|
|
- srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
|
|
|
pd = idr_read_pd(cmd.pd_handle, file->ucontext);
|
|
|
scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0);
|
|
|
- rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
|
|
|
- scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
|
|
|
-
|
|
|
- if (!pd || !scq || !rcq ||
|
|
|
- (cmd.is_srq && (!srq || srq->srq_type != IB_SRQT_BASIC))) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
attr.event_handler = ib_uverbs_qp_event_handler;
|
|
|
attr.qp_context = file;
|
|
|
attr.send_cq = scq;
|
|
@@ -1442,7 +1455,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
qp->qp_type = attr.qp_type;
|
|
|
atomic_inc(&pd->usecnt);
|
|
|
atomic_inc(&attr.send_cq->usecnt);
|
|
|
- atomic_inc(&attr.recv_cq->usecnt);
|
|
|
+ if (attr.recv_cq)
|
|
|
+ atomic_inc(&attr.recv_cq->usecnt);
|
|
|
if (attr.srq)
|
|
|
atomic_inc(&attr.srq->usecnt);
|
|
|
|
|
@@ -1468,7 +1482,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
|
|
|
|
|
|
put_pd_read(pd);
|
|
|
put_cq_read(scq);
|
|
|
- if (rcq != scq)
|
|
|
+ if (rcq && rcq != scq)
|
|
|
put_cq_read(rcq);
|
|
|
if (srq)
|
|
|
put_srq_read(srq);
|
|
@@ -1603,6 +1617,17 @@ out:
|
|
|
return ret ? ret : in_len;
|
|
|
}
|
|
|
|
|
|
+/* Remove ignored fields set in the attribute mask */
|
|
|
+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);
|
|
|
+ default:
|
|
|
+ return mask;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
|
|
|
const char __user *buf, int in_len,
|
|
|
int out_len)
|
|
@@ -1675,7 +1700,8 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
|
|
|
attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
|
|
|
attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
|
|
|
|
|
|
- ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata);
|
|
|
+ ret = qp->device->modify_qp(qp, attr,
|
|
|
+ modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
|
|
|
|
|
|
put_qp_read(qp);
|
|
|
|