drm/amdkfd: Avoid integer underflow in EOP ring size calculation.

The low 6 bits of cp_hqd_eop_control store the base-2 logarithm
of the EOP ring size. This was calculated as

order_base_2(q->eop_ring_buffer_size / 4) - 1

But order_base_2 can in theory return 0, so this could underflow
(although in practice the ring buffer size cannot be less than 4096).

Change this to

order_base_2(q->eop_ring_buffer_size / 8)

using properties of logarithms.

Also add to the above comment to make the mathematics more clear.

Reviewed-by: Kent Russell <kent.russell@amd.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit f0f43fcf8b2b3a924cad9444340921c96ed5f634)
Cc: stable@vger.kernel.org
This commit is contained in:
David Francis 2026-08-05 09:16:51 -04:00 committed by Alex Deucher
parent c883d0a132
commit 8ee521b8b1
2 changed files with 9 additions and 2 deletions

View File

@ -285,6 +285,10 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
1 << CP_HQD_IB_CONTROL__IB_EXE_DISABLE__SHIFT;
/*
* The lowest 6 bits of eop_control store the EOP ring size. If
* their value is X, the ring size is 2^(X + 1) dwords, or
* 2^(X + 3) bytes.
*
* HW does not clamp this field correctly. Maximum EOP queue size
* is constrained by per-SE EOP done signal count, which is 8-bit.
* Limit is 0xFF EOP entries (= 0x7F8 dwords). CP will not submit
@ -296,7 +300,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
*
*/
m->cp_hqd_eop_control = q->eop_ring_buffer_size ?
min(0xA, order_base_2(q->eop_ring_buffer_size / 4) - 1) : 0;
min(0xA, order_base_2(q->eop_ring_buffer_size / 8)) : 0;
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);

View File

@ -208,6 +208,9 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
mtype << CP_HQD_IB_CONTROL__MTYPE__SHIFT;
/*
* The lowest 6 bits of eop_control store the EOP ring size. If
* their value is X, the ring size is 2^(X + 1) dwords, or
* 2^(X + 3) bytes.
* HW does not clamp this field correctly. Maximum EOP queue size
* is constrained by per-SE EOP done signal count, which is 8-bit.
* Limit is 0xFF EOP entries (= 0x7F8 dwords). CP will not submit
@ -215,7 +218,7 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd,
* is safe, giving a maximum field value of 0xA.
*/
m->cp_hqd_eop_control |= q->eop_ring_buffer_size ? min(0xA,
order_base_2(q->eop_ring_buffer_size / 4) - 1) : 0;
order_base_2(q->eop_ring_buffer_size / 8)) : 0;
m->cp_hqd_eop_base_addr_lo =
lower_32_bits(q->eop_ring_buffer_address >> 8);
m->cp_hqd_eop_base_addr_hi =