summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2009-02-20 15:19:42 +1000
committerBen Skeggs <bskeggs@redhat.com>2009-02-20 15:21:42 +1000
commit393494d9bd51b8c4901bc70a339209dcde32c5d1 (patch)
tree3661f88f6d1e6b4c1effc588a115f7ac677c912d
parent6ec57ecae6fc43df8bfc5e96626967fd0cfe6c32 (diff)
nv50: fix some fbcon corruption issues
-rw-r--r--linux-core/nv50_fbcon_accel.c37
-rw-r--r--shared-core/nouveau_dma.c11
-rw-r--r--shared-core/nouveau_drv.h1
3 files changed, 48 insertions, 1 deletions
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;