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

drm/amdgpu: Fix SDMA load/unload sequence on HWS disabled mode

Fix the SDMA load and unload sequence as suggested by HW document.

Signed-off-by: shaoyun liu <shaoyun.liu@amd.com>
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Acked-by: Oded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>

authored by

Felix Kuehling and committed by
Oded Gabbay
cf21654b c209101f

+39 -18
+39 -18
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
··· 379 379 { 380 380 struct amdgpu_device *adev = get_amdgpu_device(kgd); 381 381 struct cik_sdma_rlc_registers *m; 382 + unsigned long end_jiffies; 382 383 uint32_t sdma_base_addr; 384 + uint32_t data; 383 385 384 386 m = get_sdma_mqd(mqd); 385 387 sdma_base_addr = get_sdma_base_addr(m); 386 388 387 - WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR, 388 - m->sdma_rlc_virtual_addr); 389 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, 390 + m->sdma_rlc_rb_cntl & (~SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK)); 389 391 390 - WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, 391 - m->sdma_rlc_rb_base); 392 - 393 - WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI, 394 - m->sdma_rlc_rb_base_hi); 395 - 396 - WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO, 397 - m->sdma_rlc_rb_rptr_addr_lo); 398 - 399 - WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI, 400 - m->sdma_rlc_rb_rptr_addr_hi); 392 + end_jiffies = msecs_to_jiffies(2000) + jiffies; 393 + while (true) { 394 + data = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS); 395 + if (data & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK) 396 + break; 397 + if (time_after(jiffies, end_jiffies)) 398 + return -ETIME; 399 + usleep_range(500, 1000); 400 + } 401 + if (m->sdma_engine_id) { 402 + data = RREG32(mmSDMA1_GFX_CONTEXT_CNTL); 403 + data = REG_SET_FIELD(data, SDMA1_GFX_CONTEXT_CNTL, 404 + RESUME_CTX, 0); 405 + WREG32(mmSDMA1_GFX_CONTEXT_CNTL, data); 406 + } else { 407 + data = RREG32(mmSDMA0_GFX_CONTEXT_CNTL); 408 + data = REG_SET_FIELD(data, SDMA0_GFX_CONTEXT_CNTL, 409 + RESUME_CTX, 0); 410 + WREG32(mmSDMA0_GFX_CONTEXT_CNTL, data); 411 + } 401 412 402 413 WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 403 - m->sdma_rlc_doorbell); 404 - 414 + m->sdma_rlc_doorbell); 415 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, 0); 416 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, 0); 417 + WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR, 418 + m->sdma_rlc_virtual_addr); 419 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdma_rlc_rb_base); 420 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI, 421 + m->sdma_rlc_rb_base_hi); 422 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_LO, 423 + m->sdma_rlc_rb_rptr_addr_lo); 424 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR_ADDR_HI, 425 + m->sdma_rlc_rb_rptr_addr_hi); 405 426 WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, 406 427 m->sdma_rlc_rb_cntl); 407 428 ··· 595 574 } 596 575 597 576 WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, 0); 598 - WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, 0); 599 - WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, 0); 600 - WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, 0); 577 + WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL, 578 + RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) | 579 + SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK); 601 580 602 581 return 0; 603 582 }