[PATCH] drm/amdgpu: Restrict GART size to half of the GPU pages

Russell Currey ruscur at russell.cc
Fri Nov 11 01:02:55 UTC 2016


Using the kernel zone memory size to determine the size of the GART table
introduced a regression on systems with a large amount of system memory.
On a system with 512GB RAM, driver initialisation would fail as there are
more GART entries than there are GPU pages to map to them. With 256GB RAM,
the table would barely fit, but no other allocations are possible.

Restrict the size of the GART such that it will occupy at maximum half
of the pages available to the GPU.

Fixes: a693e050 ("drm/amdgpu: use the kernel zone memory size as the max
		  remote memory in amdgpu")
Signed-off-by: Russell Currey <ruscur at russell.cc>
---
I don't know much about GPUs, restricting this to less than half might
make more sense.
---
 drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 21 +++++++++++++++------
 drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 21 +++++++++++++++------
 drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 21 +++++++++++++++------
 3 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
index b13c8aa..f8bbb17 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -264,6 +264,7 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
 
 	u32 tmp;
 	int chansize, numchan;
+	u64 max_gtt_entries;
 
 	tmp = RREG32(MC_ARB_RAMCFG);
 	if (tmp & CHANSIZE_OVERRIDE) {
@@ -313,13 +314,21 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
 	adev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
 	adev->mc.visible_vram_size = adev->mc.aper_size;
 
-	/* unless the user had overridden it, set the gart
-	 * size equal to the 1024 or vram, whichever is larger.
-	 */
-	if (amdgpu_gart_size == -1)
-		adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
-	else
+	/* unless the user had overridden it, set the GART size proportional
+	 * to system memory, but no more than half of the GPU pages. */
+	if (amdgpu_gart_size == -1) {
+		/* a table entry is 8 GPU pages */
+		max_gtt_entries = amdgpu_ttm_get_gtt_mem_size(adev) /
+			(AMDGPU_GPU_PAGE_SIZE / 8);
+
+		if (max_gtt_entries > adev->mc.visible_vram_size / 2)
+			adev->mc.gtt_size = (adev->mc.visible_vram_size / 2) *
+				AMDGPU_GPU_PAGE_SIZE / 8;
+		else
+			adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+	} else {
 		adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
+	}
 
 	gmc_v6_0_vram_gtt_location(adev, &adev->mc);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index aa0c4b9..276a662 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -329,6 +329,7 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
 {
 	u32 tmp;
 	int chansize, numchan;
+	u64 max_gtt_entries;
 
 	/* Get VRAM informations */
 	tmp = RREG32(mmMC_ARB_RAMCFG);
@@ -381,13 +382,21 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
 	if (adev->mc.visible_vram_size > adev->mc.real_vram_size)
 		adev->mc.visible_vram_size = adev->mc.real_vram_size;
 
-	/* unless the user had overridden it, set the gart
-	 * size equal to the 1024 or vram, whichever is larger.
-	 */
-	if (amdgpu_gart_size == -1)
-		adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
-	else
+	/* unless the user had overridden it, set the GART size proportional
+	 * to system memory, but no more than half of the GPU pages. */
+	if (amdgpu_gart_size == -1) {
+		/* a table entry is 8 GPU pages */
+		max_gtt_entries = amdgpu_ttm_get_gtt_mem_size(adev) /
+			(AMDGPU_GPU_PAGE_SIZE / 8);
+
+		if (max_gtt_entries > adev->mc.visible_vram_size / 2)
+			adev->mc.gtt_size = (adev->mc.visible_vram_size / 2) *
+				AMDGPU_GPU_PAGE_SIZE / 8;
+		else
+			adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+	} else {
 		adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
+	}
 
 	gmc_v7_0_vram_gtt_location(adev, &adev->mc);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index a16b220..460100a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -416,6 +416,7 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
 {
 	u32 tmp;
 	int chansize, numchan;
+	u64 max_gtt_entries;
 
 	/* Get VRAM informations */
 	tmp = RREG32(mmMC_ARB_RAMCFG);
@@ -468,13 +469,21 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
 	if (adev->mc.visible_vram_size > adev->mc.real_vram_size)
 		adev->mc.visible_vram_size = adev->mc.real_vram_size;
 
-	/* unless the user had overridden it, set the gart
-	 * size equal to the 1024 or vram, whichever is larger.
-	 */
-	if (amdgpu_gart_size == -1)
-		adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
-	else
+	/* unless the user had overridden it, set the GART size proportional
+	 * to system memory, but no more than half of the GPU pages. */
+	if (amdgpu_gart_size == -1) {
+		/* a table entry is 8 GPU pages */
+		max_gtt_entries = amdgpu_ttm_get_gtt_mem_size(adev) /
+			(AMDGPU_GPU_PAGE_SIZE / 8);
+
+		if (max_gtt_entries > adev->mc.visible_vram_size / 2)
+			adev->mc.gtt_size = (adev->mc.visible_vram_size / 2) *
+				AMDGPU_GPU_PAGE_SIZE / 8;
+		else
+			adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+	} else {
 		adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
+	}
 
 	gmc_v8_0_vram_gtt_location(adev, &adev->mc);
 
-- 
2.10.2



More information about the dri-devel mailing list