From 593b26353f1965682db955d0d2af8bc564aabdf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 23 Jan 2014 14:24:15 +0100 Subject: [PATCH 01/10] drm/radeon: fix VMID use tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we allocate a new VMID on nearly every submit. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 2 ++ drivers/gpu/drm/radeon/radeon_gart.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index c5519ca4bbc4a..4a8ac1cd6b4c6 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -867,6 +867,8 @@ struct radeon_vm { struct radeon_fence *fence; /* last flush or NULL if we still need to flush */ struct radeon_fence *last_flush; + /* last use of vmid */ + struct radeon_fence *last_id_use; }; struct radeon_vm_manager { diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 96e440061bdbf..0e9143bd35e33 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -713,7 +713,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, unsigned i; /* check if the id is still valid */ - if (vm->fence && vm->fence == rdev->vm_manager.active[vm->id]) + if (vm->last_id_use && vm->last_id_use == rdev->vm_manager.active[vm->id]) return NULL; /* we definately need to flush */ @@ -769,6 +769,9 @@ void radeon_vm_fence(struct radeon_device *rdev, radeon_fence_unref(&vm->fence); vm->fence = radeon_fence_ref(fence); + + radeon_fence_unref(&vm->last_id_use); + vm->last_id_use = radeon_fence_ref(fence); } /** @@ -1303,6 +1306,8 @@ void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) { vm->id = 0; vm->fence = NULL; + vm->last_flush = NULL; + vm->last_id_use = NULL; mutex_init(&vm->mutex); INIT_LIST_HEAD(&vm->list); INIT_LIST_HEAD(&vm->va); @@ -1341,5 +1346,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) } radeon_fence_unref(&vm->fence); radeon_fence_unref(&vm->last_flush); + radeon_fence_unref(&vm->last_id_use); mutex_unlock(&vm->mutex); } From 31dd8d9347c4bf288572ad1c5513d9b778989cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 23 Jan 2014 14:24:16 +0100 Subject: [PATCH 02/10] drm/radeon: add missing trace point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_gart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 0e9143bd35e33..a8f9b463bf2a4 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -726,6 +726,7 @@ struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, if (fence == NULL) { /* found a free one */ vm->id = i; + trace_radeon_vm_grab_id(vm->id, ring); return NULL; } From 1d7841676676691c205bfcb3d99c5997466a3408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 23 Jan 2014 14:24:17 +0100 Subject: [PATCH 03/10] drm/radeon: add ring to fence trace functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_fence.c | 6 +++--- drivers/gpu/drm/radeon/radeon_trace.h | 21 ++++++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 866744e47cfac..c37cb79a9489a 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -121,7 +121,7 @@ int radeon_fence_emit(struct radeon_device *rdev, (*fence)->seq = ++rdev->fence_drv[ring].sync_seq[ring]; (*fence)->ring = ring; radeon_fence_ring_emit(rdev, ring, *fence); - trace_radeon_fence_emit(rdev->ddev, (*fence)->seq); + trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq); return 0; } @@ -313,7 +313,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq, continue; last_seq[i] = atomic64_read(&rdev->fence_drv[i].last_seq); - trace_radeon_fence_wait_begin(rdev->ddev, target_seq[i]); + trace_radeon_fence_wait_begin(rdev->ddev, i, target_seq[i]); radeon_irq_kms_sw_irq_get(rdev, i); } @@ -332,7 +332,7 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 *target_seq, continue; radeon_irq_kms_sw_irq_put(rdev, i); - trace_radeon_fence_wait_end(rdev->ddev, target_seq[i]); + trace_radeon_fence_wait_end(rdev->ddev, i, target_seq[i]); } if (unlikely(r < 0)) diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h index 0473257d40788..f749f2c3bbdb8 100644 --- a/drivers/gpu/drm/radeon/radeon_trace.h +++ b/drivers/gpu/drm/radeon/radeon_trace.h @@ -106,42 +106,45 @@ TRACE_EVENT(radeon_vm_set_page, DECLARE_EVENT_CLASS(radeon_fence_request, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno), + TP_ARGS(dev, ring, seqno), TP_STRUCT__entry( __field(u32, dev) + __field(int, ring) __field(u32, seqno) ), TP_fast_assign( __entry->dev = dev->primary->index; + __entry->ring = ring; __entry->seqno = seqno; ), - TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno) + TP_printk("dev=%u, ring=%d, seqno=%u", + __entry->dev, __entry->ring, __entry->seqno) ); DEFINE_EVENT(radeon_fence_request, radeon_fence_emit, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno) + TP_ARGS(dev, ring, seqno) ); DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno) + TP_ARGS(dev, ring, seqno) ); DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end, - TP_PROTO(struct drm_device *dev, u32 seqno), + TP_PROTO(struct drm_device *dev, int ring, u32 seqno), - TP_ARGS(dev, seqno) + TP_ARGS(dev, ring, seqno) ); DECLARE_EVENT_CLASS(radeon_semaphore_request, From 9babd35ad72af631547c7ca294bc2e931cc40e58 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 24 Jan 2014 14:59:42 -0500 Subject: [PATCH 04/10] drm/radeon/runpm: don't runtime suspend non-PX cards Prevent runtime suspend of non-PX GPUs. Runtime suspend is not what we want in those cases. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_drv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 1235a78fbba15..ec8c388eec176 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -405,6 +405,9 @@ static int radeon_pmops_runtime_suspend(struct device *dev) if (radeon_runtime_pm == 0) return -EINVAL; + if (radeon_runtime_pm == -1 && !radeon_is_px()) + return -EINVAL; + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; drm_kms_helper_poll_disable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); @@ -427,6 +430,9 @@ static int radeon_pmops_runtime_resume(struct device *dev) if (radeon_runtime_pm == 0) return -EINVAL; + if (radeon_runtime_pm == -1 && !radeon_is_px()) + return -EINVAL; + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; pci_set_power_state(pdev, PCI_D0); From b9ace36f13c6fc46391c9d40edc648eef3a59ab0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Jan 2014 10:59:51 -0500 Subject: [PATCH 05/10] drm/radeon: skip async dma init on r6xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hw is buggy and it's not currently used, but it's currently still initialized by the driver. Skip the init. Skipping init also seems to improve stability with dpm on some r6xx asics. bug: https://bugs.freedesktop.org/show_bug.cgi?id=66963 Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/r600.c | 27 +++++---------------------- drivers/gpu/drm/radeon/radeon_cs.c | 2 +- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 3dce370adc1b7..4d69d1745d541 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2612,6 +2612,11 @@ int r600_cp_resume(struct radeon_device *rdev) ring->ready = false; return r; } + + /* RV7xx+ uses dma for paging */ + if (rdev->family < CHIP_RV770) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } @@ -2895,12 +2900,6 @@ static int r600_startup(struct radeon_device *rdev) return r; } - r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); - if (r) { - dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); - return r; - } - /* Enable IRQ */ if (!rdev->irq.installed) { r = radeon_irq_kms_init(rdev); @@ -2922,12 +2921,6 @@ static int r600_startup(struct radeon_device *rdev) if (r) return r; - ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; - r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, - DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); - if (r) - return r; - r = r600_cp_load_microcode(rdev); if (r) return r; @@ -2935,10 +2928,6 @@ static int r600_startup(struct radeon_device *rdev) if (r) return r; - r = r600_dma_resume(rdev); - if (r) - return r; - r = radeon_ib_pool_init(rdev); if (r) { dev_err(rdev->dev, "IB initialization failed (%d).\n", r); @@ -2997,7 +2986,6 @@ int r600_suspend(struct radeon_device *rdev) radeon_pm_suspend(rdev); r600_audio_fini(rdev); r600_cp_stop(rdev); - r600_dma_stop(rdev); r600_irq_suspend(rdev); radeon_wb_disable(rdev); r600_pcie_gart_disable(rdev); @@ -3077,9 +3065,6 @@ int r600_init(struct radeon_device *rdev) rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); - rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; - r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); - rdev->ih.ring_obj = NULL; r600_ih_ring_init(rdev, 64 * 1024); @@ -3092,7 +3077,6 @@ int r600_init(struct radeon_device *rdev) if (r) { dev_err(rdev->dev, "disabling GPU acceleration\n"); r600_cp_fini(rdev); - r600_dma_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); @@ -3109,7 +3093,6 @@ void r600_fini(struct radeon_device *rdev) radeon_pm_fini(rdev); r600_audio_fini(rdev); r600_cp_fini(rdev); - r600_dma_fini(rdev); r600_irq_fini(rdev); radeon_wb_fini(rdev); radeon_ib_pool_fini(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index a8e3342fd4a9d..dfb5a1db87d4a 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -138,7 +138,7 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority p->ring = R600_RING_TYPE_DMA_INDEX; else p->ring = CAYMAN_RING_TYPE_DMA1_INDEX; - } else if (p->rdev->family >= CHIP_R600) { + } else if (p->rdev->family >= CHIP_RV770) { p->ring = R600_RING_TYPE_DMA_INDEX; } else { return -EINVAL; From 50efa51afddb50a6ab47ee15614fcf180130888c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Jan 2014 11:26:33 -0500 Subject: [PATCH 06/10] drm/radeon: clean up active vram sizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we are not able to properly initialize one of the gpu engines for buffer paging, we limit vram to the size of the cpu visible aperture. We generally either use the gfx or dma engine to do this. Clean up the size limiting code to only adjust the size based on what ring is selected for buffer paging rather than making assumptions about which engine is selected for paging. Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/cik.c | 6 ++++++ drivers/gpu/drm/radeon/cik_sdma.c | 8 ++++++-- drivers/gpu/drm/radeon/ni.c | 6 +++++- drivers/gpu/drm/radeon/ni_dma.c | 8 ++++++-- drivers/gpu/drm/radeon/r600.c | 6 +++--- drivers/gpu/drm/radeon/r600_dma.c | 6 ++++-- drivers/gpu/drm/radeon/rv770.c | 3 ++- drivers/gpu/drm/radeon/si.c | 6 +++++- 8 files changed, 37 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 6ffe824624fb5..e6419ca7cd375 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -3840,6 +3840,8 @@ static void cik_cp_gfx_enable(struct radeon_device *rdev, bool enable) if (enable) WREG32(CP_ME_CNTL, 0); else { + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; } @@ -4038,6 +4040,10 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev) rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; return r; } + + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 9abea87a92133..1ecb3f1070e35 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -250,7 +250,9 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev) u32 rb_cntl, reg_offset; int i; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); for (i = 0; i < 2; i++) { if (i == 0) @@ -381,7 +383,9 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev) } } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 647b1d0fa62c3..ea932ac66fc66 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1390,7 +1390,8 @@ static void cayman_cp_enable(struct radeon_device *rdev, bool enable) if (enable) WREG32(CP_ME_CNTL, 0); else { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; @@ -1663,6 +1664,9 @@ static int cayman_cp_resume(struct radeon_device *rdev) return r; } + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c index 51424ab794327..7cf96b15377fa 100644 --- a/drivers/gpu/drm/radeon/ni_dma.c +++ b/drivers/gpu/drm/radeon/ni_dma.c @@ -157,7 +157,9 @@ void cayman_dma_stop(struct radeon_device *rdev) { u32 rb_cntl; - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); /* dma0 */ rb_cntl = RREG32(DMA_RB_CNTL + DMA0_REGISTER_OFFSET); @@ -259,7 +261,9 @@ int cayman_dma_resume(struct radeon_device *rdev) } } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || + (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 4d69d1745d541..56140b4e5bb2e 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2254,7 +2254,8 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) */ void r600_cp_stop(struct radeon_device *rdev) { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; @@ -2613,8 +2614,7 @@ int r600_cp_resume(struct radeon_device *rdev) return r; } - /* RV7xx+ uses dma for paging */ - if (rdev->family < CHIP_RV770) + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index 3452c8410bd76..b2d4c91e6272e 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -100,7 +100,8 @@ void r600_dma_stop(struct radeon_device *rdev) { u32 rb_cntl = RREG32(DMA_RB_CNTL); - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); rb_cntl &= ~DMA_RB_ENABLE; WREG32(DMA_RB_CNTL, rb_cntl); @@ -187,7 +188,8 @@ int r600_dma_resume(struct radeon_device *rdev) return r; } - radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + if (rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); return 0; } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 18e02889ec7d7..6c772e58c7845 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1071,7 +1071,8 @@ static void rv770_mc_program(struct radeon_device *rdev) */ void r700_cp_stop(struct radeon_device *rdev) { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 07ce58716e44c..e641725ae5438 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -3249,7 +3249,8 @@ static void si_cp_enable(struct radeon_device *rdev, bool enable) if (enable) WREG32(CP_ME_CNTL, 0); else { - radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT)); WREG32(SCRATCH_UMSK, 0); rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; @@ -3510,6 +3511,9 @@ static int si_cp_resume(struct radeon_device *rdev) si_enable_gui_idle_interrupt(rdev, true); + if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) + radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); + return 0; } From e9a321c6b2ac954a7dbf235f419c255a424a1273 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Jan 2014 11:54:44 -0500 Subject: [PATCH 07/10] drm/radeon: fix DAC interrupt handling on DCE5+ DCE5 and newer hardware only has 1 DAC. Use the correct offset. This may fix display problems on certain board configurations. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen.c | 4 ++-- drivers/gpu/drm/radeon/si.c | 2 +- drivers/gpu/drm/radeon/sid.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 4116d02795966..f2b9e21ce4da0 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4348,8 +4348,8 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } - /* only one DAC on DCE6 */ - if (!ASIC_IS_DCE6(rdev)) + /* only one DAC on DCE5 */ + if (!ASIC_IS_DCE5(rdev)) WREG32(DACA_AUTODETECT_INT_CONTROL, 0); WREG32(DACB_AUTODETECT_INT_CONTROL, 0); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index e641725ae5438..09ec4f6c53bb2 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -5682,7 +5682,7 @@ static void si_disable_interrupt_state(struct radeon_device *rdev) } if (!ASIC_IS_NODCE(rdev)) { - WREG32(DACA_AUTODETECT_INT_CONTROL, 0); + WREG32(DAC_AUTODETECT_INT_CONTROL, 0); tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; WREG32(DC_HPD1_INT_CONTROL, tmp); diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index caa3e61a38c25..9239a6d291280 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -822,7 +822,7 @@ # define GRPH_PFLIP_INT_MASK (1 << 0) # define GRPH_PFLIP_INT_TYPE (1 << 8) -#define DACA_AUTODETECT_INT_CONTROL 0x66c8 +#define DAC_AUTODETECT_INT_CONTROL 0x67c8 #define DC_HPD1_INT_STATUS 0x601c #define DC_HPD2_INT_STATUS 0x6028 From ffcda352b569dcf5be5c8a5f57545794acf4adb9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Jan 2014 13:04:56 -0500 Subject: [PATCH 08/10] drm/radeon: set si_notify_smc_display_change properly This is effectively a revert of 4573388c92ee60b4ed72b8d95b73df861189988c. Forcing a display active when there is none causes problems with dpm on some SI boards which results in improperly initialized dpm state and boot failures on some boards. As for the bug commit 4573388c92ee tried to address, one can manually force the state to high for better performance when using the card as a headless compute node until a better fix is developed. bugs: https://bugs.freedesktop.org/show_bug.cgi?id=73788 https://bugs.freedesktop.org/show_bug.cgi?id=69395 Signed-off-by: Alex Deucher cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si_dpm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 36a5da4791ce7..0471501338fbb 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -3590,10 +3590,9 @@ static void si_program_display_gap(struct radeon_device *rdev) /* Setting this to false forces the performance state to low if the crtcs are disabled. * This can be a problem on PowerXpress systems or if you want to use the card - * for offscreen rendering or compute if there are no crtcs enabled. Set it to - * true for now so that performance scales even if the displays are off. + * for offscreen rendering or compute if there are no crtcs enabled. */ - si_notify_smc_display_change(rdev, true /*rdev->pm.dpm.new_active_crtc_count > 0*/); + si_notify_smc_display_change(rdev, rdev->pm.dpm.new_active_crtc_count > 0); } static void si_enable_spread_spectrum(struct radeon_device *rdev, bool enable) From 6802d4bad83f50081b2788698570218aaff8d10e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 27 Jan 2014 18:29:35 -0500 Subject: [PATCH 09/10] drm/radeon/DCE4+: clear bios scratch dpms bit (v2) The BlankCrtc table in some DCE8 boards has some logic shortcuts for the vbios when this bit is set. Clear it for driver use. v2: fix typo Bug: https://bugs.freedesktop.org/show_bug.cgi?id=73420 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_atombios.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index f48bd6dc10cda..30844814c25a3 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -3938,6 +3938,10 @@ void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) /* tell the bios not to handle mode switching */ bios_6_scratch |= ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH; + /* clear the vbios dpms state */ + if (ASIC_IS_DCE4(rdev)) + bios_2_scratch &= ~ATOM_S2_DEVICE_DPMS_STATE; + if (rdev->family >= CHIP_R600) { WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); From 78fe9e545ce6d510b979dc2d8e14096a279fc519 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jan 2014 23:49:37 -0500 Subject: [PATCH 10/10] drm/radeon/dce8: workaround for atom BlankCrtc table Some DCE8 boards have a funky BlankCrtc table that results in a timeout when trying to blank the display. The timeout is harmless (all operations needed from the table are complete), but wastes time and is confusing to users so work around it. bug: https://bugs.freedesktop.org/show_bug.cgi?id=73420 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 4cf678306c9c1..a9338c85630fe 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -209,6 +209,16 @@ static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state) atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } +static const u32 vga_control_regs[6] = +{ + AVIVO_D1VGA_CONTROL, + AVIVO_D2VGA_CONTROL, + EVERGREEN_D3VGA_CONTROL, + EVERGREEN_D4VGA_CONTROL, + EVERGREEN_D5VGA_CONTROL, + EVERGREEN_D6VGA_CONTROL, +}; + static void atombios_blank_crtc(struct drm_crtc *crtc, int state) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); @@ -216,13 +226,23 @@ static void atombios_blank_crtc(struct drm_crtc *crtc, int state) struct radeon_device *rdev = dev->dev_private; int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); BLANK_CRTC_PS_ALLOCATION args; + u32 vga_control = 0; memset(&args, 0, sizeof(args)); + if (ASIC_IS_DCE8(rdev)) { + vga_control = RREG32(vga_control_regs[radeon_crtc->crtc_id]); + WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control | 1); + } + args.ucCRTC = radeon_crtc->crtc_id; args.ucBlanking = state; atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + if (ASIC_IS_DCE8(rdev)) { + WREG32(vga_control_regs[radeon_crtc->crtc_id], vga_control); + } } static void atombios_powergate_crtc(struct drm_crtc *crtc, int state)