drm/nouveau: modify gpuobj/ntfy takedown ordering
[pandora-kernel.git] / drivers / gpu / drm / nouveau / nouveau_object.c
index 67a16e0..c56ac93 100644 (file)
@@ -361,20 +361,6 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
        return 0;
 }
 
-
-static uint32_t
-nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class)
-{
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-       /*XXX: dodgy hack for now */
-       if (dev_priv->card_type >= NV_50)
-               return 24;
-       if (dev_priv->card_type >= NV_40)
-               return 32;
-       return 16;
-}
-
 /*
    DMA objects are used to reference a piece of memory in the
    framebuffer, PCI or AGP address space. Each object is 16 bytes big
@@ -606,11 +592,11 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base,
    set to 0?
 */
 static int
-nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
-                     struct nouveau_gpuobj **gpuobj_ret)
+nouveau_gpuobj_sw_new(struct nouveau_channel *chan, u32 handle, u16 class)
 {
        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct nouveau_gpuobj *gpuobj;
+       int ret;
 
        gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
        if (!gpuobj)
@@ -624,8 +610,10 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
        spin_lock(&dev_priv->ramin_lock);
        list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
        spin_unlock(&dev_priv->ramin_lock);
-       *gpuobj_ret = gpuobj;
-       return 0;
+
+       ret = nouveau_ramht_insert(chan, handle, gpuobj);
+       nouveau_gpuobj_ref(NULL, &gpuobj);
+       return ret;
 }
 
 int
@@ -634,101 +622,30 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class)
        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct drm_device *dev = chan->dev;
        struct nouveau_gpuobj_class *oc;
-       struct nouveau_gpuobj *gpuobj;
        int ret;
 
        NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);
 
        list_for_each_entry(oc, &dev_priv->classes, head) {
-               if (oc->id == class)
-                       goto found;
-       }
+               struct nouveau_exec_engine *eng = dev_priv->eng[oc->engine];
 
-       NV_ERROR(dev, "illegal object class: 0x%x\n", class);
-       return -EINVAL;
-
-found:
-       switch (oc->engine) {
-       case NVOBJ_ENGINE_SW:
-               if (dev_priv->card_type < NV_C0) {
-                       ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj);
-                       if (ret)
-                               return ret;
-                       goto insert;
-               }
-               break;
-       case NVOBJ_ENGINE_GR:
-               if ((dev_priv->card_type >= NV_20 && !chan->ramin_grctx) ||
-                   (dev_priv->card_type  < NV_20 && !chan->pgraph_ctx)) {
-                       struct nouveau_pgraph_engine *pgraph =
-                               &dev_priv->engine.graph;
+               if (oc->id != class)
+                       continue;
 
-                       ret = pgraph->create_context(chan);
-                       if (ret)
-                               return ret;
-               }
-               break;
-       case NVOBJ_ENGINE_CRYPT:
-               if (!chan->crypt_ctx) {
-                       struct nouveau_crypt_engine *pcrypt =
-                               &dev_priv->engine.crypt;
+               if (oc->engine == NVOBJ_ENGINE_SW)
+                       return nouveau_gpuobj_sw_new(chan, handle, class);
 
-                       ret = pcrypt->create_context(chan);
+               if (!chan->engctx[oc->engine]) {
+                       ret = eng->context_new(chan, oc->engine);
                        if (ret)
                                return ret;
                }
-               break;
-       }
-
-       /* we're done if this is fermi */
-       if (dev_priv->card_type >= NV_C0)
-               return 0;
 
-       ret = nouveau_gpuobj_new(dev, chan,
-                                nouveau_gpuobj_class_instmem_size(dev, class),
-                                16,
-                                NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
-                                &gpuobj);
-       if (ret) {
-               NV_ERROR(dev, "error creating gpuobj: %d\n", ret);
-               return ret;
+               return eng->object_new(chan, oc->engine, handle, class);
        }
 
-       if (dev_priv->card_type >= NV_50) {
-               nv_wo32(gpuobj,  0, class);
-               nv_wo32(gpuobj, 20, 0x00010000);
-       } else {
-               switch (class) {
-               case NV_CLASS_NULL:
-                       nv_wo32(gpuobj, 0, 0x00001030);
-                       nv_wo32(gpuobj, 4, 0xFFFFFFFF);
-                       break;
-               default:
-                       if (dev_priv->card_type >= NV_40) {
-                               nv_wo32(gpuobj, 0, class);
-#ifdef __BIG_ENDIAN
-                               nv_wo32(gpuobj, 8, 0x01000000);
-#endif
-                       } else {
-#ifdef __BIG_ENDIAN
-                               nv_wo32(gpuobj, 0, class | 0x00080000);
-#else
-                               nv_wo32(gpuobj, 0, class);
-#endif
-                       }
-               }
-       }
-       dev_priv->engine.instmem.flush(dev);
-
-       gpuobj->engine = oc->engine;
-       gpuobj->class  = oc->id;
-
-insert:
-       ret = nouveau_ramht_insert(chan, handle, gpuobj);
-       if (ret)
-               NV_ERROR(dev, "error adding gpuobj to RAMHT: %d\n", ret);
-       nouveau_gpuobj_ref(NULL, &gpuobj);
-       return ret;
+       NV_ERROR(dev, "illegal object class: 0x%x\n", class);
+       return -EINVAL;
 }
 
 static int
@@ -746,9 +663,6 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
        size = 0x2000;
        base = 0;
 
-       /* PGRAPH context */
-       size += dev_priv->engine.graph.grctx_size;
-
        if (dev_priv->card_type == NV_50) {
                /* Various fixed table thingos */
                size += 0x1400; /* mostly unknown stuff */
@@ -782,13 +696,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv);
+       struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm;
        struct nouveau_gpuobj *vram = NULL, *tt = NULL;
        int ret, i;
 
        NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
-
        if (dev_priv->card_type == NV_C0) {
-               struct nouveau_vm *vm = dev_priv->chan_vm;
                struct nouveau_vm_pgd *vpgd;
 
                ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0,
@@ -817,7 +731,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
         *  - Allocate per-channel page-directory
         *  - Link with shared channel VM
         */
-       if (dev_priv->chan_vm) {
+       if (vm) {
                u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
                u64 vm_vinst = chan->ramin->vinst + pgd_offs;
                u32 vm_pinst = chan->ramin->pinst;
@@ -830,7 +744,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                if (ret)
                        return ret;
 
-               nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd);
+               nouveau_vm_ref(vm, &chan->vm, chan->vm_pd);
        }
 
        /* RAMHT */
@@ -930,8 +844,6 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 
        NV_DEBUG(dev, "ch%d\n", chan->id);
 
-       nouveau_ramht_ref(NULL, &chan->ramht, chan);
-
        nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
        nouveau_gpuobj_ref(NULL, &chan->vm_pd);
 
@@ -995,7 +907,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
        if (init->handle == ~0)
                return -EINVAL;
 
-       chan = nouveau_channel_get(dev, file_priv, init->channel);
+       chan = nouveau_channel_get(file_priv, init->channel);
        if (IS_ERR(chan))
                return PTR_ERR(chan);
 
@@ -1022,7 +934,7 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
        struct nouveau_channel *chan;
        int ret;
 
-       chan = nouveau_channel_get(dev, file_priv, objfree->channel);
+       chan = nouveau_channel_get(file_priv, objfree->channel);
        if (IS_ERR(chan))
                return PTR_ERR(chan);