From 393494d9bd51b8c4901bc70a339209dcde32c5d1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 20 Feb 2009 15:19:42 +1000 Subject: nv50: fix some fbcon corruption issues --- linux-core/nv50_fbcon_accel.c | 37 ++++++++++++++++++++++++++++++++++++- shared-core/nouveau_dma.c | 11 +++++++++++ shared-core/nouveau_drv.h | 1 + 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/linux-core/nv50_fbcon_accel.c b/linux-core/nv50_fbcon_accel.c index e88fc5f2..b067d0df 100644 --- a/linux-core/nv50_fbcon_accel.c +++ b/linux-core/nv50_fbcon_accel.c @@ -6,9 +6,44 @@ static int nv50_fbcon_sync(struct fb_info *info) { - if (info->state != FBINFO_STATE_RUNNING) + struct nv50_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = dev_priv->channel; + int ret, i; + + if (info->state != FBINFO_STATE_RUNNING || + info->flags & FBINFO_HWACCEL_DISABLED) return 0; + if (RING_SPACE(chan, 4)) { + DRM_ERROR("GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + return 0; + } + + BEGIN_RING(chan, 0, 0x0104, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, 0, 0x0100, 1); + OUT_RING (chan, 0); + chan->m2mf_ntfy_map[3] = 0xffffffff; + FIRE_RING (chan); + + ret = -EBUSY; + for (i = 0; i < 100000; i++) { + if (chan->m2mf_ntfy_map[3] == 0) { + ret = 0; + break; + } + DRM_UDELAY(1); + } + + if (ret) { + DRM_ERROR("GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; + return 0; + } + return 0; } diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c index 276575a7..5af1577b 100644 --- a/shared-core/nouveau_dma.c +++ b/shared-core/nouveau_dma.c @@ -122,6 +122,17 @@ nouveau_dma_channel_setup(struct nouveau_channel *chan) chan->dma.pushbuf = (void *)chan->pushbuf_mem->map->handle; } + /* Map M2MF notifier object - fbcon. */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + ret = drm_bo_kmap(chan->notifier_block->bo, 0, + chan->notifier_block->bo->mem.num_pages, + &chan->notifier_block->kmap); + if (ret) + return ret; + chan->m2mf_ntfy_map = chan->notifier_block->kmap.virtual; + chan->m2mf_ntfy_map += chan->m2mf_ntfy; + } + /* Initialise DMA vars */ chan->dma.max = (chan->pushbuf_mem->size >> 2) - 2; chan->dma.put = 0; diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index b0b15a35..66660e67 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -169,6 +169,7 @@ struct nouveau_channel /* GPU object info for stuff used in-kernel (mm_enabled) */ uint32_t m2mf_ntfy; + volatile uint32_t *m2mf_ntfy_map; uint32_t vram_handle; uint32_t gart_handle; -- cgit v1.2.3