Commit 0db3dfa0 authored by Jianxin Xiong's avatar Jianxin Xiong Committed by Doug Ledford

IB/hfi1: Work request processing for fast register mr and invalidate

In order to support extended memory management support, add send side
processing of work requests of type IB_WR_REG_MR, IB_WR_LOCAL_INV, and
IB_WR_SEND_WITH_INV. The first two are local operations and are supported
for both RC and UC. Send with invalidate is only supported for RC because
the corresponding IB opcodes are not defined for UC.
Reviewed-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Reviewed-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarJianxin Xiong <jianxin.xiong@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent a2df0c83
...@@ -402,6 +402,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -402,6 +402,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
char newreq; char newreq;
int middle = 0; int middle = 0;
int delta; int delta;
int err;
ps->s_txreq = get_txreq(ps->dev, qp); ps->s_txreq = get_txreq(ps->dev, qp);
if (IS_ERR(ps->s_txreq)) if (IS_ERR(ps->s_txreq))
...@@ -477,6 +478,35 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -477,6 +478,35 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
qp->s_flags |= RVT_S_WAIT_FENCE; qp->s_flags |= RVT_S_WAIT_FENCE;
goto bail; goto bail;
} }
/*
* Local operations are processed immediately
* after all prior requests have completed
*/
if (wqe->wr.opcode == IB_WR_REG_MR ||
wqe->wr.opcode == IB_WR_LOCAL_INV) {
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
err = rvt_invalidate_rkey(
qp,
wqe->wr.ex.invalidate_rkey);
hfi1_send_complete(qp, wqe,
err ? IB_WC_LOC_PROT_ERR
: IB_WC_SUCCESS);
atomic_dec(&qp->local_ops_pending);
qp->s_hdrwords = 0;
goto done_free_tx;
}
newreq = 1; newreq = 1;
qp->s_psn = wqe->psn; qp->s_psn = wqe->psn;
} }
...@@ -491,6 +521,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -491,6 +521,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
switch (wqe->wr.opcode) { switch (wqe->wr.opcode) {
case IB_WR_SEND: case IB_WR_SEND:
case IB_WR_SEND_WITH_IMM: case IB_WR_SEND_WITH_IMM:
case IB_WR_SEND_WITH_INV:
/* If no credit, return. */ /* If no credit, return. */
if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) && if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
cmp_msn(wqe->ssn, qp->s_lsn + 1) > 0) { cmp_msn(wqe->ssn, qp->s_lsn + 1) > 0) {
...@@ -504,11 +535,17 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -504,11 +535,17 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
} }
if (wqe->wr.opcode == IB_WR_SEND) { if (wqe->wr.opcode == IB_WR_SEND) {
qp->s_state = OP(SEND_ONLY); qp->s_state = OP(SEND_ONLY);
} else { } else if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE); qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE);
/* Immediate data comes after the BTH */ /* Immediate data comes after the BTH */
ohdr->u.imm_data = wqe->wr.ex.imm_data; ohdr->u.imm_data = wqe->wr.ex.imm_data;
hwords += 1; hwords += 1;
} else {
qp->s_state = OP(SEND_ONLY_WITH_INVALIDATE);
/* Invalidate rkey comes after the BTH */
ohdr->u.ieth = cpu_to_be32(
wqe->wr.ex.invalidate_rkey);
hwords += 1;
} }
if (wqe->wr.send_flags & IB_SEND_SOLICITED) if (wqe->wr.send_flags & IB_SEND_SOLICITED)
bth0 |= IB_BTH_SOLICITED; bth0 |= IB_BTH_SOLICITED;
...@@ -671,11 +708,16 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -671,11 +708,16 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
} }
if (wqe->wr.opcode == IB_WR_SEND) { if (wqe->wr.opcode == IB_WR_SEND) {
qp->s_state = OP(SEND_LAST); qp->s_state = OP(SEND_LAST);
} else { } else if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE); qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
/* Immediate data comes after the BTH */ /* Immediate data comes after the BTH */
ohdr->u.imm_data = wqe->wr.ex.imm_data; ohdr->u.imm_data = wqe->wr.ex.imm_data;
hwords += 1; hwords += 1;
} else {
qp->s_state = OP(SEND_LAST_WITH_INVALIDATE);
/* invalidate data comes after the BTH */
ohdr->u.ieth = cpu_to_be32(wqe->wr.ex.invalidate_rkey);
hwords += 1;
} }
if (wqe->wr.send_flags & IB_SEND_SOLICITED) if (wqe->wr.send_flags & IB_SEND_SOLICITED)
bth0 |= IB_BTH_SOLICITED; bth0 |= IB_BTH_SOLICITED;
......
...@@ -372,6 +372,7 @@ static void ruc_loopback(struct rvt_qp *sqp) ...@@ -372,6 +372,7 @@ static void ruc_loopback(struct rvt_qp *sqp)
int ret; int ret;
int copy_last = 0; int copy_last = 0;
u32 to; u32 to;
int local_ops = 0;
rcu_read_lock(); rcu_read_lock();
...@@ -440,11 +441,32 @@ static void ruc_loopback(struct rvt_qp *sqp) ...@@ -440,11 +441,32 @@ static void ruc_loopback(struct rvt_qp *sqp)
sqp->s_sge.num_sge = wqe->wr.num_sge; sqp->s_sge.num_sge = wqe->wr.num_sge;
sqp->s_len = wqe->length; sqp->s_len = wqe->length;
switch (wqe->wr.opcode) { 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;
goto send_comp;
case IB_WR_SEND_WITH_INV:
if (!rvt_invalidate_rkey(qp, wqe->wr.ex.invalidate_rkey)) {
wc.wc_flags = IB_WC_WITH_INVALIDATE;
wc.ex.invalidate_rkey = wqe->wr.ex.invalidate_rkey;
}
goto send;
case IB_WR_SEND_WITH_IMM: case IB_WR_SEND_WITH_IMM:
wc.wc_flags = IB_WC_WITH_IMM; wc.wc_flags = IB_WC_WITH_IMM;
wc.ex.imm_data = wqe->wr.ex.imm_data; wc.ex.imm_data = wqe->wr.ex.imm_data;
/* FALLTHROUGH */ /* FALLTHROUGH */
case IB_WR_SEND: case IB_WR_SEND:
send:
ret = hfi1_rvt_get_rwqe(qp, 0); ret = hfi1_rvt_get_rwqe(qp, 0);
if (ret < 0) if (ret < 0)
goto op_err; goto op_err;
...@@ -583,6 +605,10 @@ static void ruc_loopback(struct rvt_qp *sqp) ...@@ -583,6 +605,10 @@ static void ruc_loopback(struct rvt_qp *sqp)
flush_send: flush_send:
sqp->s_rnr_retry = sqp->s_rnr_retry_cnt; sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
hfi1_send_complete(sqp, wqe, send_status); hfi1_send_complete(sqp, wqe, send_status);
if (local_ops) {
atomic_dec(&sqp->local_ops_pending);
local_ops = 0;
}
goto again; goto again;
rnr_nak: rnr_nak:
......
...@@ -77,6 +77,7 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -77,6 +77,7 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
u32 len; u32 len;
u32 pmtu = qp->pmtu; u32 pmtu = qp->pmtu;
int middle = 0; int middle = 0;
int err;
ps->s_txreq = get_txreq(ps->dev, qp); ps->s_txreq = get_txreq(ps->dev, qp);
if (IS_ERR(ps->s_txreq)) if (IS_ERR(ps->s_txreq))
...@@ -118,6 +119,29 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps) ...@@ -118,6 +119,29 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
clear_ahg(qp); clear_ahg(qp);
goto bail; goto bail;
} }
/*
* Local operations are processed immediately
* after all prior requests have completed.
*/
if (wqe->wr.opcode == IB_WR_REG_MR ||
wqe->wr.opcode == IB_WR_LOCAL_INV) {
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
err = rvt_invalidate_rkey(
qp, wqe->wr.ex.invalidate_rkey);
hfi1_send_complete(qp, wqe, err ? IB_WC_LOC_PROT_ERR
: IB_WC_SUCCESS);
atomic_dec(&qp->local_ops_pending);
qp->s_hdrwords = 0;
goto done_free_tx;
}
/* /*
* Start a new request. * Start a new request.
*/ */
......
...@@ -306,7 +306,10 @@ const enum ib_wc_opcode ib_hfi1_wc_opcode[] = { ...@@ -306,7 +306,10 @@ const enum ib_wc_opcode ib_hfi1_wc_opcode[] = {
[IB_WR_SEND_WITH_IMM] = IB_WC_SEND, [IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
[IB_WR_RDMA_READ] = IB_WC_RDMA_READ, [IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
[IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP, [IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
[IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD [IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD,
[IB_WR_SEND_WITH_INV] = IB_WC_SEND,
[IB_WR_LOCAL_INV] = IB_WC_LOCAL_INV,
[IB_WR_REG_MR] = IB_WC_REG_MR
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment