nouveau: Alloc cmdbuf for each channel individually
authorBen Skeggs <darktama@iinet.net.au>
Tue, 26 Dec 2006 12:30:26 +0000 (23:30 +1100)
committerBen Skeggs <darktama@iinet.net.au>
Tue, 26 Dec 2006 12:30:26 +0000 (23:30 +1100)
shared-core/nouveau_drv.h
shared-core/nouveau_fifo.c

index 4dff0c5..42397c3 100644 (file)
@@ -73,6 +73,7 @@ struct nouveau_fifo
        /* mapping of the regs controling the fifo */
        drm_local_map_t *regs;
        /* dma object for the command buffer itself */
+       struct mem_block      *cmdbuf_mem;
        struct nouveau_object *cmdbuf_obj;
        /* objects belonging to this fifo */
        struct nouveau_object *objs;
index f52f39f..1014d8a 100644 (file)
@@ -214,12 +214,14 @@ int nouveau_fifo_init(drm_device_t *dev)
        return 0;
 }
 
-static int nouveau_dma_init(struct drm_device *dev)
+static int
+nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel)
 {
        drm_nouveau_private_t *dev_priv = dev->dev_private;
        struct nouveau_config *config = &dev_priv->config;
        struct mem_block *cb;
-       int cb_min_size = nouveau_fifo_number(dev) * max(NV03_FIFO_SIZE,PAGE_SIZE);
+       struct nouveau_object *cb_dma = NULL;
+       int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
 
        /* Defaults for unconfigured values */
        if (!config->cmdbuf.location)
@@ -228,27 +230,40 @@ static int nouveau_dma_init(struct drm_device *dev)
                config->cmdbuf.size = cb_min_size;
 
        cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
-                       config->cmdbuf.location, (DRMFILE)-2);
-       /* Try defaults if that didn't succeed */
-       if (!cb) {
-               config->cmdbuf.location = NOUVEAU_MEM_FB;
-               config->cmdbuf.size = cb_min_size;
-               cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
-                               config->cmdbuf.location, (DRMFILE)-2);
-       }
+                       config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
+                       (DRMFILE)-2);
        if (!cb) {
                DRM_ERROR("Couldn't allocate DMA command buffer.\n");
                return DRM_ERR(ENOMEM);
        }
 
-       dev_priv->cmdbuf_ch_size = (uint32_t)cb->size / nouveau_fifo_number(dev);
-       dev_priv->cmdbuf_alloc = cb;
+       if (cb->flags & NOUVEAU_MEM_AGP) {
+               cb_dma = nouveau_dma_object_create(dev,
+                               cb->start, cb->size,
+                               NV_DMA_ACCESS_RO, NV_DMA_TARGET_AGP);
+       } else if (dev_priv->card_type != NV_04) {
+               cb_dma = nouveau_dma_object_create(dev,
+                               cb->start - drm_get_resource_start(dev, 1),
+                               cb->size,
+                               NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM);
+       } else {
+               /* NV04 cmdbuf hack, from original ddx.. not sure of it's
+                * exact reason for existing :)  PCI access to cmdbuf in
+                * VRAM.
+                */
+               cb_dma = nouveau_dma_object_create(dev,
+                               cb->start, cb->size,
+                               NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI);
+       }
 
-       DRM_INFO("DMA command buffer is %dKiB at 0x%08x(%s)\n",
-                       (uint32_t)cb->size>>10, (uint32_t)cb->start,
-                       config->cmdbuf.location == NOUVEAU_MEM_FB ? "VRAM" : "AGP");
-       DRM_INFO("FIFO size is %dKiB\n", dev_priv->cmdbuf_ch_size>>10);
+       if (!cb_dma) {
+               nouveau_mem_free(dev, cb);
+               DRM_ERROR("Failed to alloc DMA object for command buffer\n");
+               return DRM_ERR(ENOMEM);
+       }
 
+       dev_priv->fifos[channel].cmdbuf_mem = cb;
+       dev_priv->fifos[channel].cmdbuf_obj = cb_dma;
        return 0;
 }
 
@@ -407,15 +422,6 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,
        drm_nouveau_private_t *dev_priv = dev->dev_private;
        struct nouveau_object *cb_obj;
 
-       /* Init cmdbuf on first FIFO init, this is delayed until now to
-        * give the ddx a chance to configure the cmdbuf with SETPARAM
-        */
-       if (!dev_priv->cmdbuf_alloc) {
-               ret = nouveau_dma_init(dev);
-               if (ret)
-                       return ret;
-       }
-
        /*
         * Alright, here is the full story
         * Nvidia cards have multiple hw fifo contexts (praise them for that, 
@@ -433,44 +439,17 @@ 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);
 
-       /* allocate a dma object for the command buffer */
-       if (dev_priv->cmdbuf_alloc->flags & NOUVEAU_MEM_AGP) {
-               cb_obj = nouveau_dma_object_create(dev,
-                               dev_priv->cmdbuf_alloc->start,
-                               dev_priv->cmdbuf_alloc->size,
-                               NV_DMA_ACCESS_RO,
-                               NV_DMA_TARGET_AGP);
-
-       } else if (dev_priv->card_type != NV_04) {
-               cb_obj = nouveau_dma_object_create(dev,
-                               dev_priv->cmdbuf_alloc->start -
-                                       drm_get_resource_start(dev, 1),
-                               dev_priv->cmdbuf_alloc->size,
-                               NV_DMA_ACCESS_RO,
-                               NV_DMA_TARGET_VIDMEM);
-       } else {
-               /* NV04 cmdbuf hack, from original ddx.. not sure of it's
-                * exact reason for existing :)  PCI access to cmdbuf in
-                * VRAM.
-                */
-               cb_obj = nouveau_dma_object_create(dev,
-                               dev_priv->cmdbuf_alloc->start,
-                               dev_priv->cmdbuf_alloc->size,
-                               NV_DMA_ACCESS_RO,
-                               NV_DMA_TARGET_PCI);
-       }
-       if (!cb_obj) {
-               DRM_ERROR("unable to alloc object for command buffer\n");
-               return DRM_ERR(EINVAL);
-       }
-       dev_priv->fifos[i].cmdbuf_obj = cb_obj;
+       /* allocate a command buffer, and create a dma object for the gpu */
+       ret = nouveau_fifo_cmdbuf_alloc(dev, i);
+       if (ret) 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 = i*dev_priv->cmdbuf_ch_size;
+       init->put_base = 0;
        dev_priv->cur_fifo = init->channel;
 
        nouveau_wait_for_idle(dev);
@@ -544,14 +523,9 @@ static int nouveau_fifo_alloc(drm_device_t* dev,drm_nouveau_fifo_alloc_t* init,
        if (ret != 0)
                return ret;
 
-       /* then, the fifo itself */
-       init->cmdbuf       = dev_priv->cmdbuf_alloc->start;
-       init->cmdbuf      += init->channel * dev_priv->cmdbuf_ch_size;
-       init->cmdbuf_size  = dev_priv->cmdbuf_ch_size;
-       ret = drm_addmap(dev, init->cmdbuf, init->cmdbuf_size, _DRM_REGISTERS,
-                        0, &dev_priv->fifos[init->channel].map);
-       if (ret != 0)
-               return ret;
+       /* pass back FIFO map info to the caller */
+       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;
@@ -587,6 +561,9 @@ void nouveau_fifo_free(drm_device_t* dev,int n)
        /* reenable the fifo caches */
        NV_WRITE(NV_PFIFO_CACHES, 0x00000001);
 
+       /* Deallocate command buffer, and dma object */
+       nouveau_mem_free(dev, dev_priv->fifos[n].cmdbuf_mem);
+
        dev_priv->fifo_alloc_count--;
 }