Merge branch 'linux-4.12' of git://github.com/skeggsb/linux into drm-next
[sfrench/cifs-2.6.git] / drivers / gpu / drm / ttm / ttm_bo.c
index 17478f38dea35b933ce95bb8e2d52874aed277e3..e44626a2e6980bd390888119cb284e52214f644e 100644 (file)
@@ -982,7 +982,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
        }
 
        if (!type_found) {
-               printk(KERN_ERR TTM_PFX "No compatible memory type found.\n");
+               pr_err(TTM_PFX "No compatible memory type found\n");
                return -EINVAL;
        }
 
@@ -1020,37 +1020,44 @@ out_unlock:
        return ret;
 }
 
-bool ttm_bo_mem_compat(struct ttm_placement *placement,
-                      struct ttm_mem_reg *mem,
-                      uint32_t *new_flags)
+static bool ttm_bo_places_compat(const struct ttm_place *places,
+                                unsigned num_placement,
+                                struct ttm_mem_reg *mem,
+                                uint32_t *new_flags)
 {
-       int i;
+       unsigned i;
 
-       for (i = 0; i < placement->num_placement; i++) {
-               const struct ttm_place *heap = &placement->placement[i];
-               if (mem->mm_node &&
-                   (mem->start < heap->fpfn ||
+       for (i = 0; i < num_placement; i++) {
+               const struct ttm_place *heap = &places[i];
+
+               if (mem->mm_node && (mem->start < heap->fpfn ||
                     (heap->lpfn != 0 && (mem->start + mem->num_pages) > heap->lpfn)))
                        continue;
 
                *new_flags = heap->flags;
                if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
-                   (*new_flags & mem->placement & TTM_PL_MASK_MEM))
+                   (*new_flags & mem->placement & TTM_PL_MASK_MEM) &&
+                   (!(*new_flags & TTM_PL_FLAG_CONTIGUOUS) ||
+                    (mem->placement & TTM_PL_FLAG_CONTIGUOUS)))
                        return true;
        }
+       return false;
+}
 
-       for (i = 0; i < placement->num_busy_placement; i++) {
-               const struct ttm_place *heap = &placement->busy_placement[i];
-               if (mem->mm_node &&
-                   (mem->start < heap->fpfn ||
-                    (heap->lpfn != 0 && (mem->start + mem->num_pages) > heap->lpfn)))
-                       continue;
+bool ttm_bo_mem_compat(struct ttm_placement *placement,
+                      struct ttm_mem_reg *mem,
+                      uint32_t *new_flags)
+{
+       if (ttm_bo_places_compat(placement->placement, placement->num_placement,
+                                mem, new_flags))
+               return true;
 
-               *new_flags = heap->flags;
-               if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
-                   (*new_flags & mem->placement & TTM_PL_MASK_MEM))
-                       return true;
-       }
+       if ((placement->busy_placement != placement->placement ||
+            placement->num_busy_placement > placement->num_placement) &&
+           ttm_bo_places_compat(placement->busy_placement,
+                                placement->num_busy_placement,
+                                mem, new_flags))
+               return true;
 
        return false;
 }
@@ -1093,18 +1100,18 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
 }
 EXPORT_SYMBOL(ttm_bo_validate);
 
-int ttm_bo_init(struct ttm_bo_device *bdev,
-               struct ttm_buffer_object *bo,
-               unsigned long size,
-               enum ttm_bo_type type,
-               struct ttm_placement *placement,
-               uint32_t page_alignment,
-               bool interruptible,
-               struct file *persistent_swap_storage,
-               size_t acc_size,
-               struct sg_table *sg,
-               struct reservation_object *resv,
-               void (*destroy) (struct ttm_buffer_object *))
+int ttm_bo_init_reserved(struct ttm_bo_device *bdev,
+                        struct ttm_buffer_object *bo,
+                        unsigned long size,
+                        enum ttm_bo_type type,
+                        struct ttm_placement *placement,
+                        uint32_t page_alignment,
+                        bool interruptible,
+                        struct file *persistent_swap_storage,
+                        size_t acc_size,
+                        struct sg_table *sg,
+                        struct reservation_object *resv,
+                        void (*destroy) (struct ttm_buffer_object *))
 {
        int ret = 0;
        unsigned long num_pages;
@@ -1188,20 +1195,51 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
        if (likely(!ret))
                ret = ttm_bo_validate(bo, placement, interruptible, false);
 
-       if (!resv) {
-               ttm_bo_unreserve(bo);
+       if (unlikely(ret)) {
+               if (!resv)
+                       ttm_bo_unreserve(bo);
+
+               ttm_bo_unref(&bo);
+               return ret;
+       }
 
-       } else if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
+       if (resv && !(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {
                spin_lock(&bo->glob->lru_lock);
                ttm_bo_add_to_lru(bo);
                spin_unlock(&bo->glob->lru_lock);
        }
 
-       if (unlikely(ret))
-               ttm_bo_unref(&bo);
-
        return ret;
 }
+EXPORT_SYMBOL(ttm_bo_init_reserved);
+
+int ttm_bo_init(struct ttm_bo_device *bdev,
+               struct ttm_buffer_object *bo,
+               unsigned long size,
+               enum ttm_bo_type type,
+               struct ttm_placement *placement,
+               uint32_t page_alignment,
+               bool interruptible,
+               struct file *persistent_swap_storage,
+               size_t acc_size,
+               struct sg_table *sg,
+               struct reservation_object *resv,
+               void (*destroy) (struct ttm_buffer_object *))
+{
+       int ret;
+
+       ret = ttm_bo_init_reserved(bdev, bo, size, type, placement,
+                                  page_alignment, interruptible,
+                                  persistent_swap_storage, acc_size,
+                                  sg, resv, destroy);
+       if (ret)
+               return ret;
+
+       if (!resv)
+               ttm_bo_unreserve(bo);
+
+       return 0;
+}
 EXPORT_SYMBOL(ttm_bo_init);
 
 size_t ttm_bo_acc_size(struct ttm_bo_device *bdev,