]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/irdma: Fix data race in irdma_sc_ccq_arm
authorKrzysztof Czurylo <krzysztof.czurylo@intel.com>
Tue, 25 Nov 2025 02:53:42 +0000 (20:53 -0600)
committerLeon Romanovsky <leon@kernel.org>
Wed, 26 Nov 2025 07:26:05 +0000 (02:26 -0500)
Adds a lock around irdma_sc_ccq_arm body to prevent inter-thread data race.
Fixes data race in irdma_sc_ccq_arm() reported by KCSAN:

BUG: KCSAN: data-race in irdma_sc_ccq_arm [irdma] / irdma_sc_ccq_arm [irdma]

read to 0xffff9d51b4034220 of 8 bytes by task 255 on cpu 11:
 irdma_sc_ccq_arm+0x36/0xd0 [irdma]
 irdma_cqp_ce_handler+0x300/0x310 [irdma]
 cqp_compl_worker+0x2a/0x40 [irdma]
 process_one_work+0x402/0x7e0
 worker_thread+0xb3/0x6d0
 kthread+0x178/0x1a0
 ret_from_fork+0x2c/0x50

write to 0xffff9d51b4034220 of 8 bytes by task 89 on cpu 3:
 irdma_sc_ccq_arm+0x7e/0xd0 [irdma]
 irdma_cqp_ce_handler+0x300/0x310 [irdma]
 irdma_wait_event+0xd4/0x3e0 [irdma]
 irdma_handle_cqp_op+0xa5/0x220 [irdma]
 irdma_hw_flush_wqes+0xb1/0x300 [irdma]
 irdma_flush_wqes+0x22e/0x3a0 [irdma]
 irdma_cm_disconn_true+0x4c7/0x5d0 [irdma]
 irdma_disconnect_worker+0x35/0x50 [irdma]
 process_one_work+0x402/0x7e0
 worker_thread+0xb3/0x6d0
 kthread+0x178/0x1a0
 ret_from_fork+0x2c/0x50

value changed: 0x0000000000024000 -> 0x0000000000034000

Fixes: 3f49d6842569 ("RDMA/irdma: Implement HW Admin Queue OPs")
Signed-off-by: Krzysztof Czurylo <krzysztof.czurylo@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
Link: https://patch.msgid.link/20251125025350.180-2-tatyana.e.nikolova@intel.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/irdma/ctrl.c

index 57bf6815e71ed883ffccd0dbab5fe045f4ecbf1d..c17b1c14dfe2c33b9f6edf1503eb5e899b93ebc3 100644 (file)
@@ -3868,11 +3868,13 @@ int irdma_sc_cqp_destroy(struct irdma_sc_cqp *cqp)
  */
 void irdma_sc_ccq_arm(struct irdma_sc_cq *ccq)
 {
+       unsigned long flags;
        u64 temp_val;
        u16 sw_cq_sel;
        u8 arm_next_se;
        u8 arm_seq_num;
 
+       spin_lock_irqsave(&ccq->dev->cqp_lock, flags);
        get_64bit_val(ccq->cq_uk.shadow_area, 32, &temp_val);
        sw_cq_sel = (u16)FIELD_GET(IRDMA_CQ_DBSA_SW_CQ_SELECT, temp_val);
        arm_next_se = (u8)FIELD_GET(IRDMA_CQ_DBSA_ARM_NEXT_SE, temp_val);
@@ -3883,6 +3885,7 @@ void irdma_sc_ccq_arm(struct irdma_sc_cq *ccq)
                   FIELD_PREP(IRDMA_CQ_DBSA_ARM_NEXT_SE, arm_next_se) |
                   FIELD_PREP(IRDMA_CQ_DBSA_ARM_NEXT, 1);
        set_64bit_val(ccq->cq_uk.shadow_area, 32, temp_val);
+       spin_unlock_irqrestore(&ccq->dev->cqp_lock, flags);
 
        dma_wmb(); /* make sure shadow area is updated before arming */