diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/mm_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 859e46fc..15fd32d3 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -3460,6 +3460,47 @@ hw_was_off: | |||
3460 | pm_runtime_put_noidle(&g->dev->dev); | 3460 | pm_runtime_put_noidle(&g->dev->dev); |
3461 | } | 3461 | } |
3462 | 3462 | ||
3463 | void gk20a_mm_cbc_clean(struct gk20a *g) | ||
3464 | { | ||
3465 | struct mm_gk20a *mm = &g->mm; | ||
3466 | u32 data; | ||
3467 | s32 retry = 200; | ||
3468 | |||
3469 | gk20a_dbg_fn(""); | ||
3470 | |||
3471 | gk20a_busy_noresume(g->dev); | ||
3472 | if (!g->power_on) | ||
3473 | goto hw_was_off; | ||
3474 | |||
3475 | mutex_lock(&mm->l2_op_lock); | ||
3476 | |||
3477 | /* Flush all dirty lines from the CBC to L2 */ | ||
3478 | gk20a_writel(g, flush_l2_clean_comptags_r(), | ||
3479 | flush_l2_clean_comptags_pending_busy_f()); | ||
3480 | |||
3481 | do { | ||
3482 | data = gk20a_readl(g, flush_l2_clean_comptags_r()); | ||
3483 | |||
3484 | if (flush_l2_clean_comptags_outstanding_v(data) == | ||
3485 | flush_l2_clean_comptags_outstanding_true_v() || | ||
3486 | flush_l2_clean_comptags_pending_v(data) == | ||
3487 | flush_l2_clean_comptags_pending_busy_v()) { | ||
3488 | gk20a_dbg_info("l2_clean_comptags 0x%x", data); | ||
3489 | retry--; | ||
3490 | udelay(5); | ||
3491 | } else | ||
3492 | break; | ||
3493 | } while (retry >= 0 || !tegra_platform_is_silicon()); | ||
3494 | |||
3495 | if (tegra_platform_is_silicon() && retry < 0) | ||
3496 | gk20a_warn(dev_from_gk20a(g), | ||
3497 | "l2_clean_comptags too many retries"); | ||
3498 | |||
3499 | mutex_unlock(&mm->l2_op_lock); | ||
3500 | |||
3501 | hw_was_off: | ||
3502 | pm_runtime_put_noidle(&g->dev->dev); | ||
3503 | } | ||
3463 | 3504 | ||
3464 | int gk20a_vm_find_buffer(struct vm_gk20a *vm, u64 gpu_va, | 3505 | int gk20a_vm_find_buffer(struct vm_gk20a *vm, u64 gpu_va, |
3465 | struct dma_buf **dmabuf, | 3506 | struct dma_buf **dmabuf, |
@@ -3555,7 +3596,8 @@ int gk20a_mm_suspend(struct gk20a *g) | |||
3555 | { | 3596 | { |
3556 | gk20a_dbg_fn(""); | 3597 | gk20a_dbg_fn(""); |
3557 | 3598 | ||
3558 | g->ops.ltc.elpg_flush(g); | 3599 | g->ops.mm.cbc_clean(g); |
3600 | g->ops.mm.l2_flush(g, false); | ||
3559 | 3601 | ||
3560 | gk20a_dbg_fn("done"); | 3602 | gk20a_dbg_fn("done"); |
3561 | return 0; | 3603 | return 0; |
@@ -3591,6 +3633,7 @@ void gk20a_init_mm(struct gpu_ops *gops) | |||
3591 | gops->mm.fb_flush = gk20a_mm_fb_flush; | 3633 | gops->mm.fb_flush = gk20a_mm_fb_flush; |
3592 | gops->mm.l2_invalidate = gk20a_mm_l2_invalidate; | 3634 | gops->mm.l2_invalidate = gk20a_mm_l2_invalidate; |
3593 | gops->mm.l2_flush = gk20a_mm_l2_flush; | 3635 | gops->mm.l2_flush = gk20a_mm_l2_flush; |
3636 | gops->mm.cbc_clean = gk20a_mm_cbc_clean; | ||
3594 | gops->mm.tlb_invalidate = gk20a_mm_tlb_invalidate; | 3637 | gops->mm.tlb_invalidate = gk20a_mm_tlb_invalidate; |
3595 | gops->mm.get_iova_addr = gk20a_mm_iova_addr; | 3638 | gops->mm.get_iova_addr = gk20a_mm_iova_addr; |
3596 | gops->mm.get_physical_addr_bits = gk20a_mm_get_physical_addr_bits; | 3639 | gops->mm.get_physical_addr_bits = gk20a_mm_get_physical_addr_bits; |