summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shared-core/nouveau_dma.c11
-rw-r--r--shared-core/nouveau_drv.h1
-rw-r--r--shared-core/nouveau_fifo.c78
3 files changed, 53 insertions, 37 deletions
diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c
index ce5b6299..ab502e6a 100644
--- a/shared-core/nouveau_dma.c
+++ b/shared-core/nouveau_dma.c
@@ -37,13 +37,22 @@ nouveau_dma_channel_init(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm_channel *dchan = &dev_priv->channel;
struct nouveau_gpuobj *gpuobj = NULL;
+ struct mem_block *pushbuf;
int grclass, ret, i;
DRM_DEBUG("\n");
+ pushbuf = nouveau_mem_alloc(dev, 0, 0x8000,
+ NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
+ (struct drm_file *)-2);
+ if (!pushbuf) {
+ DRM_ERROR("Failed to allocate DMA push buffer\n");
+ return -ENOMEM;
+ }
+
/* Allocate channel */
ret = nouveau_fifo_alloc(dev, &dchan->chan, (struct drm_file *)-2,
- NvDmaFB, NvDmaTT);
+ pushbuf, NvDmaFB, NvDmaTT);
if (ret) {
DRM_ERROR("Error allocating GPU channel: %d\n", ret);
return ret;
diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h
index 10f9149e..572df46e 100644
--- a/shared-core/nouveau_drv.h
+++ b/shared-core/nouveau_drv.h
@@ -365,6 +365,7 @@ extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *,
extern int nouveau_fifo_alloc(struct drm_device *dev,
struct nouveau_channel **chan,
struct drm_file *file_priv,
+ struct mem_block *pushbuf,
uint32_t fb_ctxdma, uint32_t tt_ctxdma);
extern void nouveau_fifo_free(struct nouveau_channel *);
diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c
index f9677514..22bced14 100644
--- a/shared-core/nouveau_fifo.c
+++ b/shared-core/nouveau_fifo.c
@@ -190,46 +190,30 @@ int nouveau_fifo_init(struct drm_device *dev)
}
static int
-nouveau_fifo_cmdbuf_alloc(struct nouveau_channel *chan)
+nouveau_fifo_pushbuf_ctxdma_init(struct nouveau_channel *chan)
{
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
- struct nouveau_config *config = &dev_priv->config;
- struct mem_block *cb;
- int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
+ struct mem_block *pb = chan->pushbuf_mem;
struct nouveau_gpuobj *pushbuf = NULL;
int ret;
- /* Defaults for unconfigured values */
- if (!config->cmdbuf.location)
- config->cmdbuf.location = NOUVEAU_MEM_FB;
- if (!config->cmdbuf.size || config->cmdbuf.size < cb_min_size)
- config->cmdbuf.size = cb_min_size;
-
- cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
- config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
- (struct drm_file *)-2);
- if (!cb) {
- DRM_ERROR("Couldn't allocate DMA command buffer.\n");
- return -ENOMEM;
- }
-
- if (cb->flags & NOUVEAU_MEM_AGP) {
- ret = nouveau_gpuobj_gart_dma_new(chan, cb->start, cb->size,
+ if (pb->flags & NOUVEAU_MEM_AGP) {
+ ret = nouveau_gpuobj_gart_dma_new(chan, pb->start, pb->size,
NV_DMA_ACCESS_RO,
&pushbuf,
&chan->pushbuf_base);
} else
- if (cb->flags & NOUVEAU_MEM_PCI) {
+ if (pb->flags & NOUVEAU_MEM_PCI) {
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
- cb->start, cb->size,
+ pb->start, pb->size,
NV_DMA_ACCESS_RO,
NV_DMA_TARGET_PCI_NONLINEAR,
&pushbuf);
chan->pushbuf_base = 0;
} else if (dev_priv->card_type != NV_04) {
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
- cb->start, cb->size,
+ pb->start, pb->size,
NV_DMA_ACCESS_RO,
NV_DMA_TARGET_VIDMEM, &pushbuf);
chan->pushbuf_base = 0;
@@ -239,19 +223,13 @@ nouveau_fifo_cmdbuf_alloc(struct nouveau_channel *chan)
* VRAM.
*/
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
- cb->start +
+ pb->start +
drm_get_resource_start(dev, 1),
- cb->size, NV_DMA_ACCESS_RO,
+ pb->size, NV_DMA_ACCESS_RO,
NV_DMA_TARGET_PCI, &pushbuf);
chan->pushbuf_base = 0;
}
- if (ret) {
- nouveau_mem_free(dev, cb);
- DRM_ERROR("Error creating push buffer ctxdma: %d\n", ret);
- return ret;
- }
-
if ((ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf,
&chan->pushbuf))) {
DRM_ERROR("Error referencing push buffer ctxdma: %d\n", ret);
@@ -260,14 +238,36 @@ nouveau_fifo_cmdbuf_alloc(struct nouveau_channel *chan)
return ret;
}
- chan->pushbuf_mem = cb;
return 0;
}
+static struct mem_block *
+nouveau_fifo_user_pushbuf_alloc(struct drm_device *dev)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_config *config = &dev_priv->config;
+ struct mem_block *pb;
+ int pb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE);
+
+ /* Defaults for unconfigured values */
+ if (!config->cmdbuf.location)
+ config->cmdbuf.location = NOUVEAU_MEM_FB;
+ if (!config->cmdbuf.size || config->cmdbuf.size < pb_min_size)
+ config->cmdbuf.size = pb_min_size;
+
+ pb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size,
+ config->cmdbuf.location | NOUVEAU_MEM_MAPPED,
+ (struct drm_file *)-2);
+ if (!pb)
+ DRM_ERROR("Couldn't allocate DMA push buffer.\n");
+
+ return pb;
+}
+
/* allocates and initializes a fifo for user space consumption */
int
nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
- struct drm_file *file_priv,
+ struct drm_file *file_priv, struct mem_block *pushbuf,
uint32_t vram_handle, uint32_t tt_handle)
{
int ret;
@@ -303,6 +303,7 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
chan->dev = dev;
chan->id = channel;
chan->file_priv = file_priv;
+ chan->pushbuf_mem = pushbuf;
DRM_INFO("Allocating FIFO number %d\n", channel);
@@ -320,8 +321,8 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
return ret;
}
- /* allocate a command buffer, and create a dma object for the gpu */
- ret = nouveau_fifo_cmdbuf_alloc(chan);
+ /* Create a dma object for the push buffer */
+ ret = nouveau_fifo_pushbuf_ctxdma_init(chan);
if (ret) {
nouveau_fifo_free(chan);
return ret;
@@ -467,6 +468,7 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
struct drm_nouveau_channel_alloc *init = data;
struct drm_map_list *entry;
struct nouveau_channel *chan;
+ struct mem_block *pushbuf;
int res;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
@@ -474,7 +476,11 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
return -EINVAL;
- res = nouveau_fifo_alloc(dev, &chan, file_priv,
+ pushbuf = nouveau_fifo_user_pushbuf_alloc(dev);
+ if (!pushbuf)
+ return -ENOMEM;
+
+ res = nouveau_fifo_alloc(dev, &chan, file_priv, pushbuf,
init->fb_ctxdma_handle,
init->tt_ctxdma_handle);
if (res)