Commit 1addc126 authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Ben Skeggs

drm/nouveau/fifo/gk104: kick channels when deactivating them

Kicking channels is part of their deactivation process. Maxwell chips
are particularly sensitive to this, and can start fetching the previous
pushbuffer of a recycled channel if this is not done.

While we are at it, improve the channel preemption code to only wait for
bit 20 of 0x002634 to turn to 0, as it is the bit indicating a
preempt is pending.
Signed-off-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 9c56be4c
...@@ -165,15 +165,31 @@ gk104_fifo_context_attach(struct nvkm_object *parent, ...@@ -165,15 +165,31 @@ gk104_fifo_context_attach(struct nvkm_object *parent,
return 0; return 0;
} }
static int
gk104_fifo_chan_kick(struct gk104_fifo_chan *chan)
{
struct nvkm_object *obj = (void *)chan;
struct gk104_fifo_priv *priv = (void *)obj->engine;
nv_wr32(priv, 0x002634, chan->base.chid);
if (!nv_wait(priv, 0x002634, 0x100000, 0x000000)) {
nv_error(priv, "channel %d [%s] kick timeout\n",
chan->base.chid, nvkm_client_name(chan));
return -EBUSY;
}
return 0;
}
static int static int
gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
struct nvkm_object *object) struct nvkm_object *object)
{ {
struct nvkm_bar *bar = nvkm_bar(parent); struct nvkm_bar *bar = nvkm_bar(parent);
struct gk104_fifo_priv *priv = (void *)parent->engine;
struct gk104_fifo_base *base = (void *)parent->parent; struct gk104_fifo_base *base = (void *)parent->parent;
struct gk104_fifo_chan *chan = (void *)parent; struct gk104_fifo_chan *chan = (void *)parent;
u32 addr; u32 addr;
int ret;
switch (nv_engidx(object->engine)) { switch (nv_engidx(object->engine)) {
case NVDEV_ENGINE_SW : return 0; case NVDEV_ENGINE_SW : return 0;
...@@ -188,13 +204,9 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend, ...@@ -188,13 +204,9 @@ gk104_fifo_context_detach(struct nvkm_object *parent, bool suspend,
return -EINVAL; return -EINVAL;
} }
nv_wr32(priv, 0x002634, chan->base.chid); ret = gk104_fifo_chan_kick(chan);
if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { if (ret && suspend)
nv_error(priv, "channel %d [%s] kick timeout\n", return ret;
chan->base.chid, nvkm_client_name(chan));
if (suspend)
return -EBUSY;
}
if (addr) { if (addr) {
nv_wo32(base, addr + 0x00, 0x00000000); nv_wo32(base, addr + 0x00, 0x00000000);
...@@ -319,6 +331,7 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend) ...@@ -319,6 +331,7 @@ gk104_fifo_chan_fini(struct nvkm_object *object, bool suspend)
gk104_fifo_runlist_update(priv, chan->engine); gk104_fifo_runlist_update(priv, chan->engine);
} }
gk104_fifo_chan_kick(chan);
nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);
return nvkm_fifo_channel_fini(&chan->base, suspend); return nvkm_fifo_channel_fini(&chan->base, suspend);
} }
......
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