summaryrefslogtreecommitdiff
path: root/shared-core/nouveau_object.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core/nouveau_object.c')
-rw-r--r--shared-core/nouveau_object.c148
1 files changed, 72 insertions, 76 deletions
diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c
index b3c4b0e0..83f039db 100644
--- a/shared-core/nouveau_object.c
+++ b/shared-core/nouveau_object.c
@@ -44,8 +44,8 @@
* in the future when we can access more instance ram which isn't mapped into
* the PRAMIN aperture
*/
-uint32_t nouveau_chip_instance_get(drm_device_t *dev,
- struct mem_block *mem)
+uint32_t
+nouveau_chip_instance_get(drm_device_t *dev, struct mem_block *mem)
{
uint32_t inst = (uint32_t)mem->start >> 4;
DRM_DEBUG("****** on-chip instance for 0x%016llx = 0x%08x\n",
@@ -53,34 +53,34 @@ uint32_t nouveau_chip_instance_get(drm_device_t *dev,
return inst;
}
-static void nouveau_object_link(drm_device_t *dev, int fifo_num,
- struct nouveau_object *obj)
+static void
+nouveau_object_link(drm_device_t *dev, struct nouveau_object *obj)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
- struct nouveau_fifo *fifo = &dev_priv->fifos[fifo_num];
+ struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel];
- if (!fifo->objs) {
- fifo->objs = obj;
+ if (!chan->objs) {
+ chan->objs = obj;
return;
}
obj->prev = NULL;
- obj->next = fifo->objs;
+ obj->next = chan->objs;
- fifo->objs->prev = obj;
- fifo->objs = obj;
+ chan->objs->prev = obj;
+ chan->objs = obj;
}
-static void nouveau_object_unlink(drm_device_t *dev, int fifo_num,
- struct nouveau_object *obj)
+static void
+nouveau_object_unlink(drm_device_t *dev, struct nouveau_object *obj)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
- struct nouveau_fifo *fifo = &dev_priv->fifos[fifo_num];
+ struct nouveau_fifo *chan = &dev_priv->fifos[obj->channel];
if (obj->prev == NULL) {
if (obj->next)
obj->next->prev = NULL;
- fifo->objs = obj->next;
+ chan->objs = obj->next;
} else if (obj->next == NULL) {
if (obj->prev)
obj->prev->next = NULL;
@@ -91,11 +91,11 @@ static void nouveau_object_unlink(drm_device_t *dev, int fifo_num,
}
static struct nouveau_object *
-nouveau_object_handle_find(drm_device_t *dev, int fifo_num, uint32_t handle)
+nouveau_object_handle_find(drm_device_t *dev, int channel, uint32_t handle)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
- struct nouveau_fifo *fifo = &dev_priv->fifos[fifo_num];
- struct nouveau_object *obj = fifo->objs;
+ struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ struct nouveau_object *obj = chan->objs;
DRM_DEBUG("Looking for handle 0x%08x\n", handle);
while (obj) {
@@ -138,8 +138,8 @@ nouveau_object_handle_find(drm_device_t *dev, int fifo_num, uint32_t handle)
The key into the hash table depends on the object handle and channel id and
is given as:
*/
-static uint32_t nouveau_handle_hash(drm_device_t* dev, uint32_t handle,
- int fifo)
+static uint32_t
+nouveau_ht_handle_hash(drm_device_t *dev, int channel, uint32_t handle)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
uint32_t hash = 0;
@@ -149,19 +149,21 @@ static uint32_t nouveau_handle_hash(drm_device_t* dev, uint32_t handle,
hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1));
handle >>= dev_priv->ramht_bits;
}
- hash ^= fifo << (dev_priv->ramht_bits - 4);
+ hash ^= channel << (dev_priv->ramht_bits - 4);
return hash << 3;
}
-static int nouveau_hash_table_insert(drm_device_t* dev, int fifo,
- struct nouveau_object *obj)
+static int
+nouveau_ht_object_insert(drm_device_t* dev, int channel, uint32_t handle,
+ struct nouveau_object *obj)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
int ht_base = NV_RAMIN + dev_priv->ramht_offset;
int ht_end = ht_base + dev_priv->ramht_size;
int o_ofs, ofs;
- o_ofs = ofs = nouveau_handle_hash(dev, obj->handle, fifo);
+ obj->handle = handle;
+ o_ofs = ofs = nouveau_ht_handle_hash(dev, channel, obj->handle);
while (NV_READ(ht_base + ofs) || NV_READ(ht_base + ofs + 4)) {
ofs += 8;
@@ -174,19 +176,19 @@ static int nouveau_hash_table_insert(drm_device_t* dev, int fifo,
ofs += ht_base;
DRM_DEBUG("Channel %d - Handle 0x%08x at 0x%08x\n",
- fifo, obj->handle, ofs);
+ channel, obj->handle, ofs);
NV_WRITE(NV_RAMHT_HANDLE_OFFSET + ofs, obj->handle);
if (dev_priv->card_type >= NV_40)
NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
- (fifo << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+ (channel << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) |
(obj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT) |
nouveau_chip_instance_get(dev, obj->instance)
);
else
NV_WRITE(NV_RAMHT_CONTEXT_OFFSET + ofs,
NV_RAMHT_CONTEXT_VALID |
- (fifo << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
+ (channel << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) |
(obj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT) |
nouveau_chip_instance_get(dev, obj->instance)
);
@@ -210,7 +212,8 @@ static void nouveau_hash_table_remove(drm_device_t* dev,
}
}
-static struct nouveau_object *nouveau_instance_alloc(drm_device_t* dev)
+static struct nouveau_object *
+nouveau_object_instance_alloc(drm_device_t* dev, int channel)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
struct nouveau_object *obj;
@@ -221,6 +224,8 @@ static struct nouveau_object *nouveau_instance_alloc(drm_device_t* dev)
DRM_ERROR("couldn't alloc memory for object\n");
return NULL;
}
+
+ /* Allocate instance memory */
obj->instance = nouveau_instmem_alloc(dev,
(dev_priv->card_type >= NV_40 ? 32 : 16), 4);
if (!obj->instance) {
@@ -229,25 +234,28 @@ static struct nouveau_object *nouveau_instance_alloc(drm_device_t* dev)
return NULL;
}
+ /* Bind object to channel */
+ obj->channel = channel;
+ obj->handle = ~0;
+ nouveau_object_link(dev, obj);
+
return obj;
}
-static void nouveau_object_instance_free(drm_device_t *dev,
- struct nouveau_object *obj)
+static void
+nouveau_object_instance_free(drm_device_t *dev, struct nouveau_object *obj)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
- int count, i;
+ int i;
- if (dev_priv->card_type >= NV_40)
- count = 8;
- else
- count = 4;
+ /* Unbind object from channel */
+ nouveau_object_unlink(dev, obj);
/* Clean RAMIN entry */
DRM_DEBUG("Instance entry for 0x%08x"
"(engine %d, class 0x%x) before destroy:\n",
obj->handle, obj->engine, obj->class);
- for (i=0;i<count;i++) {
+ for (i=0; i<(obj->instance->size/4); i++) {
DRM_DEBUG(" +0x%02x: 0x%08x\n", (i*4),
INSTANCE_RD(obj->instance, i));
INSTANCE_WR(obj->instance, i, 0x00000000);
@@ -283,7 +291,7 @@ static void nouveau_object_instance_free(drm_device_t *dev,
*/
struct nouveau_object *
-nouveau_dma_object_create(drm_device_t* dev, int class,
+nouveau_object_dma_create(drm_device_t* dev, int channel, int class,
uint32_t offset, uint32_t size,
int access, int target)
{
@@ -318,7 +326,7 @@ nouveau_dma_object_create(drm_device_t* dev, int class,
frame = offset & ~0x00000FFF;
adjust = offset & 0x00000FFF;
- obj = nouveau_instance_alloc(dev);
+ obj = nouveau_object_instance_alloc(dev, channel);
if (!obj) {
DRM_ERROR("couldn't allocate DMA object\n");
return obj;
@@ -391,15 +399,15 @@ nouveau_dma_object_create(drm_device_t* dev, int class,
entry[5]:
set to 0?
*/
-static struct nouveau_object *
-nouveau_context_object_create(drm_device_t* dev, int class)
+struct nouveau_object *
+nouveau_object_gr_create(drm_device_t* dev, int channel, int class)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
struct nouveau_object *obj;
DRM_DEBUG("class=%x\n", class);
- obj = nouveau_instance_alloc(dev);
+ obj = nouveau_object_instance_alloc(dev, channel);
if (!obj) {
DRM_ERROR("couldn't allocate context object\n");
return obj;
@@ -444,29 +452,22 @@ nouveau_context_object_create(drm_device_t* dev, int class)
return obj;
}
-static void
-nouveau_object_free(drm_device_t *dev, int fifo_num, struct nouveau_object *obj)
+void
+nouveau_object_free(drm_device_t *dev, struct nouveau_object *obj)
{
- nouveau_object_unlink(dev, fifo_num, obj);
-
nouveau_object_instance_free(dev, obj);
- nouveau_hash_table_remove(dev, obj);
-
+ if (obj->handle != ~0)
+ nouveau_hash_table_remove(dev, obj);
drm_free(obj, sizeof(struct nouveau_object), DRM_MEM_DRIVER);
- return;
}
-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 fifo;
-
- fifo = nouveau_fifo_id_get(dev, filp);
- if (fifo == -1)
- return;
- while (dev_priv->fifos[fifo].objs)
- nouveau_object_free(dev, fifo, dev_priv->fifos[fifo].objs);
+ while (dev_priv->fifos[channel].objs) {
+ nouveau_object_free(dev, dev_priv->fifos[channel].objs);
+ }
}
int nouveau_ioctl_object_init(DRM_IOCTL_ARGS)
@@ -474,10 +475,10 @@ int nouveau_ioctl_object_init(DRM_IOCTL_ARGS)
DRM_DEVICE;
drm_nouveau_object_init_t init;
struct nouveau_object *obj;
- int fifo;
+ int channel;
- fifo = nouveau_fifo_id_get(dev, filp);
- if (fifo == -1)
+ channel = nouveau_fifo_id_get(dev, filp);
+ if (channel == -1)
return DRM_ERR(EINVAL);
DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_object_init_t __user *)
@@ -485,24 +486,21 @@ int nouveau_ioctl_object_init(DRM_IOCTL_ARGS)
//FIXME: check args, only allow trusted objects to be created
- if (nouveau_object_handle_find(dev, fifo, init.handle)) {
+ if (nouveau_object_handle_find(dev, channel, init.handle)) {
DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
- fifo, init.handle);
+ channel, init.handle);
return DRM_ERR(EINVAL);
}
- obj = nouveau_context_object_create(dev, init.class);
+ obj = nouveau_object_gr_create(dev, channel, init.class);
if (!obj)
return DRM_ERR(ENOMEM);
- obj->handle = init.handle;
- if (nouveau_hash_table_insert(dev, fifo, obj)) {
- nouveau_object_free(dev, fifo, obj);
+ if (nouveau_ht_object_insert(dev, channel, init.handle, obj)) {
+ nouveau_object_free(dev, obj);
return DRM_ERR(ENOMEM);
}
- nouveau_object_link(dev, fifo, obj);
-
return 0;
}
@@ -569,10 +567,10 @@ int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS)
DRM_DEVICE;
drm_nouveau_dma_object_init_t init;
struct nouveau_object *obj;
- int fifo;
+ int channel;
- fifo = nouveau_fifo_id_get(dev, filp);
- if (fifo == -1)
+ channel = nouveau_fifo_id_get(dev, filp);
+ if (channel == -1)
return DRM_ERR(EINVAL);
DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_dma_object_init_t __user *)
@@ -581,26 +579,24 @@ int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS)
if (nouveau_dma_object_check_access(dev, &init))
return DRM_ERR(EPERM);
- if (nouveau_object_handle_find(dev, fifo, init.handle)) {
+ if (nouveau_object_handle_find(dev, channel, init.handle)) {
DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
- fifo, init.handle);
+ channel, init.handle);
return DRM_ERR(EINVAL);
}
- obj = nouveau_dma_object_create(dev, init.class,
+ obj = nouveau_object_dma_create(dev, channel, init.class,
init.offset, init.size,
init.access, init.target);
if (!obj)
return DRM_ERR(ENOMEM);
obj->handle = init.handle;
- if (nouveau_hash_table_insert(dev, fifo, obj)) {
- nouveau_object_free(dev, fifo, obj);
+ if (nouveau_ht_object_insert(dev, channel, init.handle, obj)) {
+ nouveau_object_free(dev, obj);
return DRM_ERR(ENOMEM);
}
- nouveau_object_link(dev, fifo, obj);
-
return 0;
}