]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/bnxt_re: Get the WQE index from slot index while completing the WQEs
authorSelvin Xavier <selvin.xavier@broadcom.com>
Mon, 19 Aug 2024 04:47:24 +0000 (21:47 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 27 Aug 2024 13:15:57 +0000 (10:15 -0300)
While reporting the completions, SQ Work Queue index is required to
identify the WQE that generated the completions. In variable WQE mode, FW
returns the slot index for Error completions. Driver need to walk through
the shadow queue between the consumer index and producer index and matches
the slot index returned by FW. If a match is found, the next index of the
shadow queue is the WQE index to be considered for remaining poll_cq loop.

Link: https://patch.msgid.link/r/1724042847-1481-3-git-send-email-selvin.xavier@broadcom.com
Signed-off-by: Hongguang Gao <hongguang.gao@broadcom.com>
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/bnxt_re/qplib_fp.h

index 0af09e77e94b79abc5ece8d197f4edf883d7652e..2810ffe3394b66102523fe7e129739f32d9133ff 100644 (file)
@@ -2471,6 +2471,32 @@ out:
        return rc;
 }
 
+static int bnxt_qplib_get_cqe_sq_cons(struct bnxt_qplib_q *sq, u32 cqe_slot)
+{
+       struct bnxt_qplib_hwq *sq_hwq;
+       struct bnxt_qplib_swq *swq;
+       int cqe_sq_cons = -1;
+       u32 start, last;
+
+       sq_hwq = &sq->hwq;
+
+       start = sq->swq_start;
+       last = sq->swq_last;
+
+       while (last != start) {
+               swq = &sq->swq[last];
+               if (swq->slot_idx  == cqe_slot) {
+                       cqe_sq_cons = swq->next_idx;
+                       dev_err(&sq_hwq->pdev->dev, "%s: Found cons wqe = %d slot = %d\n",
+                               __func__, cqe_sq_cons, cqe_slot);
+                       break;
+               }
+
+               last = swq->next_idx;
+       }
+       return cqe_sq_cons;
+}
+
 static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
                                     struct cq_req *hwcqe,
                                     struct bnxt_qplib_cqe **pcqe, int *budget,
@@ -2478,9 +2504,10 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
 {
        struct bnxt_qplib_swq *swq;
        struct bnxt_qplib_cqe *cqe;
+       u32 cqe_sq_cons, slot_num;
        struct bnxt_qplib_qp *qp;
        struct bnxt_qplib_q *sq;
-       u32 cqe_sq_cons;
+       int cqe_cons;
        int rc = 0;
 
        qp = (struct bnxt_qplib_qp *)((unsigned long)
@@ -2498,6 +2525,20 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
                        "%s: QP in Flush QP = %p\n", __func__, qp);
                goto done;
        }
+
+       if (__is_err_cqe_for_var_wqe(qp, hwcqe->status)) {
+               slot_num = le16_to_cpu(hwcqe->sq_cons_idx);
+               cqe_cons = bnxt_qplib_get_cqe_sq_cons(sq, slot_num);
+               if (cqe_cons < 0) {
+                       dev_err(&cq->hwq.pdev->dev, "%s: Wrong SQ cons cqe_slot_indx = %d\n",
+                               __func__, slot_num);
+                       goto done;
+               }
+               cqe_sq_cons = cqe_cons;
+               dev_err(&cq->hwq.pdev->dev, "%s: cqe_sq_cons = %d swq_last = %d swq_start = %d\n",
+                       __func__, cqe_sq_cons, sq->swq_last, sq->swq_start);
+       }
+
        /* Require to walk the sq's swq to fabricate CQEs for all previously
         * signaled SWQEs due to CQE aggregation from the current sq cons
         * to the cqe_sq_cons
index f54d7a0c7dad3d599704d375fe6142e498f7e9db..2e7a4fd651b87afb822c45cf38220725ac84c48c 100644 (file)
@@ -649,4 +649,14 @@ static inline __le64 bnxt_re_update_msn_tbl(u32 st_idx, u32 npsn, u32 start_psn)
                (((start_psn) << SQ_MSN_SEARCH_START_PSN_SFT) &
                SQ_MSN_SEARCH_START_PSN_MASK));
 }
+
+static inline bool __is_var_wqe(struct bnxt_qplib_qp *qp)
+{
+       return (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE);
+}
+
+static inline bool __is_err_cqe_for_var_wqe(struct bnxt_qplib_qp *qp, u8 status)
+{
+       return (status != CQ_REQ_STATUS_OK) && __is_var_wqe(qp);
+}
 #endif /* __BNXT_QPLIB_FP_H__ */