From: <dar...@ke...> - 2009-03-25 05:07:41
|
linux-core/nouveau_dma.h | 1 + linux-core/nv50_display.c | 2 ++ linux-core/nv50_fbcon.c | 4 +++- shared-core/nouveau_drv.h | 1 + shared-core/nouveau_fifo.c | 29 ++++++++++++++++++++++++++++- shared-core/nouveau_object.c | 3 +++ 6 files changed, 38 insertions(+), 2 deletions(-) New commits: commit 62888f088f4d41ac7f30180acb526f29768436f6 Author: Ben Skeggs <bs...@re...> Date: Wed Mar 25 15:00:52 2009 +1000 nouveau: idle the channel a bit better before destroying it diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index d8ac567..332ac33 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -463,6 +463,8 @@ void nouveau_fifo_free(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; uint64_t t_start; + bool timeout = false; + int ret; DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id); @@ -472,11 +474,35 @@ void nouveau_fifo_free(struct nouveau_channel *chan) if (engine->timer.read(dev) - t_start > 2000000000ULL) { DRM_ERROR("Failed to idle channel %d before destroy." "Prepare for strangeness..\n", chan->id); + timeout = true; break; } } - /* Signal all pending fences, if any */ + /* Wait on a fence until channel goes idle, this ensures the engine + * has finished with the last push buffer completely before we destroy + * the channel. + */ + if (!timeout && dev_priv->mm_enabled) { + struct drm_fence_object *fence = NULL; + + ret = drm_fence_object_create(dev, chan->id, DRM_FENCE_TYPE_EXE, + DRM_FENCE_FLAG_EMIT, &fence); + if (ret == 0) + ret = drm_fence_object_wait(fence, 0, 1, + DRM_FENCE_TYPE_EXE); + + if (ret) { + DRM_ERROR("Failed to idle channel %d before destroy. " + "Prepare for strangeness..\n", chan->id); + timeout = true; + } + } + + /* Ensure all outstanding fences are signaled. They should be if the + * above attempts at idling were OK, but if we failed this'll tell TTM + * we're done with the buffers. + */ if (dev_priv->mm_enabled) { drm_fence_handler(dev, chan->id, chan->next_sequence, DRM_FENCE_TYPE_EXE, 0); @@ -484,6 +510,7 @@ void nouveau_fifo_free(struct nouveau_channel *chan) /*XXX: Maybe should wait for PGRAPH to finish with the stuff it fetched * from CACHE1 too? + *25/3/2009: handled in the mm_enabled case */ /* disable the fifo caches */ commit 8c46fa5a40503e4854d2f8d7dffbe09eb1333a77 Author: Ben Skeggs <bs...@re...> Date: Wed Mar 25 15:00:20 2009 +1000 nouveau: fix potential oops in gpuobj_channel_takedown diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 36a559d..454550d 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -1162,6 +1162,9 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) DRM_DEBUG("ch%d\n", chan->id); + if (!chan->ramht_refs.next) + return; + list_for_each_safe(entry, tmp, &chan->ramht_refs) { ref = list_entry(entry, struct nouveau_gpuobj_ref, list); commit 1e7d005aa0ccd86012194c8292fe55ca8534348b Author: Ben Skeggs <bs...@re...> Date: Wed Mar 25 14:59:07 2009 +1000 nouveau: prevent fbcon notifier waits when unnecessary It seems fbcon_sync will get called continually by something even while not at a console, so ignore the call unless we've previously rendered to the fbcon. diff --git a/linux-core/nouveau_dma.h b/linux-core/nouveau_dma.h index 66d567f..085c506 100644 --- a/linux-core/nouveau_dma.h +++ b/linux-core/nouveau_dma.h @@ -91,6 +91,7 @@ FIRE_RING(struct nouveau_channel *chan) if (chan->dma.cur == chan->dma.put) return; + chan->accel_done = true; DRM_MEMORYBARRIER(); chan->dma.put = chan->dma.cur; diff --git a/linux-core/nv50_fbcon.c b/linux-core/nv50_fbcon.c index dfa14ae..9e0625d 100644 --- a/linux-core/nv50_fbcon.c +++ b/linux-core/nv50_fbcon.c @@ -12,7 +12,8 @@ nv50_fbcon_sync(struct fb_info *info) struct nouveau_channel *chan = dev_priv->channel; int ret, i; - if (info->state != FBINFO_STATE_RUNNING || + if (!chan->accel_done || + info->state != FBINFO_STATE_RUNNING || info->flags & FBINFO_HWACCEL_DISABLED) return 0; @@ -44,6 +45,7 @@ nv50_fbcon_sync(struct fb_info *info) return 0; } + chan->accel_done = false; return 0; } diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 87ef8ef..0667c16 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -173,6 +173,7 @@ struct nouveau_channel volatile uint32_t *m2mf_ntfy_map; uint32_t vram_handle; uint32_t gart_handle; + bool accel_done; /* Push buffer state (only for drm's channel on !mm_enabled) */ struct { commit f4cb7a7340e1954ed282efec94a62e816918bfa7 Author: Ben Skeggs <bs...@re...> Date: Wed Mar 25 14:57:25 2009 +1000 nv50: turn off crtcs in display_disable diff --git a/linux-core/nv50_display.c b/linux-core/nv50_display.c index ac69865..b509d6d 100644 --- a/linux-core/nv50_display.c +++ b/linux-core/nv50_display.c @@ -163,11 +163,13 @@ static int nv50_display_disable(struct drm_device *dev) DRM_DEBUG("\n"); + dev_priv->in_modeset = true; list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { struct drm_crtc_helper_funcs *helper = drm_crtc->helper_private; helper->dpms(drm_crtc, DRM_MODE_DPMS_OFF); } + dev_priv->in_modeset = false; OUT_MODE(NV50_UPDATE_DISPLAY, 0); |