[PATCH rdma-next 4/4] RDMA/hns: Use unsigned comparison in the CQ cleanup loop
From: Edward Srouji
Date: Tue Sep 15 2026 - 14:00:47 EST
From: Yishai Hadas <yishaih@xxxxxxxxxx>
__hns_roce_v2_cq_clean() sweeps the CQ backwards from the producer
index down to the consumer index:
while ((int) --prod_index - (int) hr_cq->cons_index >= 0)
Both indexes are free running u32 counters, so the comparison has to
be done modulo 2^32. Casting each operand to int and subtracting
does not do that: the subtraction overflows whenever the two indexes
straddle 2^31, which is undefined behaviour, and a compiler that
assumes signed overflow cannot occur is free to discard the
subtraction and fold the expression into a plain signed comparison.
That comparison is not wraparound safe.
The kernel is built with -fno-strict-overflow, so gcc and clang both
retain the subtraction today and the generated code is unaffected;
there is no known user-visible impact from the current code. Still,
correctness here shouldn't depend on that build flag.
Replace the loop with a plain unsigned equality check instead:
while (prod_index != hr_cq->cons_index) {
--prod_index;
...
The preceding forward scan starts prod_index at cons_index and advances
it only while get_sw_cqe_v2() still reports a software owned entry, so
the two indexes stay within one CQ's worth of entries. Decrementing
prod_index reaches cons_index in exactly that many iterations regardless
of whether either counter has wrapped, because the loop no longer
compares magnitudes at all.
Signed-off-by: Yishai Hadas <yishaih@xxxxxxxxxx>
Signed-off-by: Edward Srouji <edwards@xxxxxxxxxx>
---
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 1b2504301ebea4279eb0dcb2537c3574d0122d95..35be5b038f6861f1c330739f5c97817a4c3940a7 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -3828,7 +3828,8 @@ static void __hns_roce_v2_cq_clean(struct hns_roce_cq *hr_cq, u32 qpn,
* Now backwards through the CQ, removing CQ entries
* that match our QP by overwriting them with next entries.
*/
- while ((int) --prod_index - (int) hr_cq->cons_index >= 0) {
+ while (prod_index != hr_cq->cons_index) {
+ --prod_index;
cqe = get_cqe_v2(hr_cq, prod_index & hr_cq->ib_cq.cqe);
if (hr_reg_read(cqe, CQE_LCL_QPN) == qpn) {
if (srq && hr_reg_read(cqe, CQE_S_R)) {
--
2.49.0