Patch 1 is an error path fix and depends on Jakob's previous fix for this function. Patch 2 fixes the code that decides whether a buffer object move to another memory type is necessary
All error paths will want to keep the mm node, so handle this at the function exit. This fixes an ioremap failure error path. Also add some comments to make the function a bit easier to understand.
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com Reviewed-by: Jakob Bornecrantz jakob@vmware.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/ttm/ttm_bo_util.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 8369e35..4834c46 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -343,21 +343,25 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (ret) goto out;
+ /* + * Single TTM move. NOP. + */ if (old_iomap == NULL && new_iomap == NULL) goto out2; + + /* + * Move nonexistent data. NOP. + */ if (old_iomap == NULL && ttm == NULL) goto out2;
- /* TTM might be null for moves within the same region. + /* + * TTM might be null for moves within the same region. */ if (ttm && ttm->state == tt_unpopulated) { ret = ttm->bdev->driver->ttm_tt_populate(ttm); - if (ret) { - /* if we fail here don't nuke the mm node - * as the bo still owns it */ - old_copy.mm_node = NULL; + if (ret) goto out1; - } }
add = 0; @@ -383,11 +387,8 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, prot); } else ret = ttm_copy_io_page(new_iomap, old_iomap, page); - if (ret) { - /* failing here, means keep old copy as-is */ - old_copy.mm_node = NULL; + if (ret) goto out1; - } } mb(); out2: @@ -405,7 +406,12 @@ out1: ttm_mem_reg_iounmap(bdev, old_mem, new_iomap); out: ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); - ttm_bo_mem_put(bo, &old_copy); + + /* + * On error, keep the mm node! + */ + if (!ret) + ttm_bo_mem_put(bo, &old_copy); return ret; } EXPORT_SYMBOL(ttm_bo_move_memcpy);
Also check the busy placements before deciding to move a buffer object. Failing to do this may result in a completely unneccessary move within a single memory type.
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com Reviewed-by: Jakob Bornecrantz jakob@vmware.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/ttm/ttm_bo.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index f1a857e..7298053 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -986,24 +986,32 @@ out_unlock: return ret; }
-static int ttm_bo_mem_compat(struct ttm_placement *placement, - struct ttm_mem_reg *mem) +static bool ttm_bo_mem_compat(struct ttm_placement *placement, + struct ttm_mem_reg *mem, + uint32_t *new_flags) { int i;
if (mem->mm_node && placement->lpfn != 0 && (mem->start < placement->fpfn || mem->start + mem->num_pages > placement->lpfn)) - return -1; + return false;
for (i = 0; i < placement->num_placement; i++) { - if ((placement->placement[i] & mem->placement & - TTM_PL_MASK_CACHING) && - (placement->placement[i] & mem->placement & - TTM_PL_MASK_MEM)) - return i; + *new_flags = placement->placement[i]; + if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) && + (*new_flags & mem->placement & TTM_PL_MASK_MEM)) + return true; + } + + for (i = 0; i < placement->num_busy_placement; i++) { + *new_flags = placement->busy_placement[i]; + if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) && + (*new_flags & mem->placement & TTM_PL_MASK_MEM)) + return true; } - return -1; + + return false; }
int ttm_bo_validate(struct ttm_buffer_object *bo, @@ -1012,6 +1020,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, bool no_wait_gpu) { int ret; + uint32_t new_flags;
lockdep_assert_held(&bo->resv->lock.base); /* Check that range is valid */ @@ -1022,8 +1031,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, /* * Check whether we need to move buffer. */ - ret = ttm_bo_mem_compat(placement, &bo->mem); - if (ret < 0) { + if (!ttm_bo_mem_compat(placement, &bo->mem, &new_flags)) { ret = ttm_bo_move_buffer(bo, placement, interruptible, no_wait_gpu); if (ret) @@ -1033,7 +1041,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, * Use the access and other non-mapping-related flag bits from * the compatible memory placement flags to the active flags */ - ttm_flag_masked(&bo->mem.placement, placement->placement[ret], + ttm_flag_masked(&bo->mem.placement, new_flags, ~TTM_PL_MASK_MEMTYPE); } /*
dri-devel@lists.freedesktop.org