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.c70
1 files changed, 41 insertions, 29 deletions
diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c
index 79875ca1..a394ae6e 100644
--- a/shared-core/nouveau_object.c
+++ b/shared-core/nouveau_object.c
@@ -76,7 +76,8 @@ nouveau_ramht_hash_handle(drm_device_t *dev, int channel, uint32_t handle)
hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1));
handle >>= dev_priv->ramht_bits;
}
- hash ^= channel << (dev_priv->ramht_bits - 4);
+ if (dev_priv->card_type < NV_50)
+ hash ^= channel << (dev_priv->ramht_bits - 4);
hash <<= 3;
DRM_DEBUG("ch%d handle=0x%08x hash=0x%08x\n", channel, handle, hash);
@@ -99,7 +100,7 @@ static int
nouveau_ramht_insert(drm_device_t* dev, nouveau_gpuobj_ref_t *ref)
{
drm_nouveau_private_t *dev_priv=dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[ref->channel];
+ struct nouveau_fifo *chan = dev_priv->fifos[ref->channel];
nouveau_gpuobj_t *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
nouveau_gpuobj_t *gpuobj = ref->gpuobj;
uint32_t ctx, co, ho;
@@ -148,7 +149,7 @@ static void
nouveau_ramht_remove(drm_device_t* dev, nouveau_gpuobj_ref_t *ref)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[ref->channel];
+ struct nouveau_fifo *chan = dev_priv->fifos[ref->channel];
nouveau_gpuobj_t *ramht = chan->ramht ? chan->ramht->gpuobj : NULL;
uint32_t co, ho;
@@ -183,9 +184,11 @@ nouveau_gpuobj_new(drm_device_t *dev, int channel, int size, int align,
uint32_t flags, nouveau_gpuobj_t **gpuobj_ret)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
+ nouveau_engine_func_t *engine = &dev_priv->Engine;
struct nouveau_fifo *chan = NULL;
nouveau_gpuobj_t *gpuobj;
struct mem_block *pramin = NULL;
+ int ret;
DRM_DEBUG("ch%d size=%d align=%d flags=0x%08x\n",
channel, size, align, flags);
@@ -196,7 +199,7 @@ nouveau_gpuobj_new(drm_device_t *dev, int channel, int size, int align,
if (channel >= 0) {
if (channel > nouveau_fifo_number(dev))
return DRM_ERR(EINVAL);
- chan = &dev_priv->fifos[channel];
+ chan = dev_priv->fifos[channel];
}
gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER);
@@ -230,6 +233,11 @@ nouveau_gpuobj_new(drm_device_t *dev, int channel, int size, int align,
return DRM_ERR(EINVAL);
}
+ if (!chan && (ret = engine->instmem.populate(dev, gpuobj, &size))) {
+ nouveau_gpuobj_del(dev, &gpuobj);
+ return ret;
+ }
+
/* Allocate a chunk of the PRAMIN aperture */
gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,
drm_order(align),
@@ -240,14 +248,9 @@ nouveau_gpuobj_new(drm_device_t *dev, int channel, int size, int align,
}
gpuobj->im_pramin->flags = NOUVEAU_MEM_INSTANCE;
- /* On NV50 the PRAMIN aperture is paged. When allocating from the
- * global instmem heap, alloc and bind VRAM pages into the PRAMIN
- * aperture.
- */
- if (!chan && dev_priv->card_type >= NV_50) {
- DRM_ERROR("back aperture with vram pages\n");
+ if (!chan && (ret = engine->instmem.bind(dev, gpuobj))) {
nouveau_gpuobj_del(dev, &gpuobj);
- return DRM_ERR(EINVAL);
+ return ret;
}
if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
@@ -285,6 +288,7 @@ void nouveau_gpuobj_takedown(drm_device_t *dev)
int nouveau_gpuobj_del(drm_device_t *dev, nouveau_gpuobj_t **pgpuobj)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
+ nouveau_engine_func_t *engine = &dev_priv->Engine;
nouveau_gpuobj_t *gpuobj;
DRM_DEBUG("gpuobj %p\n", pgpuobj ? *pgpuobj : NULL);
@@ -298,6 +302,8 @@ int nouveau_gpuobj_del(drm_device_t *dev, nouveau_gpuobj_t **pgpuobj)
return DRM_ERR(EINVAL);
}
+ engine->instmem.clear(dev, gpuobj);
+
if (gpuobj->im_pramin) {
if (gpuobj->flags & NVOBJ_FLAG_FAKE)
drm_free(gpuobj->im_pramin, sizeof(*gpuobj->im_pramin),
@@ -306,9 +312,6 @@ int nouveau_gpuobj_del(drm_device_t *dev, nouveau_gpuobj_t **pgpuobj)
nouveau_mem_free_block(gpuobj->im_pramin);
}
- if (gpuobj->im_backing)
- nouveau_mem_free(dev, gpuobj->im_backing);
-
if (gpuobj->next)
gpuobj->next->prev = gpuobj->prev;
if (gpuobj->prev)
@@ -342,7 +345,7 @@ nouveau_gpuobj_instance_get(drm_device_t *dev, int channel,
/* NV50 channel-local instance */
if (channel > 0) {
- cpramin = dev_priv->fifos[channel].ramin->gpuobj;
+ cpramin = dev_priv->fifos[channel]->ramin->gpuobj;
*inst = gpuobj->im_pramin->start - cpramin->im_pramin->start;
return 0;
}
@@ -358,7 +361,7 @@ nouveau_gpuobj_instance_get(drm_device_t *dev, int channel,
return 0;
} else {
/* ...from local heap */
- cpramin = dev_priv->fifos[gpuobj->im_channel].ramin->gpuobj;
+ cpramin = dev_priv->fifos[gpuobj->im_channel]->ramin->gpuobj;
*inst = (cpramin->im_backing->start - dev_priv->fb_phys) +
(gpuobj->im_pramin->start - cpramin->im_pramin->start);
return 0;
@@ -385,7 +388,7 @@ nouveau_gpuobj_ref_add(drm_device_t *dev, int channel, uint32_t handle,
if (channel >= 0) {
if (channel > nouveau_fifo_number(dev))
return DRM_ERR(EINVAL);
- chan = &dev_priv->fifos[channel];
+ chan = dev_priv->fifos[channel];
} else
if (!ref_ret)
return DRM_ERR(EINVAL);
@@ -591,9 +594,10 @@ nouveau_gpuobj_dma_new(drm_device_t *dev, int channel, int class,
INSTANCE_WR(*gpuobj, 2, frame | pte_flags);
INSTANCE_WR(*gpuobj, 3, frame | pte_flags);
} else {
- nouveau_gpuobj_del(dev, gpuobj);
- DRM_ERROR("stub\n");
- return DRM_ERR(EINVAL);
+ INSTANCE_WR(*gpuobj, 0, 0x00190000 | class);
+ INSTANCE_WR(*gpuobj, 1, offset + size - 1);
+ INSTANCE_WR(*gpuobj, 2, offset);
+ INSTANCE_WR(*gpuobj, 5, 0x00010000);
}
(*gpuobj)->engine = NVOBJ_ENGINE_SW;
@@ -672,11 +676,9 @@ nouveau_gpuobj_gr_new(drm_device_t *dev, int channel, int class,
}
if (dev_priv->card_type >= NV_50) {
- nouveau_gpuobj_del(dev, gpuobj);
- DRM_ERROR("stub!\n");
- return DRM_ERR(EINVAL);
- }
-
+ INSTANCE_WR(*gpuobj, 0, class);
+ INSTANCE_WR(*gpuobj, 5, 0x00010000);
+ } else {
switch (class) {
case NV_CLASS_NULL:
INSTANCE_WR(*gpuobj, 0, 0x00001030);
@@ -696,6 +698,7 @@ nouveau_gpuobj_gr_new(drm_device_t *dev, int channel, int class,
#endif
}
}
+ }
(*gpuobj)->engine = NVOBJ_ENGINE_GR;
(*gpuobj)->class = class;
@@ -706,7 +709,7 @@ static int
nouveau_gpuobj_channel_init_pramin(drm_device_t *dev, int channel)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ struct nouveau_fifo *chan = dev_priv->fifos[channel];
nouveau_gpuobj_t *pramin = NULL;
int size, base, ret;
@@ -719,7 +722,16 @@ nouveau_gpuobj_channel_init_pramin(drm_device_t *dev, int channel)
/* PGRAPH context */
if (dev_priv->card_type == NV_50) {
- /* RAMHT, RAMFC, PD, funny header thingo */
+ /* Various fixed table thingos */
+ size += 0x1400; /* mostly unknown stuff */
+ size += 0x4000; /* vm pd */
+ base = 0x6000;
+ /* RAMHT, not sure about setting size yet, 32KiB to be safe */
+ size += 0x8000;
+ /* RAMFC */
+ size += 0x1000;
+ /* PGRAPH context */
+ size += 0x60000;
}
DRM_DEBUG("ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n",
@@ -748,7 +760,7 @@ nouveau_gpuobj_channel_init(drm_device_t *dev, int channel,
uint32_t vram_h, uint32_t tt_h)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ struct nouveau_fifo *chan = dev_priv->fifos[channel];
nouveau_gpuobj_t *vram = NULL, *tt = NULL;
int ret;
@@ -817,7 +829,7 @@ void
nouveau_gpuobj_channel_takedown(drm_device_t *dev, int channel)
{
drm_nouveau_private_t *dev_priv = dev->dev_private;
- struct nouveau_fifo *chan = &dev_priv->fifos[channel];
+ struct nouveau_fifo *chan = dev_priv->fifos[channel];
nouveau_gpuobj_ref_t *ref;
DRM_DEBUG("ch%d\n", channel);