diff options
author | Dave Airlie <airlied@redhat.com> | 2016-12-06 11:01:33 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-12-06 11:01:33 +1000 |
commit | 17f1dfd01ca105f0d3609225c9e7079c7df483b2 (patch) | |
tree | a30e2b896d41f0bb5206825d07ffd49cff97ed64 /drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |
parent | 770ac20413ce654f6e4efaaf24e954ebb907fc3b (diff) | |
parent | e7b8243d3e0ace9f5130c3b5c3c52a50039a7501 (diff) |
Merge branch 'drm-next-4.10' of git://people.freedesktop.org/~agd5f/linux into drm-next
- lots of code cleanup
- lots of bug fixes
- expose rpm based fan info via hwmon
- lots of clock and powergating fixes
- SI register header cleanup and conversion to common format used by newer asics
* 'drm-next-4.10' of git://people.freedesktop.org/~agd5f/linux: (54 commits)
drm/amdgpu: drop is_display_hung from display funcs
drm/amdgpu/uvd: reduce IB parsing overhead on UVD5+ (v2)
drm/amdgpu/uvd: consolidate code for fetching addr from ctx
drm/amdgpu: Disable DPM in virtualization
drm/amdgpu: use AMDGPU_GEM_CREATE_VRAM_CLEARED for VM PD/PTs (v2)
drm/amdgpu: improve AMDGPU_GEM_CREATE_VRAM_CLEARED handling (v2)
drm/amdgpu: fix error handling in amdgpu_bo_create_restricted
drm/amdgpu: fix amdgpu_fill_buffer (v2)
drm/amdgpu: remove amdgpu_irq_get_delayed
amdgpu: Wrap dev_err() calls on vm faults with printk_ratelimit()
amdgpu: Use dev_err() over vanilla printk() in vm_decode_fault()
drm/amd/amdgpu: port of DCE v6 to new headers (v3)
drm/amdgpu: cleanup unused iterator members for sdma v2.4
drm/amdgpu: cleanup unused iterator members for sdma v3
drm/amdgpu:impl vgt_flush for VI(V5)
drm/amdgpu: enable uvd mgcg for Fiji.
drm/amdgpu: refine cz uvd clock gate logic.
drm/amdgpu: change log level to KERN_INFO in ci_dpm.c
drm/amdgpu: always un-gate UVD REGS path.
drm/amdgpu/sdma: fix typo in packet setup
...
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1821c05484d0..8f18b8ed2b3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1382,28 +1382,40 @@ error_free: } int amdgpu_fill_buffer(struct amdgpu_bo *bo, - uint32_t src_data, - struct reservation_object *resv, - struct dma_fence **fence) + uint32_t src_data, + struct reservation_object *resv, + 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) @@ -1411,28 +1423,43 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, if (resv) { r = amdgpu_sync_resv(adev, &job->sync, resv, - AMDGPU_FENCE_OWNER_UNDEFINED); + AMDGPU_FENCE_OWNER_UNDEFINED); if (r) { DRM_ERROR("sync failed (%d).\n", r); goto error_free; } } - dst_offset = bo->tbo.mem.start << PAGE_SHIFT; - for (i = 0; i < num_loops; i++) { - uint32_t cur_size_in_bytes = min(byte_count, max_bytes); + num_pages = bo->tbo.num_pages; + mm_node = bo->tbo.mem.mm_node; - amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, - dst_offset, cur_size_in_bytes); + while (num_pages) { + uint32_t byte_count = mm_node->size << PAGE_SHIFT; + uint64_t dst_addr; - dst_offset += cur_size_in_bytes; - byte_count -= cur_size_in_bytes; + 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_addr, 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, - AMDGPU_FENCE_OWNER_UNDEFINED, fence); + AMDGPU_FENCE_OWNER_UNDEFINED, fence); if (r) goto error_free; |