]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/nouveau/nouveau_object.c
drm/nouveau: allocate fixed amount of PRAMIN per channel on all chipsets
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / nouveau_object.c
index e7c100ba63a16d2d3b45284de22f1073767758de..b6bcb254f4ab49ab123834d78f4e62e58ac0398a 100644 (file)
@@ -132,7 +132,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
                }
        }
 
-       instmem->prepare_access(dev, true);
        co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
        do {
                if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
@@ -143,7 +142,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
                        nv_wo32(dev, ramht, (co + 4)/4, ctx);
 
                        list_add_tail(&ref->list, &chan->ramht_refs);
-                       instmem->finish_access(dev);
+                       instmem->flush(dev);
                        return 0;
                }
                NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
@@ -153,7 +152,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
                if (co >= dev_priv->ramht_size)
                        co = 0;
        } while (co != ho);
-       instmem->finish_access(dev);
 
        NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
        return -ENOMEM;
@@ -173,7 +171,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
                return;
        }
 
-       instmem->prepare_access(dev, true);
        co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
        do {
                if (nouveau_ramht_entry_valid(dev, ramht, co) &&
@@ -186,7 +183,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
                        nv_wo32(dev, ramht, (co + 4)/4, 0x00000000);
 
                        list_del(&ref->list);
-                       instmem->finish_access(dev);
+                       instmem->flush(dev);
                        return;
                }
 
@@ -195,7 +192,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
                        co = 0;
        } while (co != ho);
        list_del(&ref->list);
-       instmem->finish_access(dev);
 
        NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
                 chan->id, ref->handle);
@@ -209,7 +205,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_engine *engine = &dev_priv->engine;
        struct nouveau_gpuobj *gpuobj;
-       struct mem_block *pramin = NULL;
+       struct drm_mm *pramin = NULL;
        int ret;
 
        NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
@@ -233,25 +229,12 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
         * available.
         */
        if (chan) {
-               if (chan->ramin_heap) {
-                       NV_DEBUG(dev, "private heap\n");
-                       pramin = chan->ramin_heap;
-               } else
-               if (dev_priv->card_type < NV_50) {
-                       NV_DEBUG(dev, "global heap fallback\n");
-                       pramin = dev_priv->ramin_heap;
-               }
+               NV_DEBUG(dev, "channel heap\n");
+               pramin = &chan->ramin_heap;
        } else {
                NV_DEBUG(dev, "global heap\n");
-               pramin = dev_priv->ramin_heap;
-       }
-
-       if (!pramin) {
-               NV_ERROR(dev, "No PRAMIN heap!\n");
-               return -EINVAL;
-       }
+               pramin = &dev_priv->ramin_heap;
 
-       if (!chan) {
                ret = engine->instmem.populate(dev, gpuobj, &size);
                if (ret) {
                        nouveau_gpuobj_del(dev, &gpuobj);
@@ -260,9 +243,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
        }
 
        /* Allocate a chunk of the PRAMIN aperture */
-       gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,
-                                                   drm_order(align),
-                                                   (struct drm_file *)-2, 0);
+       gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0);
+       if (gpuobj->im_pramin)
+               gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align);
+
        if (!gpuobj->im_pramin) {
                nouveau_gpuobj_del(dev, &gpuobj);
                return -ENOMEM;
@@ -279,10 +263,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
        if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
                int i;
 
-               engine->instmem.prepare_access(dev, true);
                for (i = 0; i < gpuobj->im_pramin->size; i += 4)
                        nv_wo32(dev, gpuobj, i/4, 0);
-               engine->instmem.finish_access(dev);
+               engine->instmem.flush(dev);
        }
 
        *gpuobj_ret = gpuobj;
@@ -370,10 +353,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
        }
 
        if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
-               engine->instmem.prepare_access(dev, true);
                for (i = 0; i < gpuobj->im_pramin->size; i += 4)
                        nv_wo32(dev, gpuobj, i/4, 0);
-               engine->instmem.finish_access(dev);
+               engine->instmem.flush(dev);
        }
 
        if (gpuobj->dtor)
@@ -386,7 +368,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
                if (gpuobj->flags & NVOBJ_FLAG_FAKE)
                        kfree(gpuobj->im_pramin);
                else
-                       nouveau_mem_free_block(gpuobj->im_pramin);
+                       drm_mm_put_block(gpuobj->im_pramin);
        }
 
        list_del(&gpuobj->list);
@@ -589,7 +571,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
        list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
 
        if (p_offset != ~0) {
-               gpuobj->im_pramin = kzalloc(sizeof(struct mem_block),
+               gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node),
                                            GFP_KERNEL);
                if (!gpuobj->im_pramin) {
                        nouveau_gpuobj_del(dev, &gpuobj);
@@ -605,10 +587,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
        }
 
        if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
-               dev_priv->engine.instmem.prepare_access(dev, true);
                for (i = 0; i < gpuobj->im_pramin->size; i += 4)
                        nv_wo32(dev, gpuobj, i/4, 0);
-               dev_priv->engine.instmem.finish_access(dev);
+               dev_priv->engine.instmem.flush(dev);
        }
 
        if (pref) {
@@ -696,8 +677,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
                return ret;
        }
 
-       instmem->prepare_access(dev, true);
-
        if (dev_priv->card_type < NV_50) {
                uint32_t frame, adjust, pte_flags = 0;
 
@@ -734,7 +713,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
                nv_wo32(dev, *gpuobj, 5, flags5);
        }
 
-       instmem->finish_access(dev);
+       instmem->flush(dev);
 
        (*gpuobj)->engine = NVOBJ_ENGINE_SW;
        (*gpuobj)->class  = class;
@@ -849,7 +828,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
                return ret;
        }
 
-       dev_priv->engine.instmem.prepare_access(dev, true);
        if (dev_priv->card_type >= NV_50) {
                nv_wo32(dev, *gpuobj, 0, class);
                nv_wo32(dev, *gpuobj, 5, 0x00010000);
@@ -874,7 +852,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
                        }
                }
        }
-       dev_priv->engine.instmem.finish_access(dev);
+       dev_priv->engine.instmem.flush(dev);
 
        (*gpuobj)->engine = NVOBJ_ENGINE_GR;
        (*gpuobj)->class  = class;
@@ -920,6 +898,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
        base = 0;
 
        /* PGRAPH context */
+       size += dev_priv->engine.graph.grctx_size;
 
        if (dev_priv->card_type == NV_50) {
                /* Various fixed table thingos */
@@ -930,12 +909,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
                size += 0x8000;
                /* RAMFC */
                size += 0x1000;
-               /* PGRAPH context */
-               size += 0x70000;
        }
 
-       NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n",
-                chan->id, size, base);
        ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,
                                     &chan->ramin);
        if (ret) {
@@ -944,8 +919,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
        }
        pramin = chan->ramin->gpuobj;
 
-       ret = nouveau_mem_init_heap(&chan->ramin_heap,
-                                   pramin->im_pramin->start + base, size);
+       ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size);
        if (ret) {
                NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
                nouveau_gpuobj_ref_del(dev, &chan->ramin);
@@ -969,15 +943,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 
        NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
 
-       /* Reserve a block of PRAMIN for the channel
-        *XXX: maybe on <NV50 too at some point
-        */
-       if (0 || dev_priv->card_type == NV_50) {
-               ret = nouveau_gpuobj_channel_init_pramin(chan);
-               if (ret) {
-                       NV_ERROR(dev, "init pramin\n");
-                       return ret;
-               }
+       /* Allocate a chunk of memory for per-channel object storage */
+       ret = nouveau_gpuobj_channel_init_pramin(chan);
+       if (ret) {
+               NV_ERROR(dev, "init pramin\n");
+               return ret;
        }
 
        /* NV50 VM
@@ -988,17 +958,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
        if (dev_priv->card_type >= NV_50) {
                uint32_t vm_offset, pde;
 
-               instmem->prepare_access(dev, true);
-
                vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
                vm_offset += chan->ramin->gpuobj->im_pramin->start;
 
                ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
                                                        0, &chan->vm_pd, NULL);
-               if (ret) {
-                       instmem->finish_access(dev);
+               if (ret)
                        return ret;
-               }
                for (i = 0; i < 0x4000; i += 8) {
                        nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000);
                        nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe);
@@ -1008,10 +974,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
                                             dev_priv->gart_info.sg_ctxdma,
                                             &chan->vm_gart_pt);
-               if (ret) {
-                       instmem->finish_access(dev);
+               if (ret)
                        return ret;
-               }
                nv_wo32(dev, chan->vm_pd, pde++,
                            chan->vm_gart_pt->instance | 0x03);
                nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
@@ -1021,17 +985,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
                        ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
                                                     dev_priv->vm_vram_pt[i],
                                                     &chan->vm_vram_pt[i]);
-                       if (ret) {
-                               instmem->finish_access(dev);
+                       if (ret)
                                return ret;
-                       }
 
                        nv_wo32(dev, chan->vm_pd, pde++,
                                    chan->vm_vram_pt[i]->instance | 0x61);
                        nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
                }
 
-               instmem->finish_access(dev);
+               instmem->flush(dev);
        }
 
        /* RAMHT */
@@ -1130,8 +1092,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
        for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
                nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]);
 
-       if (chan->ramin_heap)
-               nouveau_mem_takedown(&chan->ramin_heap);
+       if (chan->ramin_heap.free_stack.next)
+               drm_mm_takedown(&chan->ramin_heap);
        if (chan->ramin)
                nouveau_gpuobj_ref_del(dev, &chan->ramin);
 
@@ -1164,10 +1126,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev)
                        return -ENOMEM;
                }
 
-               dev_priv->engine.instmem.prepare_access(dev, false);
                for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
                        gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i);
-               dev_priv->engine.instmem.finish_access(dev);
        }
 
        return 0;
@@ -1212,10 +1172,9 @@ nouveau_gpuobj_resume(struct drm_device *dev)
                if (!gpuobj->im_backing_suspend)
                        continue;
 
-               dev_priv->engine.instmem.prepare_access(dev, true);
                for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
                        nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]);
-               dev_priv->engine.instmem.finish_access(dev);
+               dev_priv->engine.instmem.flush(dev);
        }
 
        nouveau_gpuobj_suspend_cleanup(dev);
@@ -1232,7 +1191,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
        struct nouveau_channel *chan;
        int ret;
 
-       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
        NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
 
        if (init->handle == ~0)
@@ -1283,7 +1241,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
        struct nouveau_channel *chan;
        int ret;
 
-       NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
        NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
 
        ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref);