drm/nouveau: fix allocation of notifier object
[linux-2.6.git] / drivers / gpu / drm / nouveau / nouveau_dma.c
index b9c80bb..568caed 100644 (file)
@@ -28,6 +28,7 @@
 #include "drm.h"
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
+#include "nouveau_ramht.h"
 
 void
 nouveau_dma_pre_init(struct nouveau_channel *chan)
@@ -35,7 +36,7 @@ nouveau_dma_pre_init(struct nouveau_channel *chan)
        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct nouveau_bo *pushbuf = chan->pushbuf_bo;
 
-       if (dev_priv->card_type == NV_50) {
+       if (dev_priv->card_type >= NV_50) {
                const int ib_size = pushbuf->bo.mem.size / 2;
 
                chan->dma.ib_base = (pushbuf->bo.mem.size - ib_size) >> 2;
@@ -58,46 +59,35 @@ nouveau_dma_init(struct nouveau_channel *chan)
 {
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nouveau_gpuobj *m2mf = NULL;
-       struct nouveau_gpuobj *nvsw = NULL;
        int ret, i;
 
-       /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
-       ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ?
-                                   0x0039 : 0x5039, &m2mf);
-       if (ret)
-               return ret;
+       if (dev_priv->card_type >= NV_C0) {
+               ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039);
+               if (ret)
+                       return ret;
 
-       ret = nouveau_gpuobj_ref_add(dev, chan, NvM2MF, m2mf, NULL);
-       if (ret)
-               return ret;
+               ret = RING_SPACE(chan, 2);
+               if (ret)
+                       return ret;
 
-       /* Create an NV_SW object for various sync purposes */
-       ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw);
-       if (ret)
-               return ret;
+               BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0000, 1);
+               OUT_RING  (chan, 0x00009039);
+               FIRE_RING (chan);
+               return 0;
+       }
 
-       ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL);
+       /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */
+       ret = nouveau_gpuobj_gr_new(chan, NvM2MF, dev_priv->card_type < NV_50 ?
+                                   0x0039 : 0x5039);
        if (ret)
                return ret;
 
        /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
-       ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy);
+       ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000,
+                                    &chan->m2mf_ntfy);
        if (ret)
                return ret;
 
-       /* Map push buffer */
-       ret = nouveau_bo_map(chan->pushbuf_bo);
-       if (ret)
-               return ret;
-
-       /* Map M2MF notifier object - fbcon. */
-       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = nouveau_bo_map(chan->notifier_bo);
-               if (ret)
-                       return ret;
-       }
-
        /* Insert NOPS for NOUVEAU_DMA_SKIPS */
        ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
        if (ret)
@@ -107,20 +97,15 @@ nouveau_dma_init(struct nouveau_channel *chan)
                OUT_RING(chan, 0);
 
        /* Initialise NV_MEMORY_TO_MEMORY_FORMAT */
-       ret = RING_SPACE(chan, 4);
+       ret = RING_SPACE(chan, 6);
        if (ret)
                return ret;
        BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
-       OUT_RING(chan, NvM2MF);
-       BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
-       OUT_RING(chan, NvNotify0);
-
-       /* Initialise NV_SW */
-       ret = RING_SPACE(chan, 2);
-       if (ret)
-               return ret;
-       BEGIN_RING(chan, NvSubSw, 0, 1);
-       OUT_RING(chan, NvSw);
+       OUT_RING  (chan, NvM2MF);
+       BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
+       OUT_RING  (chan, NvNotify0);
+       OUT_RING  (chan, chan->vram_handle);
+       OUT_RING  (chan, chan->gart_handle);
 
        /* Sit back and pray the channel works.. */
        FIRE_RING(chan);
@@ -179,17 +164,22 @@ READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
 
 void
 nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
-             int delta, int dwords)
+             int delta, int length)
 {
        struct nouveau_bo *pb = chan->pushbuf_bo;
-       uint64_t offset = (bo->bo.mem.mm_node->start << PAGE_SHIFT) + delta;
+       uint64_t offset = bo->bo.offset + delta;
        int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
 
        BUG_ON(chan->dma.ib_free < 1);
-       nouveau_bo_wr32(pb, ip++, offset);
-       nouveau_bo_wr32(pb, ip++, dwords << 10);
+       nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
+       nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8);
 
        chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;
+
+       DRM_MEMORYBARRIER();
+       /* Flush writes. */
+       nouveau_bo_rd32(pb, 0);
+
        nvchan_wr32(chan, 0x8c, chan->dma.ib_put);
        chan->dma.ib_free--;
 }
@@ -214,7 +204,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
 
                chan->dma.ib_free = get - chan->dma.ib_put;
                if (chan->dma.ib_free <= 0)
-                       chan->dma.ib_free += chan->dma.ib_max + 1;
+                       chan->dma.ib_free += chan->dma.ib_max;
        }
 
        return 0;