DF-1332 / fix.diff
diff --git a/sys/dev/drm/amd/amdgpu/amdgpu_ttm.c b/sys/dev/drm/amd/amdgpu/amdgpu_ttm.c --- a/sys/dev/drm/amd/amdgpu/amdgpu_ttm.c +++ b/sys/dev/drm/amd/amdgpu/amdgpu_ttm.c @@ -2180,9 +2180,14 @@ mm_node = bo->tbo.mem.mm_node; num_loops = 0; while (num_pages) { - uint32_t byte_count = mm_node->size << PAGE_SHIFT; + uint64_t byte_count = (uint64_t)mm_node->size << PAGE_SHIFT; + uint32_t bc32 = byte_count > max_bytes ? max_bytes : (uint32_t)byte_count; - num_loops += DIV_ROUND_UP(byte_count, max_bytes); + /* mm_node->size << PAGE_SHIFT can exceed UINT32_MAX; never + * report zero bytes to DIV_ROUND_UP or the VRAM clear is + * skipped entirely (DF-1332). */ + num_loops += DIV_ROUND_UP(bc32, max_bytes) + + (byte_count > UINT32_MAX ? byte_count / max_bytes : 0); num_pages -= mm_node->size; ++mm_node; } @@ -2208,12 +2213,13 @@ mm_node = bo->tbo.mem.mm_node; while (num_pages) { - uint32_t byte_count = mm_node->size << PAGE_SHIFT; + uint64_t byte_count = (uint64_t)mm_node->size << PAGE_SHIFT; uint64_t dst_addr; dst_addr = amdgpu_mm_node_addr(&bo->tbo, mm_node, &bo->tbo.mem); while (byte_count) { - uint32_t cur_size_in_bytes = min(byte_count, max_bytes); + uint32_t cur_size_in_bytes = byte_count > max_bytes ? + max_bytes : (uint32_t)byte_count; amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, dst_addr, cur_size_in_bytes); |