PFIFO context destruction triggers this automagically now.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
u32 grctx_size;
};
-static void
-nv50_graph_fifo_access(struct drm_device *dev, bool enabled)
-{
- const uint32_t mask = 0x00010001;
-
- if (enabled)
- nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | mask);
- else
- nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) & ~mask);
-}
-
-static struct nouveau_channel *
-nv50_graph_channel(struct drm_device *dev)
-{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- uint32_t inst;
- int i;
-
- /* Be sure we're not in the middle of a context switch or bad things
- * will happen, such as unloading the wrong pgraph context.
- */
- if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000))
- NV_ERROR(dev, "Ctxprog is still running\n");
-
- inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
- if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
- return NULL;
- inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12;
-
- for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
- struct nouveau_channel *chan = dev_priv->channels.ptr[i];
-
- if (chan && chan->ramin && chan->ramin->vinst == inst)
- return chan;
- }
-
- return NULL;
-}
-
static int
nv50_graph_do_load_context(struct drm_device *dev, uint32_t inst)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20;
- unsigned long flags;
-
- NV_DEBUG(dev, "ch%d\n", chan->id);
-
- if (!chan->ramin)
- return;
-
- spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
- nv_wr32(dev, NV03_PFIFO_CACHES, 0);
- nv50_graph_fifo_access(dev, false);
-
- if (nv50_graph_channel(dev) == chan)
- nv50_graph_unload_context(dev);
for (i = hdr; i < hdr + 24; i += 4)
nv_wo32(chan->ramin, i, 0);
dev_priv->engine.instmem.flush(dev);
- nv50_graph_fifo_access(dev, true);
- nv_wr32(dev, NV03_PFIFO_CACHES, 1);
- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
-
- nouveau_gpuobj_ref(NULL, &grctx);
-
atomic_dec(&chan->vm->engref[engine]);
+ nouveau_gpuobj_ref(NULL, &grctx);
chan->engctx[engine] = NULL;
}
static void
nv50_mpeg_context_del(struct nouveau_channel *chan, int engine)
{
- struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
struct nouveau_gpuobj *ctx = chan->engctx[engine];
struct drm_device *dev = chan->dev;
- unsigned long flags;
- u32 inst, i;
-
- if (!chan->ramin)
- return;
-
- inst = chan->ramin->vinst >> 12;
- inst |= 0x80000000;
-
- spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
- if (nv_rd32(dev, 0x00b318) == inst)
- nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
+ int i;
for (i = 0x00; i <= 0x14; i += 4)
nv_wo32(chan->ramin, CTX_PTR(dev, i), 0x00000000);
+
nouveau_gpuobj_ref(NULL, &ctx);
chan->engctx[engine] = NULL;
}
nva3_copy_context_del(struct nouveau_channel *chan, int engine)
{
struct nouveau_gpuobj *ctx = chan->engctx[engine];
- struct drm_device *dev = chan->dev;
- u32 inst;
-
- inst = (chan->ramin->vinst >> 12);
- inst |= 0x40000000;
-
- /* disable fifo access */
- nv_wr32(dev, 0x104048, 0x00000000);
- /* mark channel as unloaded if it's currently active */
- if (nv_rd32(dev, 0x104050) == inst)
- nv_mask(dev, 0x104050, 0x40000000, 0x00000000);
- /* mark next channel as invalid if it's about to be loaded */
- if (nv_rd32(dev, 0x104054) == inst)
- nv_mask(dev, 0x104054, 0x40000000, 0x00000000);
- /* restore fifo access */
- nv_wr32(dev, 0x104048, 0x00000003);
-
- for (inst = 0xc0; inst <= 0xd4; inst += 4)
- nv_wo32(chan->ramin, inst, 0x00000000);
+ int i;
- nouveau_gpuobj_ref(NULL, &ctx);
+ for (i = 0xc0; i <= 0xd4; i += 4)
+ nv_wo32(chan->ramin, i, 0x00000000);
atomic_dec(&chan->vm->engref[engine]);
+ nouveau_gpuobj_ref(NULL, &ctx);
chan->engctx[engine] = ctx;
}