Skip to contentSkip to conversation

drm/amd/amdgpu: fix UVD mc offsets

PATCH Superseded Piotr Redlewski 1 participant 2 messages Nov 10, 2017 1 message not in the archive

Subsystems (2)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 drm/amd/amdgpu: fix UVD mc offsets

When UVD bo is created, its size is based on the information from firmware header (ucode_size_bytes). The same value should be be used when programming UVD mc controller offsets, otherwise it can happen that (mmUVD_VCPU_CACHE_OFFSET2 + mmUVD_VCPU_CACHE_SIZE2) will point AMDGPU_GPU_PAGE_SIZE bytes after the UVD bo end.

Second issue is that when programming the mmUVD_VCPU_CACHE_SIZE0 register, AMDGPU_UVD_FIRMWARE_OFFSET should be taken into account. If it isn't, (mmUVD_VCPU_CACHE_OFFSET2 + mmUVD_VCPU_CACHE_SIZE2) will always point AMDGPU_UVD_FIRMWARE_OFFSET bytes after the UVD bo end.

v2: move firmware size calculation into macro definition

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 4 ++++
 drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c   | 2 +-
 drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c   | 2 +-
 drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c   | 2 +-
 drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c   | 2 +-
 5 files changed, 8 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h +4 -0
index 3553b92bf69a..b459d0bbd454 100644
@@ -31,6 +31,10 @@
 #define AMDGPU_UVD_SESSION_SIZE		(50*1024)
 #define AMDGPU_UVD_FIRMWARE_OFFSET	256
 
+#define AMDGPU_UVD_FIRMWARE_SIZE(adev)    \
+	(le32_to_cpu(((const struct common_firmware_header *)(adev)->uvd.fw->data)->ucode_size_bytes) + \
+	 8 - AMDGPU_UVD_FIRMWARE_OFFSET)
+
 struct amdgpu_uvd {
 	struct amdgpu_bo	*vcpu_bo;
 	void			*cpu_addr;
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +1 -1
index 15771a53038e..b13ae34be1c2 100644
@@ -563,7 +563,7 @@ static void uvd_v4_2_mc_resume(struct amdgpu_device *adev)
 
 	/* programm the VCPU memory controller bits 0-27 */
 	addr = (adev->uvd.gpu_addr + AMDGPU_UVD_FIRMWARE_OFFSET) >> 3;
-	size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4) >> 3;
+	size = AMDGPU_UVD_FIRMWARE_SIZE(adev) >> 3;
 	WREG32(mmUVD_VCPU_CACHE_OFFSET0, addr);
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +1 -1
index 3b29aaba783a..a4b0f1d842b7 100644
@@ -258,7 +258,7 @@ static void uvd_v5_0_mc_resume(struct amdgpu_device *adev)
 			upper_32_bits(adev->uvd.gpu_addr));
 
 	offset = AMDGPU_UVD_FIRMWARE_OFFSET;
-	size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
+	size = AMDGPU_UVD_FIRMWARE_SIZE(adev);
 	WREG32(mmUVD_VCPU_CACHE_OFFSET0, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +1 -1
index 0c01825a8b9e..0e8b887cf03e 100644
@@ -603,7 +603,7 @@ static void uvd_v6_0_mc_resume(struct amdgpu_device *adev)
 			upper_32_bits(adev->uvd.gpu_addr));
 
 	offset = AMDGPU_UVD_FIRMWARE_OFFSET;
-	size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
+	size = AMDGPU_UVD_FIRMWARE_SIZE(adev);
 	WREG32(mmUVD_VCPU_CACHE_OFFSET0, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +1 -1
index 7b77339feb1a..6d4470626d25 100644
@@ -616,7 +616,7 @@ static int uvd_v7_0_resume(void *handle)
  */
 static void uvd_v7_0_mc_resume(struct amdgpu_device *adev)
 {
-	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
+	uint32_t size = AMDGPU_UVD_FIRMWARE_SIZE(adev);
 	uint32_t offset;
 
 	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
Signature · 6 lines
2.15.0

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

A message that is not in the archive (sent off-list or not yet received): 20171110142649.4565-1-predlewski-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

#2 lore raw

Apperently I didn't test this patch enough - UVD boots, vdpauinfo reports correctly, but actual video playback performance is severly impacted. Version 3 of this patch is on the way.

Regards,
Piotr

Quoted 96 lines · Piotr Redlewski

When UVD bo is created, its size is based on the information from firmware header (ucode_size_bytes). The same value should be be used when programming UVD mc controller offsets, otherwise it can happen that (mmUVD_VCPU_CACHE_OFFSET2 + mmUVD_VCPU_CACHE_SIZE2) will point AMDGPU_GPU_PAGE_SIZE bytes after the UVD bo end.

Second issue is that when programming the mmUVD_VCPU_CACHE_SIZE0 register, AMDGPU_UVD_FIRMWARE_OFFSET should be taken into account. If it isn't, (mmUVD_VCPU_CACHE_OFFSET2 + mmUVD_VCPU_CACHE_SIZE2) will always point AMDGPU_UVD_FIRMWARE_OFFSET bytes after the UVD bo end.

v2: move firmware size calculation into macro definition

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 4 ++++
 drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c   | 2 +-
 drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c   | 2 +-
 drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c   | 2 +-
 drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c   | 2 +-
 5 files changed, 8 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h +4 -0
index 3553b92bf69a..b459d0bbd454 100644
@@ -31,6 +31,10 @@
 #define AMDGPU_UVD_SESSION_SIZE		(50*1024)
 #define AMDGPU_UVD_FIRMWARE_OFFSET	256
 
+#define AMDGPU_UVD_FIRMWARE_SIZE(adev)    \
+	(le32_to_cpu(((const struct common_firmware_header *)(adev)->uvd.fw->data)->ucode_size_bytes) + \
+	 8 - AMDGPU_UVD_FIRMWARE_OFFSET)
+
 struct amdgpu_uvd {
 	struct amdgpu_bo	*vcpu_bo;
 	void			*cpu_addr;
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +1 -1
index 15771a53038e..b13ae34be1c2 100644
@@ -563,7 +563,7 @@ static void uvd_v4_2_mc_resume(struct amdgpu_device *adev)
 
 	/* programm the VCPU memory controller bits 0-27 */
 	addr = (adev->uvd.gpu_addr + AMDGPU_UVD_FIRMWARE_OFFSET) >> 3;
-	size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4) >> 3;
+	size = AMDGPU_UVD_FIRMWARE_SIZE(adev) >> 3;
 	WREG32(mmUVD_VCPU_CACHE_OFFSET0, addr);
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +1 -1
index 3b29aaba783a..a4b0f1d842b7 100644
@@ -258,7 +258,7 @@ static void uvd_v5_0_mc_resume(struct amdgpu_device *adev)
 			upper_32_bits(adev->uvd.gpu_addr));
 
 	offset = AMDGPU_UVD_FIRMWARE_OFFSET;
-	size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
+	size = AMDGPU_UVD_FIRMWARE_SIZE(adev);
 	WREG32(mmUVD_VCPU_CACHE_OFFSET0, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +1 -1
index 0c01825a8b9e..0e8b887cf03e 100644
@@ -603,7 +603,7 @@ static void uvd_v6_0_mc_resume(struct amdgpu_device *adev)
 			upper_32_bits(adev->uvd.gpu_addr));
 
 	offset = AMDGPU_UVD_FIRMWARE_OFFSET;
-	size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
+	size = AMDGPU_UVD_FIRMWARE_SIZE(adev);
 	WREG32(mmUVD_VCPU_CACHE_OFFSET0, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +1 -1
index 7b77339feb1a..6d4470626d25 100644
@@ -616,7 +616,7 @@ static int uvd_v7_0_resume(void *handle)
  */
 static void uvd_v7_0_mc_resume(struct amdgpu_device *adev)
 {
-	uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
+	uint32_t size = AMDGPU_UVD_FIRMWARE_SIZE(adev);
 	uint32_t offset;
 
 	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
Signature · 6 lines
2.15.0

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx