drm/radeon: fall back to GTT if bo creation/validation in VRAM fails.
authorMichel Dänzer <daenzer@vmware.com>
Thu, 8 Jul 2010 02:43:28 +0000 (12:43 +1000)
committerDave Airlie <airlied@redhat.com>
Mon, 2 Aug 2010 00:00:08 +0000 (10:00 +1000)
This fixes a problem where on low VRAM cards we'd run out of space for validation.

[airlied: Tested on my M7, Thinkpad T42, compiz works with no problems.]

Signed-off-by: Michel Dänzer <daenzer@vmware.com>
Cc: stable@kernel.org
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon_object.c

index d5b9373..0afd1e6 100644 (file)
@@ -110,6 +110,7 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
        bo->surface_reg = -1;
        INIT_LIST_HEAD(&bo->list);
 
+retry:
        radeon_ttm_placement_from_domain(bo, domain);
        /* Kernel allocation are uninterruptible */
        mutex_lock(&rdev->vram_mutex);
@@ -118,10 +119,15 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
                        &radeon_ttm_bo_destroy);
        mutex_unlock(&rdev->vram_mutex);
        if (unlikely(r != 0)) {
-               if (r != -ERESTARTSYS)
+               if (r != -ERESTARTSYS) {
+                       if (domain == RADEON_GEM_DOMAIN_VRAM) {
+                               domain |= RADEON_GEM_DOMAIN_GTT;
+                               goto retry;
+                       }
                        dev_err(rdev->dev,
                                "object_init failed for (%lu, 0x%08X)\n",
                                size, domain);
+               }
                return r;
        }
        *bo_ptr = bo;
@@ -321,6 +327,7 @@ int radeon_bo_list_validate(struct list_head *head)
 {
        struct radeon_bo_list *lobj;
        struct radeon_bo *bo;
+       u32 domain;
        int r;
 
        list_for_each_entry(lobj, head, list) {
@@ -333,17 +340,19 @@ int radeon_bo_list_validate(struct list_head *head)
        list_for_each_entry(lobj, head, list) {
                bo = lobj->bo;
                if (!bo->pin_count) {
-                       if (lobj->wdomain) {
-                               radeon_ttm_placement_from_domain(bo,
-                                                               lobj->wdomain);
-                       } else {
-                               radeon_ttm_placement_from_domain(bo,
-                                                               lobj->rdomain);
-                       }
+                       domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
+                       
+               retry:
+                       radeon_ttm_placement_from_domain(bo, domain);
                        r = ttm_bo_validate(&bo->tbo, &bo->placement,
                                                true, false, false);
-                       if (unlikely(r))
+                       if (unlikely(r)) {
+                               if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
+                                       domain |= RADEON_GEM_DOMAIN_GTT;
+                                       goto retry;
+                               }
                                return r;
+                       }
                }
                lobj->gpu_offset = radeon_bo_gpu_offset(bo);
                lobj->tiling_flags = bo->tiling_flags;