diff options
author | Emily Deng <Emily.Deng@amd.com> | 2018-08-17 06:25:36 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-08-27 12:11:08 -0400 |
commit | 3890d11153e20ed48de2adca4261788f72b93f66 (patch) | |
tree | 077f2742f794b99e57a97bec71fd5be632fad554 /drivers/gpu/drm/amd/amdgpu | |
parent | 39b62541aac396d18108c160ddb956a22483046d (diff) |
drm/amdgpu: use kiq to do invalidate tlb
To avoid the tlb flush not interrupted by world switch, use kiq and one
command to do tlb invalidate.
v2:
Refine the invalidate lock position.
Signed-off-by: Emily Deng <Emily.Deng@amd.com>
Reviewed-and-Tested-by: Rex Zhu <Rex.Zhu@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 74 |
3 files changed, 71 insertions, 10 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 6265b88135fc..19ef7711d944 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -212,6 +212,10 @@ enum amdgpu_kiq_irq { | |||
212 | AMDGPU_CP_KIQ_IRQ_LAST | 212 | AMDGPU_CP_KIQ_IRQ_LAST |
213 | }; | 213 | }; |
214 | 214 | ||
215 | #define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */ | ||
216 | #define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */ | ||
217 | #define MAX_KIQ_REG_TRY 20 | ||
218 | |||
215 | int amdgpu_device_ip_set_clockgating_state(void *dev, | 219 | int amdgpu_device_ip_set_clockgating_state(void *dev, |
216 | enum amd_ip_block_type block_type, | 220 | enum amd_ip_block_type block_type, |
217 | enum amd_clockgating_state state); | 221 | enum amd_clockgating_state state); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 21adb1b6e5cb..38856365580d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | |||
@@ -22,9 +22,6 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "amdgpu.h" | 24 | #include "amdgpu.h" |
25 | #define MAX_KIQ_REG_WAIT 5000 /* in usecs, 5ms */ | ||
26 | #define MAX_KIQ_REG_BAILOUT_INTERVAL 5 /* in msecs, 5ms */ | ||
27 | #define MAX_KIQ_REG_TRY 20 | ||
28 | 25 | ||
29 | uint64_t amdgpu_csa_vaddr(struct amdgpu_device *adev) | 26 | uint64_t amdgpu_csa_vaddr(struct amdgpu_device *adev) |
30 | { | 27 | { |
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 7300be4816a9..46183c7730c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | |||
@@ -311,6 +311,58 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid) | |||
311 | return req; | 311 | return req; |
312 | } | 312 | } |
313 | 313 | ||
314 | signed long amdgpu_kiq_reg_write_reg_wait(struct amdgpu_device *adev, | ||
315 | uint32_t reg0, uint32_t reg1, | ||
316 | uint32_t ref, uint32_t mask) | ||
317 | { | ||
318 | signed long r, cnt = 0; | ||
319 | unsigned long flags; | ||
320 | uint32_t seq; | ||
321 | struct amdgpu_kiq *kiq = &adev->gfx.kiq; | ||
322 | struct amdgpu_ring *ring = &kiq->ring; | ||
323 | |||
324 | if (!ring->ready) | ||
325 | return -EINVAL; | ||
326 | |||
327 | spin_lock_irqsave(&kiq->ring_lock, flags); | ||
328 | |||
329 | amdgpu_ring_alloc(ring, 32); | ||
330 | amdgpu_ring_emit_reg_write_reg_wait(ring, reg0, reg1, | ||
331 | ref, mask); | ||
332 | amdgpu_fence_emit_polling(ring, &seq); | ||
333 | amdgpu_ring_commit(ring); | ||
334 | spin_unlock_irqrestore(&kiq->ring_lock, flags); | ||
335 | |||
336 | r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); | ||
337 | |||
338 | /* don't wait anymore for gpu reset case because this way may | ||
339 | * block gpu_recover() routine forever, e.g. this virt_kiq_rreg | ||
340 | * is triggered in TTM and ttm_bo_lock_delayed_workqueue() will | ||
341 | * never return if we keep waiting in virt_kiq_rreg, which cause | ||
342 | * gpu_recover() hang there. | ||
343 | * | ||
344 | * also don't wait anymore for IRQ context | ||
345 | * */ | ||
346 | if (r < 1 && (adev->in_gpu_reset || in_interrupt())) | ||
347 | goto failed_kiq; | ||
348 | |||
349 | might_sleep(); | ||
350 | |||
351 | while (r < 1 && cnt++ < MAX_KIQ_REG_TRY) { | ||
352 | msleep(MAX_KIQ_REG_BAILOUT_INTERVAL); | ||
353 | r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); | ||
354 | } | ||
355 | |||
356 | if (cnt > MAX_KIQ_REG_TRY) | ||
357 | goto failed_kiq; | ||
358 | |||
359 | return 0; | ||
360 | |||
361 | failed_kiq: | ||
362 | pr_err("failed to invalidate tlb with kiq\n"); | ||
363 | return r; | ||
364 | } | ||
365 | |||
314 | /* | 366 | /* |
315 | * GART | 367 | * GART |
316 | * VMID 0 is the physical GPU addresses as used by the kernel. | 368 | * VMID 0 is the physical GPU addresses as used by the kernel. |
@@ -332,13 +384,19 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, | |||
332 | /* Use register 17 for GART */ | 384 | /* Use register 17 for GART */ |
333 | const unsigned eng = 17; | 385 | const unsigned eng = 17; |
334 | unsigned i, j; | 386 | unsigned i, j; |
335 | 387 | int r; | |
336 | spin_lock(&adev->gmc.invalidate_lock); | ||
337 | 388 | ||
338 | for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { | 389 | for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { |
339 | struct amdgpu_vmhub *hub = &adev->vmhub[i]; | 390 | struct amdgpu_vmhub *hub = &adev->vmhub[i]; |
340 | u32 tmp = gmc_v9_0_get_invalidate_req(vmid); | 391 | u32 tmp = gmc_v9_0_get_invalidate_req(vmid); |
341 | 392 | ||
393 | r = amdgpu_kiq_reg_write_reg_wait(adev, hub->vm_inv_eng0_req + eng, | ||
394 | hub->vm_inv_eng0_ack + eng, tmp, 1 << vmid); | ||
395 | if (!r) | ||
396 | continue; | ||
397 | |||
398 | spin_lock(&adev->gmc.invalidate_lock); | ||
399 | |||
342 | WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp); | 400 | WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp); |
343 | 401 | ||
344 | /* Busy wait for ACK.*/ | 402 | /* Busy wait for ACK.*/ |
@@ -349,8 +407,10 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, | |||
349 | break; | 407 | break; |
350 | cpu_relax(); | 408 | cpu_relax(); |
351 | } | 409 | } |
352 | if (j < 100) | 410 | if (j < 100) { |
411 | spin_unlock(&adev->gmc.invalidate_lock); | ||
353 | continue; | 412 | continue; |
413 | } | ||
354 | 414 | ||
355 | /* Wait for ACK with a delay.*/ | 415 | /* Wait for ACK with a delay.*/ |
356 | for (j = 0; j < adev->usec_timeout; j++) { | 416 | for (j = 0; j < adev->usec_timeout; j++) { |
@@ -360,13 +420,13 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, | |||
360 | break; | 420 | break; |
361 | udelay(1); | 421 | udelay(1); |
362 | } | 422 | } |
363 | if (j < adev->usec_timeout) | 423 | if (j < adev->usec_timeout) { |
424 | spin_unlock(&adev->gmc.invalidate_lock); | ||
364 | continue; | 425 | continue; |
365 | 426 | } | |
427 | spin_unlock(&adev->gmc.invalidate_lock); | ||
366 | DRM_ERROR("Timeout waiting for VM flush ACK!\n"); | 428 | DRM_ERROR("Timeout waiting for VM flush ACK!\n"); |
367 | } | 429 | } |
368 | |||
369 | spin_unlock(&adev->gmc.invalidate_lock); | ||
370 | } | 430 | } |
371 | 431 | ||
372 | static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, | 432 | static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring, |