drm/nouveau: Fix pushbufs over the 4GB mark.
authorFrancisco Jerez <currojerez@riseup.net>
Sat, 19 Nov 2011 10:57:52 +0000 (11:57 +0100)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 21 Dec 2011 09:01:46 +0000 (19:01 +1000)
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Tested-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_debugfs.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nv50_fifo.c

index bb6ec9ef8676a6300f6de6fc221cc5b5c7c7199e..a018defb7621fd2e1c91e45f271485bebd9b17c5 100644 (file)
@@ -187,6 +187,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
        nouveau_dma_pre_init(chan);
        chan->user_put = 0x40;
        chan->user_get = 0x44;
+       if (dev_priv->card_type >= NV_50)
+                chan->user_get_hi = 0x60;
 
        /* disable the fifo caches */
        pfifo->reassign(dev, false);
index f52c2db3529efd6277b9c187095f5e96744bbdb9..fa2ec491f6a7e56b40708a7a92eb7b9292666a35 100644 (file)
@@ -44,7 +44,7 @@ nouveau_debugfs_channel_info(struct seq_file *m, void *data)
        seq_printf(m, "channel id    : %d\n", chan->id);
 
        seq_printf(m, "cpu fifo state:\n");
-       seq_printf(m, "          base: 0x%08x\n", chan->pushbuf_base);
+       seq_printf(m, "          base: 0x%10llx\n", chan->pushbuf_base);
        seq_printf(m, "           max: 0x%08x\n", chan->dma.max << 2);
        seq_printf(m, "           cur: 0x%08x\n", chan->dma.cur << 2);
        seq_printf(m, "           put: 0x%08x\n", chan->dma.put << 2);
index 00bc6eaad558069a2d59c392124a120e57ddc6e8..4c2e4e5925feb549a71826c81a11342d53167118 100644 (file)
@@ -134,11 +134,13 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
  *  -EBUSY if timeout exceeded
  */
 static inline int
-READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
+READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
 {
-       uint32_t val;
+       uint64_t val;
 
        val = nvchan_rd32(chan, chan->user_get);
+        if (chan->user_get_hi)
+                val |= (uint64_t)nvchan_rd32(chan, chan->user_get_hi) << 32;
 
        /* reset counter as long as GET is still advancing, this is
         * to avoid misdetecting a GPU lockup if the GPU happens to
@@ -218,8 +220,8 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
 static int
 nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
 {
-       uint32_t cnt = 0, prev_get = 0;
-       int ret;
+       uint64_t prev_get = 0;
+       int ret, cnt = 0;
 
        ret = nv50_dma_push_wait(chan, slots + 1);
        if (unlikely(ret))
@@ -261,8 +263,8 @@ nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
 int
 nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size)
 {
-       uint32_t prev_get = 0, cnt = 0;
-       int get;
+       uint64_t prev_get = 0;
+       int cnt = 0, get;
 
        if (chan->dma.ib_max)
                return nv50_dma_wait(chan, slots, size);
index 0af525820347f950262474b6beaac0a21f88fa56..38134a9c75780a16ab4f646aa978f4d85719ecea 100644 (file)
@@ -232,6 +232,7 @@ struct nouveau_channel {
        /* mapping of the regs controlling the fifo */
        void __iomem *user;
        uint32_t user_get;
+       uint32_t user_get_hi;
        uint32_t user_put;
 
        /* Fencing */
@@ -249,7 +250,7 @@ struct nouveau_channel {
        struct nouveau_gpuobj *pushbuf;
        struct nouveau_bo     *pushbuf_bo;
        struct nouveau_vma     pushbuf_vma;
-       uint32_t               pushbuf_base;
+       uint64_t               pushbuf_base;
 
        /* Notifier memory */
        struct nouveau_bo *notifier_bo;
index c34a074f7ea17761dee36e2943ce3b656a609b0d..3bc2a565c20be72dc2d43b9aa360c542818a24dd 100644 (file)
@@ -230,6 +230,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
        struct drm_device *dev = chan->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_gpuobj *ramfc = NULL;
+        uint64_t ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4;
        unsigned long flags;
        int ret;
 
@@ -280,8 +281,9 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
        nv_wo32(ramfc, 0x7c, 0x30000001);
        nv_wo32(ramfc, 0x78, 0x00000000);
        nv_wo32(ramfc, 0x3c, 0x403f6078);
-       nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4);
-       nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16);
+       nv_wo32(ramfc, 0x50, lower_32_bits(ib_offset));
+       nv_wo32(ramfc, 0x54, upper_32_bits(ib_offset) |
+                drm_order(chan->dma.ib_max + 1) << 16);
 
        if (dev_priv->chipset != 0x50) {
                nv_wo32(chan->ramin, 0, chan->id);