]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/nouveau/nouveau_gem.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nouveau_gem.c
index 9a1fdcf400c2fea235544f062fe8b33cd1b01fd4..506c508b7edaa43821ad64d8155d0520cb794158 100644 (file)
@@ -48,9 +48,6 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
                return;
        nvbo->gem = NULL;
 
-       if (unlikely(nvbo->cpu_filp))
-               ttm_bo_synccpu_write_release(bo);
-
        if (unlikely(nvbo->pin_refcnt)) {
                nvbo->pin_refcnt = 1;
                nouveau_bo_unpin(nvbo);
@@ -106,32 +103,6 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
        return 0;
 }
 
-static bool
-nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-       if (dev_priv->card_type >= NV_50) {
-               switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
-               case 0x0000:
-               case 0x1800:
-               case 0x2800:
-               case 0x4800:
-               case 0x7000:
-               case 0x7400:
-               case 0x7a00:
-               case 0xe000:
-                       return true;
-               }
-       } else {
-               if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK))
-                       return true;
-       }
-
-       NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags);
-       return false;
-}
-
 int
 nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
                      struct drm_file *file_priv)
@@ -146,11 +117,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
        if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
                dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
 
-       if (req->channel_hint) {
-               NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint,
-                                                    file_priv, chan);
-       }
-
        if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM)
                flags |= TTM_PL_FLAG_VRAM;
        if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART)
@@ -158,13 +124,23 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
        if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU)
                flags |= TTM_PL_FLAG_SYSTEM;
 
-       if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags))
+       if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) {
+               NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags);
                return -EINVAL;
+       }
+
+       if (req->channel_hint) {
+               chan = nouveau_channel_get(dev, file_priv, req->channel_hint);
+               if (IS_ERR(chan))
+                       return PTR_ERR(chan);
+       }
 
        ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags,
                              req->info.tile_mode, req->info.tile_flags, false,
                              (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE),
                              &nvbo);
+       if (chan)
+               nouveau_channel_put(&chan);
        if (ret)
                return ret;
 
@@ -231,15 +207,8 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
 
        list_for_each_safe(entry, tmp, list) {
                nvbo = list_entry(entry, struct nouveau_bo, entry);
-               if (likely(fence)) {
-                       struct nouveau_fence *prev_fence;
-
-                       spin_lock(&nvbo->bo.lock);
-                       prev_fence = nvbo->bo.sync_obj;
-                       nvbo->bo.sync_obj = nouveau_fence_ref(fence);
-                       spin_unlock(&nvbo->bo.lock);
-                       nouveau_fence_unref((void *)&prev_fence);
-               }
+
+               nouveau_bo_fence(nvbo, fence);
 
                if (unlikely(nvbo->validate_mapped)) {
                        ttm_bo_kunmap(&nvbo->kmap);
@@ -299,14 +268,15 @@ retry:
                        return -EINVAL;
                }
 
-               ret = ttm_bo_reserve(&nvbo->bo, false, false, true, sequence);
+               ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence);
                if (ret) {
                        validate_fini(op, NULL);
-                       if (ret == -EAGAIN)
-                               ret = ttm_bo_wait_unreserved(&nvbo->bo, false);
+                       if (unlikely(ret == -EAGAIN))
+                               ret = ttm_bo_wait_unreserved(&nvbo->bo, true);
                        drm_gem_object_unreference_unlocked(gem);
-                       if (ret) {
-                               NV_ERROR(dev, "fail reserve\n");
+                       if (unlikely(ret)) {
+                               if (ret != -ERESTARTSYS)
+                                       NV_ERROR(dev, "fail reserve\n");
                                return ret;
                        }
                        goto retry;
@@ -331,25 +301,6 @@ retry:
                        validate_fini(op, NULL);
                        return -EINVAL;
                }
-
-               if (unlikely(atomic_read(&nvbo->bo.cpu_writers) > 0)) {
-                       validate_fini(op, NULL);
-
-                       if (nvbo->cpu_filp == file_priv) {
-                               NV_ERROR(dev, "bo %p mapped by process trying "
-                                             "to validate it!\n", nvbo);
-                               return -EINVAL;
-                       }
-
-                       mutex_unlock(&drm_global_mutex);
-                       ret = ttm_bo_wait_cpu(&nvbo->bo, false);
-                       mutex_lock(&drm_global_mutex);
-                       if (ret) {
-                               NV_ERROR(dev, "fail wait_cpu\n");
-                               return ret;
-                       }
-                       goto retry;
-               }
        }
 
        return 0;
@@ -383,11 +334,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
                }
 
                nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan;
-               ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
-                                     false, false, false);
+               ret = nouveau_bo_validate(nvbo, true, false, false);
                nvbo->channel = NULL;
                if (unlikely(ret)) {
-                       NV_ERROR(dev, "fail ttm_validate\n");
+                       if (ret != -ERESTARTSYS)
+                               NV_ERROR(dev, "fail ttm_validate\n");
                        return ret;
                }
 
@@ -439,13 +390,15 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
 
        ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
        if (unlikely(ret)) {
-               NV_ERROR(dev, "validate_init\n");
+               if (ret != -ERESTARTSYS)
+                       NV_ERROR(dev, "validate_init\n");
                return ret;
        }
 
        ret = validate_list(chan, &op->vram_list, pbbo, user_buffers);
        if (unlikely(ret < 0)) {
-               NV_ERROR(dev, "validate vram_list\n");
+               if (ret != -ERESTARTSYS)
+                       NV_ERROR(dev, "validate vram_list\n");
                validate_fini(op, NULL);
                return ret;
        }
@@ -453,7 +406,8 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
 
        ret = validate_list(chan, &op->gart_list, pbbo, user_buffers);
        if (unlikely(ret < 0)) {
-               NV_ERROR(dev, "validate gart_list\n");
+               if (ret != -ERESTARTSYS)
+                       NV_ERROR(dev, "validate gart_list\n");
                validate_fini(op, NULL);
                return ret;
        }
@@ -461,7 +415,8 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
 
        ret = validate_list(chan, &op->both_list, pbbo, user_buffers);
        if (unlikely(ret < 0)) {
-               NV_ERROR(dev, "validate both_list\n");
+               if (ret != -ERESTARTSYS)
+                       NV_ERROR(dev, "validate both_list\n");
                validate_fini(op, NULL);
                return ret;
        }
@@ -557,9 +512,9 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
                                data |= r->vor;
                }
 
-               spin_lock(&nvbo->bo.lock);
+               spin_lock(&nvbo->bo.bdev->fence_lock);
                ret = ttm_bo_wait(&nvbo->bo, false, false, false);
-               spin_unlock(&nvbo->bo.lock);
+               spin_unlock(&nvbo->bo.bdev->fence_lock);
                if (ret) {
                        NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret);
                        break;
@@ -585,7 +540,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
        struct nouveau_fence *fence = NULL;
        int i, j, ret = 0, do_reloc = 0;
 
-       NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
+       chan = nouveau_channel_get(dev, file_priv, req->channel);
+       if (IS_ERR(chan))
+               return PTR_ERR(chan);
 
        req->vram_available = dev_priv->fb_aper_free;
        req->gart_available = dev_priv->gart_info.aper_free;
@@ -595,28 +552,34 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
        if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
                NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n",
                         req->nr_push, NOUVEAU_GEM_MAX_PUSH);
+               nouveau_channel_put(&chan);
                return -EINVAL;
        }
 
        if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
                NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n",
                         req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
+               nouveau_channel_put(&chan);
                return -EINVAL;
        }
 
        if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
                NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n",
                         req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
+               nouveau_channel_put(&chan);
                return -EINVAL;
        }
 
        push = u_memcpya(req->push, req->nr_push, sizeof(*push));
-       if (IS_ERR(push))
+       if (IS_ERR(push)) {
+               nouveau_channel_put(&chan);
                return PTR_ERR(push);
+       }
 
        bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
        if (IS_ERR(bo)) {
                kfree(push);
+               nouveau_channel_put(&chan);
                return PTR_ERR(bo);
        }
 
@@ -639,7 +602,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
        ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
                                           req->nr_buffers, &op, &do_reloc);
        if (ret) {
-               NV_ERROR(dev, "validate: %d\n", ret);
+               if (ret != -ERESTARTSYS)
+                       NV_ERROR(dev, "validate: %d\n", ret);
                goto out;
        }
 
@@ -732,7 +696,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 
 out:
        validate_fini(&op, fence);
-       nouveau_fence_unref((void**)&fence);
+       nouveau_fence_unref(&fence);
        kfree(bo);
        kfree(push);
 
@@ -750,6 +714,7 @@ out_next:
                req->suffix1 = 0x00000000;
        }
 
+       nouveau_channel_put(&chan);
        return ret;
 }
 
@@ -781,26 +746,9 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
                return -ENOENT;
        nvbo = nouveau_gem_object(gem);
 
-       if (nvbo->cpu_filp) {
-               if (nvbo->cpu_filp == file_priv)
-                       goto out;
-
-               ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait);
-               if (ret)
-                       goto out;
-       }
-
-       if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) {
-               spin_lock(&nvbo->bo.lock);
-               ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait);
-               spin_unlock(&nvbo->bo.lock);
-       } else {
-               ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait);
-               if (ret == 0)
-                       nvbo->cpu_filp = file_priv;
-       }
-
-out:
+       spin_lock(&nvbo->bo.bdev->fence_lock);
+       ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait);
+       spin_unlock(&nvbo->bo.bdev->fence_lock);
        drm_gem_object_unreference_unlocked(gem);
        return ret;
 }
@@ -809,26 +757,7 @@ int
 nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
                           struct drm_file *file_priv)
 {
-       struct drm_nouveau_gem_cpu_prep *req = data;
-       struct drm_gem_object *gem;
-       struct nouveau_bo *nvbo;
-       int ret = -EINVAL;
-
-       gem = drm_gem_object_lookup(dev, file_priv, req->handle);
-       if (!gem)
-               return -ENOENT;
-       nvbo = nouveau_gem_object(gem);
-
-       if (nvbo->cpu_filp != file_priv)
-               goto out;
-       nvbo->cpu_filp = NULL;
-
-       ttm_bo_synccpu_write_release(&nvbo->bo);
-       ret = 0;
-
-out:
-       drm_gem_object_unreference_unlocked(gem);
-       return ret;
+       return 0;
 }
 
 int