Commit 7bdc53f9 authored by Yong Zhao's avatar Yong Zhao Committed by Alex Deucher
Browse files

drm/amdgpu: Fix a bug in amdgpu_fill_buffer()



When max_bytes is not 8 bytes aligned and bo size is larger than
max_bytes, the last 8 bytes in a ttm node may be left unchanged.
For example, on pre SDMA 4.0, max_bytes = 0x1fffff, and the bo size
is 0x200000, the problem will happen.

In order to fix the problem, we separately store the max nums of
PTEs/PDEs a single operation can set in amdgpu_vm_pte_funcs
structure, rather than inferring it from bytes limit of SDMA
constant fill, i.e. fill_max_bytes.

Together with the fix, we replace the hard code value "10" in
amdgpu_vm_bo_update_mapping() with the corresponding values from
structure amdgpu_vm_pte_funcs.

Signed-off-by: default avatarYong Zhao <yong.zhao@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent dfe5c2b7
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -302,6 +302,13 @@ struct amdgpu_vm_pte_funcs {
	void (*write_pte)(struct amdgpu_ib *ib, uint64_t pe,
			  uint64_t value, unsigned count,
			  uint32_t incr);

	/* maximum nums of PTEs/PDEs in a single operation */
	uint32_t	set_max_nums_pte_pde;

	/* number of dw to reserve per operation */
	unsigned	set_pte_pde_num_dw;

	/* for linear pte/pde updates without addr mapping */
	void (*set_pte_pde)(struct amdgpu_ib *ib,
			    uint64_t pe,
+4 −4
Original line number Diff line number Diff line
@@ -1527,8 +1527,8 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
		       struct dma_fence **fence)
{
	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
	/* max_bytes applies to SDMA_OP_PTEPDE as well as SDMA_OP_CONST_FILL*/
	uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
	uint32_t max_bytes = 8 *
			adev->vm_manager.vm_pte_funcs->set_max_nums_pte_pde;
	struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;

	struct drm_mm_node *mm_node;
@@ -1560,8 +1560,8 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
		++mm_node;
	}

	/* 10 double words for each SDMA_OP_PTEPDE cmd */
	num_dw = num_loops * 10;
	/* num of dwords for each SDMA_OP_PTEPDE cmd */
	num_dw = num_loops * adev->vm_manager.vm_pte_funcs->set_pte_pde_num_dw;

	/* for IB padding */
	num_dw += 64;
+3 −2
Original line number Diff line number Diff line
@@ -1606,10 +1606,11 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,

	} else {
		/* set page commands needed */
		ndw += ncmds * 10;
		ndw += ncmds * adev->vm_manager.vm_pte_funcs->set_pte_pde_num_dw;

		/* extra commands for begin/end fragments */
		ndw += 2 * 10 * adev->vm_manager.fragment_size;
		ndw += 2 * adev->vm_manager.vm_pte_funcs->set_pte_pde_num_dw
				* adev->vm_manager.fragment_size;

		params.func = amdgpu_vm_do_set_ptes;
	}
+3 −0
Original line number Diff line number Diff line
@@ -1389,6 +1389,9 @@ static void cik_sdma_set_buffer_funcs(struct amdgpu_device *adev)
static const struct amdgpu_vm_pte_funcs cik_sdma_vm_pte_funcs = {
	.copy_pte = cik_sdma_vm_copy_pte,
	.write_pte = cik_sdma_vm_write_pte,

	.set_max_nums_pte_pde = 0x1fffff >> 3,
	.set_pte_pde_num_dw = 10,
	.set_pte_pde = cik_sdma_vm_set_pte_pde,
};

+3 −0
Original line number Diff line number Diff line
@@ -1326,6 +1326,9 @@ static void sdma_v2_4_set_buffer_funcs(struct amdgpu_device *adev)
static const struct amdgpu_vm_pte_funcs sdma_v2_4_vm_pte_funcs = {
	.copy_pte = sdma_v2_4_vm_copy_pte,
	.write_pte = sdma_v2_4_vm_write_pte,

	.set_max_nums_pte_pde = 0x1fffff >> 3,
	.set_pte_pde_num_dw = 10,
	.set_pte_pde = sdma_v2_4_vm_set_pte_pde,
};

Loading