Commit 4e03b4af authored by Francisco Jerez's avatar Francisco Jerez Committed by Ben Skeggs

drm/nouveau: Fix pushbufs over the 4GB mark.

Signed-off-by: default avatarFrancisco Jerez <currojerez@riseup.net>
Tested-by: default avatarBen Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 045da4e5
...@@ -187,6 +187,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, ...@@ -187,6 +187,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
nouveau_dma_pre_init(chan); nouveau_dma_pre_init(chan);
chan->user_put = 0x40; chan->user_put = 0x40;
chan->user_get = 0x44; chan->user_get = 0x44;
if (dev_priv->card_type >= NV_50)
chan->user_get_hi = 0x60;
/* disable the fifo caches */ /* disable the fifo caches */
pfifo->reassign(dev, false); pfifo->reassign(dev, false);
......
...@@ -44,7 +44,7 @@ nouveau_debugfs_channel_info(struct seq_file *m, void *data) ...@@ -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, "channel id : %d\n", chan->id);
seq_printf(m, "cpu fifo state:\n"); 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, " max: 0x%08x\n", chan->dma.max << 2);
seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2); seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2);
seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2); seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2);
......
...@@ -134,11 +134,13 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) ...@@ -134,11 +134,13 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
* -EBUSY if timeout exceeded * -EBUSY if timeout exceeded
*/ */
static inline int 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); 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 /* reset counter as long as GET is still advancing, this is
* to avoid misdetecting a GPU lockup if the GPU happens to * 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) ...@@ -218,8 +220,8 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
static int static int
nv50_dma_wait(struct nouveau_channel *chan, int slots, int count) nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
{ {
uint32_t cnt = 0, prev_get = 0; uint64_t prev_get = 0;
int ret; int ret, cnt = 0;
ret = nv50_dma_push_wait(chan, slots + 1); ret = nv50_dma_push_wait(chan, slots + 1);
if (unlikely(ret)) if (unlikely(ret))
...@@ -261,8 +263,8 @@ nv50_dma_wait(struct nouveau_channel *chan, int slots, int count) ...@@ -261,8 +263,8 @@ nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
int int
nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size) nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size)
{ {
uint32_t prev_get = 0, cnt = 0; uint64_t prev_get = 0;
int get; int cnt = 0, get;
if (chan->dma.ib_max) if (chan->dma.ib_max)
return nv50_dma_wait(chan, slots, size); return nv50_dma_wait(chan, slots, size);
......
...@@ -232,6 +232,7 @@ struct nouveau_channel { ...@@ -232,6 +232,7 @@ struct nouveau_channel {
/* mapping of the regs controlling the fifo */ /* mapping of the regs controlling the fifo */
void __iomem *user; void __iomem *user;
uint32_t user_get; uint32_t user_get;
uint32_t user_get_hi;
uint32_t user_put; uint32_t user_put;
/* Fencing */ /* Fencing */
...@@ -249,7 +250,7 @@ struct nouveau_channel { ...@@ -249,7 +250,7 @@ struct nouveau_channel {
struct nouveau_gpuobj *pushbuf; struct nouveau_gpuobj *pushbuf;
struct nouveau_bo *pushbuf_bo; struct nouveau_bo *pushbuf_bo;
struct nouveau_vma pushbuf_vma; struct nouveau_vma pushbuf_vma;
uint32_t pushbuf_base; uint64_t pushbuf_base;
/* Notifier memory */ /* Notifier memory */
struct nouveau_bo *notifier_bo; struct nouveau_bo *notifier_bo;
......
...@@ -230,6 +230,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) ...@@ -230,6 +230,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *ramfc = NULL; struct nouveau_gpuobj *ramfc = NULL;
uint64_t ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4;
unsigned long flags; unsigned long flags;
int ret; int ret;
...@@ -280,8 +281,9 @@ nv50_fifo_create_context(struct nouveau_channel *chan) ...@@ -280,8 +281,9 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
nv_wo32(ramfc, 0x7c, 0x30000001); nv_wo32(ramfc, 0x7c, 0x30000001);
nv_wo32(ramfc, 0x78, 0x00000000); nv_wo32(ramfc, 0x78, 0x00000000);
nv_wo32(ramfc, 0x3c, 0x403f6078); nv_wo32(ramfc, 0x3c, 0x403f6078);
nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4); nv_wo32(ramfc, 0x50, lower_32_bits(ib_offset));
nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16); nv_wo32(ramfc, 0x54, upper_32_bits(ib_offset) |
drm_order(chan->dma.ib_max + 1) << 16);
if (dev_priv->chipset != 0x50) { if (dev_priv->chipset != 0x50) {
nv_wo32(chan->ramin, 0, chan->id); nv_wo32(chan->ramin, 0, chan->id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment