Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdkfd: Fix partial migrate issue

For partial migrate from ram to vram, the migrate->cpages is not
equal to migrate->npages, should use migrate->npages to check all needed
migrate pages which could be copied or not.

And only need to set those pages could be migrated to migrate->dst[i], or
the migrate_vma_pages will migrate the wrong pages based on the migrate->dst[i].

v2:
Add mpages to break the loop earlier.

v3:
Uses MIGRATE_PFN_MIGRATE to identify whether page could be migrated.

v4:
Correct the error part.

Signed-off-by: Emily Deng <Emily.Deng@amd.com>
Reviewed-by: Philip Yang<Philip.Yang@amd.com>
Suggested-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Emily Deng and committed by
Alex Deucher
b5f022fe 19b7f7c7

+14 -8
+14 -8
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
··· 278 278 struct migrate_vma *migrate, struct dma_fence **mfence, 279 279 dma_addr_t *scratch, uint64_t ttm_res_offset) 280 280 { 281 - uint64_t npages = migrate->cpages; 281 + uint64_t npages = migrate->npages; 282 282 struct amdgpu_device *adev = node->adev; 283 283 struct device *dev = adev->dev; 284 284 struct amdgpu_res_cursor cursor; 285 + uint64_t mpages = 0; 285 286 dma_addr_t *src; 286 287 uint64_t *dst; 287 288 uint64_t i, j; ··· 296 295 297 296 amdgpu_res_first(prange->ttm_res, ttm_res_offset, 298 297 npages << PAGE_SHIFT, &cursor); 299 - for (i = j = 0; i < npages; i++) { 298 + for (i = j = 0; (i < npages) && (mpages < migrate->cpages); i++) { 300 299 struct page *spage; 301 300 302 - dst[i] = cursor.start + (j << PAGE_SHIFT); 303 - migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]); 304 - svm_migrate_get_vram_page(prange, migrate->dst[i]); 305 - migrate->dst[i] = migrate_pfn(migrate->dst[i]); 306 - 301 + if (migrate->src[i] & MIGRATE_PFN_MIGRATE) { 302 + dst[i] = cursor.start + (j << PAGE_SHIFT); 303 + migrate->dst[i] = svm_migrate_addr_to_pfn(adev, dst[i]); 304 + svm_migrate_get_vram_page(prange, migrate->dst[i]); 305 + migrate->dst[i] = migrate_pfn(migrate->dst[i]); 306 + mpages++; 307 + } 307 308 spage = migrate_pfn_to_page(migrate->src[i]); 308 309 if (spage && !is_zone_device_page(spage)) { 309 310 src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE, ··· 356 353 out_free_vram_pages: 357 354 if (r) { 358 355 pr_debug("failed %d to copy memory to vram\n", r); 359 - while (i--) { 356 + for (i = 0; i < npages && mpages; i++) { 357 + if (!dst[i]) 358 + continue; 360 359 svm_migrate_put_vram_page(adev, dst[i]); 361 360 migrate->dst[i] = 0; 361 + mpages--; 362 362 } 363 363 } 364 364