IB/{qib, hfi1}: Avoid flow control testing for RDMA write operation
authorMike Marciniszyn <mike.marciniszyn@intel.com>
Tue, 22 Aug 2017 01:26:20 +0000 (18:26 -0700)
committerDoug Ledford <dledford@redhat.com>
Mon, 28 Aug 2017 23:12:16 +0000 (19:12 -0400)
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>
drivers/infiniband/hw/hfi1/rc.c
drivers/infiniband/hw/qib/qib_rc.c

index 99defcc0ce45575fa9b15a4bd01f7ebc58a23f8e..e1cf0c08ca6fbde7d4555cbd8abfe4916f860736 100644 (file)
@@ -442,7 +442,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
                case IB_WR_RDMA_WRITE:
                        if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
                                qp->s_lsn++;
-                       /* FALLTHROUGH */
+                       goto no_flow_control;
                case IB_WR_RDMA_WRITE_WITH_IMM:
                        /* If no credit, return. */
                        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;
                                goto bail;
                        }
+no_flow_control:
                        put_ib_reth_vaddr(
                                wqe->rdma_wr.remote_addr,
                                &ohdr->u.rc.reth);
index 4ddbcac5eabe6834f90ecac5885b75495493264a..e9a91736b12dbe281f6413afa47ccf320d1dc276 100644 (file)
@@ -348,7 +348,7 @@ int qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags)
                case IB_WR_RDMA_WRITE:
                        if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
                                qp->s_lsn++;
-                       /* FALLTHROUGH */
+                       goto no_flow_control;
                case IB_WR_RDMA_WRITE_WITH_IMM:
                        /* If no credit, return. */
                        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;
                                goto bail;
                        }
-
+no_flow_control:
                        ohdr->u.rc.reth.vaddr =
                                cpu_to_be64(wqe->rdma_wr.remote_addr);
                        ohdr->u.rc.reth.rkey =