From 7c1e59fb0c5043d3d369f5feb8e195a6a3da3457 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 14 Nov 2007 04:24:36 +1100 Subject: nouveau: Attempt to wait for channel idle before we destroy it. --- shared-core/nouveau_fifo.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'shared-core') 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)); -- cgit v1.2.3