nouveau: Always allocate drm's push buffer in VRAM

Fixes #11868
main
Ben Skeggs 2007-08-08 16:37:55 +10:00
parent 40f2156356
commit 05633ca370
3 changed files with 53 additions and 37 deletions

View File

@ -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;

View File

@ -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 *);

View File

@ -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)