diff mbox

[2/3] drm/radeon: try to keep current vram GPU address

Message ID 1343421145-14257-3-git-send-email-j.glisse@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jerome Glisse July 27, 2012, 8:32 p.m. UTC
From: Jerome Glisse <jglisse@redhat.com>

It seems we can't move the VRAM GPU address without disabling CRTC.
Thus if we want to support flicker free boot from UEFI to X, we need
to keep the VRAM GPU address UEFI programmed. So far on all UEFI
checked this address was something sane.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
---
 drivers/gpu/drm/radeon/evergreen.c   |   10 +++-
 drivers/gpu/drm/radeon/r600.c        |  105 ++++++++++++++++++++--------------
 drivers/gpu/drm/radeon/radeon_asic.h |    3 +-
 drivers/gpu/drm/radeon/rv770.c       |   44 ++------------
 drivers/gpu/drm/radeon/si.c          |   59 ++-----------------
 5 files changed, 80 insertions(+), 141 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index db85262..c56fa0a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2166,6 +2166,7 @@  static void evergreen_gpu_init(struct radeon_device *rdev)
 
 int evergreen_mc_init(struct radeon_device *rdev)
 {
+	u64 fb_base;
 	u32 tmp;
 	int chansize, numchan;
 
@@ -2217,7 +2218,14 @@  int evergreen_mc_init(struct radeon_device *rdev)
 		rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
 	}
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	r700_vram_gtt_location(rdev, &rdev->mc);
+	fb_base = RREG32(MC_VM_FB_LOCATION) & 0xffff;
+	fb_base <<= 24;
+	if ((rdev->family == CHIP_PALM) ||
+	    (rdev->family == CHIP_SUMO) ||
+	    (rdev->family == CHIP_SUMO2)) {
+		fb_base |= ((RREG32(MC_FUS_VM_FB_OFFSET) >> 20) & 0xf) << 20;
+	}
+	r600_vram_gtt_location(rdev, &rdev->mc, fb_base, 1ULL << 36ULL);
 	radeon_update_bandwidth_info(rdev);
 
 	return 0;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 637280f..87f47b6 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1097,69 +1097,84 @@  static void r600_mc_program(struct radeon_device *rdev)
  * r600_vram_gtt_location - try to find VRAM & GTT location
  * @rdev: radeon device structure holding all necessary informations
  * @mc: memory controller structure holding memory informations
+ * @fb_base: current start address of VRAM
+ * @mc_max: maximum address supported by the MC controler (32bits on
+ *          r6xx/r7xx, 36bits on evergreen, 40bits cayman and newer)
  *
- * Function will place try to place VRAM at same place as in CPU (PCI)
- * address space as some GPU seems to have issue when we reprogram at
- * different address space.
+ * Function will place try to not move VRAM start address. But if VRAM
+ * conflict with AGP then we move VRAM as we have more issue with moving
+ * AGP than with moving VRAM start address.
  *
- * If there is not enough space to fit the unvisible VRAM after the
- * aperture then we limit the VRAM size to the aperture.
+ * We will also move VRAM if current address + VRAM size overflow mc_max.
  *
- * If we are using AGP then place VRAM adjacent to AGP aperture are we need
- * them to be in one from GPU point of view so that we can program GPU to
- * catch access outside them (weird GPU policy see ??).
- *
- * This function will never fails, worst case are limiting VRAM or GTT.
+ * GTT is place before VRAM if there is enough room there, or after VRAM.
+ * GTT is shrink to maximum size we can find, we shrink GTT instead of
+ * VRAM as VRAM is better than GTT :)
  *
  * Note: GTT start, end, size should be initialized before calling this
  * function on AGP platform.
  */
-static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
+void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc,
+				uint64_t fb, uint64_t mc_max)
 {
-	u64 size_bf, size_af;
+	/* try to keep same vram address */
+	mc->vram_start = fb;
 
-	if (mc->mc_vram_size > 0xE0000000) {
-		/* leave room for at least 512M GTT */
-		dev_warn(rdev->dev, "limiting VRAM\n");
-		mc->real_vram_size = 0xE0000000;
-		mc->mc_vram_size = 0xE0000000;
+	/* make sure there is enough room for vram */
+	if ((mc->vram_start + mc->mc_vram_size) > mc_max) {
+		/* moving fb, show me the GPU on which this happen free beer reward */
+		mc->vram_start = mc_max - mc->mc_vram_size;
 	}
+	mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
+
 	if (rdev->flags & RADEON_IS_AGP) {
-		size_bf = mc->gtt_start;
-		size_af = 0xFFFFFFFF - mc->gtt_end;
-		if (size_bf > size_af) {
-			if (mc->mc_vram_size > size_bf) {
-				dev_warn(rdev->dev, "limiting VRAM\n");
-				mc->real_vram_size = size_bf;
-				mc->mc_vram_size = size_bf;
-			}
-			mc->vram_start = mc->gtt_start - mc->mc_vram_size;
-		} else {
-			if (mc->mc_vram_size > size_af) {
-				dev_warn(rdev->dev, "limiting VRAM\n");
-				mc->real_vram_size = size_af;
-				mc->mc_vram_size = size_af;
+		if ((fb + mc->mc_vram_size) >= mc->gtt_start && fb < mc->gtt_end) {
+			/* current configuration overlap */
+			if (mc->gtt_start > mc->mc_vram_size) {
+				mc->vram_start = 0;
+			} else {
+				mc->vram_start = mc->gtt_end + 1;
+				if ((mc->vram_start + mc->mc_vram_size) > mc_max) {
+					/* show me the GPU on which this happen free beer reward */
+					mc->real_vram_size = mc_max - mc->vram_start;
+					mc->mc_vram_size = mc->real_vram_size;
+					dev_warn(rdev->dev, "limiting VRAM 0x%016llx\n", mc->mc_vram_size);
+				}
 			}
-			mc->vram_start = mc->gtt_end + 1;
+			mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
 		}
-		mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-		dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
-				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;
+		mc->gtt_start = 0;
+		if (mc->gtt_size > mc->vram_start) {
+			mc->gtt_start = mc->vram_end + 1;
+			if ((mc->gtt_start + mc->gtt_size) > mc_max) {
+				/* limit gtt */
+				u64 size_bf, size_af;
+
+				size_bf = mc->vram_start;
+				size_af = mc_max - mc->gtt_start;
+				if (size_bf > size_af) {
+					mc->gtt_start = 0;
+					mc->gtt_size = size_bf;
+				} else {
+					mc->gtt_size = size_af;
+				}
+				dev_warn(rdev->dev, "limiting GTT to 0x%016llx\n", mc->gtt_size);
+			}
 		}
-		radeon_vram_location(rdev, &rdev->mc, base);
-		rdev->mc.gtt_base_align = 0;
-		radeon_gtt_location(rdev, mc);
+		mc->gtt_end = mc->gtt_start + mc->gtt_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);
+	dev_info(rdev->dev, "GTT: %lluM 0x%016llX - 0x%016llX\n",
+			mc->gtt_size >> 20, mc->gtt_start, mc->gtt_end);
 }
 
 int r600_mc_init(struct radeon_device *rdev)
 {
+	u64 fb_base;
 	u32 tmp;
 	int chansize, numchan;
 
@@ -1197,7 +1212,9 @@  int r600_mc_init(struct radeon_device *rdev)
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	r600_vram_gtt_location(rdev, &rdev->mc);
+	fb_base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
+	fb_base <<= 24ULL;
+	r600_vram_gtt_location(rdev, &rdev->mc, fb_base, 1ULL << 32ULL);
 
 	if (rdev->flags & RADEON_IS_IGP) {
 		rs690_pm_info(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 0d445e7..accd2ca 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -368,6 +368,8 @@  void r600_kms_blit_copy(struct radeon_device *rdev,
 			unsigned num_gpu_pages,
 			struct radeon_sa_bo *vb);
 int r600_mc_wait_for_idle(struct radeon_device *rdev);
+void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc,
+				uint64_t fb, uint64_t mc_max);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -378,7 +380,6 @@  int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
 void rv770_pm_misc(struct radeon_device *rdev);
 u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
-void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 void r700_cp_stop(struct radeon_device *rdev);
 void r700_cp_fini(struct radeon_device *rdev);
 
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index ca8ffec..a5b915d 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -800,47 +800,9 @@  static void rv770_gpu_init(struct radeon_device *rdev)
 	WREG32(VC_ENHANCE, 0);
 }
 
-void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
-{
-	u64 size_bf, size_af;
-
-	if (mc->mc_vram_size > 0xE0000000) {
-		/* leave room for at least 512M GTT */
-		dev_warn(rdev->dev, "limiting VRAM\n");
-		mc->real_vram_size = 0xE0000000;
-		mc->mc_vram_size = 0xE0000000;
-	}
-	if (rdev->flags & RADEON_IS_AGP) {
-		size_bf = mc->gtt_start;
-		size_af = 0xFFFFFFFF - mc->gtt_end;
-		if (size_bf > size_af) {
-			if (mc->mc_vram_size > size_bf) {
-				dev_warn(rdev->dev, "limiting VRAM\n");
-				mc->real_vram_size = size_bf;
-				mc->mc_vram_size = size_bf;
-			}
-			mc->vram_start = mc->gtt_start - mc->mc_vram_size;
-		} else {
-			if (mc->mc_vram_size > size_af) {
-				dev_warn(rdev->dev, "limiting VRAM\n");
-				mc->real_vram_size = size_af;
-				mc->mc_vram_size = size_af;
-			}
-			mc->vram_start = mc->gtt_end + 1;
-		}
-		mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-		dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
-				mc->mc_vram_size >> 20, mc->vram_start,
-				mc->vram_end, mc->real_vram_size >> 20);
-	} else {
-		radeon_vram_location(rdev, &rdev->mc, 0);
-		rdev->mc.gtt_base_align = 0;
-		radeon_gtt_location(rdev, mc);
-	}
-}
-
 int rv770_mc_init(struct radeon_device *rdev)
 {
+	u64 fb_base;
 	u32 tmp;
 	int chansize, numchan;
 
@@ -878,7 +840,9 @@  int rv770_mc_init(struct radeon_device *rdev)
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	r700_vram_gtt_location(rdev, &rdev->mc);
+	fb_base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
+	fb_base <<= 24ULL;
+	r600_vram_gtt_location(rdev, &rdev->mc, fb_base, 1ULL << 32ULL);
 	radeon_update_bandwidth_info(rdev);
 
 	return 0;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index c053f81..439dd81 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -2229,62 +2229,9 @@  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)
-{
-	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);
-	rdev->mc.gtt_base_align = 0;
-	si_gtt_location(rdev, mc);
-}
-
 static int si_mc_init(struct radeon_device *rdev)
 {
+	u64 fb_base;
 	u32 tmp;
 	int chansize, numchan;
 
@@ -2337,7 +2284,9 @@  static int si_mc_init(struct radeon_device *rdev)
 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
-	si_vram_gtt_location(rdev, &rdev->mc);
+	fb_base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF;
+	fb_base <<= 24ULL;
+	r600_vram_gtt_location(rdev, &rdev->mc, fb_base, 1ULL << 40ULL);
 	radeon_update_bandwidth_info(rdev);
 
 	return 0;