Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d594e46a authored by Jerome Glisse's avatar Jerome Glisse Committed by Dave Airlie
Browse files

drm/radeon/kms: simplify memory controller setup V2



Get rid of _location and use _start/_end also simplify the
computation of vram_start|end & gtt_start|end. For R1XX-R2XX
we place VRAM at the same address of PCI aperture, those GPU
shouldn't have much memory and seems to behave better when
setup that way. For R3XX and newer we place VRAM at 0. For
R6XX-R7XX AGP we place VRAM before or after AGP aperture this
might limit to limit the VRAM size but it's very unlikely.
For IGP we don't change the VRAM placement.

Tested on (compiz,quake3,suspend/resume):
PCI/PCIE:RV280,R420,RV515,RV570,RV610,RV710
AGP:RV100,RV280,R420,RV350,RV620(RPB*),RV730
IGP:RS480(RPB*),RS690,RS780(RPB*),RS880

RPB: resume previously broken

V2 correct commit message to reflect more accurately the bug
and move VRAM placement to 0 for most of the GPU to avoid
limiting VRAM.

Signed-off-by: default avatarJerome Glisse <jglisse@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 44ca7478
Loading
Loading
Loading
Loading
+11 −40
Original line number Diff line number Diff line
@@ -439,7 +439,6 @@ int evergreen_mc_init(struct radeon_device *rdev)
	fixed20_12 a;
	u32 tmp;
	int chansize, numchan;
	int r;

	/* Get VRAM informations */
	rdev->mc.vram_is_ddr = true;
@@ -475,48 +474,12 @@ int evergreen_mc_init(struct radeon_device *rdev)
	/* size in MB on evergreen */
	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;
	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024;

	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
	/* FIXME remove this once we support unmappable VRAM */
	if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
		rdev->mc.mc_vram_size = rdev->mc.aper_size;

	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
		rdev->mc.real_vram_size = rdev->mc.aper_size;

	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r)
			return r;
		/* gtt_size is setup by radeon_agp_init */
		rdev->mc.gtt_location = rdev->mc.agp_base;
		tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size;
		/* Try to put vram before or after AGP because we
		 * we want SYSTEM_APERTURE to cover both VRAM and
		 * AGP so that GPU can catch out of VRAM/AGP access
		 */
		if (rdev->mc.gtt_location > rdev->mc.mc_vram_size) {
			/* Enought place before */
			rdev->mc.vram_location = rdev->mc.gtt_location -
							rdev->mc.mc_vram_size;
		} else if (tmp > rdev->mc.mc_vram_size) {
			/* Enought place after */
			rdev->mc.vram_location = rdev->mc.gtt_location +
							rdev->mc.gtt_size;
		} else {
			/* Try to setup VRAM then AGP might not
			 * not work on some card
			 */
			rdev->mc.vram_location = 0x00000000UL;
			rdev->mc.gtt_location = rdev->mc.mc_vram_size;
	}
	} else {
		rdev->mc.vram_location = 0x00000000UL;
		rdev->mc.gtt_location = rdev->mc.mc_vram_size;
		rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
	}
	rdev->mc.vram_start = rdev->mc.vram_location;
	rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
	rdev->mc.gtt_start = rdev->mc.gtt_location;
	rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
	r600_vram_gtt_location(rdev, &rdev->mc);
	/* FIXME: we should enforce default clock in case GPU is not in
	 * default setup
	 */
@@ -525,6 +488,7 @@ int evergreen_mc_init(struct radeon_device *rdev)
	rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
	return 0;
}

int evergreen_gpu_reset(struct radeon_device *rdev)
{
	/* FIXME: implement for evergreen */
@@ -726,6 +690,13 @@ int evergreen_init(struct radeon_device *rdev)
	r = radeon_fence_driver_init(rdev);
	if (r)
		return r;
	/* initialize AGP */
	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r)
			radeon_agp_disable(rdev);
	}
	/* initialize memory controller */
	r = evergreen_mc_init(rdev);
	if (r)
		return r;
+32 −61
Original line number Diff line number Diff line
@@ -202,9 +202,8 @@ int r100_pci_gart_enable(struct radeon_device *rdev)
	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
	WREG32(RADEON_AIC_CNTL, tmp);
	/* set address range for PCI address translate */
	WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location);
	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
	WREG32(RADEON_AIC_HI_ADDR, tmp);
	WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_start);
	WREG32(RADEON_AIC_HI_ADDR, rdev->mc.gtt_end);
	/* set PCI GART page-table base address */
	WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr);
	tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN;
@@ -1957,17 +1956,17 @@ static u32 r100_get_accessible_vram(struct radeon_device *rdev)
void r100_vram_init_sizes(struct radeon_device *rdev)
{
	u64 config_aper_size;
	u32 accessible;

	/* work out accessible VRAM */
	rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev);
	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
	config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);

	if (rdev->flags & RADEON_IS_IGP) {
		uint32_t tom;
		/* read NB_TOM to get the amount of ram stolen for the GPU */
		tom = RREG32(RADEON_NB_TOM);
		rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
		/* for IGPs we need to keep VRAM where it was put by the BIOS */
		rdev->mc.vram_location = (tom & 0xffff) << 16;
		WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
		rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
	} else {
@@ -1979,31 +1978,20 @@ void r100_vram_init_sizes(struct radeon_device *rdev)
			rdev->mc.real_vram_size = 8192 * 1024;
			WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
		}
		/* let driver place VRAM */
		rdev->mc.vram_location = 0xFFFFFFFFUL;
		/* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 
		  * Novell bug 204882 + along with lots of ubuntu ones */
		 * Novell bug 204882 + along with lots of ubuntu ones
		 */
		if (config_aper_size > rdev->mc.real_vram_size)
			rdev->mc.mc_vram_size = config_aper_size;
		else
			rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
	}

	/* work out accessible VRAM */
	accessible = r100_get_accessible_vram(rdev);

	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);

	if (accessible > rdev->mc.aper_size)
		accessible = rdev->mc.aper_size;

	if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
	/* FIXME remove this once we support unmappable VRAM */
	if (rdev->mc.mc_vram_size > rdev->mc.aper_size) {
		rdev->mc.mc_vram_size = rdev->mc.aper_size;

	if (rdev->mc.real_vram_size > rdev->mc.aper_size)
		rdev->mc.real_vram_size = rdev->mc.aper_size;
	}
}

void r100_vga_set_state(struct radeon_device *rdev, bool state)
{
@@ -2019,11 +2007,18 @@ void r100_vga_set_state(struct radeon_device *rdev, bool state)
	WREG32(RADEON_CONFIG_CNTL, temp);
}

void r100_vram_info(struct radeon_device *rdev)
void r100_mc_init(struct radeon_device *rdev)
{
	r100_vram_get_type(rdev);
	u64 base;

	r100_vram_get_type(rdev);
	r100_vram_init_sizes(rdev);
	base = rdev->mc.aper_base;
	if (rdev->flags & RADEON_IS_IGP)
		base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
	radeon_vram_location(rdev, &rdev->mc, base);
	if (!(rdev->flags & RADEON_IS_AGP))
		radeon_gtt_location(rdev, &rdev->mc);
}


@@ -3294,10 +3289,9 @@ void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save)
void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save)
{
	/* Update base address for crtc */
	WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_location);
	WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_start);
	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
		WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR,
				rdev->mc.vram_location);
		WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, rdev->mc.vram_start);
	}
	/* Restore CRTC registers */
	WREG8(R_0003C2_GENMO_WT, save->GENMO_WT);
@@ -3458,32 +3452,6 @@ void r100_fini(struct radeon_device *rdev)
	rdev->bios = NULL;
}

int r100_mc_init(struct radeon_device *rdev)
{
	int r;
	u32 tmp;

	/* Setup GPU memory space */
	rdev->mc.vram_location = 0xFFFFFFFFUL;
	rdev->mc.gtt_location = 0xFFFFFFFFUL;
	if (rdev->flags & RADEON_IS_IGP) {
		tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM));
		rdev->mc.vram_location = tmp << 16;
	}
	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r) {
			radeon_agp_disable(rdev);
		} else {
			rdev->mc.gtt_location = rdev->mc.agp_base;
		}
	}
	r = radeon_mc_setup(rdev);
	if (r)
		return r;
	return 0;
}

int r100_init(struct radeon_device *rdev)
{
	int r;
@@ -3526,12 +3494,15 @@ int r100_init(struct radeon_device *rdev)
	radeon_get_clock_info(rdev->ddev);
	/* Initialize power management */
	radeon_pm_init(rdev);
	/* Get vram informations */
	r100_vram_info(rdev);
	/* Initialize memory controller (also test AGP) */
	r = r100_mc_init(rdev);
	if (r)
		return r;
	/* initialize AGP */
	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r) {
			radeon_agp_disable(rdev);
		}
	}
	/* initialize VRAM */
	r100_mc_init(rdev);
	/* Fence driver */
	r = radeon_fence_driver_init(rdev);
	if (r)
+15 −12
Original line number Diff line number Diff line
@@ -121,15 +121,15 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
	/* discard memory request outside of configured range */
	tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location);
	tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - RADEON_GPU_PAGE_SIZE;
	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start);
	tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK;
	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp);
	WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
	WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
	table_addr = rdev->gart.table_addr;
	WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr);
	/* FIXME: setup default page */
	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_location);
	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start);
	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
	/* Clear error */
	WREG32_PCIE(0x18, 0);
@@ -459,13 +459,12 @@ int r300_gpu_reset(struct radeon_device *rdev)
/*
 * r300,r350,rv350,rv380 VRAM info
 */
void r300_vram_info(struct radeon_device *rdev)
void r300_mc_init(struct radeon_device *rdev)
{
	uint32_t tmp;

	/* DDR for all card after R300 & IGP */
	rdev->mc.vram_is_ddr = true;

	tmp = RREG32(RADEON_MEM_CNTL);
	tmp &= R300_MEM_NUM_CHANNELS_MASK;
	switch (tmp) {
@@ -474,8 +473,9 @@ void r300_vram_info(struct radeon_device *rdev)
	case 2: rdev->mc.vram_width = 256; break;
	default:  rdev->mc.vram_width = 128; break;
	}

	r100_vram_init_sizes(rdev);
	if (!(rdev->flags & RADEON_IS_AGP))
		radeon_gtt_location(rdev, &rdev->mc);
}

void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
@@ -1377,12 +1377,15 @@ int r300_init(struct radeon_device *rdev)
	radeon_get_clock_info(rdev->ddev);
	/* Initialize power management */
	radeon_pm_init(rdev);
	/* Get vram informations */
	r300_vram_info(rdev);
	/* Initialize memory controller (also test AGP) */
	r = r420_mc_init(rdev);
	if (r)
		return r;
	/* initialize AGP */
	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r) {
			radeon_agp_disable(rdev);
		}
	}
	/* initialize memory controller */
	r300_mc_init(rdev);
	/* Fence driver */
	r = radeon_fence_driver_init(rdev);
	if (r)
+8 −28
Original line number Diff line number Diff line
@@ -40,28 +40,6 @@ static void r420_set_reg_safe(struct radeon_device *rdev)
	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm);
}

int r420_mc_init(struct radeon_device *rdev)
{
	int r;

	/* Setup GPU memory space */
	rdev->mc.vram_location = 0xFFFFFFFFUL;
	rdev->mc.gtt_location = 0xFFFFFFFFUL;
	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r) {
			radeon_agp_disable(rdev);
		} else {
			rdev->mc.gtt_location = rdev->mc.agp_base;
		}
	}
	r = radeon_mc_setup(rdev);
	if (r) {
		return r;
	}
	return 0;
}

void r420_pipes_init(struct radeon_device *rdev)
{
	unsigned tmp;
@@ -349,13 +327,15 @@ int r420_init(struct radeon_device *rdev)
	radeon_get_clock_info(rdev->ddev);
	/* Initialize power management */
	radeon_pm_init(rdev);
	/* Get vram informations */
	r300_vram_info(rdev);
	/* Initialize memory controller (also test AGP) */
	r = r420_mc_init(rdev);
	/* initialize AGP */
	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r) {
		return r;
			radeon_agp_disable(rdev);
		}
	}
	/* initialize memory controller */
	r300_mc_init(rdev);
	r420_debugfs(rdev);
	/* Fence driver */
	r = radeon_fence_driver_init(rdev);
+13 −8
Original line number Diff line number Diff line
@@ -119,13 +119,15 @@ static void r520_vram_get_type(struct radeon_device *rdev)
		rdev->mc.vram_width *= 2;
}

void r520_vram_info(struct radeon_device *rdev)
void r520_mc_init(struct radeon_device *rdev)
{
	fixed20_12 a;

	r520_vram_get_type(rdev);

	r100_vram_init_sizes(rdev);
	radeon_vram_location(rdev, &rdev->mc, 0);
	if (!(rdev->flags & RADEON_IS_AGP))
		radeon_gtt_location(rdev, &rdev->mc);
	/* FIXME: we should enforce default clock in case GPU is not in
	 * default setup
	 */
@@ -267,12 +269,15 @@ int r520_init(struct radeon_device *rdev)
	radeon_get_clock_info(rdev->ddev);
	/* Initialize power management */
	radeon_pm_init(rdev);
	/* Get vram informations */
	r520_vram_info(rdev);
	/* Initialize memory controller (also test AGP) */
	r = r420_mc_init(rdev);
	if (r)
		return r;
	/* initialize AGP */
	if (rdev->flags & RADEON_IS_AGP) {
		r = radeon_agp_init(rdev);
		if (r) {
			radeon_agp_disable(rdev);
		}
	}
	/* initialize memory controller */
	r520_mc_init(rdev);
	rv515_debugfs(rdev);
	/* Fence driver */
	r = radeon_fence_driver_init(rdev);
Loading