OSDN Git Service

nouveau: make sure cmdbuf object gets destroyed
authorBen Skeggs <skeggsb@gmail.com>
Tue, 13 Mar 2007 03:51:55 +0000 (14:51 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Tue, 13 Mar 2007 03:55:54 +0000 (14:55 +1100)
shared-core/nouveau_drv.h
shared-core/nouveau_fifo.c
shared-core/nouveau_object.c
shared-core/nouveau_state.c

index a4b0589..c27c93e 100644 (file)
@@ -191,7 +191,7 @@ extern int  nouveau_fifo_id_get(drm_device_t *dev, DRMFILE filp);
 extern void nouveau_fifo_free(drm_device_t *dev, int channel);
 
 /* nouveau_object.c */
-extern void nouveau_object_cleanup(drm_device_t *dev, DRMFILE filp);
+extern void nouveau_object_cleanup(drm_device_t *dev, int channel);
 extern struct nouveau_object *
 nouveau_object_gr_create(drm_device_t *dev, int channel, int class);
 extern struct nouveau_object *
index 8c4e830..3ffb051 100644 (file)
@@ -527,15 +527,20 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,
        if (i==nouveau_fifo_number(dev))
                return DRM_ERR(EINVAL);
 
+       /* that fifo is used */
+       dev_priv->fifos[i].used = 1;
+       dev_priv->fifos[i].filp = filp;
+       /* FIFO has no objects yet */
+       dev_priv->fifos[i].objs = NULL;
+
        /* allocate a command buffer, and create a dma object for the gpu */
        ret = nouveau_fifo_cmdbuf_alloc(dev, i);
-       if (ret) return ret;
+       if (ret) {
+               nouveau_fifo_free(dev, i);
+               return ret;
+       }
        cb_obj = dev_priv->fifos[i].cmdbuf_obj;
 
-       /* that fifo is used */
-       dev_priv->fifos[i].used=1;
-       dev_priv->fifos[i].filp=filp;
-
        init->channel  = i;
        init->put_base = 0;
        dev_priv->cur_fifo = init->channel;
@@ -638,8 +643,6 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,
        init->cmdbuf       = dev_priv->fifos[init->channel].cmdbuf_mem->start;
        init->cmdbuf_size  = dev_priv->fifos[init->channel].cmdbuf_mem->size;
 
-       /* FIFO has no objects yet */
-       dev_priv->fifos[init->channel].objs = NULL;
        dev_priv->fifo_alloc_count++;
 
        DRM_INFO("%s: initialised FIFO %d\n", __func__, init->channel);
@@ -647,43 +650,51 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,
 }
 
 /* stops a fifo */
-void nouveau_fifo_free(drm_device_t* dev,int n)
+void nouveau_fifo_free(drm_device_t* dev, int channel)
 {
        drm_nouveau_private_t *dev_priv = dev->dev_private;
+       struct nouveau_fifo *chan = &dev_priv->fifos[channel];
        int i;
        int ctx_size = nouveau_fifo_ctx_size(dev);
 
-       dev_priv->fifos[n].used=0;
-       DRM_INFO("%s: freeing fifo %d\n", __func__, n);
+       chan->used = 0;
+       DRM_INFO("%s: freeing fifo %d\n", __func__, channel);
 
        /* disable the fifo caches */
        NV_WRITE(NV03_PFIFO_CACHES, 0x00000000);
 
-       NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)&~(1<<n));
+       NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<<channel));
        // FIXME XXX needs more code
        
        /* Clean RAMFC */
        for (i=0;i<ctx_size;i+=4) {
                DRM_DEBUG("RAMFC +%02x: 0x%08x\n", i, NV_READ(NV_RAMIN +
-                                       dev_priv->ramfc_offset + n*ctx_size + i));
-               NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset + n*ctx_size + i, 0);
+                                       dev_priv->ramfc_offset + 
+                                       channel*ctx_size + i));
+               NV_WRITE(NV_RAMIN + dev_priv->ramfc_offset +
+                               channel*ctx_size + i, 0);
        }
 
+       /* Cleanup PGRAPH state */
        if (dev_priv->card_type >= NV_40)
-               nouveau_instmem_free(dev, dev_priv->fifos[n].ramin_grctx);
+               nouveau_instmem_free(dev, chan->ramin_grctx);
        else if (dev_priv->card_type >= NV_30) {
        }
        else if (dev_priv->card_type >= NV_20) {
                /* clear ctx table */
-               INSTANCE_WR(dev_priv->ctx_table, n, 0);
-               nouveau_instmem_free(dev, dev_priv->fifos[n].ramin_grctx);
+               INSTANCE_WR(dev_priv->ctx_table, channel, 0);
+               nouveau_instmem_free(dev, chan->ramin_grctx);
        }
 
        /* reenable the fifo caches */
        NV_WRITE(NV03_PFIFO_CACHES, 0x00000001);
 
-       /* Deallocate command buffer, and dma object */
-       nouveau_mem_free(dev, dev_priv->fifos[n].cmdbuf_mem);
+       /* Deallocate command buffer */
+       if (chan->cmdbuf_mem)
+               nouveau_mem_free(dev, chan->cmdbuf_mem);
+
+       /* Destroy objects belonging to the channel */
+       nouveau_object_cleanup(dev, channel);
 
        dev_priv->fifo_alloc_count--;
 }
index c5cf849..83f039d 100644 (file)
@@ -461,17 +461,13 @@ nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj)
        drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
 }
 
-void nouveau_object_cleanup(drm_device_t *dev, DRMFILE filp)
+void nouveau_object_cleanup(drm_device_t *dev, int channel)
 {
        drm_nouveau_private_t *dev_priv=dev->dev_private;
-       int channel;
-
-       channel = nouveau_fifo_id_get(dev, filp);
-       if (channel == -1)
-               return;
 
-       while (dev_priv->fifos[channel].objs)
+       while (dev_priv->fifos[channel].objs) {
                nouveau_object_free(dev, dev_priv->fifos[channel].objs);
+       }
 }
 
 int nouveau_ioctl_object_init(DRM_IOCTL_ARGS)
index e1fc633..ed45c16 100644 (file)
@@ -34,7 +34,6 @@ void nouveau_preclose(drm_device_t * dev, DRMFILE filp)
 
        nouveau_mem_release(filp,dev_priv->fb_heap);
        nouveau_mem_release(filp,dev_priv->agp_heap);
-       nouveau_object_cleanup(dev, filp);
        nouveau_fifo_cleanup(dev, filp);
 }