drm/ttm: Fix memory type compatibility check
authorThomas Hellstrom <thellstrom@vmware.com>
Mon, 28 Oct 2013 09:02:19 +0000 (02:02 -0700)
committerBen Hutchings <ben@decadent.org.uk>
Fri, 3 Jan 2014 04:33:17 +0000 (04:33 +0000)
commit 59c8e66378fb78adbcd05f0d09783dde6fef282b upstream.

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>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
drivers/gpu/drm/ttm/ttm_bo.c

index 0d27bff..22a89cd 100644 (file)
@@ -1101,24 +1101,32 @@ out_unlock:
        return ret;
 }
 
        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))
 {
        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++) {
 
        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,
 }
 
 int ttm_bo_validate(struct ttm_buffer_object *bo,
@@ -1127,6 +1135,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
                        bool no_wait_gpu)
 {
        int ret;
                        bool no_wait_gpu)
 {
        int ret;
+       uint32_t new_flags;
 
        BUG_ON(!atomic_read(&bo->reserved));
        /* Check that range is valid */
 
        BUG_ON(!atomic_read(&bo->reserved));
        /* Check that range is valid */
@@ -1137,8 +1146,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
        /*
         * Check whether we need to move buffer.
         */
        /*
         * 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_reserve, no_wait_gpu);
                if (ret)
                        return ret;
                ret = ttm_bo_move_buffer(bo, placement, interruptible, no_wait_reserve, no_wait_gpu);
                if (ret)
                        return ret;
@@ -1147,7 +1155,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
                 */
                 * 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);
        }
        /*
                                ~TTM_PL_MASK_MEMTYPE);
        }
        /*