nouveau: Alloc cmdbuf for each channel individually
parent
72cb361c5c
commit
9e019df757
|
@ -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;
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue