RDMA/rxe: Add rxe_is_fenced() subroutine
authorBob Pearson <rpearsonhpe@gmail.com>
Thu, 30 Jun 2022 19:04:18 +0000 (14:04 -0500)
committerJason Gunthorpe <jgg@nvidia.com>
Fri, 22 Jul 2022 20:43:00 +0000 (17:43 -0300)
The code thc that decides whether to defer execution of a wqe in
rxe_requester.c is isolated into a subroutine rxe_is_fenced() and removed
from the call to req_next_wqe(). The condition whether a wqe should be
fenced is changed to comply with the IBA. Currently an operation is fenced
if the fence bit is set in the wqe flags and the last wqe has not
completed. For normal operations the IBA actually only requires that the
last read or atomic operation is complete.

Link: https://lore.kernel.org/r/20220630190425.2251-2-rpearsonhpe@gmail.com
Signed-off-by: Bob Pearson <rpearsonhpe@gmail.com>
Reviewed-by: Li Zhijian <lizhijian@fujitsu.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/sw/rxe/rxe_req.c

index dec4dda..12a4a47 100644 (file)
@@ -160,16 +160,36 @@ static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
                     (wqe->state != wqe_state_processing)))
                return NULL;
 
-       if (unlikely((wqe->wr.send_flags & IB_SEND_FENCE) &&
-                                                    (index != cons))) {
-               qp->req.wait_fence = 1;
-               return NULL;
-       }
-
        wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp);
        return wqe;
 }
 
+/**
+ * rxe_wqe_is_fenced - check if next wqe is fenced
+ * @qp: the queue pair
+ * @wqe: the next wqe
+ *
+ * Returns: 1 if wqe needs to wait
+ *         0 if wqe is ready to go
+ */
+static int rxe_wqe_is_fenced(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
+{
+       /* Local invalidate fence (LIF) see IBA 10.6.5.1
+        * Requires ALL previous operations on the send queue
+        * are complete. Make mandatory for the rxe driver.
+        */
+       if (wqe->wr.opcode == IB_WR_LOCAL_INV)
+               return qp->req.wqe_index != queue_get_consumer(qp->sq.queue,
+                                               QUEUE_TYPE_FROM_CLIENT);
+
+       /* Fence see IBA 10.8.3.3
+        * Requires that all previous read and atomic operations
+        * are complete.
+        */
+       return (wqe->wr.send_flags & IB_SEND_FENCE) &&
+               atomic_read(&qp->req.rd_atomic) != qp->attr.max_rd_atomic;
+}
+
 static int next_opcode_rc(struct rxe_qp *qp, u32 opcode, int fits)
 {
        switch (opcode) {
@@ -633,6 +653,11 @@ next_wqe:
        if (unlikely(!wqe))
                goto exit;
 
+       if (rxe_wqe_is_fenced(qp, wqe)) {
+               qp->req.wait_fence = 1;
+               goto exit;
+       }
+
        if (wqe->mask & WR_LOCAL_OP_MASK) {
                ret = rxe_do_local_ops(qp, wqe);
                if (unlikely(ret))