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

Commit 4ad9c1c7 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/radeon: only save UVD bo when we have open handles



Otherwise just reinitialize from scratch on resume,
and so make it more likely to succeed.

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 6fab3feb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -6980,7 +6980,7 @@ int cik_uvd_resume(struct radeon_device *rdev)

	/* programm the VCPU memory controller bits 0-27 */
	addr = rdev->uvd.gpu_addr >> 3;
	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
	WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
	WREG32(UVD_VCPU_CACHE_SIZE0, size);

+1 −1
Original line number Diff line number Diff line
@@ -1468,7 +1468,6 @@ struct radeon_uvd {
	void			*cpu_addr;
	uint64_t		gpu_addr;
	void			*saved_bo;
	unsigned		fw_size;
	atomic_t		handles[RADEON_MAX_UVD_HANDLES];
	struct drm_file		*filp[RADEON_MAX_UVD_HANDLES];
	struct delayed_work	idle_work;
@@ -2066,6 +2065,7 @@ struct radeon_device {
	const struct firmware *mec_fw;	/* CIK MEC firmware */
	const struct firmware *sdma_fw;	/* CIK SDMA firmware */
	const struct firmware *smc_fw;	/* SMC firmware */
	const struct firmware *uvd_fw;	/* UVD firmware */
	struct r600_blit r600_blit;
	struct r600_vram_scratch vram_scratch;
	int msi_enabled; /* msi enabled */
+1 −1
Original line number Diff line number Diff line
@@ -782,7 +782,7 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring)

		} else {
			/* put fence directly behind firmware */
			index = ALIGN(rdev->uvd.fw_size, 8);
			index = ALIGN(rdev->uvd_fw->size, 8);
			rdev->fence_drv[ring].cpu_addr = rdev->uvd.cpu_addr + index;
			rdev->fence_drv[ring].gpu_addr = rdev->uvd.gpu_addr + index;
		}
+33 −13
Original line number Diff line number Diff line
@@ -56,7 +56,6 @@ static void radeon_uvd_idle_work_handler(struct work_struct *work);

int radeon_uvd_init(struct radeon_device *rdev)
{
	const struct firmware *fw;
	unsigned long bo_size;
	const char *fw_name;
	int i, r;
@@ -105,14 +104,14 @@ int radeon_uvd_init(struct radeon_device *rdev)
		return -EINVAL;
	}

	r = request_firmware(&fw, fw_name, rdev->dev);
	r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
	if (r) {
		dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
			fw_name);
		return r;
	}

	bo_size = RADEON_GPU_PAGE_ALIGN(fw->size + 8) +
	bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
		  RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE;
	r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
			     RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->uvd.vcpu_bo);
@@ -145,12 +144,6 @@ int radeon_uvd_init(struct radeon_device *rdev)

	radeon_bo_unreserve(rdev->uvd.vcpu_bo);

	rdev->uvd.fw_size = fw->size;
	memset(rdev->uvd.cpu_addr, 0, bo_size);
	memcpy(rdev->uvd.cpu_addr, fw->data, fw->size);

	release_firmware(fw);

	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
		atomic_set(&rdev->uvd.handles[i], 0);
		rdev->uvd.filp[i] = NULL;
@@ -174,33 +167,60 @@ void radeon_uvd_fini(struct radeon_device *rdev)
	}

	radeon_bo_unref(&rdev->uvd.vcpu_bo);

	release_firmware(rdev->uvd_fw);
}

int radeon_uvd_suspend(struct radeon_device *rdev)
{
	unsigned size;
	void *ptr;
	int i;

	if (rdev->uvd.vcpu_bo == NULL)
		return 0;

	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
		if (atomic_read(&rdev->uvd.handles[i]))
			break;

	if (i == RADEON_MAX_UVD_HANDLES)
		return 0;

	size = radeon_bo_size(rdev->uvd.vcpu_bo);
	size -= rdev->uvd_fw->size;

	ptr = rdev->uvd.cpu_addr;
	ptr += rdev->uvd_fw->size;

	rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
	memcpy(rdev->uvd.saved_bo, rdev->uvd.cpu_addr, size);
	memcpy(rdev->uvd.saved_bo, ptr, size);

	return 0;
}

int radeon_uvd_resume(struct radeon_device *rdev)
{
	unsigned size;
	void *ptr;

	if (rdev->uvd.vcpu_bo == NULL)
		return -EINVAL;

	memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);

	size = radeon_bo_size(rdev->uvd.vcpu_bo);
	size -= rdev->uvd_fw->size;

	ptr = rdev->uvd.cpu_addr;
	ptr += rdev->uvd_fw->size;

	if (rdev->uvd.saved_bo != NULL) {
		unsigned size = radeon_bo_size(rdev->uvd.vcpu_bo);
		memcpy(rdev->uvd.cpu_addr, rdev->uvd.saved_bo, size);
		memcpy(ptr, rdev->uvd.saved_bo, size);
		kfree(rdev->uvd.saved_bo);
		rdev->uvd.saved_bo = NULL;
	}
	} else
		memset(ptr, 0, size);

	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -813,7 +813,7 @@ int rv770_uvd_resume(struct radeon_device *rdev)

	/* programm the VCPU memory controller bits 0-27 */
	addr = rdev->uvd.gpu_addr >> 3;
	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd.fw_size + 4) >> 3;
	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
	WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
	WREG32(UVD_VCPU_CACHE_SIZE0, size);