char newreq;
int middle = 0;
int delta;
- int err;
ps->s_txreq = get_txreq(ps->dev, qp);
if (IS_ERR(ps->s_txreq))
*/
if (wqe->wr.opcode == IB_WR_REG_MR ||
wqe->wr.opcode == IB_WR_LOCAL_INV) {
+ int local_ops = 0;
+ int err = 0;
+
if (qp->s_last != qp->s_cur)
goto bail;
if (++qp->s_cur == qp->s_size)
qp->s_cur = 0;
if (++qp->s_tail == qp->s_size)
qp->s_tail = 0;
- if (wqe->wr.opcode == IB_WR_REG_MR)
- err = rvt_fast_reg_mr(
- qp, wqe->reg_wr.mr,
- wqe->reg_wr.key,
- wqe->reg_wr.access);
- else
+ if (!(wqe->wr.send_flags &
+ RVT_SEND_COMPLETION_ONLY)) {
err = rvt_invalidate_rkey(
qp,
wqe->wr.ex.invalidate_rkey);
+ local_ops = 1;
+ }
hfi1_send_complete(qp, wqe,
err ? IB_WC_LOC_PROT_ERR
: IB_WC_SUCCESS);
- atomic_dec(&qp->local_ops_pending);
+ if (local_ops)
+ atomic_dec(&qp->local_ops_pending);
qp->s_hdrwords = 0;
goto done_free_tx;
}
sqp->s_len = wqe->length;
switch (wqe->wr.opcode) {
case IB_WR_REG_MR:
- if (rvt_fast_reg_mr(sqp, wqe->reg_wr.mr, wqe->reg_wr.key,
- wqe->reg_wr.access))
- send_status = IB_WC_LOC_PROT_ERR;
- local_ops = 1;
goto send_comp;
case IB_WR_LOCAL_INV:
- if (rvt_invalidate_rkey(sqp, wqe->wr.ex.invalidate_rkey))
- send_status = IB_WC_LOC_PROT_ERR;
- local_ops = 1;
+ if (!(wqe->wr.send_flags & RVT_SEND_COMPLETION_ONLY)) {
+ if (rvt_invalidate_rkey(sqp,
+ wqe->wr.ex.invalidate_rkey))
+ send_status = IB_WC_LOC_PROT_ERR;
+ local_ops = 1;
+ }
goto send_comp;
case IB_WR_SEND_WITH_INV:
u32 len;
u32 pmtu = qp->pmtu;
int middle = 0;
- int err;
ps->s_txreq = get_txreq(ps->dev, qp);
if (IS_ERR(ps->s_txreq))
*/
if (wqe->wr.opcode == IB_WR_REG_MR ||
wqe->wr.opcode == IB_WR_LOCAL_INV) {
+ int local_ops = 0;
+ int err = 0;
+
if (qp->s_last != qp->s_cur)
goto bail;
if (++qp->s_cur == qp->s_size)
qp->s_cur = 0;
- if (wqe->wr.opcode == IB_WR_REG_MR)
- err = rvt_fast_reg_mr(qp, wqe->reg_wr.mr,
- wqe->reg_wr.key,
- wqe->reg_wr.access);
- else
+ if (!(wqe->wr.send_flags & RVT_SEND_COMPLETION_ONLY)) {
err = rvt_invalidate_rkey(
qp, wqe->wr.ex.invalidate_rkey);
+ local_ops = 1;
+ }
hfi1_send_complete(qp, wqe, err ? IB_WC_LOC_PROT_ERR
: IB_WC_SUCCESS);
- atomic_dec(&qp->local_ops_pending);
+ if (local_ops)
+ atomic_dec(&qp->local_ops_pending);
qp->s_hdrwords = 0;
goto done_free_tx;
}
int ret;
size_t cplen;
bool reserved_op;
+ int local_ops_delayed = 0;
BUILD_BUG_ON(IB_QPT_MAX >= (sizeof(u32) * BITS_PER_BYTE));
cplen = ret;
/*
- * Local operations including fast register and local invalidate
- * can be processed immediately w/o being posted to the send queue
- * if neither fencing nor completion generation is needed. However,
- * once fencing or completion is requested, direct processing of
- * following local operations must be disabled until all the local
- * operations posted to the send queue have completed. This is
- * necessary to ensure the correct ordering.
+ * Local operations include fast register and local invalidate.
+ * Fast register needs to be processed immediately because the
+ * registered lkey may be used by following work requests and the
+ * lkey needs to be valid at the time those requests are posted.
+ * Local invalidate can be processed immediately if fencing is
+ * not required and no previous local invalidate ops are pending.
+ * Signaled local operations that have been processed immediately
+ * need to have requests with "completion only" flags set posted
+ * to the send queue in order to generate completions.
*/
- if ((rdi->post_parms[wr->opcode].flags & RVT_OPERATION_LOCAL) &&
- !(wr->send_flags & (IB_SEND_FENCE | IB_SEND_SIGNALED)) &&
- !atomic_read(&qp->local_ops_pending)) {
- struct ib_reg_wr *reg = reg_wr(wr);
-
+ if ((rdi->post_parms[wr->opcode].flags & RVT_OPERATION_LOCAL)) {
switch (wr->opcode) {
case IB_WR_REG_MR:
- return rvt_fast_reg_mr(qp, reg->mr, reg->key,
- reg->access);
+ ret = rvt_fast_reg_mr(qp,
+ reg_wr(wr)->mr,
+ reg_wr(wr)->key,
+ reg_wr(wr)->access);
+ if (ret || !(wr->send_flags & IB_SEND_SIGNALED))
+ return ret;
+ break;
case IB_WR_LOCAL_INV:
- return rvt_invalidate_rkey(qp, wr->ex.invalidate_rkey);
+ if ((wr->send_flags & IB_SEND_FENCE) ||
+ atomic_read(&qp->local_ops_pending)) {
+ local_ops_delayed = 1;
+ } else {
+ ret = rvt_invalidate_rkey(
+ qp, wr->ex.invalidate_rkey);
+ if (ret || !(wr->send_flags & IB_SEND_SIGNALED))
+ return ret;
+ }
+ break;
default:
return -EINVAL;
}
}
if (rdi->post_parms[wr->opcode].flags & RVT_OPERATION_LOCAL) {
- atomic_inc(&qp->local_ops_pending);
+ if (local_ops_delayed)
+ atomic_inc(&qp->local_ops_pending);
+ else
+ wqe->wr.send_flags |= RVT_SEND_COMPLETION_ONLY;
wqe->ssn = 0;
wqe->psn = 0;
wqe->lpsn = 0;
* Internal send flags
*/
#define RVT_SEND_RESERVE_USED IB_SEND_RESERVED_START
+#define RVT_SEND_COMPLETION_ONLY (IB_SEND_RESERVED_START << 1)
/*
* Send work request queue entry.