From d99896ad3452ee019dae71b0fc7056da62673273 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 Apr 2013 13:22:17 -0400 Subject: [PATCH] drm/radeon: avoid moving the MC vram location When setting up the memory controller, avoid moving the vram location if possible. This should avoid problems with hangs and corruption at boot especially on UEFI systems due to invalid reads from the display hardware when try and move the location of vram. May fix: https://bugs.freedesktop.org/show_bug.cgi?id=43655 https://bugs.freedesktop.org/show_bug.cgi?id=62976 et al. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen.c | 4 ++- drivers/gpu/drm/radeon/r600.c | 11 +++---- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_device.c | 15 ++++++++- drivers/gpu/drm/radeon/rv770.c | 8 ++++- drivers/gpu/drm/radeon/si.c | 50 ++++--------------------------- 6 files changed, 35 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 305a657..88f76e9 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1425,6 +1425,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s void evergreen_mc_program(struct radeon_device *rdev) { struct evergreen_mc_save save; + u32 mc_vm_fb_location = RREG32(MC_VM_FB_LOCATION); u32 tmp; int i, j; @@ -1477,7 +1478,8 @@ void evergreen_mc_program(struct radeon_device *rdev) } tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); - WREG32(MC_VM_FB_LOCATION, tmp); + if (tmp != mc_vm_fb_location) + WREG32(MC_VM_FB_LOCATION, tmp); WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 0740db3..1edf65f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1049,6 +1049,7 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev) static void r600_mc_program(struct radeon_device *rdev) { struct rv515_mc_save save; + u32 mc_vm_fb_location = RREG32(MC_VM_FB_LOCATION); u32 tmp; int i, j; @@ -1090,7 +1091,8 @@ static void r600_mc_program(struct radeon_device *rdev) WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); - WREG32(MC_VM_FB_LOCATION, tmp); + if (tmp != mc_vm_fb_location) + WREG32(MC_VM_FB_LOCATION, tmp); WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); WREG32(HDP_NONSURFACE_INFO, (2 << 7)); WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); @@ -1166,11 +1168,8 @@ static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc mc->mc_vram_size >> 20, mc->vram_start, mc->vram_end, mc->real_vram_size >> 20); } else { - u64 base = 0; - if (rdev->flags & RADEON_IS_IGP) { - base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; - base <<= 24; - } + u64 base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; radeon_vram_location(rdev, &rdev->mc, base); rdev->mc.gtt_base_align = 0; radeon_gtt_location(rdev, mc); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8263af3..8bd8753 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -517,6 +517,7 @@ struct radeon_mc { bool vram_is_ddr; bool igp_sideport_enabled; u64 gtt_base_align; + u64 mc_mask; }; bool radeon_combios_sideport_present(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 44b8034..62d0ba3 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -359,7 +359,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 uint64_t limit = (uint64_t)radeon_vram_limit << 20; mc->vram_start = base; - if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) { + if (mc->mc_vram_size > (rdev->mc.mc_mask - base + 1)) { dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); mc->real_vram_size = mc->aper_size; mc->mc_vram_size = mc->aper_size; @@ -394,7 +394,7 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) { u64 size_af, size_bf; - size_af = ((0xFFFFFFFF - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; + size_af = ((rdev->mc.mc_mask - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; size_bf = mc->vram_start & ~mc->gtt_base_align; if (size_bf > size_af) { if (mc->gtt_size > size_bf) { @@ -1068,6 +1068,17 @@ int radeon_device_init(struct radeon_device *rdev, radeon_agp_disable(rdev); } + /* Set the internal MC address mask + * This is the max address of the GPU's + * internal address space. + */ + if (rdev->family >= CHIP_CAYMAN) + rdev->mc.mc_mask = 0xffffffffffULL; /* 40 bit MC */ + else if (rdev->family >= CHIP_CEDAR) + rdev->mc.mc_mask = 0xfffffffffULL; /* 36 bit MC */ + else + rdev->mc.mc_mask = 0xffffffffULL; /* 32 bit MC */ + /* set DMA mask + need_dma32 flags. * PCIE - can handle 40-bits. * IGP - can handle 40-bits diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index d63fe1d..4b3dc2e 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -264,6 +264,7 @@ static void rv770_agp_enable(struct radeon_device *rdev) static void rv770_mc_program(struct radeon_device *rdev) { struct rv515_mc_save save; + u32 mc_vm_fb_location = RREG32(MC_VM_FB_LOCATION); u32 tmp; int i, j; @@ -310,7 +311,8 @@ static void rv770_mc_program(struct radeon_device *rdev) WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); - WREG32(MC_VM_FB_LOCATION, tmp); + if (tmp != mc_vm_fb_location) + WREG32(MC_VM_FB_LOCATION, tmp); WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); WREG32(HDP_NONSURFACE_INFO, (2 << 7)); WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); @@ -861,7 +863,9 @@ void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) mc->mc_vram_size >> 20, mc->vram_start, mc->vram_end, mc->real_vram_size >> 20); } else { - radeon_vram_location(rdev, &rdev->mc, 0); + u64 base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; + radeon_vram_location(rdev, &rdev->mc, base); rdev->mc.gtt_base_align = 0; radeon_gtt_location(rdev, mc); } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index bafbe32..a6e0506 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2493,6 +2493,7 @@ bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) static void si_mc_program(struct radeon_device *rdev) { struct evergreen_mc_save save; + u32 mc_vm_fb_location = RREG32(MC_VM_FB_LOCATION); u32 tmp; int i, j; @@ -2521,7 +2522,8 @@ static void si_mc_program(struct radeon_device *rdev) rdev->vram_scratch.gpu_addr >> 12); tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); - WREG32(MC_VM_FB_LOCATION, tmp); + if (tmp != mc_vm_fb_location) + WREG32(MC_VM_FB_LOCATION, tmp); /* XXX double check these! */ WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30)); @@ -2538,58 +2540,20 @@ static void si_mc_program(struct radeon_device *rdev) rv515_vga_render_disable(rdev); } -/* SI MC address space is 40 bits */ -static void si_vram_location(struct radeon_device *rdev, - struct radeon_mc *mc, u64 base) -{ - mc->vram_start = base; - if (mc->mc_vram_size > (0xFFFFFFFFFFULL - base + 1)) { - dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); - mc->real_vram_size = mc->aper_size; - mc->mc_vram_size = mc->aper_size; - } - mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; - dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", - mc->mc_vram_size >> 20, mc->vram_start, - mc->vram_end, mc->real_vram_size >> 20); -} - -static void si_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) -{ - u64 size_af, size_bf; - - size_af = ((0xFFFFFFFFFFULL - mc->vram_end) + mc->gtt_base_align) & ~mc->gtt_base_align; - size_bf = mc->vram_start & ~mc->gtt_base_align; - if (size_bf > size_af) { - if (mc->gtt_size > size_bf) { - dev_warn(rdev->dev, "limiting GTT\n"); - mc->gtt_size = size_bf; - } - mc->gtt_start = (mc->vram_start & ~mc->gtt_base_align) - mc->gtt_size; - } else { - if (mc->gtt_size > size_af) { - dev_warn(rdev->dev, "limiting GTT\n"); - mc->gtt_size = size_af; - } - mc->gtt_start = (mc->vram_end + 1 + mc->gtt_base_align) & ~mc->gtt_base_align; - } - mc->gtt_end = mc->gtt_start + mc->gtt_size - 1; - dev_info(rdev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n", - mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end); -} - static void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) { + u64 base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; + base <<= 24; if (mc->mc_vram_size > 0xFFC0000000ULL) { /* leave room for at least 1024M GTT */ dev_warn(rdev->dev, "limiting VRAM\n"); mc->real_vram_size = 0xFFC0000000ULL; mc->mc_vram_size = 0xFFC0000000ULL; } - si_vram_location(rdev, &rdev->mc, 0); + radeon_vram_location(rdev, &rdev->mc, base); rdev->mc.gtt_base_align = 0; - si_gtt_location(rdev, mc); + radeon_gtt_location(rdev, mc); } static int si_mc_init(struct radeon_device *rdev) -- 1.7.7.5