summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-11-14 04:24:36 +1100
committerBen Skeggs <skeggsb@gmail.com>2007-11-14 04:26:49 +1100
commit7c1e59fb0c5043d3d369f5feb8e195a6a3da3457 (patch)
tree934b0efd833dd3e794ecdb5774f6a66a820837fa /shared-core
parent53ab6026cfb20bfdf34b245e41af424be62941a8 (diff)
nouveau: Attempt to wait for channel idle before we destroy it.
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/nouveau_fifo.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index 7e109ada..3c993f3e 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -402,9 +402,31 @@ void nouveau_fifo_free(struct nouveau_channel *chan)
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_engine *engine = &dev_priv->Engine;
+ uint64_t t_start;
DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id);
+ /* Disable channel switching, if this channel isn't currenly
+ * active re-enable it if there's still pending commands.
+ * We really should do a manual context switch here, but I'm
+ * not sure I trust our ability to do this reliably yet..
+ */
+ NV_WRITE(NV03_PFIFO_CACHES, 0);
+ if (engine->fifo.channel_id(dev) != chan->id &&
+ NV_READ(chan->get) != NV_READ(chan->put)) {
+ NV_WRITE(NV03_PFIFO_CACHES, 1);
+ }
+
+ /* Give the channel a chance to idle, wait 2s (hopefully) */
+ t_start = engine->timer.read(dev);
+ while (NV_READ(chan->get) != NV_READ(chan->put)) {
+ if (engine->timer.read(dev) - t_start > 2000000000ULL) {
+ DRM_ERROR("Failed to idle channel %d before destroy."
+ "Prepare for strangeness..\n", chan->id);
+ break;
+ }
+ }
+
/* disable the fifo caches */
NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, NV_READ(NV04_PFIFO_CACHE1_DMA_PUSH)&(~0x1));