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;
