From 695599f18d907bb277805581bbe208b0e083e7d9 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 24 Jun 2007 19:03:35 +1000 Subject: nouveau: Nuke DMA_OBJECT_INIT ioctl (bumps interface to 0.0.7) For various reasons, this ioctl was a bad idea. At channel creation we now automatically create DMA objects covering available VRAM and GART memory, where the client used to do this themselves. However, there is still a need to be able to create DMA objects pointing at specific areas of memory (ie. notifiers). Each channel is now allocated a small amount of memory from which a client can suballocate things (such as notifiers), and have a DMA object created which covers the suballocated area. The NOTIFIER_ALLOC ioctl exposes this functionality. --- shared-core/nouveau_notifier.c | 154 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 shared-core/nouveau_notifier.c (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c new file mode 100644 index 00000000..ab6f8c2d --- /dev/null +++ b/shared-core/nouveau_notifier.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2007 Ben Skeggs. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "nouveau_drv.h" + +int +nouveau_notifier_init_channel(drm_device_t *dev, int channel, DRMFILE filp) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + int flags, ret; + + /*TODO: PCI notifier blocks */ + if (dev_priv->agp_heap) + flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; + else + flags = NOUVEAU_MEM_FB; + + chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,filp); + if (!chan->notifier_block) + return DRM_ERR(ENOMEM); + + ret = nouveau_mem_init_heap(&chan->notifier_heap, + 0, chan->notifier_block->size); + if (ret) + return ret; + + return 0; +} + +void +nouveau_notifier_takedown_channel(drm_device_t *dev, int channel) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + + if (chan->notifier_block) { + nouveau_mem_free(dev, chan->notifier_block); + chan->notifier_block = NULL; + } + + /*XXX: heap destroy */ +} + +int +nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle, + int count, uint32_t *b_offset) +{ + drm_nouveau_private_t *dev_priv = dev->dev_private; + struct nouveau_fifo *chan = &dev_priv->fifos[channel]; + struct nouveau_object *obj; + struct mem_block *mem; + uint32_t offset; + int target; + + if (!chan->notifier_heap) { + DRM_ERROR("Channel %d doesn't have a notifier heap!\n", + channel); + return DRM_ERR(EINVAL); + } + + mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, chan->filp); + if (!mem) { + DRM_ERROR("Channel %d notifier block full\n", channel); + return DRM_ERR(ENOMEM); + } + mem->flags = NOUVEAU_MEM_NOTIFIER; + + offset = chan->notifier_block->start + mem->start; + if (chan->notifier_block->flags & NOUVEAU_MEM_FB) { + offset -= drm_get_resource_start(dev, 1); + target = NV_DMA_TARGET_VIDMEM; + } else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { + offset -= dev_priv->agp_phys; + target = NV_DMA_TARGET_AGP; + } else { + DRM_ERROR("Bad DMA target, flags 0x%08x!\n", + chan->notifier_block->flags); + return DRM_ERR(EINVAL); + } + + obj = nouveau_object_dma_create(dev, channel, NV_CLASS_DMA_IN_MEMORY, + offset, mem->size, NV_DMA_ACCESS_RW, + target); + if (!obj) { + nouveau_mem_free_block(mem); + DRM_ERROR("Error creating notifier ctxdma\n"); + return DRM_ERR(ENOMEM); + } + + obj->handle = handle; + if (nouveau_ht_object_insert(dev, channel, handle, obj)) { + nouveau_object_free(dev, obj); + nouveau_mem_free_block(mem); + DRM_ERROR("Error inserting notifier ctxdma into RAMHT\n"); + return DRM_ERR(ENOMEM); + } + + *b_offset = mem->start; + return 0; +} + +int +nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_nouveau_notifier_alloc_t na; + int ret; + + DRM_COPY_FROM_USER_IOCTL(na, (drm_nouveau_notifier_alloc_t __user*)data, + sizeof(na)); + + if (!nouveau_fifo_owner(dev, filp, na.channel)) { + DRM_ERROR("pid %d doesn't own channel %d\n", + DRM_CURRENTPID, na.channel); + return DRM_ERR(EPERM); + } + + ret = nouveau_notifier_alloc(dev, na.channel, na.handle, + na.count, &na.offset); + if (ret) + return ret; + + DRM_COPY_TO_USER_IOCTL((drm_nouveau_notifier_alloc_t __user*)data, + na, sizeof(na)); + return 0; +} + -- cgit v1.2.3 From 68ecf61647e9ec16d59cc8f50550d11478eb3118 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 25 Jun 2007 15:42:55 +1000 Subject: nouveau: never touch PRAMIN with NV_WRITE, cleanup RAMHT code a bit --- shared-core/nouveau_notifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index ab6f8c2d..0cfe733e 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -115,7 +115,7 @@ nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle, } obj->handle = handle; - if (nouveau_ht_object_insert(dev, channel, handle, obj)) { + if (nouveau_ramht_insert(dev, channel, handle, obj)) { nouveau_object_free(dev, obj); nouveau_mem_free_block(mem); DRM_ERROR("Error inserting notifier ctxdma into RAMHT\n"); -- cgit v1.2.3 From 163f8526123ffa38783fc911b5f7a19debce7f73 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 2 Jul 2007 19:31:18 +1000 Subject: nouveau: rewrite gpu object code Allows multiple references to a single object, needed to support PCI(E)GART scatter-gather DMA objects which would quickly fill PRAMIN if each channel had its own. Handle per-channel private instmem areas. This is needed to support NV50, but might be something we want to do on earlier chipsets at some point? Everything that touches PRAMIN is a GPU object. --- shared-core/nouveau_notifier.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 0cfe733e..4d5e26ab 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -74,10 +74,10 @@ nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle, { drm_nouveau_private_t *dev_priv = dev->dev_private; struct nouveau_fifo *chan = &dev_priv->fifos[channel]; - struct nouveau_object *obj; + nouveau_gpuobj_t *nobj = NULL; struct mem_block *mem; uint32_t offset; - int target; + int target, ret; if (!chan->notifier_heap) { DRM_ERROR("Channel %d doesn't have a notifier heap!\n", @@ -105,21 +105,19 @@ nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle, return DRM_ERR(EINVAL); } - obj = nouveau_object_dma_create(dev, channel, NV_CLASS_DMA_IN_MEMORY, - offset, mem->size, NV_DMA_ACCESS_RW, - target); - if (!obj) { + if ((ret = nouveau_gpuobj_dma_new(dev, channel, NV_CLASS_DMA_IN_MEMORY, + offset, mem->size, + NV_DMA_ACCESS_RW, target, &nobj))) { nouveau_mem_free_block(mem); - DRM_ERROR("Error creating notifier ctxdma\n"); - return DRM_ERR(ENOMEM); + DRM_ERROR("Error creating notifier ctxdma: %d\n", ret); + return ret; } - obj->handle = handle; - if (nouveau_ramht_insert(dev, channel, handle, obj)) { - nouveau_object_free(dev, obj); + if ((ret = nouveau_gpuobj_ref_add(dev, channel, handle, nobj, NULL))) { + nouveau_gpuobj_del(dev, &nobj); nouveau_mem_free_block(mem); - DRM_ERROR("Error inserting notifier ctxdma into RAMHT\n"); - return DRM_ERR(ENOMEM); + DRM_ERROR("Error referencing notifier ctxdma: %d\n", ret); + return ret; } *b_offset = mem->start; -- cgit v1.2.3 From c806bba4665bb369168ee0b453fa28e2e0bf2a5d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 5 Jul 2007 00:12:33 +1000 Subject: nouveau/nv50: Initial channel/object support Should be OK on G84 for a single channel, multiple channels *almost* work. Untested on G80. --- shared-core/nouveau_notifier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 4d5e26ab..9e792e57 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -33,7 +33,7 @@ int nouveau_notifier_init_channel(drm_device_t *dev, int channel, DRMFILE filp) { 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]; int flags, ret; /*TODO: PCI notifier blocks */ @@ -58,7 +58,7 @@ void nouveau_notifier_takedown_channel(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]; if (chan->notifier_block) { nouveau_mem_free(dev, chan->notifier_block); @@ -73,7 +73,7 @@ nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle, int count, uint32_t *b_offset) { 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 *nobj = NULL; struct mem_block *mem; uint32_t offset; -- cgit v1.2.3 From 023f7d9c0064f912415c92a85c3a9d722191909f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 9 Jul 2007 23:58:00 +1000 Subject: nouveau: Allocate mappable VRAM for notifiers.. --- shared-core/nouveau_notifier.c | 1 + 1 file changed, 1 insertion(+) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 9e792e57..30216293 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -41,6 +41,7 @@ nouveau_notifier_init_channel(drm_device_t *dev, int channel, DRMFILE filp) flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; else flags = NOUVEAU_MEM_FB; + flags |= NOUVEAU_MEM_MAPPED; chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,filp); if (!chan->notifier_block) -- cgit v1.2.3 From 750371cb6ea9a64c9d4d4d3b9716c3c68d810d48 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 12 Jul 2007 10:15:16 +1000 Subject: nouveau: separate region_offset into map_handle and offset. --- shared-core/nouveau_notifier.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 30216293..7d892064 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -95,10 +95,8 @@ nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle, offset = chan->notifier_block->start + mem->start; if (chan->notifier_block->flags & NOUVEAU_MEM_FB) { - offset -= drm_get_resource_start(dev, 1); target = NV_DMA_TARGET_VIDMEM; } else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { - offset -= dev_priv->agp_phys; target = NV_DMA_TARGET_AGP; } else { DRM_ERROR("Bad DMA target, flags 0x%08x!\n", -- cgit v1.2.3 From 0029713451af6f5f216079775ff77cae9b423c0e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jul 2007 15:09:31 +1000 Subject: nouveau: nuke internal typedefs, and drm_device_t use. --- shared-core/nouveau_notifier.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 7d892064..36dba654 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -30,9 +30,9 @@ #include "nouveau_drv.h" int -nouveau_notifier_init_channel(drm_device_t *dev, int channel, DRMFILE filp) +nouveau_notifier_init_channel(struct drm_device *dev, int channel, DRMFILE filp) { - drm_nouveau_private_t *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fifo *chan = dev_priv->fifos[channel]; int flags, ret; @@ -56,9 +56,9 @@ nouveau_notifier_init_channel(drm_device_t *dev, int channel, DRMFILE filp) } void -nouveau_notifier_takedown_channel(drm_device_t *dev, int channel) +nouveau_notifier_takedown_channel(struct drm_device *dev, int channel) { - drm_nouveau_private_t *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fifo *chan = dev_priv->fifos[channel]; if (chan->notifier_block) { @@ -70,12 +70,12 @@ nouveau_notifier_takedown_channel(drm_device_t *dev, int channel) } int -nouveau_notifier_alloc(drm_device_t *dev, int channel, uint32_t handle, +nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, int count, uint32_t *b_offset) { - drm_nouveau_private_t *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fifo *chan = dev_priv->fifos[channel]; - nouveau_gpuobj_t *nobj = NULL; + struct nouveau_gpuobj *nobj = NULL; struct mem_block *mem; uint32_t offset; int target, ret; @@ -127,11 +127,12 @@ int nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS) { DRM_DEVICE; - drm_nouveau_notifier_alloc_t na; + struct drm_nouveau_notifier_alloc na; int ret; - DRM_COPY_FROM_USER_IOCTL(na, (drm_nouveau_notifier_alloc_t __user*)data, - sizeof(na)); + DRM_COPY_FROM_USER_IOCTL(na, + (struct drm_nouveau_notifier_alloc __user*)data, + sizeof(na)); if (!nouveau_fifo_owner(dev, filp, na.channel)) { DRM_ERROR("pid %d doesn't own channel %d\n", @@ -144,7 +145,7 @@ nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS) if (ret) return ret; - DRM_COPY_TO_USER_IOCTL((drm_nouveau_notifier_alloc_t __user*)data, + DRM_COPY_TO_USER_IOCTL((struct drm_nouveau_notifier_alloc __user*)data, na, sizeof(na)); return 0; } -- cgit v1.2.3 From ec67c2def9af16bf9252d6742aec815b817f135a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 15 Jul 2007 17:18:15 +1000 Subject: nouveau: G8x PCIEGART Actually a NV04-NV50 ttm backend for both PCI and PCIEGART, but PCIGART support for G8X using the current mm has been hacked on top of it. --- shared-core/nouveau_notifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 36dba654..238e3c8b 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -37,7 +37,8 @@ nouveau_notifier_init_channel(struct drm_device *dev, int channel, DRMFILE filp) int flags, ret; /*TODO: PCI notifier blocks */ - if (dev_priv->agp_heap) + if (dev_priv->agp_heap && + dev_priv->gart_info.type != NOUVEAU_GART_SGDMA) flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; else flags = NOUVEAU_MEM_FB; -- cgit v1.2.3 From e39286eb5eab8846a228863abf8f1b8b07a9e29d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 19 Jul 2007 17:00:17 -0700 Subject: Remove DRM_ERR OS macro. This was used to make all ioctl handlers return -errno on linux and errno on *BSD. Instead, just return -errno in shared code, and flip sign on return from shared code to *BSD code. --- shared-core/nouveau_notifier.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 238e3c8b..425e471c 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -46,7 +46,7 @@ nouveau_notifier_init_channel(struct drm_device *dev, int channel, DRMFILE filp) chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,filp); if (!chan->notifier_block) - return DRM_ERR(ENOMEM); + return -ENOMEM; ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, chan->notifier_block->size); @@ -84,13 +84,13 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, if (!chan->notifier_heap) { DRM_ERROR("Channel %d doesn't have a notifier heap!\n", channel); - return DRM_ERR(EINVAL); + return -EINVAL; } mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, chan->filp); if (!mem) { DRM_ERROR("Channel %d notifier block full\n", channel); - return DRM_ERR(ENOMEM); + return -ENOMEM; } mem->flags = NOUVEAU_MEM_NOTIFIER; @@ -102,7 +102,7 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, } else { DRM_ERROR("Bad DMA target, flags 0x%08x!\n", chan->notifier_block->flags); - return DRM_ERR(EINVAL); + return -EINVAL; } if ((ret = nouveau_gpuobj_dma_new(dev, channel, NV_CLASS_DMA_IN_MEMORY, @@ -138,7 +138,7 @@ nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS) if (!nouveau_fifo_owner(dev, filp, na.channel)) { DRM_ERROR("pid %d doesn't own channel %d\n", DRM_CURRENTPID, na.channel); - return DRM_ERR(EPERM); + return -EPERM; } ret = nouveau_notifier_alloc(dev, na.channel, na.handle, -- cgit v1.2.3 From c1119b1b092527fbb6950d0b5e51e076ddb00f29 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 20 Jul 2007 06:39:25 -0700 Subject: Replace filp in ioctl arguments with drm_file *file_priv. As a fallout, replace filp storage with file_priv storage for "unique identifier of a client" all over the DRM. There is a 1:1 mapping, so this should be a noop. This could be a minor performance improvement, as everything on Linux dereferenced filp to get file_priv anyway, while only the mmap ioctls went the other direction. --- shared-core/nouveau_notifier.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 425e471c..6a78bb23 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -30,7 +30,8 @@ #include "nouveau_drv.h" int -nouveau_notifier_init_channel(struct drm_device *dev, int channel, DRMFILE filp) +nouveau_notifier_init_channel(struct drm_device *dev, int channel, + struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fifo *chan = dev_priv->fifos[channel]; @@ -44,7 +45,8 @@ nouveau_notifier_init_channel(struct drm_device *dev, int channel, DRMFILE filp) flags = NOUVEAU_MEM_FB; flags |= NOUVEAU_MEM_MAPPED; - chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags,filp); + chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, + file_priv); if (!chan->notifier_block) return -ENOMEM; @@ -87,7 +89,8 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, return -EINVAL; } - mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, chan->filp); + mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, + chan->file_priv); if (!mem) { DRM_ERROR("Channel %d notifier block full\n", channel); return -ENOMEM; @@ -135,7 +138,7 @@ nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS) (struct drm_nouveau_notifier_alloc __user*)data, sizeof(na)); - if (!nouveau_fifo_owner(dev, filp, na.channel)) { + if (!nouveau_fifo_owner(dev, file_priv, na.channel)) { DRM_ERROR("pid %d doesn't own channel %d\n", DRM_CURRENTPID, na.channel); return -EPERM; -- cgit v1.2.3 From 5b38e134163cc375e91424c4688cc9328c6e9082 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 19 Jul 2007 17:11:11 -0700 Subject: Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE. The data is now in kernel space, copied in/out as appropriate according to the This results in DRM_COPY_{TO,FROM}_USER going away, and error paths to deal with those failures. This also means that XFree86 4.2.0 support for i810 DRM is lost. --- shared-core/nouveau_notifier.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 6a78bb23..24a306e8 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -128,29 +128,22 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, } int -nouveau_ioctl_notifier_alloc(DRM_IOCTL_ARGS) +nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - struct drm_nouveau_notifier_alloc na; + struct drm_nouveau_notifier_alloc *na = data; int ret; - DRM_COPY_FROM_USER_IOCTL(na, - (struct drm_nouveau_notifier_alloc __user*)data, - sizeof(na)); - - if (!nouveau_fifo_owner(dev, file_priv, na.channel)) { + if (!nouveau_fifo_owner(dev, file_priv, na->channel)) { DRM_ERROR("pid %d doesn't own channel %d\n", - DRM_CURRENTPID, na.channel); + DRM_CURRENTPID, na->channel); return -EPERM; } - ret = nouveau_notifier_alloc(dev, na.channel, na.handle, - na.count, &na.offset); + ret = nouveau_notifier_alloc(dev, na->channel, na->handle, + na->count, &na->offset); if (ret) return ret; - DRM_COPY_TO_USER_IOCTL((struct drm_nouveau_notifier_alloc __user*)data, - na, sizeof(na)); return 0; } -- cgit v1.2.3 From f01026eae69e81ae16a69a014ba3bcfb286fc7a4 Mon Sep 17 00:00:00 2001 From: Arthur Huillet Date: Fri, 27 Jul 2007 15:48:04 +0200 Subject: nouveau: creating notifier in PCI memory for PCIGART --- shared-core/nouveau_notifier.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 24a306e8..7a982ba4 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -41,10 +41,13 @@ nouveau_notifier_init_channel(struct drm_device *dev, int channel, if (dev_priv->agp_heap && dev_priv->gart_info.type != NOUVEAU_GART_SGDMA) flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; + else if ( dev_priv->pci_heap ) + flags = NOUVEAU_MEM_PCI; else flags = NOUVEAU_MEM_FB; flags |= NOUVEAU_MEM_MAPPED; +DRM_DEBUG("Allocating notifier block in %d\n", flags); chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, file_priv); if (!chan->notifier_block) @@ -102,6 +105,8 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, target = NV_DMA_TARGET_VIDMEM; } else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { target = NV_DMA_TARGET_AGP; + } else if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) { + target = NV_DMA_TARGET_PCI_NONLINEAR; } else { DRM_ERROR("Bad DMA target, flags 0x%08x!\n", chan->notifier_block->flags); -- cgit v1.2.3 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_notifier.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 7a982ba4..b1090587 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -30,11 +30,10 @@ #include "nouveau_drv.h" int -nouveau_notifier_init_channel(struct drm_device *dev, int channel, - struct drm_file *file_priv) +nouveau_notifier_init_channel(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]; int flags, ret; /*TODO: PCI notifier blocks */ @@ -47,9 +46,9 @@ nouveau_notifier_init_channel(struct drm_device *dev, int channel, flags = NOUVEAU_MEM_FB; flags |= NOUVEAU_MEM_MAPPED; -DRM_DEBUG("Allocating notifier block in %d\n", flags); + DRM_DEBUG("Allocating notifier block in %d\n", flags); chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, - file_priv); + (struct drm_file *)-2); if (!chan->notifier_block) return -ENOMEM; @@ -62,25 +61,23 @@ DRM_DEBUG("Allocating notifier block in %d\n", flags); } void -nouveau_notifier_takedown_channel(struct drm_device *dev, int channel) +nouveau_notifier_takedown_channel(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; if (chan->notifier_block) { nouveau_mem_free(dev, chan->notifier_block); chan->notifier_block = NULL; } - /*XXX: heap destroy */ + nouveau_mem_takedown(&chan->notifier_heap); } int -nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, +nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, int count, uint32_t *b_offset) { - 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 *nobj = NULL; struct mem_block *mem; uint32_t offset; @@ -88,14 +85,14 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, if (!chan->notifier_heap) { DRM_ERROR("Channel %d doesn't have a notifier heap!\n", - channel); + chan->id); return -EINVAL; } mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, chan->file_priv); if (!mem) { - DRM_ERROR("Channel %d notifier block full\n", channel); + DRM_ERROR("Channel %d notifier block full\n", chan->id); return -ENOMEM; } mem->flags = NOUVEAU_MEM_NOTIFIER; @@ -113,7 +110,7 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, return -EINVAL; } - 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, offset, mem->size, NV_DMA_ACCESS_RW, target, &nobj))) { nouveau_mem_free_block(mem); @@ -121,7 +118,7 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, return ret; } - if ((ret = nouveau_gpuobj_ref_add(dev, channel, handle, nobj, NULL))) { + if ((ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL))) { nouveau_gpuobj_del(dev, &nobj); nouveau_mem_free_block(mem); DRM_ERROR("Error referencing notifier ctxdma: %d\n", ret); @@ -133,19 +130,16 @@ nouveau_notifier_alloc(struct drm_device *dev, int channel, uint32_t handle, } int -nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_nouveau_notifier_alloc *na = data; + struct nouveau_channel *chan; int ret; - if (!nouveau_fifo_owner(dev, file_priv, na->channel)) { - DRM_ERROR("pid %d doesn't own channel %d\n", - DRM_CURRENTPID, na->channel); - return -EPERM; - } + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); - ret = nouveau_notifier_alloc(dev, na->channel, na->handle, - na->count, &na->offset); + ret = nouveau_notifier_alloc(chan, na->handle, na->count, &na->offset); if (ret) return ret; -- 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_notifier.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index b1090587..31547aae 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -73,6 +73,16 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan) nouveau_mem_takedown(&chan->notifier_heap); } +static void +nouveau_notifier_gpuobj_dtor(struct drm_device *dev, + struct nouveau_gpuobj *gpuobj) +{ + DRM_DEBUG("\n"); + + if (gpuobj->priv) + nouveau_mem_free_block(gpuobj->priv); +} + int nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, int count, uint32_t *b_offset) @@ -90,7 +100,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, } mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, - chan->file_priv); + (struct drm_file *)-2); if (!mem) { DRM_ERROR("Channel %d notifier block full\n", chan->id); return -ENOMEM; @@ -117,6 +127,8 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, DRM_ERROR("Error creating notifier ctxdma: %d\n", ret); return ret; } + nobj->dtor = nouveau_notifier_gpuobj_dtor; + nobj->priv = mem; if ((ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL))) { nouveau_gpuobj_del(dev, &nobj); @@ -133,10 +145,11 @@ int nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_notifier_alloc *na = data; + struct drm_nouveau_notifierobj_alloc *na = data; struct nouveau_channel *chan; int ret; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); ret = nouveau_notifier_alloc(chan, na->handle, na->count, &na->offset); -- cgit v1.2.3 From c3faa589b09616acdfd827be1719f6c2706c49ab Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Aug 2007 13:36:54 +1000 Subject: nouveau: Allow GART notifiers when using sgdma code. --- shared-core/nouveau_notifier.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 31547aae..91f605ec 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -37,14 +37,13 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) int flags, ret; /*TODO: PCI notifier blocks */ - if (dev_priv->agp_heap && - dev_priv->gart_info.type != NOUVEAU_GART_SGDMA) - flags = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; - else if ( dev_priv->pci_heap ) + if (dev_priv->agp_heap) + flags = NOUVEAU_MEM_AGP; + else if (dev_priv->pci_heap) flags = NOUVEAU_MEM_PCI; else flags = NOUVEAU_MEM_FB; - flags |= NOUVEAU_MEM_MAPPED; + flags |= (NOUVEAU_MEM_MAPPED | NOUVEAU_MEM_FB_ACCEPTABLE); DRM_DEBUG("Allocating notifier block in %d\n", flags); chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, @@ -88,6 +87,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, int count, uint32_t *b_offset) { struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *nobj = NULL; struct mem_block *mem; uint32_t offset; @@ -107,18 +107,29 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, } mem->flags = NOUVEAU_MEM_NOTIFIER; - offset = chan->notifier_block->start + mem->start; + offset = chan->notifier_block->start; if (chan->notifier_block->flags & NOUVEAU_MEM_FB) { target = NV_DMA_TARGET_VIDMEM; - } else if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { - target = NV_DMA_TARGET_AGP; - } else if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) { + } else + if (chan->notifier_block->flags & NOUVEAU_MEM_AGP) { + if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA && + dev_priv->card_type < NV_50) { + ret = nouveau_sgdma_get_page(dev, offset, &offset); + if (ret) + return ret; + target = NV_DMA_TARGET_PCI; + } else { + target = NV_DMA_TARGET_AGP; + } + } else + if (chan->notifier_block->flags & NOUVEAU_MEM_PCI) { target = NV_DMA_TARGET_PCI_NONLINEAR; } else { DRM_ERROR("Bad DMA target, flags 0x%08x!\n", chan->notifier_block->flags); return -EINVAL; } + offset += mem->start; if ((ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, mem->size, -- cgit v1.2.3 From 10f9b7bd0b471487371813083bd3481629b2a56f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Aug 2007 14:14:23 +1000 Subject: nouveau: Use count parameter in nouveau_notifier_alloc(). --- shared-core/nouveau_notifier.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 91f605ec..71b8cbe1 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -45,11 +45,12 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) flags = NOUVEAU_MEM_FB; flags |= (NOUVEAU_MEM_MAPPED | NOUVEAU_MEM_FB_ACCEPTABLE); - DRM_DEBUG("Allocating notifier block in %d\n", flags); chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, (struct drm_file *)-2); if (!chan->notifier_block) return -ENOMEM; + DRM_DEBUG("Allocated notifier block in 0x%08x\n", + chan->notifier_block->flags); ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, chan->notifier_block->size); @@ -99,7 +100,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, return -EINVAL; } - mem = nouveau_mem_alloc_block(chan->notifier_heap, 32, 0, + mem = nouveau_mem_alloc_block(chan->notifier_heap, count*32, 0, (struct drm_file *)-2); if (!mem) { DRM_ERROR("Channel %d notifier block full\n", chan->id); -- cgit v1.2.3 From dc60c452e6ac72ebc4e5c73153d4d9d8c9edfae5 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Fri, 21 Sep 2007 22:27:53 +0200 Subject: nouveau: fix notifiers on PPC. --- shared-core/nouveau_notifier.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 71b8cbe1..fbd4b56f 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -37,9 +37,12 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) int flags, ret; /*TODO: PCI notifier blocks */ +#if defined(__powerpc__) if (dev_priv->agp_heap) flags = NOUVEAU_MEM_AGP; - else if (dev_priv->pci_heap) + else +#endif + if (dev_priv->pci_heap) flags = NOUVEAU_MEM_PCI; else flags = NOUVEAU_MEM_FB; -- cgit v1.2.3 From 7587e9682c1b70930c015915d588b42ccd00c7c4 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Fri, 21 Sep 2007 22:42:39 +0200 Subject: nouveau: fix ppc and get it right this time. --- shared-core/nouveau_notifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index fbd4b56f..d3b79683 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -37,7 +37,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) int flags, ret; /*TODO: PCI notifier blocks */ -#if defined(__powerpc__) +#ifndef __powerpc__ if (dev_priv->agp_heap) flags = NOUVEAU_MEM_AGP; else -- cgit v1.2.3 From 0d2554f83e72cae1bc44e476fbed4fc78873264f Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 12 Oct 2007 23:43:31 +0300 Subject: nouveau: Make notifiers go into PCI memory On some hardware notifers in AGP memory just don't work. --- shared-core/nouveau_notifier.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index d3b79683..c361bc69 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -36,17 +36,8 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; int flags, ret; - /*TODO: PCI notifier blocks */ -#ifndef __powerpc__ - if (dev_priv->agp_heap) - flags = NOUVEAU_MEM_AGP; - else -#endif - if (dev_priv->pci_heap) - flags = NOUVEAU_MEM_PCI; - else - flags = NOUVEAU_MEM_FB; - flags |= (NOUVEAU_MEM_MAPPED | NOUVEAU_MEM_FB_ACCEPTABLE); + flags = (NOUVEAU_MEM_PCI | NOUVEAU_MEM_MAPPED | + NOUVEAU_MEM_FB_ACCEPTABLE); chan->notifier_block = nouveau_mem_alloc(dev, 0, PAGE_SIZE, flags, (struct drm_file *)-2); -- cgit v1.2.3 From 837e364353b3137ce87b5cce9c06f05a3d603201 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sun, 14 Oct 2007 10:56:31 -0400 Subject: nouveau: fix warning. --- shared-core/nouveau_notifier.c | 1 - 1 file changed, 1 deletion(-) (limited to 'shared-core/nouveau_notifier.c') diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index c361bc69..31e2b244 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -33,7 +33,6 @@ int nouveau_notifier_init_channel(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; int flags, ret; flags = (NOUVEAU_MEM_PCI | NOUVEAU_MEM_MAPPED | -- cgit v1.2.3