]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/nouveau/nv50_instmem.c
drm: block userspace under allocating buffer and having drivers overwrite it (v2)
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nv50_instmem.c
index 5f21df31f3aa7f69beac46ff65dc11885a5f02bd..37c7b48ab24af8a37c3e8ac29656b989ec5935f5 100644 (file)
@@ -35,8 +35,6 @@ struct nv50_instmem_priv {
        struct nouveau_gpuobj_ref *pramin_pt;
        struct nouveau_gpuobj_ref *pramin_bar;
        struct nouveau_gpuobj_ref *fb_bar;
-
-       bool last_access_wr;
 };
 
 #define NV50_INSTMEM_PAGE_SHIFT 12
@@ -147,7 +145,7 @@ nv50_instmem_init(struct drm_device *dev)
        if (ret)
                return ret;
 
-       if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base))
+       if (drm_mm_init(&chan->ramin_heap, c_base, c_size - c_base))
                return -ENOMEM;
 
        /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */
@@ -241,7 +239,7 @@ nv50_instmem_init(struct drm_device *dev)
                return ret;
        BAR0_WI32(priv->fb_bar->gpuobj, 0x00, 0x7fc00000);
        BAR0_WI32(priv->fb_bar->gpuobj, 0x04, 0x40000000 +
-                                             drm_get_resource_len(dev, 1) - 1);
+                                             pci_resource_len(dev->pdev, 1) - 1);
        BAR0_WI32(priv->fb_bar->gpuobj, 0x08, 0x40000000);
        BAR0_WI32(priv->fb_bar->gpuobj, 0x0c, 0x00000000);
        BAR0_WI32(priv->fb_bar->gpuobj, 0x10, 0x00000000);
@@ -262,23 +260,18 @@ nv50_instmem_init(struct drm_device *dev)
 
        /* Assume that praying isn't enough, check that we can re-read the
         * entire fake channel back from the PRAMIN BAR */
-       dev_priv->engine.instmem.prepare_access(dev, false);
        for (i = 0; i < c_size; i += 4) {
                if (nv_rd32(dev, NV_RAMIN + i) != nv_ri32(dev, i)) {
                        NV_ERROR(dev, "Error reading back PRAMIN at 0x%08x\n",
                                                                        i);
-                       dev_priv->engine.instmem.finish_access(dev);
                        return -EINVAL;
                }
        }
-       dev_priv->engine.instmem.finish_access(dev);
 
        nv_wr32(dev, NV50_PUNK_BAR0_PRAMIN, save_nv001700);
 
        /* Global PRAMIN heap */
-       if (nouveau_mem_init_heap(&dev_priv->ramin_heap,
-                                 c_size, dev_priv->ramin_size - c_size)) {
-               dev_priv->ramin_heap = NULL;
+       if (drm_mm_init(&dev_priv->ramin_heap, c_size, dev_priv->ramin_size - c_size)) {
                NV_ERROR(dev, "Failed to init RAMIN heap\n");
        }
 
@@ -321,7 +314,7 @@ nv50_instmem_takedown(struct drm_device *dev)
                nouveau_gpuobj_del(dev, &chan->vm_pd);
                nouveau_gpuobj_ref_del(dev, &chan->ramfc);
                nouveau_gpuobj_ref_del(dev, &chan->ramin);
-               nouveau_mem_takedown(&chan->ramin_heap);
+               drm_mm_takedown(&chan->ramin_heap);
 
                dev_priv->fifos[0] = dev_priv->fifos[127] = NULL;
                kfree(chan);
@@ -436,14 +429,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
        if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound)
                return -EINVAL;
 
-       NV_DEBUG(dev, "st=0x%0llx sz=0x%0llx\n",
+       NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n",
                 gpuobj->im_pramin->start, gpuobj->im_pramin->size);
 
        pte     = (gpuobj->im_pramin->start >> 12) << 1;
        pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;
        vram    = gpuobj->im_backing_start;
 
-       NV_DEBUG(dev, "pramin=0x%llx, pte=%d, pte_end=%d\n",
+       NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n",
                 gpuobj->im_pramin->start, pte, pte_end);
        NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start);
 
@@ -453,27 +446,15 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
                vram |= 0x30;
        }
 
-       dev_priv->engine.instmem.prepare_access(dev, true);
        while (pte < pte_end) {
                nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram));
                nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram));
                vram += NV50_INSTMEM_PAGE_SIZE;
        }
-       dev_priv->engine.instmem.finish_access(dev);
-
-       nv_wr32(dev, 0x100c80, 0x00040001);
-       if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-               NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (1)\n");
-               NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-               return -EBUSY;
-       }
+       dev_priv->engine.instmem.flush(dev);
 
-       nv_wr32(dev, 0x100c80, 0x00060001);
-       if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-               NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-               NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-               return -EBUSY;
-       }
+       nv50_vm_flush(dev, 4);
+       nv50_vm_flush(dev, 6);
 
        gpuobj->im_bound = 1;
        return 0;
@@ -492,36 +473,37 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
        pte     = (gpuobj->im_pramin->start >> 12) << 1;
        pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte;
 
-       dev_priv->engine.instmem.prepare_access(dev, true);
        while (pte < pte_end) {
                nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000);
                nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000);
        }
-       dev_priv->engine.instmem.finish_access(dev);
+       dev_priv->engine.instmem.flush(dev);
 
        gpuobj->im_bound = 0;
        return 0;
 }
 
 void
-nv50_instmem_prepare_access(struct drm_device *dev, bool write)
+nv50_instmem_flush(struct drm_device *dev)
 {
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
-
-       priv->last_access_wr = write;
+       nv_wr32(dev, 0x00330c, 0x00000001);
+       if (!nv_wait(0x00330c, 0x00000002, 0x00000000))
+               NV_ERROR(dev, "PRAMIN flush timeout\n");
 }
 
 void
-nv50_instmem_finish_access(struct drm_device *dev)
+nv84_instmem_flush(struct drm_device *dev)
 {
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
+       nv_wr32(dev, 0x070000, 0x00000001);
+       if (!nv_wait(0x070000, 0x00000002, 0x00000000))
+               NV_ERROR(dev, "PRAMIN flush timeout\n");
+}
 
-       if (priv->last_access_wr) {
-               nv_wr32(dev, 0x070000, 0x00000001);
-               if (!nv_wait(0x070000, 0x00000001, 0x00000000))
-                       NV_ERROR(dev, "PRAMIN flush timeout\n");
-       }
+void
+nv50_vm_flush(struct drm_device *dev, int engine)
+{
+       nv_wr32(dev, 0x100c80, (engine << 16) | 1);
+       if (!nv_wait(0x100c80, 0x00000001, 0x00000000))
+               NV_ERROR(dev, "vm flush timeout: engine %d\n", engine);
 }