mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 22:14:03 +02:00
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:
parent
c883d0a132
commit
8ee521b8b1
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user