Commit f4d46119 authored by Kaike Wan's avatar Kaike Wan Committed by Jason Gunthorpe

IB/hfi1: Drop all TID RDMA READ RESP packets after r_next_psn

When a TID sequence error occurs while receiving TID RDMA READ RESP
packets, all packets after flow->flow_state.r_next_psn should be dropped,
including those response packets for subsequent segments.

The current implementation will drop the subsequent response packets for
the segment to complete next, but may accept packets for subsequent
segments and therefore mistakenly advance the r_next_psn fields for the
corresponding software flows. This may result in failures to complete
subsequent segments after the current segment is completed.

The fix is to only use the flow pointed by req->clear_tail for checking
KDETH PSN instead of finding a flow from the request's flow array.

Fixes: b885d5be ("IB/hfi1: Unify the software PSN check for TID RDMA READ/WRITE")
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20190715164540.74174.54702.stgit@awfm-01.aw.intel.comReviewed-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarKaike Wan <kaike.wan@intel.com>
Signed-off-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent dc25b239
...@@ -1674,34 +1674,6 @@ static struct tid_rdma_flow *find_flow_ib(struct tid_rdma_request *req, ...@@ -1674,34 +1674,6 @@ static struct tid_rdma_flow *find_flow_ib(struct tid_rdma_request *req,
return NULL; return NULL;
} }
static struct tid_rdma_flow *
__find_flow_ranged(struct tid_rdma_request *req, u16 head, u16 tail,
u32 psn, u16 *fidx)
{
for ( ; CIRC_CNT(head, tail, MAX_FLOWS);
tail = CIRC_NEXT(tail, MAX_FLOWS)) {
struct tid_rdma_flow *flow = &req->flows[tail];
u32 spsn, lpsn;
spsn = full_flow_psn(flow, flow->flow_state.spsn);
lpsn = full_flow_psn(flow, flow->flow_state.lpsn);
if (cmp_psn(psn, spsn) >= 0 && cmp_psn(psn, lpsn) <= 0) {
if (fidx)
*fidx = tail;
return flow;
}
}
return NULL;
}
static struct tid_rdma_flow *find_flow(struct tid_rdma_request *req,
u32 psn, u16 *fidx)
{
return __find_flow_ranged(req, req->setup_head, req->clear_tail, psn,
fidx);
}
/* TID RDMA READ functions */ /* TID RDMA READ functions */
u32 hfi1_build_tid_rdma_read_packet(struct rvt_swqe *wqe, u32 hfi1_build_tid_rdma_read_packet(struct rvt_swqe *wqe,
struct ib_other_headers *ohdr, u32 *bth1, struct ib_other_headers *ohdr, u32 *bth1,
...@@ -2789,19 +2761,7 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd, ...@@ -2789,19 +2761,7 @@ static bool handle_read_kdeth_eflags(struct hfi1_ctxtdata *rcd,
* to prevent continuous Flow Sequence errors for any * to prevent continuous Flow Sequence errors for any
* packets that could be still in the fabric. * packets that could be still in the fabric.
*/ */
flow = find_flow(req, psn, NULL); flow = &req->flows[req->clear_tail];
if (!flow) {
/*
* We can't find the IB PSN matching the
* received KDETH PSN. The only thing we can
* do at this point is report the error to
* the QP.
*/
hfi1_kern_read_tid_flow_free(qp);
spin_unlock(&qp->s_lock);
rvt_rc_error(qp, IB_WC_LOC_QP_OP_ERR);
return ret;
}
if (priv->s_flags & HFI1_R_TID_SW_PSN) { if (priv->s_flags & HFI1_R_TID_SW_PSN) {
diff = cmp_psn(psn, diff = cmp_psn(psn,
flow->flow_state.r_next_psn); flow->flow_state.r_next_psn);
......
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