summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-07-09 15:37:37 +1000
committerBen Skeggs <skeggsb@gmail.com>2007-07-09 16:16:44 +1000
commit3c58195ccd346cc61f98b9f89cf074edf6886723 (patch)
tree435c95f8ea6b1355f8269d7884fbee55b23f4e07
parentc806bba4665bb369168ee0b453fa28e2e0bf2a5d (diff)
downloaddrm-3c58195ccd346cc61f98b9f89cf074edf6886723.tar.gz
nouveau: Avoid oops
Turns out lastclose() gets called even if firstopen() has never been...
-rw-r--r--shared-core/nouveau_drv.h6
-rw-r--r--shared-core/nouveau_state.c23
2 files changed, 21 insertions, 8 deletions
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index 81972db5..12b78a7e 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -184,6 +184,12 @@ typedef struct nouveau_engine_func {
} nouveau_engine_func_t;
typedef struct drm_nouveau_private {
+ enum {
+ NOUVEAU_CARD_INIT_DOWN,
+ NOUVEAU_CARD_INIT_DONE,
+ NOUVEAU_CARD_INIT_FAILED
+ } init_state;
+
/* the card type, takes NV_* as values */
int card_type;
/* exact chipset, derived from NV_PMC_BOOT_0 */
diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c
index bcb974bf..c51d7d5d 100644
--- a/shared-core/nouveau_state.c
+++ b/shared-core/nouveau_state.c
@@ -280,6 +280,7 @@ static int nouveau_card_init(drm_device_t *dev)
ret = nouveau_init_engine_ptrs(dev);
if (ret) return ret;
engine = &dev_priv->Engine;
+ dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
/* Initialise instance memory, must happen before mem_init so we
* know exactly how much VRAM we're able to use for "normal"
@@ -316,6 +317,7 @@ static int nouveau_card_init(drm_device_t *dev)
/* what about PVIDEO/PCRTC/PRAMDAC etc? */
+ dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
return 0;
}
@@ -324,14 +326,18 @@ static void nouveau_card_takedown(drm_device_t *dev)
drm_nouveau_private_t *dev_priv = dev->dev_private;
nouveau_engine_func_t *engine = &dev_priv->Engine;
- engine->fifo.takedown(dev);
- engine->graph.takedown(dev);
- engine->fb.takedown(dev);
- engine->timer.takedown(dev);
- engine->mc.takedown(dev);
- nouveau_gpuobj_takedown(dev);
- nouveau_mem_close(dev);
- engine->instmem.takedown(dev);
+ if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
+ engine->fifo.takedown(dev);
+ engine->graph.takedown(dev);
+ engine->fb.takedown(dev);
+ engine->timer.takedown(dev);
+ engine->mc.takedown(dev);
+ nouveau_gpuobj_takedown(dev);
+ nouveau_mem_close(dev);
+ engine->instmem.takedown(dev);
+
+ dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
+ }
}
/* here a client dies, release the stuff that was allocated for its filp */
@@ -371,6 +377,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
dev_priv->card_type=flags&NOUVEAU_FAMILY;
dev_priv->flags=flags&NOUVEAU_FLAGS;
+ dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
dev->dev_private = (void *)dev_priv;