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

drm/amdkfd: Fix possible infinite loop

When the loop predicating timeout parameter passed happens to
not be a multiple of 20 the unsigned integer will overflow and
the loop will become unbounded.

Signed-off-by: Edward O'Callaghan <funfunctor@folklore1984.net>
Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>

authored by

Edward O'Callaghan and committed by
Oded Gabbay
1d602430 ad16a469

+18 -16
+9 -8
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
··· 103 103 uint32_t pipe_id, uint32_t queue_id); 104 104 105 105 static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, 106 - unsigned int timeout, uint32_t pipe_id, 106 + unsigned int utimeout, uint32_t pipe_id, 107 107 uint32_t queue_id); 108 108 static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd); 109 109 static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, 110 - unsigned int timeout); 110 + unsigned int utimeout); 111 111 static int kgd_address_watch_disable(struct kgd_dev *kgd); 112 112 static int kgd_address_watch_execute(struct kgd_dev *kgd, 113 113 unsigned int watch_point_id, ··· 437 437 } 438 438 439 439 static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, 440 - unsigned int timeout, uint32_t pipe_id, 440 + unsigned int utimeout, uint32_t pipe_id, 441 441 uint32_t queue_id) 442 442 { 443 443 struct amdgpu_device *adev = get_amdgpu_device(kgd); 444 444 uint32_t temp; 445 + int timeout = utimeout; 445 446 446 447 acquire_queue(kgd, pipe_id, queue_id); 447 448 WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, 0); ··· 453 452 temp = RREG32(mmCP_HQD_ACTIVE); 454 453 if (temp & CP_HQD_ACTIVE__ACTIVE_MASK) 455 454 break; 456 - if (timeout == 0) { 457 - pr_err("kfd: cp queue preemption time out (%dms)\n", 458 - temp); 455 + if (timeout <= 0) { 456 + pr_err("kfd: cp queue preemption time out.\n"); 459 457 release_queue(kgd); 460 458 return -ETIME; 461 459 } ··· 467 467 } 468 468 469 469 static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, 470 - unsigned int timeout) 470 + unsigned int utimeout) 471 471 { 472 472 struct amdgpu_device *adev = get_amdgpu_device(kgd); 473 473 struct cik_sdma_rlc_registers *m; 474 474 uint32_t sdma_base_addr; 475 475 uint32_t temp; 476 + int timeout = utimeout; 476 477 477 478 m = get_sdma_mqd(mqd); 478 479 sdma_base_addr = get_sdma_base_addr(m); ··· 486 485 temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS); 487 486 if (temp & SDMA0_STATUS_REG__RB_CMD_IDLE__SHIFT) 488 487 break; 489 - if (timeout == 0) 488 + if (timeout <= 0) 490 489 return -ETIME; 491 490 msleep(20); 492 491 timeout -= 20;
+9 -8
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
··· 62 62 uint32_t pipe_id, uint32_t queue_id); 63 63 static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd); 64 64 static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, 65 - unsigned int timeout, uint32_t pipe_id, 65 + unsigned int utimeout, uint32_t pipe_id, 66 66 uint32_t queue_id); 67 67 static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, 68 - unsigned int timeout); 68 + unsigned int utimeout); 69 69 static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid); 70 70 static int kgd_address_watch_disable(struct kgd_dev *kgd); 71 71 static int kgd_address_watch_execute(struct kgd_dev *kgd, ··· 349 349 } 350 350 351 351 static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, 352 - unsigned int timeout, uint32_t pipe_id, 352 + unsigned int utimeout, uint32_t pipe_id, 353 353 uint32_t queue_id) 354 354 { 355 355 struct amdgpu_device *adev = get_amdgpu_device(kgd); 356 356 uint32_t temp; 357 + int timeout = utimeout; 357 358 358 359 acquire_queue(kgd, pipe_id, queue_id); 359 360 ··· 364 363 temp = RREG32(mmCP_HQD_ACTIVE); 365 364 if (temp & CP_HQD_ACTIVE__ACTIVE_MASK) 366 365 break; 367 - if (timeout == 0) { 368 - pr_err("kfd: cp queue preemption time out (%dms)\n", 369 - temp); 366 + if (timeout <= 0) { 367 + pr_err("kfd: cp queue preemption time out.\n"); 370 368 release_queue(kgd); 371 369 return -ETIME; 372 370 } ··· 378 378 } 379 379 380 380 static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, 381 - unsigned int timeout) 381 + unsigned int utimeout) 382 382 { 383 383 struct amdgpu_device *adev = get_amdgpu_device(kgd); 384 384 struct cik_sdma_rlc_registers *m; 385 385 uint32_t sdma_base_addr; 386 386 uint32_t temp; 387 + int timeout = utimeout; 387 388 388 389 m = get_sdma_mqd(mqd); 389 390 sdma_base_addr = get_sdma_base_addr(m); ··· 397 396 temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS); 398 397 if (temp & SDMA0_STATUS_REG__RB_CMD_IDLE__SHIFT) 399 398 break; 400 - if (timeout == 0) 399 + if (timeout <= 0) 401 400 return -ETIME; 402 401 msleep(20); 403 402 timeout -= 20;