@@ -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;
@@ -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);
@@ -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);
@@ -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;
@@ -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;