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

drm/amdgpu: fix amdgpu_fill_buffer (v2)



The mem start is relative to the domain in the address space, so this
worked only when VRAM was mapped at offset 0.

It also didn't handled multiple drm_mm_nodes for split VRAM.

v2: rebase on dma_fence renaming

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3b1c9036
Loading
Loading
Loading
Loading
+48 −21
Original line number Diff line number Diff line
@@ -1387,23 +1387,35 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
		       struct dma_fence **fence)
{
	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
	struct amdgpu_job *job;
	uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
	struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;

	uint32_t max_bytes, byte_count;
	uint64_t dst_offset;
	struct drm_mm_node *mm_node;
	unsigned long num_pages;
	unsigned int num_loops, num_dw;
	unsigned int i;

	struct amdgpu_job *job;
	int r;

	byte_count = bo->tbo.num_pages << PAGE_SHIFT;
	max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
	num_loops = DIV_ROUND_UP(byte_count, max_bytes);
	if (!ring->ready) {
		DRM_ERROR("Trying to clear memory with ring turned off.\n");
		return -EINVAL;
	}

	num_pages = bo->tbo.num_pages;
	mm_node = bo->tbo.mem.mm_node;
	num_loops = 0;
	while (num_pages) {
		uint32_t byte_count = mm_node->size << PAGE_SHIFT;

		num_loops += DIV_ROUND_UP(byte_count, max_bytes);
		num_pages -= mm_node->size;
		++mm_node;
	}
	num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw;

	/* for IB padding */
	while (num_dw & 0x7)
		num_dw++;
	num_dw += 64;

	r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job);
	if (r)
@@ -1418,17 +1430,32 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
		}
	}

	dst_offset = bo->tbo.mem.start << PAGE_SHIFT;
	for (i = 0; i < num_loops; i++) {
	num_pages = bo->tbo.num_pages;
	mm_node = bo->tbo.mem.mm_node;

	while (num_pages) {
		uint32_t byte_count = mm_node->size << PAGE_SHIFT;
		uint64_t dst_addr;

		r = amdgpu_mm_node_addr(&bo->tbo, mm_node,
					&bo->tbo.mem, &dst_addr);
		if (r)
			return r;

		while (byte_count) {
			uint32_t cur_size_in_bytes = min(byte_count, max_bytes);

			amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data,
				dst_offset, cur_size_in_bytes);
						dst_addr, cur_size_in_bytes);

		dst_offset += cur_size_in_bytes;
			dst_addr += cur_size_in_bytes;
			byte_count -= cur_size_in_bytes;
		}

		num_pages -= mm_node->size;
		++mm_node;
	}

	amdgpu_ring_pad_ib(ring, &job->ibs[0]);
	WARN_ON(job->ibs[0].length_dw > num_dw);
	r = amdgpu_job_submit(job, ring, &adev->mman.entity,