From beaa0c9a28b30a6ba3292184d04875b6a597e433 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2007 03:40:43 +1000 Subject: nouveau: Pass channel struct around instead of channel id. --- shared-core/nouveau_object.c | 150 ++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 81 deletions(-) (limited to 'shared-core/nouveau_object.c') diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index e8b12bb7..274bb2a7 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -100,7 +100,7 @@ static int nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) { struct drm_nouveau_private *dev_priv=dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[ref->channel]; + struct nouveau_channel *chan = dev_priv->fifos[ref->channel]; struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; struct nouveau_gpuobj *gpuobj = ref->gpuobj; uint32_t ctx, co, ho; @@ -149,7 +149,7 @@ static void nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[ref->channel]; + struct nouveau_channel *chan = dev_priv->fifos[ref->channel]; struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; uint32_t co, ho; @@ -180,34 +180,28 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) } int -nouveau_gpuobj_new(struct drm_device *dev, int channel, int size, int align, - uint32_t flags, struct nouveau_gpuobj **gpuobj_ret) +nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, + int size, int align, uint32_t flags, + struct nouveau_gpuobj **gpuobj_ret) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine_func *engine = &dev_priv->Engine; - struct nouveau_fifo *chan = NULL; + struct nouveau_engine *engine = &dev_priv->Engine; struct nouveau_gpuobj *gpuobj; struct mem_block *pramin = NULL; int ret; DRM_DEBUG("ch%d size=%d align=%d flags=0x%08x\n", - channel, size, align, flags); + chan ? chan->id : -1, size, align, flags); if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL) return -EINVAL; - if (channel >= 0) { - if (channel > nouveau_fifo_number(dev)) - return -EINVAL; - chan = dev_priv->fifos[channel]; - } - gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER); if (!gpuobj) return -ENOMEM; DRM_DEBUG("gpuobj %p\n", gpuobj); gpuobj->flags = flags; - gpuobj->im_channel = channel; + gpuobj->im_channel = chan ? chan->id : -1; /* Choose between global instmem heap, and per-channel private * instmem heap. On dev_private; - struct nouveau_engine_func *engine = &dev_priv->Engine; + struct nouveau_engine *engine = &dev_priv->Engine; struct nouveau_gpuobj *gpuobj; DRM_DEBUG("gpuobj %p\n", pgpuobj ? *pgpuobj : NULL); @@ -325,7 +319,8 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) } static int -nouveau_gpuobj_instance_get(struct drm_device *dev, int channel, +nouveau_gpuobj_instance_get(struct drm_device *dev, + struct nouveau_channel *chan, struct nouveau_gpuobj *gpuobj, uint32_t *inst) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -337,15 +332,15 @@ nouveau_gpuobj_instance_get(struct drm_device *dev, int channel, return 0; } - if ((channel > 0) && gpuobj->im_channel != channel) { + if (chan && gpuobj->im_channel != chan->id) { DRM_ERROR("Channel mismatch: obj %d, ref %d\n", - gpuobj->im_channel, channel); + gpuobj->im_channel, chan->id); return -EINVAL; } /* NV50 channel-local instance */ - if (channel > 0) { - cpramin = dev_priv->fifos[channel]->ramin->gpuobj; + if (chan > 0) { + cpramin = chan->ramin->gpuobj; *inst = gpuobj->im_pramin->start - cpramin->im_pramin->start; return 0; } @@ -371,29 +366,25 @@ nouveau_gpuobj_instance_get(struct drm_device *dev, int channel, } int -nouveau_gpuobj_ref_add(struct drm_device *dev, int channel, uint32_t handle, - struct nouveau_gpuobj *gpuobj, struct nouveau_gpuobj_ref **ref_ret) +nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan, + uint32_t handle, struct nouveau_gpuobj *gpuobj, + struct nouveau_gpuobj_ref **ref_ret) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = NULL; struct nouveau_gpuobj_ref *ref; uint32_t instance; int ret; - DRM_DEBUG("ch%d h=0x%08x gpuobj=%p\n", channel, handle, gpuobj); + DRM_DEBUG("ch%d h=0x%08x gpuobj=%p\n", + chan ? chan->id : -1, handle, gpuobj); if (!dev_priv || !gpuobj || (ref_ret && *ref_ret != NULL)) return -EINVAL; - if (channel >= 0) { - if (channel > nouveau_fifo_number(dev)) - return -EINVAL; - chan = dev_priv->fifos[channel]; - } else - if (!ref_ret) + if (!chan && !ref_ret) return -EINVAL; - ret = nouveau_gpuobj_instance_get(dev, channel, gpuobj, &instance); + ret = nouveau_gpuobj_instance_get(dev, chan, gpuobj, &instance); if (ret) return ret; @@ -401,7 +392,7 @@ nouveau_gpuobj_ref_add(struct drm_device *dev, int channel, uint32_t handle, if (!ref) return -ENOMEM; ref->gpuobj = gpuobj; - ref->channel = channel; + ref->channel = chan ? chan->id : -1; ref->instance = instance; if (!ref_ret) { @@ -452,8 +443,9 @@ int nouveau_gpuobj_ref_del(struct drm_device *dev, struct nouveau_gpuobj_ref **p } int -nouveau_gpuobj_new_ref(struct drm_device *dev, int oc, int rc, uint32_t handle, - int size, int align, uint32_t flags, +nouveau_gpuobj_new_ref(struct drm_device *dev, + struct nouveau_channel *oc, struct nouveau_channel *rc, + uint32_t handle, int size, int align, uint32_t flags, struct nouveau_gpuobj_ref **ref) { struct nouveau_gpuobj *gpuobj = NULL; @@ -471,11 +463,9 @@ nouveau_gpuobj_new_ref(struct drm_device *dev, int oc, int rc, uint32_t handle, } static int -nouveau_gpuobj_ref_find(struct drm_device *dev, int channel, uint32_t handle, +nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, struct nouveau_gpuobj_ref **ref_ret) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; struct nouveau_gpuobj_ref *ref = chan->ramht_refs; while (ref) { @@ -524,7 +514,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size, } if (pref) { - if ((i = nouveau_gpuobj_ref_add(dev, -1, 0, gpuobj, pref))) { + if ((i = nouveau_gpuobj_ref_add(dev, NULL, 0, gpuobj, pref))) { nouveau_gpuobj_del(dev, &gpuobj); return i; } @@ -577,10 +567,11 @@ nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class) to it that can be used to set up context objects. */ int -nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class, - uint64_t offset, uint64_t size, int access, int target, - struct nouveau_gpuobj **gpuobj) +nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, + uint64_t offset, uint64_t size, int access, + int target, struct nouveau_gpuobj **gpuobj) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; uint32_t is_scatter_gather = 0; @@ -591,7 +582,7 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class, DRM_DEBUG("ch%d class=0x%04x offset=0x%llx size=0x%llx\n", - channel, class, offset, size); + chan->id, class, offset, size); DRM_DEBUG("access=%d target=%d\n", access, target); switch (target) { @@ -608,7 +599,7 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class, break; } - ret = nouveau_gpuobj_new(dev, channel, + ret = nouveau_gpuobj_new(dev, chan, is_scatter_gather ? ((page_count << 2) + 12) : nouveau_gpuobj_class_instmem_size(dev, class), 16, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -711,19 +702,19 @@ nouveau_gpuobj_dma_new(struct drm_device *dev, int channel, int class, } int -nouveau_gpuobj_gart_dma_new(struct drm_device *dev, int channel, +nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan, uint64_t offset, uint64_t size, int access, struct nouveau_gpuobj **gpuobj, uint32_t *o_ret) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; if (dev_priv->gart_info.type == NOUVEAU_GART_AGP || (dev_priv->card_type >= NV_50 && dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) { - ret = nouveau_gpuobj_dma_new(dev, channel, - NV_CLASS_DMA_IN_MEMORY, + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, size, access, NV_DMA_TARGET_AGP, gpuobj); if (o_ret) @@ -798,15 +789,16 @@ nouveau_gpuobj_gart_dma_new(struct drm_device *dev, int channel, set to 0? */ int -nouveau_gpuobj_gr_new(struct drm_device *dev, int channel, int class, +nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, struct nouveau_gpuobj **gpuobj) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; - DRM_DEBUG("ch%d class=0x%04x\n", channel, class); + DRM_DEBUG("ch%d class=0x%04x\n", chan->id, class); - ret = nouveau_gpuobj_new(dev, channel, + ret = nouveau_gpuobj_new(dev, chan, nouveau_gpuobj_class_instmem_size(dev, class), 16, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -847,14 +839,14 @@ nouveau_gpuobj_gr_new(struct drm_device *dev, int channel, int class, } static int -nouveau_gpuobj_channel_init_pramin(struct drm_device *dev, int channel) +nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; struct nouveau_gpuobj *pramin = NULL; int size, base, ret; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); /* Base amount for object storage (4KiB enough?) */ size = 0x1000; @@ -876,8 +868,8 @@ nouveau_gpuobj_channel_init_pramin(struct drm_device *dev, int channel) } DRM_DEBUG("ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n", - channel, size, base); - ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, size, 0x1000, 0, + chan->id, size, base); + ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, &chan->ramin); if (ret) { DRM_ERROR("Error allocating channel PRAMIN: %d\n", ret); @@ -897,21 +889,21 @@ nouveau_gpuobj_channel_init_pramin(struct drm_device *dev, int channel) } int -nouveau_gpuobj_channel_init(struct drm_device *dev, int channel, +nouveau_gpuobj_channel_init(struct nouveau_channel *chan, uint32_t vram_h, uint32_t tt_h) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; struct nouveau_gpuobj *vram = NULL, *tt = NULL; int ret, i; - DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", channel, vram_h, tt_h); + DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); /* Reserve a block of PRAMIN for the channel *XXX: maybe on card_type == NV_50) { - ret = nouveau_gpuobj_channel_init_pramin(dev, channel); + ret = nouveau_gpuobj_channel_init_pramin(chan); if (ret) return ret; } @@ -930,7 +922,7 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel, INSTANCE_WR(chan->vm_pd, (i+4)/4, 0xdeadcafe); } - if ((ret = nouveau_gpuobj_ref_add(dev, -1, 0, + if ((ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->gart_info.sg_ctxdma, &chan->vm_gart_pt))) return ret; @@ -941,12 +933,12 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel, /* RAMHT */ if (dev_priv->card_type < NV_50) { - ret = nouveau_gpuobj_ref_add(dev, -1, 0, dev_priv->ramht, + ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->ramht, &chan->ramht); if (ret) return ret; } else { - ret = nouveau_gpuobj_new_ref(dev, channel, channel, 0, + ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 0x8000, 16, NVOBJ_FLAG_ZERO_ALLOC, &chan->ramht); @@ -955,7 +947,7 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel, } /* VRAM ctxdma */ - if ((ret = nouveau_gpuobj_dma_new(dev, channel, NV_CLASS_DMA_IN_MEMORY, + if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, dev_priv->fb_available_size, NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, &vram))) { @@ -963,20 +955,19 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel, return ret; } - if ((ret = nouveau_gpuobj_ref_add(dev, channel, vram_h, vram, NULL))) { + if ((ret = nouveau_gpuobj_ref_add(dev, chan, vram_h, vram, NULL))) { DRM_ERROR("Error referencing VRAM ctxdma: %d\n", ret); return ret; } /* TT memory ctxdma */ if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { - ret = nouveau_gpuobj_gart_dma_new(dev, channel, 0, + ret = nouveau_gpuobj_gart_dma_new(chan, 0, dev_priv->gart_info.aper_size, NV_DMA_ACCESS_RW, &tt, NULL); } else if (dev_priv->pci_heap) { - ret = nouveau_gpuobj_dma_new(dev, channel, - NV_CLASS_DMA_IN_MEMORY, + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, dev->sg->pages * PAGE_SIZE, NV_DMA_ACCESS_RW, NV_DMA_TARGET_PCI_NONLINEAR, &tt); @@ -990,7 +981,7 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel, return ret; } - ret = nouveau_gpuobj_ref_add(dev, channel, tt_h, tt, NULL); + ret = nouveau_gpuobj_ref_add(dev, chan, tt_h, tt, NULL); if (ret) { DRM_ERROR("Error referencing TT ctxdma: %d\n", ret); return ret; @@ -1000,13 +991,12 @@ nouveau_gpuobj_channel_init(struct drm_device *dev, int channel, } void -nouveau_gpuobj_channel_takedown(struct drm_device *dev, int channel) +nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; + struct drm_device *dev = chan->dev; struct nouveau_gpuobj_ref *ref; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); while ((ref = chan->ramht_refs)) { chan->ramht_refs = ref->next; @@ -1024,35 +1014,33 @@ nouveau_gpuobj_channel_takedown(struct drm_device *dev, int channel) } -int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { + struct nouveau_channel *chan; struct drm_nouveau_grobj_alloc *init = data; struct nouveau_gpuobj *gr = NULL; int ret; - if (!nouveau_fifo_owner(dev, file_priv, init->channel)) { - DRM_ERROR("pid %d doesn't own channel %d\n", - DRM_CURRENTPID, init->channel); - return -EINVAL; - } + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); //FIXME: check args, only allow trusted objects to be created if (init->handle == ~0) return -EINVAL; - if (nouveau_gpuobj_ref_find(dev, init->channel, init->handle, NULL) == + + if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) return -EEXIST; - ret = nouveau_gpuobj_gr_new(dev, init->channel, init->class, &gr); + ret = nouveau_gpuobj_gr_new(chan, init->class, &gr); if (ret) { DRM_ERROR("Error creating gr object: %d (%d/0x%08x)\n", ret, init->channel, init->handle); return ret; } - if ((ret = nouveau_gpuobj_ref_add(dev, init->channel, init->handle, - gr, NULL))) { + if ((ret = nouveau_gpuobj_ref_add(dev, chan, init->handle, gr, NULL))) { DRM_ERROR("Error referencing gr object: %d (%d/0x%08x\n)", ret, init->channel, init->handle); nouveau_gpuobj_del(dev, &gr); -- cgit v1.2.3 From 97770db72040dc032130413e0cdabc1777560a75 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2007 21:45:18 +1000 Subject: nouveau: Various internal and external API changes 1. DRM_NOUVEAU_GPUOBJ_FREE Used to free GPU objects. The obvious usage case is for Gr objects, but notifiers can also be destroyed in the same way. GPU objects gain a destructor method and private data fields with this change, so other specialised cases (like notifiers) can be implemented on top of gpuobjs. 2. DRM_NOUVEAU_CHANNEL_FREE 3. DRM_NOUVEAU_CARD_INIT Ideally we'd do init during module load, but this isn't currently possible. Doing init during firstopen() is bad as X has a love of opening/closing the DRM many times during startup. Once the modesetting-101 branch is merged this can go away. IRQs are enabled in nouveau_card_init() now, rather than having the X server call drmCtlInstHandler(). We'll need this for when we give the kernel module its own channel. 4. DRM_NOUVEAU_GETPARAM Add CHIPSET_ID value, which will return the chipset id derived from NV_PMC_BOOT_0. 4. Use list_* in a few places, rather than home-brewed stuff. --- shared-core/nouveau_object.c | 99 +++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 25 deletions(-) (limited to 'shared-core/nouveau_object.c') diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 274bb2a7..22ad23cd 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -131,6 +131,8 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) ref->channel, co, ref->handle, ctx); INSTANCE_WR(ramht, (co + 0)/4, ref->handle); INSTANCE_WR(ramht, (co + 4)/4, ctx); + + list_add_tail(&ref->list, &chan->ramht_refs); return 0; } DRM_DEBUG("collision ch%d 0x%08x: h=0x%08x\n", @@ -167,6 +169,8 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) INSTANCE_RD(ramht, (co + 4))); INSTANCE_WR(ramht, (co + 0)/4, 0x00000000); INSTANCE_WR(ramht, (co + 4)/4, 0x00000000); + + list_del(&ref->list); return; } @@ -203,6 +207,8 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, gpuobj->flags = flags; gpuobj->im_channel = chan ? chan->id : -1; + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + /* Choose between global instmem heap, and per-channel private * instmem heap. On gpuobj_all) { - gpuobj->next = dev_priv->gpuobj_all; - gpuobj->next->prev = gpuobj; + *gpuobj_ret = gpuobj; + return 0; +} + +int +nouveau_gpuobj_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + INIT_LIST_HEAD(&dev_priv->gpuobj_list); + + if (dev_priv->card_type < NV_50) { + if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset, + dev_priv->ramht_size, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ALLOW_NO_REFS, + &dev_priv->ramht, NULL))) + return ret; } - dev_priv->gpuobj_all = gpuobj; - *gpuobj_ret = gpuobj; return 0; } -void nouveau_gpuobj_takedown(struct drm_device *dev) +void +nouveau_gpuobj_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *gpuobj = NULL; + struct list_head *entry, *tmp; DRM_DEBUG("\n"); - while ((gpuobj = dev_priv->gpuobj_all)) { + nouveau_gpuobj_del(dev, &dev_priv->ramht); + + list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { + gpuobj = list_entry(entry, struct nouveau_gpuobj, list); + DRM_ERROR("gpuobj %p still exists at takedown, refs=%d\n", gpuobj, gpuobj->refcount); gpuobj->refcount = 0; @@ -279,7 +305,8 @@ void nouveau_gpuobj_takedown(struct drm_device *dev) } } -int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) +int +nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->Engine; @@ -296,6 +323,9 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) return -EINVAL; } + if (gpuobj->dtor) + gpuobj->dtor(dev, gpuobj); + engine->instmem.clear(dev, gpuobj); if (gpuobj->im_pramin) { @@ -306,12 +336,7 @@ int nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) nouveau_mem_free_block(gpuobj->im_pramin); } - if (gpuobj->next) - gpuobj->next->prev = gpuobj->prev; - if (gpuobj->prev) - gpuobj->prev->next = gpuobj->next; - else - dev_priv->gpuobj_all = gpuobj->next; + list_del(&gpuobj->list); *pgpuobj = NULL; drm_free(gpuobj, sizeof(*gpuobj), DRM_MEM_DRIVER); @@ -403,9 +428,6 @@ nouveau_gpuobj_ref_add(struct drm_device *dev, struct nouveau_channel *chan, drm_free(ref, sizeof(*ref), DRM_MEM_DRIVER); return ret; } - - ref->next = chan->ramht_refs; - chan->ramht_refs = ref; } else { ref->handle = ~0; *ref_ret = ref; @@ -462,19 +484,21 @@ nouveau_gpuobj_new_ref(struct drm_device *dev, return 0; } -static int +int nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, struct nouveau_gpuobj_ref **ref_ret) { - struct nouveau_gpuobj_ref *ref = chan->ramht_refs; + struct nouveau_gpuobj_ref *ref; + struct list_head *entry, *tmp; + + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); - while (ref) { if (ref->handle == handle) { if (ref_ret) *ref_ret = ref; return 0; } - ref = ref->next; } return -EINVAL; @@ -499,6 +523,8 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size, gpuobj->im_channel = -1; gpuobj->flags = flags | NVOBJ_FLAG_FAKE; + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block), DRM_MEM_DRIVER); if (!gpuobj->im_pramin) { @@ -897,6 +923,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_gpuobj *vram = NULL, *tt = NULL; int ret, i; + INIT_LIST_HEAD(&chan->ramht_refs); + DRM_DEBUG("ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); /* Reserve a block of PRAMIN for the channel @@ -994,14 +1022,17 @@ void nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; + struct list_head *entry, *tmp; struct nouveau_gpuobj_ref *ref; DRM_DEBUG("ch%d\n", chan->id); - while ((ref = chan->ramht_refs)) { - chan->ramht_refs = ref->next; + list_for_each_safe(entry, tmp, &chan->ramht_refs) { + ref = list_entry(entry, struct nouveau_gpuobj_ref, list); + nouveau_gpuobj_ref_del(dev, &ref); } + nouveau_gpuobj_ref_del(dev, &chan->ramht); nouveau_gpuobj_del(dev, &chan->vm_pd); @@ -1022,6 +1053,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct nouveau_gpuobj *gr = NULL; int ret; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); //FIXME: check args, only allow trusted objects to be created @@ -1029,8 +1061,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, if (init->handle == ~0) return -EINVAL; - if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == - 0) + if (nouveau_gpuobj_ref_find(chan, init->handle, NULL) == 0) return -EEXIST; ret = nouveau_gpuobj_gr_new(chan, init->class, &gr); @@ -1050,3 +1081,21 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, return 0; } +int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_gpuobj_free *objfree = data; + struct nouveau_gpuobj_ref *ref; + struct nouveau_channel *chan; + int ret; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); + + if ((ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref))) + return ret; + nouveau_gpuobj_ref_del(dev, &ref); + + return 0; +} + -- cgit v1.2.3 From 66f5232d9393f6886d8fd1a60b2d75cd009b972c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 7 Aug 2007 01:51:46 +1000 Subject: nouveau: Init global gpuobj list early, unbreaks sgdma code. --- shared-core/nouveau_object.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'shared-core/nouveau_object.c') diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 22ad23cd..bb096531 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -270,8 +270,6 @@ nouveau_gpuobj_init(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; - INIT_LIST_HEAD(&dev_priv->gpuobj_list); - if (dev_priv->card_type < NV_50) { if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset, dev_priv->ramht_size, -- cgit v1.2.3 From 39907f613b6c84499c34c9a6ece5f5dde64788c0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 10 Aug 2007 13:53:10 +1000 Subject: nouveau: Allow creation of gpuobjs before any other init has taken place. --- shared-core/nouveau_object.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'shared-core/nouveau_object.c') diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index bb096531..d4142e44 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -264,12 +264,26 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, return 0; } +int +nouveau_gpuobj_early_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + INIT_LIST_HEAD(&dev_priv->gpuobj_list); + + return 0; +} + int nouveau_gpuobj_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; + DRM_DEBUG("\n"); + if (dev_priv->card_type < NV_50) { if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset, dev_priv->ramht_size, @@ -286,12 +300,20 @@ void nouveau_gpuobj_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj = NULL; - struct list_head *entry, *tmp; DRM_DEBUG("\n"); nouveau_gpuobj_del(dev, &dev_priv->ramht); +} + +void +nouveau_gpuobj_late_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj = NULL; + struct list_head *entry, *tmp; + + DRM_DEBUG("\n"); list_for_each_safe(entry, tmp, &dev_priv->gpuobj_list) { gpuobj = list_entry(entry, struct nouveau_gpuobj, list); -- cgit v1.2.3 From a46104674f129e873b8dfa29cf8aac9c67bd77be Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 10 Aug 2007 13:54:26 +1000 Subject: nouveau/nv50: demagic instmem setup. --- shared-core/nouveau_object.c | 50 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) (limited to 'shared-core/nouveau_object.c') diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index d4142e44..e0cb334f 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -72,6 +72,8 @@ nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) uint32_t hash = 0; int i; + DRM_DEBUG("ch%d handle=0x%08x\n", channel, handle); + for (i=32;i>0;i-=dev_priv->ramht_bits) { hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); handle >>= dev_priv->ramht_bits; @@ -80,7 +82,7 @@ nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) hash ^= channel << (dev_priv->ramht_bits - 4); hash <<= 3; - DRM_DEBUG("ch%d handle=0x%08x hash=0x%08x\n", channel, handle, hash); + DRM_DEBUG("hash=0x%08x\n", hash); return hash; } @@ -286,7 +288,7 @@ nouveau_gpuobj_init(struct drm_device *dev) if (dev_priv->card_type < NV_50) { if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset, - dev_priv->ramht_size, + ~0, dev_priv->ramht_size, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ALLOW_NO_REFS, &dev_priv->ramht, NULL))) @@ -346,7 +348,13 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) if (gpuobj->dtor) gpuobj->dtor(dev, gpuobj); - engine->instmem.clear(dev, gpuobj); + if (gpuobj->im_backing) { + if (gpuobj->flags & NVOBJ_FLAG_FAKE) + drm_free(gpuobj->im_backing, + sizeof(*gpuobj->im_backing), DRM_MEM_DRIVER); + else + engine->instmem.clear(dev, gpuobj); + } if (gpuobj->im_pramin) { if (gpuobj->flags & NVOBJ_FLAG_FAKE) @@ -525,7 +533,8 @@ nouveau_gpuobj_ref_find(struct nouveau_channel *chan, uint32_t handle, } int -nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size, +nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, + uint32_t b_offset, uint32_t size, uint32_t flags, struct nouveau_gpuobj **pgpuobj, struct nouveau_gpuobj_ref **pref) { @@ -533,8 +542,8 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size, struct nouveau_gpuobj *gpuobj = NULL; int i; - DRM_DEBUG("offset=0x%08x size=0x%08x flags=0x%08x\n", - offset, size, flags); + DRM_DEBUG("p_offset=0x%08x b_offset=0x%08x size=0x%08x flags=0x%08x\n", + p_offset, b_offset, size, flags); gpuobj = drm_calloc(1, sizeof(*gpuobj), DRM_MEM_DRIVER); if (!gpuobj) @@ -545,14 +554,27 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t offset, uint32_t size, list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); - gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block), - DRM_MEM_DRIVER); - if (!gpuobj->im_pramin) { - nouveau_gpuobj_del(dev, &gpuobj); - return -ENOMEM; + if (p_offset != ~0) { + gpuobj->im_pramin = drm_calloc(1, sizeof(struct mem_block), + DRM_MEM_DRIVER); + if (!gpuobj->im_pramin) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + gpuobj->im_pramin->start = p_offset; + gpuobj->im_pramin->size = size; + } + + if (b_offset != ~0) { + gpuobj->im_backing = drm_calloc(1, sizeof(struct mem_block), + DRM_MEM_DRIVER); + if (!gpuobj->im_backing) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + gpuobj->im_backing->start = b_offset; + gpuobj->im_backing->size = size; } - gpuobj->im_pramin->start = offset; - gpuobj->im_pramin->size = size; if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { for (i = 0; i < gpuobj->im_pramin->size; i += 4) @@ -962,7 +984,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200; vm_offset += chan->ramin->gpuobj->im_pramin->start; - if ((ret = nouveau_gpuobj_new_fake(dev, vm_offset, 0x4000, + if ((ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000, 0, &chan->vm_pd, NULL))) return ret; for (i=0; i<0x4000; i+=8) { -- cgit v1.2.3 From 8645dac8952473dc3e09ba7a7a9db3fbdf75215f Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Wed, 22 Aug 2007 23:17:56 +0200 Subject: nouveau : fix some potential crashes with objects causing hash collision --- shared-core/nouveau_object.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'shared-core/nouveau_object.c') diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index e0cb334f..fbce7702 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -141,8 +141,13 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) ref->channel, co, INSTANCE_RD(ramht, co/4)); co += 8; - if (co >= dev_priv->ramht_size) + if (co >= dev_priv->ramht_size) { + DRM_INFO("no space left after collision\n"); co = 0; + /* exit as it seems to cause crash with nouveau_demo and + * 0xdead0001 object */ + break; + } } while (co != ho); DRM_ERROR("RAMHT space exhausted. ch=%d\n", ref->channel); -- cgit v1.2.3