Merge branch 'topic/usb-audio' into for-linus
[pandora-kernel.git] / drivers / gpu / drm / ttm / ttm_bo.c
index c1c407f..c2b0d71 100644 (file)
@@ -43,7 +43,6 @@
 #define TTM_BO_HASH_ORDER 13
 
 static int ttm_bo_setup_vm(struct ttm_buffer_object *bo);
-static void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo);
 static int ttm_bo_swapout(struct ttm_mem_shrink *shrink);
 
 static inline uint32_t ttm_bo_type_flags(unsigned type)
@@ -224,6 +223,9 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
        TTM_ASSERT_LOCKED(&bo->mutex);
        bo->ttm = NULL;
 
+       if (bdev->need_dma32)
+               page_flags |= TTM_PAGE_FLAG_DMA32;
+
        switch (bo->type) {
        case ttm_bo_type_device:
                if (zero_alloc)
@@ -304,6 +306,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
 
        }
 
+       if (bdev->driver->move_notify)
+               bdev->driver->move_notify(bo, mem);
+
        if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
            !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
                ret = ttm_bo_move_ttm(bo, evict, no_wait, mem);
@@ -655,31 +660,52 @@ retry_pre_get:
        return 0;
 }
 
+static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man,
+                                     uint32_t cur_placement,
+                                     uint32_t proposed_placement)
+{
+       uint32_t caching = proposed_placement & TTM_PL_MASK_CACHING;
+       uint32_t result = proposed_placement & ~TTM_PL_MASK_CACHING;
+
+       /**
+        * Keep current caching if possible.
+        */
+
+       if ((cur_placement & caching) != 0)
+               result |= (cur_placement & caching);
+       else if ((man->default_caching & caching) != 0)
+               result |= man->default_caching;
+       else if ((TTM_PL_FLAG_CACHED & caching) != 0)
+               result |= TTM_PL_FLAG_CACHED;
+       else if ((TTM_PL_FLAG_WC & caching) != 0)
+               result |= TTM_PL_FLAG_WC;
+       else if ((TTM_PL_FLAG_UNCACHED & caching) != 0)
+               result |= TTM_PL_FLAG_UNCACHED;
+
+       return result;
+}
+
+
 static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man,
                                 bool disallow_fixed,
                                 uint32_t mem_type,
-                                uint32_t mask, uint32_t *res_mask)
+                                uint32_t proposed_placement,
+                                uint32_t *masked_placement)
 {
        uint32_t cur_flags = ttm_bo_type_flags(mem_type);
 
        if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed)
                return false;
 
-       if ((cur_flags & mask & TTM_PL_MASK_MEM) == 0)
+       if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0)
                return false;
 
-       if ((mask & man->available_caching) == 0)
+       if ((proposed_placement & man->available_caching) == 0)
                return false;
-       if (mask & man->default_caching)
-               cur_flags |= man->default_caching;
-       else if (mask & TTM_PL_FLAG_CACHED)
-               cur_flags |= TTM_PL_FLAG_CACHED;
-       else if (mask & TTM_PL_FLAG_WC)
-               cur_flags |= TTM_PL_FLAG_WC;
-       else
-               cur_flags |= TTM_PL_FLAG_UNCACHED;
 
-       *res_mask = cur_flags;
+       cur_flags |= (proposed_placement & man->available_caching);
+
+       *masked_placement = cur_flags;
        return true;
 }
 
@@ -723,6 +749,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (!type_ok)
                        continue;
 
+               cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
+                                                 cur_flags);
+
                if (mem_type == TTM_PL_SYSTEM)
                        break;
 
@@ -779,6 +808,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                                          proposed_placement, &cur_flags))
                        continue;
 
+               cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
+                                                 cur_flags);
+
                ret = ttm_bo_mem_force_space(bdev, mem, mem_type,
                                             interruptible, no_wait);
 
@@ -1150,13 +1182,14 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
 
 int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type)
 {
-       struct ttm_mem_type_manager *man = &bdev->man[mem_type];
+       struct ttm_mem_type_manager *man;
        int ret = -EINVAL;
 
        if (mem_type >= TTM_NUM_MEM_TYPES) {
                printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", mem_type);
                return ret;
        }
+       man = &bdev->man[mem_type];
 
        if (!man->has_type) {
                printk(KERN_ERR TTM_PFX "Trying to take down uninitialized "
@@ -1305,7 +1338,8 @@ EXPORT_SYMBOL(ttm_bo_device_release);
 
 int ttm_bo_device_init(struct ttm_bo_device *bdev,
                       struct ttm_mem_global *mem_glob,
-                      struct ttm_bo_driver *driver, uint64_t file_page_offset)
+                      struct ttm_bo_driver *driver, uint64_t file_page_offset,
+                      bool need_dma32)
 {
        int ret = -EINVAL;
 
@@ -1342,6 +1376,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,
        INIT_LIST_HEAD(&bdev->ddestroy);
        INIT_LIST_HEAD(&bdev->swap_lru);
        bdev->dev_mapping = NULL;
+       bdev->need_dma32 = need_dma32;
        ttm_mem_init_shrink(&bdev->shrink, ttm_bo_swapout);
        ret = ttm_mem_register_shrink(mem_glob, &bdev->shrink);
        if (unlikely(ret != 0)) {
@@ -1419,6 +1454,7 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
 
        unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1);
 }
+EXPORT_SYMBOL(ttm_bo_unmap_virtual);
 
 static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo)
 {
@@ -1540,6 +1576,10 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
                        driver->sync_obj_unref(&sync_obj);
                        driver->sync_obj_unref(&tmp_obj);
                        spin_lock(&bo->lock);
+               } else {
+                       spin_unlock(&bo->lock);
+                       driver->sync_obj_unref(&sync_obj);
+                       spin_lock(&bo->lock);
                }
        }
        return 0;