Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
[pandora-kernel.git] / drivers / gpu / drm / radeon / radeon_object.c
index 1227747..d5b9373 100644 (file)
@@ -112,9 +112,11 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
 
        radeon_ttm_placement_from_domain(bo, domain);
        /* Kernel allocation are uninterruptible */
+       mutex_lock(&rdev->vram_mutex);
        r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type,
                        &bo->placement, 0, 0, !kernel, NULL, size,
                        &radeon_ttm_bo_destroy);
+       mutex_unlock(&rdev->vram_mutex);
        if (unlikely(r != 0)) {
                if (r != -ERESTARTSYS)
                        dev_err(rdev->dev,
@@ -166,11 +168,15 @@ void radeon_bo_kunmap(struct radeon_bo *bo)
 void radeon_bo_unref(struct radeon_bo **bo)
 {
        struct ttm_buffer_object *tbo;
+       struct radeon_device *rdev;
 
        if ((*bo) == NULL)
                return;
+       rdev = (*bo)->rdev;
        tbo = &((*bo)->tbo);
+       mutex_lock(&rdev->vram_mutex);
        ttm_bo_unref(&tbo);
+       mutex_unlock(&rdev->vram_mutex);
        if (tbo == NULL)
                *bo = NULL;
 }
@@ -192,7 +198,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
        }
        for (i = 0; i < bo->placement.num_placement; i++)
                bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
-       r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+       r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
        if (likely(r == 0)) {
                bo->pin_count = 1;
                if (gpu_addr != NULL)
@@ -216,7 +222,7 @@ int radeon_bo_unpin(struct radeon_bo *bo)
                return 0;
        for (i = 0; i < bo->placement.num_placement; i++)
                bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
-       r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+       r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
        if (unlikely(r != 0))
                dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo);
        return r;
@@ -295,6 +301,7 @@ int radeon_bo_list_reserve(struct list_head *head)
                r = radeon_bo_reserve(lobj->bo, false);
                if (unlikely(r != 0))
                        return r;
+               lobj->reserved = true;
        }
        return 0;
 }
@@ -305,7 +312,7 @@ void radeon_bo_list_unreserve(struct list_head *head)
 
        list_for_each_entry(lobj, head, list) {
                /* only unreserve object we successfully reserved */
-               if (radeon_bo_is_reserved(lobj->bo))
+               if (lobj->reserved && radeon_bo_is_reserved(lobj->bo))
                        radeon_bo_unreserve(lobj->bo);
        }
 }
@@ -316,6 +323,9 @@ int radeon_bo_list_validate(struct list_head *head)
        struct radeon_bo *bo;
        int r;
 
+       list_for_each_entry(lobj, head, list) {
+               lobj->reserved = false;
+       }
        r = radeon_bo_list_reserve(head);
        if (unlikely(r != 0)) {
                return r;
@@ -331,7 +341,7 @@ int radeon_bo_list_validate(struct list_head *head)
                                                                lobj->rdomain);
                        }
                        r = ttm_bo_validate(&bo->tbo, &bo->placement,
-                                               true, false);
+                                               true, false, false);
                        if (unlikely(r))
                                return r;
                }
@@ -499,11 +509,33 @@ void radeon_bo_move_notify(struct ttm_buffer_object *bo,
        radeon_bo_check_tiling(rbo, 0, 1);
 }
 
-void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
+int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
 {
+       struct radeon_device *rdev;
        struct radeon_bo *rbo;
+       unsigned long offset, size;
+       int r;
+
        if (!radeon_ttm_bo_is_radeon_bo(bo))
-               return;
+               return 0;
        rbo = container_of(bo, struct radeon_bo, tbo);
        radeon_bo_check_tiling(rbo, 0, 0);
+       rdev = rbo->rdev;
+       if (bo->mem.mem_type == TTM_PL_VRAM) {
+               size = bo->mem.num_pages << PAGE_SHIFT;
+               offset = bo->mem.mm_node->start << PAGE_SHIFT;
+               if ((offset + size) > rdev->mc.visible_vram_size) {
+                       /* hurrah the memory is not visible ! */
+                       radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM);
+                       rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT;
+                       r = ttm_bo_validate(bo, &rbo->placement, false, true, false);
+                       if (unlikely(r != 0))
+                               return r;
+                       offset = bo->mem.mm_node->start << PAGE_SHIFT;
+                       /* this should not happen */
+                       if ((offset + size) > rdev->mc.visible_vram_size)
+                               return -EINVAL;
+               }
+       }
+       return 0;
 }