drm/nv50: fix iommu errors caused by device reading from address 0
[safe/jmp/linux-2.6] / drivers / gpu / drm / nouveau / nouveau_dma.h
index 04e85d8..8b05c15 100644 (file)
@@ -31,6 +31,9 @@
 #define NOUVEAU_DMA_DEBUG 0
 #endif
 
+void nv50_dma_push(struct nouveau_channel *, struct nouveau_bo *,
+                  int delta, int length);
+
 /*
  * There's a hw race condition where you can't jump to your PUT offset,
  * to avoid this we jump to offset + SKIPS and fill the difference with
 /* Hardcoded object assignments to subchannels (subchannel id). */
 enum {
        NvSubM2MF       = 0,
-       NvSub2D         = 1,
-       NvSubCtxSurf2D  = 1,
-       NvSubGdiRect    = 2,
-       NvSubImageBlit  = 3
+       NvSubSw         = 1,
+       NvSub2D         = 2,
+       NvSubCtxSurf2D  = 2,
+       NvSubGdiRect    = 3,
+       NvSubImageBlit  = 4
 };
 
 /* Object handles. */
@@ -67,6 +71,7 @@ enum {
        NvClipRect      = 0x8000000b,
        NvGdiRect       = 0x8000000c,
        NvImageBlit     = 0x8000000d,
+       NvSw            = 0x8000000e,
 
        /* G80+ display objects */
        NvEvoVRAM       = 0x01000000,
@@ -94,13 +99,11 @@ enum {
 static __must_check inline int
 RING_SPACE(struct nouveau_channel *chan, int size)
 {
-       if (chan->dma.free < size) {
-               int ret;
+       int ret;
 
-               ret = nouveau_dma_wait(chan, size);
-               if (ret)
-                       return ret;
-       }
+       ret = nouveau_dma_wait(chan, 1, size);
+       if (ret)
+               return ret;
 
        chan->dma.free -= size;
        return 0;
@@ -144,7 +147,13 @@ FIRE_RING(struct nouveau_channel *chan)
                return;
        chan->accel_done = true;
 
-       WRITE_PUT(chan->dma.cur);
+       if (chan->dma.ib_max) {
+               nv50_dma_push(chan, chan->pushbuf_bo, chan->dma.put << 2,
+                             (chan->dma.cur - chan->dma.put) << 2);
+       } else {
+               WRITE_PUT(chan->dma.cur);
+       }
+
        chan->dma.put = chan->dma.cur;
 }