diff mbox series

[for-next,2/4] RDMA/bnxt_re: Get the WQE index from slot index while completing the WQEs

Message ID 1723317553-13002-3-git-send-email-selvin.xavier@broadcom.com (mailing list archive)
State Superseded
Headers show
Series RDMA/bnxt_re: Use variable size Work Queue entry for Gen P7 adapters | expand

Commit Message

Selvin Xavier Aug. 10, 2024, 7:19 p.m. UTC
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.

Signed-off-by: Hongguang Gao <hong``guang.gao@broadcom.com>
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
---
 drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 ++++++++++++++++++++++++++++++++
 drivers/infiniband/hw/bnxt_re/qplib_fp.h | 10 ++++++++
 2 files changed, 50 insertions(+)

Comments

Zhu Yanjun Aug. 12, 2024, 8:48 a.m. UTC | #1
在 2024/8/11 3:19, Selvin Xavier 写道:
> 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.
> 
> Signed-off-by: Hongguang Gao <hong``guang.gao@broadcom.com>
> Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
> ---
>   drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 ++++++++++++++++++++++++++++++++
>   drivers/infiniband/hw/bnxt_re/qplib_fp.h | 10 ++++++++
>   2 files changed, 50 insertions(+)
> 
> diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
> index 0af09e7..b49f49c 100644
> --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
> +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
> @@ -2471,6 +2471,32 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
>   	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,
> @@ -2481,6 +2507,7 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
>   	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,19 @@ 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)) {
> +		cqe_cons = bnxt_qplib_get_cqe_sq_cons(sq, hwcqe->sq_cons_idx);
> +		if (cqe_cons < 0) {
> +			dev_err(&cq->hwq.pdev->dev, "%s: Wrong SQ cons cqe_slot_indx = %d\n",
> +				__func__, hwcqe->sq_cons_idx);
> +			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
> diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
> index f54d7a0..2e7a4fd 100644
> --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
> +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
> @@ -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)

IIRC, inline is not needed here. The compiler will determine if the 
function inline is needed or not.

It is a trivial problem.

Zhu Yanjun

> +{
> +	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)

ditto.

> +{
> +	return (status != CQ_REQ_STATUS_OK) && __is_var_wqe(qp);
> +}
>   #endif /* __BNXT_QPLIB_FP_H__ */
Leon Romanovsky Aug. 12, 2024, 10:08 a.m. UTC | #2
On Mon, Aug 12, 2024 at 04:48:44PM +0800, Zhu Yanjun wrote:
> 在 2024/8/11 3:19, Selvin Xavier 写道:
> > 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.
> > 
> > Signed-off-by: Hongguang Gao <hong``guang.gao@broadcom.com>
> > Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
> > ---
> >   drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 ++++++++++++++++++++++++++++++++
> >   drivers/infiniband/hw/bnxt_re/qplib_fp.h | 10 ++++++++
> >   2 files changed, 50 insertions(+)
> > 
> > diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
> > index 0af09e7..b49f49c 100644
> > --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
> > +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
> > @@ -2471,6 +2471,32 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
> >   	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,
> > @@ -2481,6 +2507,7 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
> >   	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,19 @@ 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)) {
> > +		cqe_cons = bnxt_qplib_get_cqe_sq_cons(sq, hwcqe->sq_cons_idx);
> > +		if (cqe_cons < 0) {
> > +			dev_err(&cq->hwq.pdev->dev, "%s: Wrong SQ cons cqe_slot_indx = %d\n",
> > +				__func__, hwcqe->sq_cons_idx);
> > +			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
> > diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
> > index f54d7a0..2e7a4fd 100644
> > --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
> > +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
> > @@ -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)
> 
> IIRC, inline is not needed here. The compiler will determine if the function
> inline is needed or not.

Selvin added inline functions to *.h file and not to *.c file.

Thanks

> 
> It is a trivial problem.
> 
> Zhu Yanjun
> 
> > +{
> > +	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)
> 
> ditto.
> 
> > +{
> > +	return (status != CQ_REQ_STATUS_OK) && __is_var_wqe(qp);
> > +}
> >   #endif /* __BNXT_QPLIB_FP_H__ */
>
Zhu Yanjun Aug. 12, 2024, 10:45 a.m. UTC | #3
在 2024/8/12 18:08, Leon Romanovsky 写道:
> On Mon, Aug 12, 2024 at 04:48:44PM +0800, Zhu Yanjun wrote:
>> 在 2024/8/11 3:19, Selvin Xavier 写道:
>>> 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.
>>>
>>> Signed-off-by: Hongguang Gao <hong``guang.gao@broadcom.com>
>>> Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
>>> ---
>>>    drivers/infiniband/hw/bnxt_re/qplib_fp.c | 40 ++++++++++++++++++++++++++++++++
>>>    drivers/infiniband/hw/bnxt_re/qplib_fp.h | 10 ++++++++
>>>    2 files changed, 50 insertions(+)
>>>
>>> diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
>>> index 0af09e7..b49f49c 100644
>>> --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
>>> +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
>>> @@ -2471,6 +2471,32 @@ static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
>>>    	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,
>>> @@ -2481,6 +2507,7 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
>>>    	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,19 @@ 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)) {
>>> +		cqe_cons = bnxt_qplib_get_cqe_sq_cons(sq, hwcqe->sq_cons_idx);
>>> +		if (cqe_cons < 0) {
>>> +			dev_err(&cq->hwq.pdev->dev, "%s: Wrong SQ cons cqe_slot_indx = %d\n",
>>> +				__func__, hwcqe->sq_cons_idx);
>>> +			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
>>> diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
>>> index f54d7a0..2e7a4fd 100644
>>> --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
>>> +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
>>> @@ -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)
>> IIRC, inline is not needed here. The compiler will determine if the function
>> inline is needed or not.
> Selvin added inline functions to *.h file and not to *.c file.

Yeah. I mistook that these 2 functions were in *.c file.

Thanks.

Zhu Yanjun

>
> Thanks
>
>> It is a trivial problem.
>>
>> Zhu Yanjun
>>
>>> +{
>>> +	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)
>> ditto.
>>
>>> +{
>>> +	return (status != CQ_REQ_STATUS_OK) && __is_var_wqe(qp);
>>> +}
>>>    #endif /* __BNXT_QPLIB_FP_H__ */
diff mbox series

Patch

diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
index 0af09e7..b49f49c 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -2471,6 +2471,32 @@  static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
 	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,
@@ -2481,6 +2507,7 @@  static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
 	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,19 @@  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)) {
+		cqe_cons = bnxt_qplib_get_cqe_sq_cons(sq, hwcqe->sq_cons_idx);
+		if (cqe_cons < 0) {
+			dev_err(&cq->hwq.pdev->dev, "%s: Wrong SQ cons cqe_slot_indx = %d\n",
+				__func__, hwcqe->sq_cons_idx);
+			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
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
index f54d7a0..2e7a4fd 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -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__ */