diff options
author | Christian König <christian.koenig@amd.com> | 2016-11-17 06:06:38 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-11-23 15:08:44 -0500 |
commit | f29224a6197dc71a7f3c557f41ae56c58192c345 (patch) | |
tree | 488feb44c7e16a065ca1c355a74642c6bb036091 /drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |
parent | 3b1c9036a678e917c2df6ed12cb96681b7dd92b4 (diff) |
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: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
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: | |||
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | int amdgpu_fill_buffer(struct amdgpu_bo *bo, | 1384 | int amdgpu_fill_buffer(struct amdgpu_bo *bo, |
1385 | uint32_t src_data, | 1385 | uint32_t src_data, |
1386 | struct reservation_object *resv, | 1386 | struct reservation_object *resv, |
1387 | struct dma_fence **fence) | 1387 | struct dma_fence **fence) |
1388 | { | 1388 | { |
1389 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); | 1389 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); |
1390 | struct amdgpu_job *job; | 1390 | uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes; |
1391 | struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; | 1391 | struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; |
1392 | 1392 | ||
1393 | uint32_t max_bytes, byte_count; | 1393 | struct drm_mm_node *mm_node; |
1394 | uint64_t dst_offset; | 1394 | unsigned long num_pages; |
1395 | unsigned int num_loops, num_dw; | 1395 | unsigned int num_loops, num_dw; |
1396 | unsigned int i; | 1396 | |
1397 | struct amdgpu_job *job; | ||
1397 | int r; | 1398 | int r; |
1398 | 1399 | ||
1399 | byte_count = bo->tbo.num_pages << PAGE_SHIFT; | 1400 | if (!ring->ready) { |
1400 | max_bytes = adev->mman.buffer_funcs->fill_max_bytes; | 1401 | DRM_ERROR("Trying to clear memory with ring turned off.\n"); |
1401 | num_loops = DIV_ROUND_UP(byte_count, max_bytes); | 1402 | return -EINVAL; |
1403 | } | ||
1404 | |||
1405 | num_pages = bo->tbo.num_pages; | ||
1406 | mm_node = bo->tbo.mem.mm_node; | ||
1407 | num_loops = 0; | ||
1408 | while (num_pages) { | ||
1409 | uint32_t byte_count = mm_node->size << PAGE_SHIFT; | ||
1410 | |||
1411 | num_loops += DIV_ROUND_UP(byte_count, max_bytes); | ||
1412 | num_pages -= mm_node->size; | ||
1413 | ++mm_node; | ||
1414 | } | ||
1402 | num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw; | 1415 | num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw; |
1403 | 1416 | ||
1404 | /* for IB padding */ | 1417 | /* for IB padding */ |
1405 | while (num_dw & 0x7) | 1418 | num_dw += 64; |
1406 | num_dw++; | ||
1407 | 1419 | ||
1408 | r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job); | 1420 | r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job); |
1409 | if (r) | 1421 | if (r) |
@@ -1411,28 +1423,43 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, | |||
1411 | 1423 | ||
1412 | if (resv) { | 1424 | if (resv) { |
1413 | r = amdgpu_sync_resv(adev, &job->sync, resv, | 1425 | r = amdgpu_sync_resv(adev, &job->sync, resv, |
1414 | AMDGPU_FENCE_OWNER_UNDEFINED); | 1426 | AMDGPU_FENCE_OWNER_UNDEFINED); |
1415 | if (r) { | 1427 | if (r) { |
1416 | DRM_ERROR("sync failed (%d).\n", r); | 1428 | DRM_ERROR("sync failed (%d).\n", r); |
1417 | goto error_free; | 1429 | goto error_free; |
1418 | } | 1430 | } |
1419 | } | 1431 | } |
1420 | 1432 | ||
1421 | dst_offset = bo->tbo.mem.start << PAGE_SHIFT; | 1433 | num_pages = bo->tbo.num_pages; |
1422 | for (i = 0; i < num_loops; i++) { | 1434 | mm_node = bo->tbo.mem.mm_node; |
1423 | uint32_t cur_size_in_bytes = min(byte_count, max_bytes); | ||
1424 | 1435 | ||
1425 | amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, | 1436 | while (num_pages) { |
1426 | dst_offset, cur_size_in_bytes); | 1437 | uint32_t byte_count = mm_node->size << PAGE_SHIFT; |
1438 | uint64_t dst_addr; | ||
1427 | 1439 | ||
1428 | dst_offset += cur_size_in_bytes; | 1440 | r = amdgpu_mm_node_addr(&bo->tbo, mm_node, |
1429 | byte_count -= cur_size_in_bytes; | 1441 | &bo->tbo.mem, &dst_addr); |
1442 | if (r) | ||
1443 | return r; | ||
1444 | |||
1445 | while (byte_count) { | ||
1446 | uint32_t cur_size_in_bytes = min(byte_count, max_bytes); | ||
1447 | |||
1448 | amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, | ||
1449 | dst_addr, cur_size_in_bytes); | ||
1450 | |||
1451 | dst_addr += cur_size_in_bytes; | ||
1452 | byte_count -= cur_size_in_bytes; | ||
1453 | } | ||
1454 | |||
1455 | num_pages -= mm_node->size; | ||
1456 | ++mm_node; | ||
1430 | } | 1457 | } |
1431 | 1458 | ||
1432 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); | 1459 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); |
1433 | WARN_ON(job->ibs[0].length_dw > num_dw); | 1460 | WARN_ON(job->ibs[0].length_dw > num_dw); |
1434 | r = amdgpu_job_submit(job, ring, &adev->mman.entity, | 1461 | r = amdgpu_job_submit(job, ring, &adev->mman.entity, |
1435 | AMDGPU_FENCE_OWNER_UNDEFINED, fence); | 1462 | AMDGPU_FENCE_OWNER_UNDEFINED, fence); |
1436 | if (r) | 1463 | if (r) |
1437 | goto error_free; | 1464 | goto error_free; |
1438 | 1465 | ||