浏览代码

IB/{qib, hfi1}: Avoid flow control testing for RDMA write operation

Section 9.7.7.2.5 of the 1.3 IBTA spec clearly says that receive
credits should never apply to RDMA write.

qib and hfi1 were doing that.  The following situation will result
in a QP hang:
- A prior SEND or RDMA_WRITE with immmediate consumed the last
  credit for a QP using RC receive buffer credits
- The prior op is acked so there are no more acks
- The peer ULP fails to post receive for some reason
- An RDMA write sees that the credits are exhausted and waits
- The peer ULP posts receive buffers
- The ULP posts a send or RDMA write that will be hung

The fix is to avoid the credit test for the RDMA write operation.

Cc: <stable@vger.kernel.org>
Reviewed-by: Kaike Wan <kaike.wan@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Mike Marciniszyn 8 年之前
父节点
当前提交
5b0ef650bd
共有 2 个文件被更改,包括 4 次插入3 次删除
  1. 2 1
      drivers/infiniband/hw/hfi1/rc.c
  2. 2 2
      drivers/infiniband/hw/qib/qib_rc.c

+ 2 - 1
drivers/infiniband/hw/hfi1/rc.c

@@ -442,7 +442,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
 		case IB_WR_RDMA_WRITE:
 		case IB_WR_RDMA_WRITE:
 			if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
 			if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
 				qp->s_lsn++;
 				qp->s_lsn++;
-			/* FALLTHROUGH */
+			goto no_flow_control;
 		case IB_WR_RDMA_WRITE_WITH_IMM:
 		case IB_WR_RDMA_WRITE_WITH_IMM:
 			/* If no credit, return. */
 			/* If no credit, return. */
 			if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
 			if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
@@ -450,6 +450,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
 				qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
 				qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
 				goto bail;
 				goto bail;
 			}
 			}
+no_flow_control:
 			put_ib_reth_vaddr(
 			put_ib_reth_vaddr(
 				wqe->rdma_wr.remote_addr,
 				wqe->rdma_wr.remote_addr,
 				&ohdr->u.rc.reth);
 				&ohdr->u.rc.reth);

+ 2 - 2
drivers/infiniband/hw/qib/qib_rc.c

@@ -348,7 +348,7 @@ int qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags)
 		case IB_WR_RDMA_WRITE:
 		case IB_WR_RDMA_WRITE:
 			if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
 			if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
 				qp->s_lsn++;
 				qp->s_lsn++;
-			/* FALLTHROUGH */
+			goto no_flow_control;
 		case IB_WR_RDMA_WRITE_WITH_IMM:
 		case IB_WR_RDMA_WRITE_WITH_IMM:
 			/* If no credit, return. */
 			/* If no credit, return. */
 			if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
 			if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
@@ -356,7 +356,7 @@ int qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags)
 				qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
 				qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
 				goto bail;
 				goto bail;
 			}
 			}
-
+no_flow_control:
 			ohdr->u.rc.reth.vaddr =
 			ohdr->u.rc.reth.vaddr =
 				cpu_to_be64(wqe->rdma_wr.remote_addr);
 				cpu_to_be64(wqe->rdma_wr.remote_addr);
 			ohdr->u.rc.reth.rkey =
 			ohdr->u.rc.reth.rkey =