]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
RDMA/bnxt_re: Fix the handling of control path response data
authorSelvin Xavier <selvin.xavier@broadcom.com>
Wed, 20 Sep 2023 08:41:19 +0000 (01:41 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Oct 2023 20:03:05 +0000 (22:03 +0200)
commit 9fc5f9a92fe6897dbed7b9295b234cb7e3cc9d11 upstream.

Flag that indicate control path command completion should be cleared
only after copying the command response data. As soon as the is_in_used
flag is clear, the waiting thread can proceed with wrong response
data.  This wrong data is causing multiple issues like wrong lkey
used in data traffic and wrong AH Id etc.

Use a memory barrier to ensure that the response data
is copied and visible to the process waiting on a different
cpu core before clearing the is_in_used flag.

Clear the is_in_used after copying the command response.

Fixes: bcfee4ce3e01 ("RDMA/bnxt_re: remove redundant cmdq_bitmap")
Signed-off-by: Saravanan Vajravel <saravanan.vajravel@broadcom.com>
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
Link: https://lore.kernel.org/r/1695199280-13520-2-git-send-email-selvin.xavier@broadcom.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c

index bc3aea4592b9df35887903722494d38088e0aaf1..27da7f9f4ebdc8b170004fc7c3075ab81945e064 100644 (file)
@@ -664,7 +664,6 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
                blocked = cookie & RCFW_CMD_IS_BLOCKING;
                cookie &= RCFW_MAX_COOKIE_VALUE;
                crsqe = &rcfw->crsqe_tbl[cookie];
-               crsqe->is_in_used = false;
 
                if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED,
                                       &rcfw->cmdq.flags),
@@ -680,8 +679,14 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
                        atomic_dec(&rcfw->timeout_send);
 
                if (crsqe->is_waiter_alive) {
-                       if (crsqe->resp)
+                       if (crsqe->resp) {
                                memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
+                               /* Insert write memory barrier to ensure that
+                                * response data is copied before clearing the
+                                * flags
+                                */
+                               smp_wmb();
+                       }
                        if (!blocked)
                                wait_cmds++;
                }
@@ -693,6 +698,8 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
                if (!is_waiter_alive)
                        crsqe->resp = NULL;
 
+               crsqe->is_in_used = false;
+
                hwq->cons += req_size;
 
                /* This is a case to handle below scenario -