From be3099f26547f48066bbdd7a36578b54da9170b4 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sun, 22 Jul 2007 09:51:34 +0100 Subject: Fix copy'n'paste-o in FreeBSD drawable code. --- bsd-core/drm_drawable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsd-core/drm_drawable.c b/bsd-core/drm_drawable.c index 14a29407..7e038ab9 100644 --- a/bsd-core/drm_drawable.c +++ b/bsd-core/drm_drawable.c @@ -45,7 +45,7 @@ drm_drawable_compare(struct bsd_drm_drawable_info *a, { if (a->handle > b->handle) return 1; - if (a->handle > b->handle) + if (a->handle < b->handle) return -1; return 0; } -- cgit v1.2.3 From f2528cbc965858c6a7a81d659f9d5f4da290b5ae Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 25 Jul 2007 12:54:15 -0700 Subject: Improve the drawable test to use multiple drawables. --- tests/updatedraw.c | 63 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/tests/updatedraw.c b/tests/updatedraw.c index 1186783a..2f22fef2 100644 --- a/tests/updatedraw.c +++ b/tests/updatedraw.c @@ -83,16 +83,10 @@ set_draw_cliprects_2(int fd, int drawable) assert(ret == 0); } -/** - * Tests drawable management: adding, removing, and updating the cliprects of - * drawables. - */ -int main(int argc, char **argv) +static int add_drawable(int fd) { drm_draw_t drawarg; - int fd, ret, drawable; - - fd = drm_open_any_master(); + int ret; /* Create a drawable. * IOCTL_ADD_DRAW is RDWR, though it should really just be RD @@ -100,27 +94,54 @@ int main(int argc, char **argv) drawarg.handle = 0; ret = ioctl(fd, DRM_IOCTL_ADD_DRAW, &drawarg); assert(ret == 0); - drawable = drawarg.handle; + return drawarg.handle; +} - /* Do a series of cliprect updates */ - set_draw_cliprects_empty(fd, drawable); - set_draw_cliprects_2(fd, drawable); - set_draw_cliprects_empty(fd, drawable); +static int rm_drawable(int fd, int drawable, int fail) +{ + drm_draw_t drawarg; + int ret; - /* Remove our drawable */ + /* Create a drawable. + * IOCTL_ADD_DRAW is RDWR, though it should really just be RD + */ drawarg.handle = drawable; ret = ioctl(fd, DRM_IOCTL_RM_DRAW, &drawarg); - assert(ret == 0); - drawable = drawarg.handle; + if (!fail) + assert(ret == 0); + else + assert(ret == -1 && errno == EINVAL); + + return drawarg.handle; +} + +/** + * Tests drawable management: adding, removing, and updating the cliprects of + * drawables. + */ +int main(int argc, char **argv) +{ + int fd, ret, d1, d2; + + fd = drm_open_any_master(); + + d1 = add_drawable(fd); + d2 = add_drawable(fd); + /* Do a series of cliprect updates */ + set_draw_cliprects_empty(fd, d1); + set_draw_cliprects_empty(fd, d2); + set_draw_cliprects_2(fd, d1); + set_draw_cliprects_empty(fd, d1); + + /* Remove our drawables */ + rm_drawable(fd, d1, 0); + rm_drawable(fd, d2, 0); /* Check that removing an unknown drawable returns error */ - drawarg.handle = 0x7fffffff; - ret = ioctl(fd, DRM_IOCTL_RM_DRAW, &drawarg); - assert(ret == -1 && errno == EINVAL); - drawable = drawarg.handle; + rm_drawable(fd, 0x7fffffff, 1); /* Attempt to set cliprects on a nonexistent drawable */ - set_draw_cliprects_empty_fail(fd, drawable); + set_draw_cliprects_empty_fail(fd, d1); close(fd); return 0; -- cgit v1.2.3 From e2d00715cc1d3919aadd5066ef7355049f417bd2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 26 Jul 2007 13:25:21 +1000 Subject: drm: fix size argument for copy to/from user --- linux-core/drm_bo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 75d89e46..b47b657f 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1720,7 +1720,7 @@ int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr if (next != 0) { curuserarg = (void __user *)next; if (copy_from_user(&curarg, curuserarg, - sizeof(arg)) != 0) + sizeof(curarg)) != 0) return -EFAULT; arg = &curarg; } @@ -1768,7 +1768,7 @@ int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr arg->d.rep.bo_info = rep; if (arg != data) { if (copy_to_user(curuserarg, &curarg, - sizeof(arg)) != 0) + sizeof(curarg)) != 0) return -EFAULT; } } while (next != 0); -- cgit v1.2.3 From 4175dd818110bd10d6d09190d30c271e89202b18 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 26 Jul 2007 15:26:36 +1000 Subject: drm/bo: set the req pointer for each buffer to validate --- linux-core/drm_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index b47b657f..467d03ff 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1729,7 +1729,7 @@ int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr next = arg->next; continue; } - + req = &arg->d.req; ret = 0; switch (req->op) { case drm_bo_validate: -- 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(+) 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 283eaa25594347267df4e6e5eedbb9d17bb3682c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 31 Jul 2007 09:22:45 +1000 Subject: drm: fix fencing refcount error This extra increase was causing fence leaks on my system, due to create/user add already increasing it twice no need for a 3rd go. --- linux-core/drm_fence.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index c4f7da15..fdb2a4db 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -597,7 +597,6 @@ int drm_fence_create_ioctl(struct drm_device *dev, void *data, struct drm_file * * usage > 0. No need to lock dev->struct_mutex; */ - atomic_inc(&fence->usage); arg->handle = fence->base.hash.key; read_lock_irqsave(&fm->lock, flags); @@ -830,7 +829,7 @@ int drm_fence_buffers_ioctl(struct drm_device *dev, void *data, struct drm_file DRM_FENCE_FLAG_SHAREABLE); if (ret) return ret; - atomic_inc(&fence->usage); + arg->handle = fence->base.hash.key; read_lock_irqsave(&fm->lock, flags); -- cgit v1.2.3 From c395d27a725f170645704bfc0d27b1e935b53c83 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 25 Jul 2007 14:32:15 +1000 Subject: drm/fence: shut up lockdep --- linux-core/drm_fence.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux-core/drm_fence.c b/linux-core/drm_fence.c index fdb2a4db..2f16f7ef 100644 --- a/linux-core/drm_fence.c +++ b/linux-core/drm_fence.c @@ -520,9 +520,10 @@ void drm_fence_manager_init(struct drm_device * dev) struct drm_fence_class_manager *class; struct drm_fence_driver *fed = dev->driver->fence_driver; int i; + unsigned long flags; rwlock_init(&fm->lock); - write_lock(&fm->lock); + write_lock_irqsave(&fm->lock, flags); fm->initialized = 0; if (!fed) goto out_unlock; @@ -541,7 +542,7 @@ void drm_fence_manager_init(struct drm_device * dev) atomic_set(&fm->count, 0); out_unlock: - write_unlock(&fm->lock); + write_unlock_irqrestore(&fm->lock, flags); } void drm_fence_manager_takedown(struct drm_device * dev) -- cgit v1.2.3 From 7602e4f8a67d777437502672b4f74d9b990535ce Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 2 Aug 2007 19:13:45 +1000 Subject: drm: add unlocked ioctl code path - not used yet --- linux-core/drmP.h | 2 ++ linux-core/drm_drv.c | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 2b7e0a44..a61efcff 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -911,6 +911,8 @@ extern void drm_exit(struct drm_driver *driver); extern void drm_cleanup_pci(struct pci_dev *pdev); extern int drm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern long drm_unlocked_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg); extern long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index cc676bda..bb15987e 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -573,6 +573,12 @@ static int drm_version(struct drm_device *dev, void *data, */ int drm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +{ + return drm_unlocked_ioctl(filp, cmd, arg); +} +EXPORT_SYMBOL(drm_ioctl); + +long drm_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct drm_file *file_priv = filp->private_data; struct drm_device *dev = file_priv->head->dev; @@ -650,7 +656,7 @@ err_i1: DRM_DEBUG("ret = %x\n", retcode); return retcode; } -EXPORT_SYMBOL(drm_ioctl); +EXPORT_SYMBOL(drm_unlocked_ioctl); drm_local_map_t *drm_getsarea(struct drm_device *dev) { -- cgit v1.2.3 From 405c48b857a967c1174b27a5db975668e1d6a9f8 Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Thu, 2 Aug 2007 20:06:37 +0200 Subject: Add libdrm source dir, to build tests from a different build dir --- tests/Makefile.am | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 3b97fb79..38a07a35 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ - -I $(top_srcdir)/shared-core + -I $(top_srcdir)/shared-core \ + -I $(top_srcdir)/libdrm noinst_PROGRAMS = \ dristat \ @@ -20,4 +21,5 @@ TESTS = openclose \ updatedraw EXTRA_PROGRAMS = $(TESTS) -CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES) \ No newline at end of file +CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES) + -- cgit v1.2.3 From 2453ba19b6f9956ea5d412a66d5d33c8a8b301b2 Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Fri, 3 Aug 2007 23:06:39 +0200 Subject: nouveau:nv10: fill and use load,save graph context functions --- shared-core/nv10_graph.c | 55 +++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c index 930fcbdf..ce1cbfa7 100644 --- a/shared-core/nv10_graph.c +++ b/shared-core/nv10_graph.c @@ -544,24 +544,42 @@ static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) return -1; } -static void restore_ctx_regs(struct drm_device *dev, int channel) +int nv10_graph_load_context(struct drm_device *dev, int channel) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fifo *fifo = dev_priv->fifos[channel]; int i, j; + for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) NV_WRITE(nv10_graph_ctx_regs[i], fifo->pgraph_ctx[i]); if (dev_priv->chipset>=0x17) { for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) NV_WRITE(nv17_graph_ctx_regs[j], fifo->pgraph_ctx[i]); } - nouveau_wait_for_idle(dev); + + return 0; +} + +int nv10_graph_save_context(struct drm_device *dev, int channel) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo *fifo = dev_priv->fifos[channel]; + int i, j; + + for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) + fifo->pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); + if (dev_priv->chipset>=0x17) { + for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) + fifo->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); + } + + return 0; } void nouveau_nv10_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - int channel, channel_old, i, j; + int channel, channel_old; channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); @@ -574,14 +592,7 @@ void nouveau_nv10_context_switch(struct drm_device *dev) NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000); NV_WRITE(NV_PFIFO_CACHES, 0x00000000); #endif - - // save PGRAPH context - for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) - dev_priv->fifos[channel_old]->pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); - if (dev_priv->chipset>=0x17) { - for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) - dev_priv->fifos[channel_old]->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); - } + nv10_graph_save_context(dev, channel_old); nouveau_wait_for_idle(dev); @@ -589,15 +600,12 @@ void nouveau_nv10_context_switch(struct drm_device *dev) NV_WRITE(NV10_PGRAPH_CTX_USER, (NV_READ(NV10_PGRAPH_CTX_USER) & 0xffffff) | (0x1f << 24)); nouveau_wait_for_idle(dev); - // restore PGRAPH context -#if 1 - restore_ctx_regs(dev, channel); -#endif + + nv10_graph_load_context(dev, channel); NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24); NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); - #if 0 NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000001); @@ -611,6 +619,7 @@ void nouveau_nv10_context_switch(struct drm_device *dev) if (offset > 0) \ fifo->pgraph_ctx[offset] = val; \ } while (0) + int nv10_graph_create_context(struct drm_device *dev, int channel) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fifo *fifo = dev_priv->fifos[channel]; @@ -654,7 +663,7 @@ int nv10_graph_create_context(struct drm_device *dev, int channel) { /* for the first channel init the regs */ if (dev_priv->fifo_alloc_count == 0) - restore_ctx_regs(dev, channel); + nv10_graph_load_context(dev, channel); //XXX should be saved/restored for each fifo @@ -667,18 +676,6 @@ void nv10_graph_destroy_context(struct drm_device *dev, int channel) { } -int nv10_graph_load_context(struct drm_device *dev, int channel) -{ - DRM_ERROR("stub!\n"); - return 0; -} - -int nv10_graph_save_context(struct drm_device *dev, int channel) -{ - DRM_ERROR("stub!\n"); - return 0; -} - int nv10_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; int i; -- 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. --- linux-core/nouveau_sgdma.c | 2 +- shared-core/nouveau_drv.h | 391 ++++++++++++++++++++++------------------- shared-core/nouveau_fifo.c | 104 ++++++----- shared-core/nouveau_notifier.c | 42 ++--- shared-core/nouveau_object.c | 150 ++++++++-------- shared-core/nouveau_state.c | 7 +- shared-core/nv04_fifo.c | 29 ++- shared-core/nv04_graph.c | 15 +- shared-core/nv10_fifo.c | 27 ++- shared-core/nv10_graph.c | 49 +++--- shared-core/nv20_graph.c | 68 +++---- shared-core/nv30_graph.c | 35 ++-- shared-core/nv40_fifo.c | 24 +-- shared-core/nv40_graph.c | 26 ++- shared-core/nv50_fifo.c | 41 +++-- shared-core/nv50_graph.c | 27 ++- 16 files changed, 516 insertions(+), 521 deletions(-) diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c index 0ddac952..6393a469 100644 --- a/linux-core/nouveau_sgdma.c +++ b/linux-core/nouveau_sgdma.c @@ -211,7 +211,7 @@ nouveau_sgdma_init(struct drm_device *dev) obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8; } - if ((ret = nouveau_gpuobj_new(dev, -1, obj_size, 16, + if ((ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, NVOBJ_FLAG_ALLOW_NO_REFS | NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &gpuobj))) { diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index dd323a0b..8ec91898 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -92,8 +92,11 @@ struct nouveau_gpuobj_ref { int handle; }; -struct nouveau_fifo +struct nouveau_channel { + struct drm_device *dev; + int id; + /* owner of this fifo */ struct drm_file *file_priv; /* mapping of the fifo itself */ @@ -136,57 +139,64 @@ struct nouveau_config { } cmdbuf; }; -struct nouveau_engine_func { - struct { - void *priv; +struct nouveau_instmem_engine { + void *priv; - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); - int (*populate)(struct drm_device *, struct nouveau_gpuobj *, - uint32_t *size); - void (*clear)(struct drm_device *, struct nouveau_gpuobj *); - int (*bind)(struct drm_device *, struct nouveau_gpuobj *); - int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); - } instmem; + int (*populate)(struct drm_device *, struct nouveau_gpuobj *, + uint32_t *size); + void (*clear)(struct drm_device *, struct nouveau_gpuobj *); + int (*bind)(struct drm_device *, struct nouveau_gpuobj *); + int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); +}; - struct { - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - } mc; +struct nouveau_mc_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; - struct { - int (*init)(struct drm_device *dev); - uint64_t (*read)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - } timer; +struct nouveau_timer_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); + uint64_t (*read)(struct drm_device *dev); +}; - struct { - int (*init)(struct drm_device *dev); - void (*takedown)(struct drm_device *dev); - } fb; +struct nouveau_fb_engine { + int (*init)(struct drm_device *dev); + void (*takedown)(struct drm_device *dev); +}; - struct { - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); +struct nouveau_fifo_engine { + void *priv; - int (*create_context)(struct drm_device *, int channel); - void (*destroy_context)(struct drm_device *, int channel); - int (*load_context)(struct drm_device *, int channel); - int (*save_context)(struct drm_device *, int channel); - } graph; + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); - struct { - void *priv; + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*save_context)(struct nouveau_channel *); +}; - int (*init)(struct drm_device *); - void (*takedown)(struct drm_device *); +struct nouveau_pgraph_engine { + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); - int (*create_context)(struct drm_device *, int channel); - void (*destroy_context)(struct drm_device *, int channel); - int (*load_context)(struct drm_device *, int channel); - int (*save_context)(struct drm_device *, int channel); - } fifo; + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + int (*load_context)(struct nouveau_channel *); + int (*save_context)(struct nouveau_channel *); +}; + +struct nouveau_engine { + struct nouveau_instmem_engine instmem; + struct nouveau_mc_engine mc; + struct nouveau_timer_engine timer; + struct nouveau_fb_engine fb; + struct nouveau_pgraph_engine graph; + struct nouveau_fifo_engine fifo; }; struct drm_nouveau_private { @@ -207,9 +217,9 @@ struct drm_nouveau_private { drm_local_map_t *ramin; /* NV40 onwards */ int fifo_alloc_count; - struct nouveau_fifo *fifos[NV_MAX_FIFO_NUMBER]; + struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER]; - struct nouveau_engine_func Engine; + struct nouveau_engine Engine; /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ struct nouveau_gpuobj *ramht; @@ -262,93 +272,108 @@ struct drm_nouveau_private { struct nouveau_gpuobj *gpuobj_all; }; +#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (!nouveau_fifo_owner(dev, (cl), (id))) { \ + DRM_ERROR("pid %d doesn't own channel %d\n", \ + DRM_CURRENTPID, (id)); \ + return -EPERM; \ + } \ + (ch) = nv->fifos[(id)]; \ +} while(0) + /* nouveau_state.c */ -extern void nouveau_preclose(struct drm_device * dev, - struct drm_file *file_priv); -extern int nouveau_load(struct drm_device *dev, unsigned long flags); -extern int nouveau_firstopen(struct drm_device *dev); -extern void nouveau_lastclose(struct drm_device *dev); -extern int nouveau_unload(struct drm_device *dev); -extern int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void nouveau_wait_for_idle(struct drm_device *dev); -extern int nouveau_ioctl_card_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); +extern int nouveau_load(struct drm_device *, unsigned long flags); +extern int nouveau_firstopen(struct drm_device *); +extern void nouveau_lastclose(struct drm_device *); +extern int nouveau_unload(struct drm_device *); +extern int nouveau_ioctl_getparam(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_setparam(struct drm_device *, void *data, + struct drm_file *); +extern void nouveau_wait_for_idle(struct drm_device *); +extern int nouveau_ioctl_card_init(struct drm_device *, void *data, + struct drm_file *); /* nouveau_mem.c */ -extern int nouveau_mem_init_heap(struct mem_block **, - uint64_t start, uint64_t size); +extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start, + uint64_t size); extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *, uint64_t size, int align2, - struct drm_file *file_priv); -extern void nouveau_mem_takedown(struct mem_block **heap); -extern void nouveau_mem_free_block(struct mem_block *); -extern uint64_t nouveau_mem_fb_amount(struct drm_device *dev); -extern void nouveau_mem_release(struct drm_file *file_priv, - struct mem_block *heap); -extern int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern struct mem_block* nouveau_mem_alloc(struct drm_device *dev, + struct drm_file *); +extern void nouveau_mem_takedown(struct mem_block **heap); +extern void nouveau_mem_free_block(struct mem_block *); +extern uint64_t nouveau_mem_fb_amount(struct drm_device *); +extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); +extern int nouveau_ioctl_mem_alloc(struct drm_device *, void *data, + struct drm_file *); +extern int nouveau_ioctl_mem_free(struct drm_device *, void *data, + struct drm_file *); +extern struct mem_block* nouveau_mem_alloc(struct drm_device *, int alignment, uint64_t size, - int flags, - struct drm_file *file_priv); -extern void nouveau_mem_free(struct drm_device* dev, struct mem_block*); -extern int nouveau_mem_init(struct drm_device *dev); -extern void nouveau_mem_close(struct drm_device *dev); + int flags, struct drm_file *); +extern void nouveau_mem_free(struct drm_device *dev, struct mem_block*); +extern int nouveau_mem_init(struct drm_device *); +extern void nouveau_mem_close(struct drm_device *); /* nouveau_notifier.c */ -extern int nouveau_notifier_init_channel(struct drm_device *, int channel, - struct drm_file *file_priv); -extern void nouveau_notifier_takedown_channel(struct drm_device *, int channel); -extern int nouveau_notifier_alloc(struct drm_device *, int channel, - uint32_t handle, int cout, uint32_t *offset); -extern int nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int nouveau_notifier_init_channel(struct nouveau_channel *); +extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); +extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, + int cout, uint32_t *offset); +extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data, + struct drm_file *); /* nouveau_fifo.c */ -extern int nouveau_fifo_init(struct drm_device *dev); -extern int nouveau_fifo_number(struct drm_device *dev); -extern int nouveau_fifo_ctx_size(struct drm_device *dev); -extern void nouveau_fifo_cleanup(struct drm_device *dev, - struct drm_file *file_priv); -extern int nouveau_fifo_owner(struct drm_device *dev, - struct drm_file *file_priv, int channel); -extern void nouveau_fifo_free(struct drm_device *dev, int channel); +extern int nouveau_fifo_init(struct drm_device *); +extern int nouveau_fifo_number(struct drm_device *); +extern int nouveau_fifo_ctx_size(struct drm_device *); +extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *); +extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, + int channel); +extern void nouveau_fifo_free(struct nouveau_channel *); /* nouveau_object.c */ -extern void nouveau_gpuobj_takedown(struct drm_device *dev); -extern int nouveau_gpuobj_channel_init(struct drm_device *, int channel, +extern void nouveau_gpuobj_takedown(struct drm_device *); +extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, uint32_t vram_h, uint32_t tt_h); -extern void nouveau_gpuobj_channel_takedown(struct drm_device *, int channel); -extern int nouveau_gpuobj_new(struct drm_device *, int channel, int size, int align, - uint32_t flags, struct nouveau_gpuobj **); +extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); +extern int nouveau_gpuobj_new(struct drm_device *, struct nouveau_channel *, + int size, int align, uint32_t flags, + struct nouveau_gpuobj **); extern int nouveau_gpuobj_del(struct drm_device *, struct nouveau_gpuobj **); -extern int nouveau_gpuobj_ref_add(struct drm_device *, int channel, uint32_t handle, - struct nouveau_gpuobj *, +extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *, + uint32_t handle, struct nouveau_gpuobj *, + struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_del(struct drm_device *, struct nouveau_gpuobj_ref **); -extern int nouveau_gpuobj_ref_del(struct drm_device *, struct nouveau_gpuobj_ref **); -extern int nouveau_gpuobj_new_ref(struct drm_device *, int chan_obj, int chan_ref, +extern int nouveau_gpuobj_new_ref(struct drm_device *, + struct nouveau_channel *alloc_chan, + struct nouveau_channel *ref_chan, uint32_t handle, int size, int align, uint32_t flags, struct nouveau_gpuobj_ref **); extern int nouveau_gpuobj_new_fake(struct drm_device *, uint32_t offset, uint32_t size, uint32_t flags, - struct nouveau_gpuobj**, + struct nouveau_gpuobj **, struct nouveau_gpuobj_ref**); -extern int nouveau_gpuobj_dma_new(struct drm_device *, int channel, int class, - uint64_t offset, uint64_t size, - int access, int target, - struct nouveau_gpuobj **); -extern int nouveau_gpuobj_gart_dma_new(struct drm_device *, int channel, +extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, + uint64_t offset, uint64_t size, int access, + int target, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, uint64_t offset, uint64_t size, int access, struct nouveau_gpuobj **, uint32_t *o_ret); -extern int nouveau_gpuobj_gr_new(struct drm_device *, int channel, int class, +extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, struct nouveau_gpuobj **); -extern int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, + struct drm_file *); /* nouveau_irq.c */ extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); -extern void nouveau_irq_preinstall(struct drm_device*); -extern void nouveau_irq_postinstall(struct drm_device*); -extern void nouveau_irq_uninstall(struct drm_device*); +extern void nouveau_irq_preinstall(struct drm_device *); +extern void nouveau_irq_postinstall(struct drm_device *); +extern void nouveau_irq_uninstall(struct drm_device *); /* nouveau_sgdma.c */ extern int nouveau_sgdma_init(struct drm_device *); @@ -358,131 +383,131 @@ extern int nouveau_sgdma_nottm_hack_init(struct drm_device *); extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *); /* nv04_fb.c */ -extern int nv04_fb_init(struct drm_device *dev); -extern void nv04_fb_takedown(struct drm_device *dev); +extern int nv04_fb_init(struct drm_device *); +extern void nv04_fb_takedown(struct drm_device *); /* nv10_fb.c */ -extern int nv10_fb_init(struct drm_device *dev); -extern void nv10_fb_takedown(struct drm_device *dev); +extern int nv10_fb_init(struct drm_device *); +extern void nv10_fb_takedown(struct drm_device *); /* nv40_fb.c */ -extern int nv40_fb_init(struct drm_device *dev); -extern void nv40_fb_takedown(struct drm_device *dev); +extern int nv40_fb_init(struct drm_device *); +extern void nv40_fb_takedown(struct drm_device *); /* nv04_fifo.c */ -extern int nv04_fifo_create_context(struct drm_device *dev, int channel); -extern void nv04_fifo_destroy_context(struct drm_device *dev, int channel); -extern int nv04_fifo_load_context(struct drm_device *dev, int channel); -extern int nv04_fifo_save_context(struct drm_device *dev, int channel); +extern int nv04_fifo_create_context(struct nouveau_channel *); +extern void nv04_fifo_destroy_context(struct nouveau_channel *); +extern int nv04_fifo_load_context(struct nouveau_channel *); +extern int nv04_fifo_save_context(struct nouveau_channel *); /* nv10_fifo.c */ -extern int nv10_fifo_create_context(struct drm_device *dev, int channel); -extern void nv10_fifo_destroy_context(struct drm_device *dev, int channel); -extern int nv10_fifo_load_context(struct drm_device *dev, int channel); -extern int nv10_fifo_save_context(struct drm_device *dev, int channel); +extern int nv10_fifo_create_context(struct nouveau_channel *); +extern void nv10_fifo_destroy_context(struct nouveau_channel *); +extern int nv10_fifo_load_context(struct nouveau_channel *); +extern int nv10_fifo_save_context(struct nouveau_channel *); /* nv40_fifo.c */ -extern int nv40_fifo_create_context(struct drm_device *, int channel); -extern void nv40_fifo_destroy_context(struct drm_device *, int channel); -extern int nv40_fifo_load_context(struct drm_device *, int channel); -extern int nv40_fifo_save_context(struct drm_device *, int channel); +extern int nv40_fifo_create_context(struct nouveau_channel *); +extern void nv40_fifo_destroy_context(struct nouveau_channel *); +extern int nv40_fifo_load_context(struct nouveau_channel *); +extern int nv40_fifo_save_context(struct nouveau_channel *); /* nv50_fifo.c */ extern int nv50_fifo_init(struct drm_device *); extern void nv50_fifo_takedown(struct drm_device *); -extern int nv50_fifo_create_context(struct drm_device *, int channel); -extern void nv50_fifo_destroy_context(struct drm_device *, int channel); -extern int nv50_fifo_load_context(struct drm_device *, int channel); -extern int nv50_fifo_save_context(struct drm_device *, int channel); +extern int nv50_fifo_create_context(struct nouveau_channel *); +extern void nv50_fifo_destroy_context(struct nouveau_channel *); +extern int nv50_fifo_load_context(struct nouveau_channel *); +extern int nv50_fifo_save_context(struct nouveau_channel *); /* nv04_graph.c */ -extern void nouveau_nv04_context_switch(struct drm_device *dev); -extern int nv04_graph_init(struct drm_device *dev); -extern void nv04_graph_takedown(struct drm_device *dev); -extern int nv04_graph_create_context(struct drm_device *dev, int channel); -extern void nv04_graph_destroy_context(struct drm_device *dev, int channel); -extern int nv04_graph_load_context(struct drm_device *dev, int channel); -extern int nv04_graph_save_context(struct drm_device *dev, int channel); +extern void nouveau_nv04_context_switch(struct drm_device *); +extern int nv04_graph_init(struct drm_device *); +extern void nv04_graph_takedown(struct drm_device *); +extern int nv04_graph_create_context(struct nouveau_channel *); +extern void nv04_graph_destroy_context(struct nouveau_channel *); +extern int nv04_graph_load_context(struct nouveau_channel *); +extern int nv04_graph_save_context(struct nouveau_channel *); /* nv10_graph.c */ -extern void nouveau_nv10_context_switch(struct drm_device *dev); -extern int nv10_graph_init(struct drm_device *dev); -extern void nv10_graph_takedown(struct drm_device *dev); -extern int nv10_graph_create_context(struct drm_device *dev, int channel); -extern void nv10_graph_destroy_context(struct drm_device *dev, int channel); -extern int nv10_graph_load_context(struct drm_device *dev, int channel); -extern int nv10_graph_save_context(struct drm_device *dev, int channel); +extern void nouveau_nv10_context_switch(struct drm_device *); +extern int nv10_graph_init(struct drm_device *); +extern void nv10_graph_takedown(struct drm_device *); +extern int nv10_graph_create_context(struct nouveau_channel *); +extern void nv10_graph_destroy_context(struct nouveau_channel *); +extern int nv10_graph_load_context(struct nouveau_channel *); +extern int nv10_graph_save_context(struct nouveau_channel *); /* nv20_graph.c */ -extern void nouveau_nv20_context_switch(struct drm_device *dev); -extern int nv20_graph_init(struct drm_device *dev); -extern void nv20_graph_takedown(struct drm_device *dev); -extern int nv20_graph_create_context(struct drm_device *dev, int channel); -extern void nv20_graph_destroy_context(struct drm_device *dev, int channel); -extern int nv20_graph_load_context(struct drm_device *dev, int channel); -extern int nv20_graph_save_context(struct drm_device *dev, int channel); +extern void nouveau_nv20_context_switch(struct drm_device *); +extern int nv20_graph_init(struct drm_device *); +extern void nv20_graph_takedown(struct drm_device *); +extern int nv20_graph_create_context(struct nouveau_channel *); +extern void nv20_graph_destroy_context(struct nouveau_channel *); +extern int nv20_graph_load_context(struct nouveau_channel *); +extern int nv20_graph_save_context(struct nouveau_channel *); /* nv30_graph.c */ -extern int nv30_graph_init(struct drm_device *dev); -extern void nv30_graph_takedown(struct drm_device *dev); -extern int nv30_graph_create_context(struct drm_device *, int channel); -extern void nv30_graph_destroy_context(struct drm_device *, int channel); -extern int nv30_graph_load_context(struct drm_device *, int channel); -extern int nv30_graph_save_context(struct drm_device *, int channel); +extern int nv30_graph_init(struct drm_device *); +extern void nv30_graph_takedown(struct drm_device *); +extern int nv30_graph_create_context(struct nouveau_channel *); +extern void nv30_graph_destroy_context(struct nouveau_channel *); +extern int nv30_graph_load_context(struct nouveau_channel *); +extern int nv30_graph_save_context(struct nouveau_channel *); /* nv40_graph.c */ extern int nv40_graph_init(struct drm_device *); extern void nv40_graph_takedown(struct drm_device *); -extern int nv40_graph_create_context(struct drm_device *, int channel); -extern void nv40_graph_destroy_context(struct drm_device *, int channel); -extern int nv40_graph_load_context(struct drm_device *, int channel); -extern int nv40_graph_save_context(struct drm_device *, int channel); +extern int nv40_graph_create_context(struct nouveau_channel *); +extern void nv40_graph_destroy_context(struct nouveau_channel *); +extern int nv40_graph_load_context(struct nouveau_channel *); +extern int nv40_graph_save_context(struct nouveau_channel *); /* nv50_graph.c */ extern int nv50_graph_init(struct drm_device *); extern void nv50_graph_takedown(struct drm_device *); -extern int nv50_graph_create_context(struct drm_device *, int channel); -extern void nv50_graph_destroy_context(struct drm_device *, int channel); -extern int nv50_graph_load_context(struct drm_device *, int channel); -extern int nv50_graph_save_context(struct drm_device *, int channel); +extern int nv50_graph_create_context(struct nouveau_channel *); +extern void nv50_graph_destroy_context(struct nouveau_channel *); +extern int nv50_graph_load_context(struct nouveau_channel *); +extern int nv50_graph_save_context(struct nouveau_channel *); /* nv04_instmem.c */ -extern int nv04_instmem_init(struct drm_device *dev); -extern void nv04_instmem_takedown(struct drm_device *dev); -extern int nv04_instmem_populate(struct drm_device*, struct nouveau_gpuobj*, +extern int nv04_instmem_init(struct drm_device *); +extern void nv04_instmem_takedown(struct drm_device *); +extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, uint32_t *size); -extern void nv04_instmem_clear(struct drm_device*, struct nouveau_gpuobj*); -extern int nv04_instmem_bind(struct drm_device*, struct nouveau_gpuobj*); -extern int nv04_instmem_unbind(struct drm_device*, struct nouveau_gpuobj*); +extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); +extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); /* nv50_instmem.c */ -extern int nv50_instmem_init(struct drm_device *dev); -extern void nv50_instmem_takedown(struct drm_device *dev); -extern int nv50_instmem_populate(struct drm_device*, struct nouveau_gpuobj*, +extern int nv50_instmem_init(struct drm_device *); +extern void nv50_instmem_takedown(struct drm_device *); +extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, uint32_t *size); -extern void nv50_instmem_clear(struct drm_device*, struct nouveau_gpuobj*); -extern int nv50_instmem_bind(struct drm_device*, struct nouveau_gpuobj*); -extern int nv50_instmem_unbind(struct drm_device*, struct nouveau_gpuobj*); +extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); +extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); /* nv04_mc.c */ -extern int nv04_mc_init(struct drm_device *dev); -extern void nv04_mc_takedown(struct drm_device *dev); +extern int nv04_mc_init(struct drm_device *); +extern void nv04_mc_takedown(struct drm_device *); /* nv40_mc.c */ -extern int nv40_mc_init(struct drm_device *dev); -extern void nv40_mc_takedown(struct drm_device *dev); +extern int nv40_mc_init(struct drm_device *); +extern void nv40_mc_takedown(struct drm_device *); /* nv50_mc.c */ -extern int nv50_mc_init(struct drm_device *dev); -extern void nv50_mc_takedown(struct drm_device *dev); +extern int nv50_mc_init(struct drm_device *); +extern void nv50_mc_takedown(struct drm_device *); /* nv04_timer.c */ -extern int nv04_timer_init(struct drm_device *dev); -extern uint64_t nv04_timer_read(struct drm_device *dev); -extern void nv04_timer_takedown(struct drm_device *dev); +extern int nv04_timer_init(struct drm_device *); +extern uint64_t nv04_timer_read(struct drm_device *); +extern void nv04_timer_takedown(struct drm_device *); extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); + unsigned long arg); #if defined(__powerpc__) #define NV_READ(reg) in_be32((void __iomem *)(dev_priv->mmio)->handle + (reg) ) diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index e5d3ab3c..c7ce1d8d 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -186,10 +186,10 @@ int nouveau_fifo_init(struct drm_device *dev) } static int -nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) +nouveau_fifo_cmdbuf_alloc(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_config *config = &dev_priv->config; struct mem_block *cb; int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE); @@ -211,37 +211,34 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) } if (cb->flags & NOUVEAU_MEM_AGP) { - ret = nouveau_gpuobj_gart_dma_new(dev, channel, - cb->start, cb->size, + ret = nouveau_gpuobj_gart_dma_new(chan, cb->start, cb->size, NV_DMA_ACCESS_RO, &pushbuf, &chan->pushbuf_base); } else if (cb->flags & NOUVEAU_MEM_PCI) { - ret = nouveau_gpuobj_dma_new(dev, channel, - NV_CLASS_DMA_IN_MEMORY, + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, cb->start, cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI_NONLINEAR, &pushbuf); chan->pushbuf_base = 0; } else if (dev_priv->card_type != NV_04) { - ret = nouveau_gpuobj_dma_new - (dev, channel, NV_CLASS_DMA_IN_MEMORY, - cb->start, - cb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM, - &pushbuf); + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + cb->start, cb->size, + NV_DMA_ACCESS_RO, + NV_DMA_TARGET_VIDMEM, &pushbuf); chan->pushbuf_base = 0; } else { /* NV04 cmdbuf hack, from original ddx.. not sure of it's * exact reason for existing :) PCI access to cmdbuf in * VRAM. */ - ret = nouveau_gpuobj_dma_new - (dev, channel, NV_CLASS_DMA_IN_MEMORY, - cb->start + drm_get_resource_start(dev, 1), - cb->size, NV_DMA_ACCESS_RO, - NV_DMA_TARGET_PCI, &pushbuf); + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + cb->start + + drm_get_resource_start(dev, 1), + cb->size, NV_DMA_ACCESS_RO, + NV_DMA_TARGET_PCI, &pushbuf); chan->pushbuf_base = 0; } @@ -251,7 +248,7 @@ nouveau_fifo_cmdbuf_alloc(struct drm_device *dev, int channel) return ret; } - if ((ret = nouveau_gpuobj_ref_add(dev, channel, 0, pushbuf, + if ((ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf))) { DRM_ERROR("Error referencing push buffer ctxdma: %d\n", ret); if (pushbuf != dev_priv->gart_info.sg_ctxdma) @@ -270,8 +267,8 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, { int ret; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine_func *engine = &dev_priv->Engine; - struct nouveau_fifo *chan; + struct nouveau_engine *engine = &dev_priv->Engine; + struct nouveau_channel *chan; int channel; /* @@ -293,34 +290,36 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, return -EINVAL; (*chan_ret) = channel; - dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_fifo), + dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel), DRM_MEM_DRIVER); if (!dev_priv->fifos[channel]) return -ENOMEM; dev_priv->fifo_alloc_count++; chan = dev_priv->fifos[channel]; + chan->dev = dev; + chan->id = channel; chan->file_priv = file_priv; DRM_INFO("Allocating FIFO number %d\n", channel); /* Setup channel's default objects */ - ret = nouveau_gpuobj_channel_init(dev, channel, vram_handle, tt_handle); + ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); if (ret) { - nouveau_fifo_free(dev, channel); + nouveau_fifo_free(chan); return ret; } /* allocate a command buffer, and create a dma object for the gpu */ - ret = nouveau_fifo_cmdbuf_alloc(dev, channel); + ret = nouveau_fifo_cmdbuf_alloc(chan); if (ret) { - nouveau_fifo_free(dev, channel); + nouveau_fifo_free(chan); return ret; } /* Allocate space for per-channel fixed notifier memory */ - ret = nouveau_notifier_init_channel(dev, channel, file_priv); + ret = nouveau_notifier_init_channel(chan); if (ret) { - nouveau_fifo_free(dev, channel); + nouveau_fifo_free(chan); return ret; } @@ -333,16 +332,16 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000); /* Create a graphics context for new channel */ - ret = engine->graph.create_context(dev, channel); + ret = engine->graph.create_context(chan); if (ret) { - nouveau_fifo_free(dev, channel); + nouveau_fifo_free(chan); return ret; } /* Construct inital RAMFC for new channel */ - ret = engine->fifo.create_context(dev, channel); + ret = engine->fifo.create_context(chan); if (ret) { - nouveau_fifo_free(dev, channel); + nouveau_fifo_free(chan); return ret; } @@ -359,15 +358,15 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, * other case, the GPU will handle this when it switches contexts. */ if (dev_priv->fifo_alloc_count == 1) { - ret = engine->fifo.load_context(dev, channel); + ret = engine->fifo.load_context(chan); if (ret) { - nouveau_fifo_free(dev, channel); + nouveau_fifo_free(chan); return ret; } - ret = engine->graph.load_context(dev, channel); + ret = engine->graph.load_context(chan); if (ret) { - nouveau_fifo_free(dev, channel); + nouveau_fifo_free(chan); return ret; } @@ -399,28 +398,23 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, } /* stops a fifo */ -void nouveau_fifo_free(struct drm_device *dev, int channel) +void nouveau_fifo_free(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine_func *engine = &dev_priv->Engine; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; - - if (!chan) { - DRM_ERROR("Freeing non-existant channel %d\n", channel); - return; - } + struct nouveau_engine *engine = &dev_priv->Engine; - DRM_INFO("%s: freeing fifo %d\n", __func__, channel); + DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id); /* disable the fifo caches */ NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); // FIXME XXX needs more code - engine->fifo.destroy_context(dev, channel); + engine->fifo.destroy_context(chan); /* Cleanup PGRAPH state */ - engine->graph.destroy_context(dev, channel); + engine->graph.destroy_context(chan); /* reenable the fifo caches */ NV_WRITE(NV03_PFIFO_CACHES, 0x00000001); @@ -432,12 +426,12 @@ void nouveau_fifo_free(struct drm_device *dev, int channel) chan->pushbuf_mem = NULL; } - nouveau_notifier_takedown_channel(dev, channel); + nouveau_notifier_takedown_channel(chan); /* Destroy objects belonging to the channel */ - nouveau_gpuobj_channel_takedown(dev, channel); + nouveau_gpuobj_channel_takedown(chan); - dev_priv->fifos[channel] = NULL; + dev_priv->fifos[chan->id] = NULL; dev_priv->fifo_alloc_count--; drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER); } @@ -445,14 +439,16 @@ void nouveau_fifo_free(struct drm_device *dev, int channel) /* cleanups all the fifos from file_priv */ void nouveau_fifo_cleanup(struct drm_device *dev, struct drm_file *file_priv) { - int i; struct drm_nouveau_private *dev_priv = dev->dev_private; + int i; DRM_DEBUG("clearing FIFO enables from file_priv\n"); - for(i=0;ififos[i] && - dev_priv->fifos[i]->file_priv==file_priv) - nouveau_fifo_free(dev,i); + for(i = 0; i < nouveau_fifo_number(dev); i++) { + struct nouveau_channel *chan = dev_priv->fifos[i]; + + if (chan && chan->file_priv == file_priv) + nouveau_fifo_free(chan); + } } int @@ -477,7 +473,7 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct d struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_fifo_alloc *init = data; struct drm_map_list *entry; - struct nouveau_fifo *chan; + struct nouveau_channel *chan; int res; if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) 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; 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); diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index f45f2783..26ba8fbf 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -93,7 +93,7 @@ static uint64_t nouveau_stub_timer_read(struct drm_device *dev) { return 0; } static int nouveau_init_engine_ptrs(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine_func *engine = &dev_priv->Engine; + struct nouveau_engine *engine = &dev_priv->Engine; switch (dev_priv->chipset & 0xf0) { case 0x00: @@ -270,7 +270,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) static int nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine_func *engine; + struct nouveau_engine *engine; int ret; /* Map any PCI resources we need on the card */ @@ -332,7 +332,7 @@ static int nouveau_card_init(struct drm_device *dev) static void nouveau_card_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine_func *engine = &dev_priv->Engine; + struct nouveau_engine *engine = &dev_priv->Engine; if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { engine->fifo.takedown(dev); @@ -526,6 +526,7 @@ void nouveau_wait_for_idle(struct drm_device *dev) uint32_t status; do { uint32_t pmc_e = NV_READ(NV03_PMC_ENABLE); + (void)pmc_e; status = NV_READ(NV04_PGRAPH_STATUS); if (!status) break; diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c index 564efd0b..4d61f4fe 100644 --- a/shared-core/nv04_fifo.c +++ b/shared-core/nv04_fifo.c @@ -36,13 +36,13 @@ #define NV04_RAMFC__SIZE 32 int -nv04_fifo_create_context(struct drm_device *dev, int channel) +nv04_fifo_create_context(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 ret; - if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(channel), + if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), NV04_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -62,30 +62,29 @@ nv04_fifo_create_context(struct drm_device *dev, int channel) 0)); /* enable the fifo dma operation */ - NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<id)); return 0; } void -nv04_fifo_destroy_context(struct drm_device *dev, int channel) +nv04_fifo_destroy_context(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]; - - NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<id)); - if (chan->ramfc) - nouveau_gpuobj_ref_del(dev, &chan->ramfc); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); } int -nv04_fifo_load_context(struct drm_device *dev, int channel) +nv04_fifo_load_context(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]; uint32_t tmp; - NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | channel); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, (1<<8) | chan->id); NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET, RAMFC_RD(DMA_GET)); NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT, RAMFC_RD(DMA_PUT)); @@ -107,10 +106,10 @@ nv04_fifo_load_context(struct drm_device *dev, int channel) } int -nv04_fifo_save_context(struct drm_device *dev, int channel) +nv04_fifo_save_context(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]; uint32_t tmp; RAMFC_WR(DMA_PUT, NV04_PFIFO_CACHE1_DMA_PUT); diff --git a/shared-core/nv04_graph.c b/shared-core/nv04_graph.c index e35e3071..b2ea7804 100644 --- a/shared-core/nv04_graph.c +++ b/shared-core/nv04_graph.c @@ -336,14 +336,13 @@ void nouveau_nv04_context_switch(struct drm_device *dev) NV_WRITE(NV04_PGRAPH_FIFO,0x1); } -int nv04_graph_create_context(struct drm_device *dev, int channel) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - DRM_DEBUG("nv04_graph_context_create %d\n", channel); +int nv04_graph_create_context(struct nouveau_channel *chan) { + DRM_DEBUG("nv04_graph_context_create %d\n", chan->id); - memset(dev_priv->fifos[channel]->pgraph_ctx, 0, sizeof(dev_priv->fifos[channel]->pgraph_ctx)); + memset(chan->pgraph_ctx, 0, sizeof(chan->pgraph_ctx)); //dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; - dev_priv->fifos[channel]->pgraph_ctx[0] = 0x0001ffff; + chan->pgraph_ctx[0] = 0x0001ffff; /* is it really needed ??? */ //dev_priv->fifos[channel].pgraph_ctx[1] = NV_READ(NV_PGRAPH_DEBUG_4); //dev_priv->fifos[channel].pgraph_ctx[2] = NV_READ(0x004006b0); @@ -351,17 +350,17 @@ int nv04_graph_create_context(struct drm_device *dev, int channel) { return 0; } -void nv04_graph_destroy_context(struct drm_device *dev, int channel) +void nv04_graph_destroy_context(struct nouveau_channel *chan) { } -int nv04_graph_load_context(struct drm_device *dev, int channel) +int nv04_graph_load_context(struct nouveau_channel *chan) { DRM_ERROR("stub!\n"); return 0; } -int nv04_graph_save_context(struct drm_device *dev, int channel) +int nv04_graph_save_context(struct nouveau_channel *chan) { DRM_ERROR("stub!\n"); return 0; diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c index 7b9c665b..47af0ff0 100644 --- a/shared-core/nv10_fifo.c +++ b/shared-core/nv10_fifo.c @@ -37,13 +37,13 @@ #define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) int -nv10_fifo_create_context(struct drm_device *dev, int channel) +nv10_fifo_create_context(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 ret; - if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(channel), + if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -65,30 +65,29 @@ nv10_fifo_create_context(struct drm_device *dev, int channel) 0); /* enable the fifo dma operation */ - NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<id)); return 0; } void -nv10_fifo_destroy_context(struct drm_device *dev, int channel) +nv10_fifo_destroy_context(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]; - NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<id)); - if (chan->ramfc) - nouveau_gpuobj_ref_del(dev, &chan->ramfc); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); } int -nv10_fifo_load_context(struct drm_device *dev, int channel) +nv10_fifo_load_context(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]; uint32_t tmp; - NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00000100 | channel); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00000100 | chan->id); NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET)); NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUT , RAMFC_RD(DMA_PUT)); @@ -124,10 +123,10 @@ nv10_fifo_load_context(struct drm_device *dev, int channel) } int -nv10_fifo_save_context(struct drm_device *dev, int channel) +nv10_fifo_save_context(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]; uint32_t tmp; RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); diff --git a/shared-core/nv10_graph.c b/shared-core/nv10_graph.c index ce1cbfa7..a2df2d71 100644 --- a/shared-core/nv10_graph.c +++ b/shared-core/nv10_graph.c @@ -544,33 +544,33 @@ static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) return -1; } -int nv10_graph_load_context(struct drm_device *dev, int channel) +int nv10_graph_load_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *fifo = dev_priv->fifos[channel]; int i, j; for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) - NV_WRITE(nv10_graph_ctx_regs[i], fifo->pgraph_ctx[i]); + NV_WRITE(nv10_graph_ctx_regs[i], chan->pgraph_ctx[i]); if (dev_priv->chipset>=0x17) { for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) - NV_WRITE(nv17_graph_ctx_regs[j], fifo->pgraph_ctx[i]); + NV_WRITE(nv17_graph_ctx_regs[j], chan->pgraph_ctx[i]); } return 0; } -int nv10_graph_save_context(struct drm_device *dev, int channel) +int nv10_graph_save_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *fifo = dev_priv->fifos[channel]; int i, j; for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) - fifo->pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); + chan->pgraph_ctx[i] = NV_READ(nv10_graph_ctx_regs[i]); if (dev_priv->chipset>=0x17) { for (j = 0; j < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++,j++) - fifo->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); + chan->pgraph_ctx[i] = NV_READ(nv17_graph_ctx_regs[j]); } return 0; @@ -579,12 +579,17 @@ int nv10_graph_save_context(struct drm_device *dev, int channel) void nouveau_nv10_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - int channel, channel_old; + struct nouveau_channel *next, *last; + int chid; - channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); - channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + next = dev_priv->fifos[chid]; - DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + last = dev_priv->fifos[chid]; + + DRM_INFO("NV: PGRAPH context switch interrupt channel %x -> %x\n", + last->id, next->id); NV_WRITE(NV04_PGRAPH_FIFO,0x0); #if 0 @@ -592,7 +597,7 @@ void nouveau_nv10_context_switch(struct drm_device *dev) NV_WRITE(NV_PFIFO_CACH1_PUL1, 0x00000000); NV_WRITE(NV_PFIFO_CACHES, 0x00000000); #endif - nv10_graph_save_context(dev, channel_old); + nv10_graph_save_context(last); nouveau_wait_for_idle(dev); @@ -601,10 +606,10 @@ void nouveau_nv10_context_switch(struct drm_device *dev) nouveau_wait_for_idle(dev); - nv10_graph_load_context(dev, channel); + nv10_graph_load_context(next); NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); - NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV10_PGRAPH_CTX_USER, next->id << 24); NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); #if 0 NV_WRITE(NV_PFIFO_CACH1_PUL0, 0x00000001); @@ -617,17 +622,17 @@ void nouveau_nv10_context_switch(struct drm_device *dev) #define NV_WRITE_CTX(reg, val) do { \ int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \ if (offset > 0) \ - fifo->pgraph_ctx[offset] = val; \ + chan->pgraph_ctx[offset] = val; \ } while (0) -int nv10_graph_create_context(struct drm_device *dev, int channel) { +int nv10_graph_create_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *fifo = dev_priv->fifos[channel]; uint32_t tmp, vramsz; - DRM_DEBUG("nv10_graph_context_create %d\n", channel); + DRM_DEBUG("nv10_graph_context_create %d\n", chan->id); - memset(fifo->pgraph_ctx, 0, sizeof(fifo->pgraph_ctx)); + memset(chan->pgraph_ctx, 0, sizeof(chan->pgraph_ctx)); /* per channel init from ddx */ tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00; @@ -663,7 +668,7 @@ int nv10_graph_create_context(struct drm_device *dev, int channel) { /* for the first channel init the regs */ if (dev_priv->fifo_alloc_count == 0) - nv10_graph_load_context(dev, channel); + nv10_graph_load_context(chan); //XXX should be saved/restored for each fifo @@ -672,7 +677,7 @@ int nv10_graph_create_context(struct drm_device *dev, int channel) { return 0; } -void nv10_graph_destroy_context(struct drm_device *dev, int channel) +void nv10_graph_destroy_context(struct nouveau_channel *chan) { } diff --git a/shared-core/nv20_graph.c b/shared-core/nv20_graph.c index 1670c527..d397390f 100644 --- a/shared-core/nv20_graph.c +++ b/shared-core/nv20_graph.c @@ -29,39 +29,36 @@ #define NV20_GRCTX_SIZE (3529*4) -int nv20_graph_create_context(struct drm_device *dev, int channel) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; +int nv20_graph_create_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; unsigned int ctx_size = NV20_GRCTX_SIZE; int ret; - if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, ctx_size, 16, + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx))) return ret; /* Initialise default context values */ - INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, channel<<24); /* CTX_USER */ + INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, chan->id<<24); /* CTX_USER */ - INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel, + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, chan->ramin_grctx->instance >> 4); return 0; } -void nv20_graph_destroy_context(struct drm_device *dev, int channel) { +void nv20_graph_destroy_context(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]; - if (chan->ramin_grctx) - nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); + nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); - INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel, 0); + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0); } static void nv20_graph_rdi(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; + struct drm_nouveau_private *dev_priv = dev->dev_private; int i; NV_WRITE(NV10_PGRAPH_RDI_INDEX, 0x2c80000); @@ -73,13 +70,12 @@ static void nv20_graph_rdi(struct drm_device *dev) { /* Save current context (from PGRAPH) into the channel's context */ -int nv20_graph_save_context(struct drm_device *dev, int channel) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; +int nv20_graph_save_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t instance; - instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, channel); + instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, chan->id); if (!instance) { return -EINVAL; } @@ -94,20 +90,19 @@ int nv20_graph_save_context(struct drm_device *dev, int channel) { /* Restore the context for a specific channel into PGRAPH */ -int nv20_graph_load_context(struct drm_device *dev, int channel) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; +int nv20_graph_load_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t instance; - instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, channel); + instance = INSTANCE_RD(dev_priv->ctx_table->gpuobj, chan->id); if (!instance) { return -EINVAL; } if (instance != (chan->ramin_grctx->instance >> 4)) DRM_ERROR("nv20_graph_load_context_current : bad instance\n"); - NV_WRITE(NV10_PGRAPH_CTX_USER, channel << 24); + NV_WRITE(NV10_PGRAPH_CTX_USER, chan->id << 24); NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_SIZE, instance); NV_WRITE(NV10_PGRAPH_CHANNEL_CTX_POINTER, 1 /* restore ctx */); return 0; @@ -116,27 +111,32 @@ int nv20_graph_load_context(struct drm_device *dev, int channel) { void nouveau_nv20_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - int channel, channel_old; + struct nouveau_channel *next, *last; + int chid; + + chid = NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); + next = dev_priv->fifos[chid]; - channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); - channel_old = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (nouveau_fifo_number(dev)-1); + last = dev_priv->fifos[chid]; - DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",channel_old, channel); + DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n", + last->id, next->id); NV_WRITE(NV04_PGRAPH_FIFO,0x0); - nv20_graph_save_context(dev, channel_old); + nv20_graph_save_context(last); nouveau_wait_for_idle(dev); NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000); - nv20_graph_load_context(dev, channel); + nv20_graph_load_context(next); nouveau_wait_for_idle(dev); - if ((NV_READ(NV10_PGRAPH_CTX_USER) >> 24) != channel) - DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", channel, NV_READ(NV10_PGRAPH_CTX_USER) >> 24); + if ((NV_READ(NV10_PGRAPH_CTX_USER) >> 24) != next->id) + DRM_ERROR("nouveau_nv20_context_switch : wrong channel restored %x %x!!!\n", next->id, NV_READ(NV10_PGRAPH_CTX_USER) >> 24); NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100); NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF); @@ -157,7 +157,7 @@ int nv20_graph_init(struct drm_device *dev) { /* Create Context Pointer Table */ dev_priv->ctx_table_size = 32 * 4; - if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, + if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, dev_priv->ctx_table_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ctx_table))) diff --git a/shared-core/nv30_graph.c b/shared-core/nv30_graph.c index 4ed2e2ba..c605c84e 100644 --- a/shared-core/nv30_graph.c +++ b/shared-core/nv30_graph.c @@ -100,11 +100,10 @@ static void nv30_graph_context_init(struct drm_device *dev, struct nouveau_gpuob } -int nv30_graph_create_context(struct drm_device *dev, int channel) +int nv30_graph_create_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); unsigned int ctx_size; int ret; @@ -116,7 +115,7 @@ int nv30_graph_create_context(struct drm_device *dev, int channel) break; } - if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, ctx_size, 16, + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx))) return ret; @@ -124,23 +123,22 @@ int nv30_graph_create_context(struct drm_device *dev, int channel) /* Initialise default context values */ ctx_init(dev, chan->ramin_grctx->gpuobj); - INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, channel<<24); /* CTX_USER */ - INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel, + INSTANCE_WR(chan->ramin_grctx->gpuobj, 10, chan->id<<24); /* CTX_USER */ + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, chan->ramin_grctx->instance >> 4); return 0; } -void nv30_graph_destroy_context(struct drm_device *dev, int channel) +void nv30_graph_destroy_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; if (chan->ramin_grctx) nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); - INSTANCE_WR(dev_priv->ctx_table->gpuobj, channel, 0); + INSTANCE_WR(dev_priv->ctx_table->gpuobj, chan->id, 0); } static int @@ -161,10 +159,10 @@ nouveau_graph_wait_idle(struct drm_device *dev) return 0; } -int nv30_graph_load_context(struct drm_device *dev, int channel) +int nv30_graph_load_context(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]; uint32_t inst; if (!chan->ramin_grctx) @@ -178,10 +176,10 @@ int nv30_graph_load_context(struct drm_device *dev, int channel) return nouveau_graph_wait_idle(dev); } -int nv30_graph_save_context(struct drm_device *dev, int channel) +int nv30_graph_save_context(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]; uint32_t inst; if (!chan->ramin_grctx) @@ -197,8 +195,7 @@ int nv30_graph_save_context(struct drm_device *dev, int channel) int nv30_graph_init(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; + struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t vramsz, tmp; int ret, i; @@ -209,7 +206,7 @@ int nv30_graph_init(struct drm_device *dev) /* Create Context Pointer Table */ dev_priv->ctx_table_size = 32 * 4; - if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, + if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, dev_priv->ctx_table_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ctx_table))) diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c index ecb1d21e..f04c2882 100644 --- a/shared-core/nv40_fifo.c +++ b/shared-core/nv40_fifo.c @@ -37,13 +37,13 @@ #define NV40_RAMFC__SIZE 128 int -nv40_fifo_create_context(struct drm_device *dev, int channel) +nv40_fifo_create_context(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 ret; - if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(channel), + if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -68,27 +68,27 @@ nv40_fifo_create_context(struct drm_device *dev, int channel) RAMFC_WR(DMA_TIMESLICE , 0x0001FFFF); /* enable the fifo dma operation */ - NV_WRITE(NV04_PFIFO_MODE,NV_READ(NV04_PFIFO_MODE)|(1<id)); return 0; } void -nv40_fifo_destroy_context(struct drm_device *dev, int channel) +nv40_fifo_destroy_context(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]; - NV_WRITE(NV04_PFIFO_MODE, NV_READ(NV04_PFIFO_MODE)&~(1<id)); if (chan->ramfc) nouveau_gpuobj_ref_del(dev, &chan->ramfc); } int -nv40_fifo_load_context(struct drm_device *dev, int channel) +nv40_fifo_load_context(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]; uint32_t tmp, tmp2; NV_WRITE(NV04_PFIFO_CACHE1_DMA_GET , RAMFC_RD(DMA_GET)); @@ -135,7 +135,7 @@ nv40_fifo_load_context(struct drm_device *dev, int channel) NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, tmp); /* Set channel active, and in DMA mode */ - NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00010000 | channel); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1 , 0x00010000 | chan->id); /* Reset DMA_CTL_AT_INFO to INVALID */ tmp = NV_READ(NV04_PFIFO_CACHE1_DMA_CTL) & ~(1<<31); NV_WRITE(NV04_PFIFO_CACHE1_DMA_CTL, tmp); @@ -144,10 +144,10 @@ nv40_fifo_load_context(struct drm_device *dev, int channel) } int -nv40_fifo_save_context(struct drm_device *dev, int channel) +nv40_fifo_save_context(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]; uint32_t tmp; RAMFC_WR(DMA_PUT , NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c index 441dbae7..c79b63cc 100644 --- a/shared-core/nv40_graph.c +++ b/shared-core/nv40_graph.c @@ -1224,11 +1224,10 @@ nv4e_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) } int -nv40_graph_create_context(struct drm_device *dev, int channel) +nv40_graph_create_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = - (struct drm_nouveau_private *)dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); unsigned int ctx_size; int ret; @@ -1272,7 +1271,7 @@ nv40_graph_create_context(struct drm_device *dev, int channel) break; } - if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, ctx_size, 16, + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, ctx_size, 16, NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx))) return ret; @@ -1284,13 +1283,9 @@ nv40_graph_create_context(struct drm_device *dev, int channel) } void -nv40_graph_destroy_context(struct drm_device *dev, int channel) +nv40_graph_destroy_context(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; - - if (chan->ramin_grctx) - nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); + nouveau_gpuobj_ref_del(chan->dev, &chan->ramin_grctx); } static int @@ -1327,10 +1322,9 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) *XXX: fails sometimes, not sure why.. */ int -nv40_graph_save_context(struct drm_device *dev, int channel) +nv40_graph_save_context(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; uint32_t inst; if (!chan->ramin_grctx) @@ -1344,10 +1338,10 @@ nv40_graph_save_context(struct drm_device *dev, int channel) * XXX: fails sometimes.. not sure why */ int -nv40_graph_load_context(struct drm_device *dev, int channel) +nv40_graph_load_context(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]; uint32_t inst; int ret; diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c index f7b98220..a5e79260 100644 --- a/shared-core/nv50_fifo.c +++ b/shared-core/nv50_fifo.c @@ -63,7 +63,7 @@ static int nv50_fifo_channel_enable(struct drm_device *dev, int channel) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; + struct nouveau_channel *chan = dev_priv->fifos[channel]; DRM_DEBUG("ch%d\n", channel); @@ -150,7 +150,7 @@ nv50_fifo_init_regs(struct drm_device *dev) DRM_DEBUG("\n"); - if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, 0x1000, + if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 0x1000, 0x1000, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -191,7 +191,7 @@ nv50_fifo_init(struct drm_device *dev) nv50_fifo_init_reset(dev); - if ((ret = nouveau_gpuobj_new_ref(dev, -1, -1, 0, (128+2)*4, 0x1000, + if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &priv->thingo))) { DRM_ERROR("error creating thingo: %d\n", ret); @@ -225,14 +225,14 @@ nv50_fifo_takedown(struct drm_device *dev) } int -nv50_fifo_create_context(struct drm_device *dev, int channel) +nv50_fifo_create_context(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 *ramfc = NULL; int ret; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); if (IS_G80) { uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start; @@ -242,7 +242,7 @@ nv50_fifo_create_context(struct drm_device *dev, int channel) &ramfc, &chan->ramfc))) return ret; } else { - if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, 0x100, + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 0x100, 256, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -266,15 +266,15 @@ nv50_fifo_create_context(struct drm_device *dev, int channel) INSTANCE_WR(ramfc, 0x4c/4, chan->pushbuf_mem->size - 1); if (!IS_G80) { - INSTANCE_WR(chan->ramin->gpuobj, 0, channel); + INSTANCE_WR(chan->ramin->gpuobj, 0, chan->id); INSTANCE_WR(chan->ramin->gpuobj, 1, chan->ramfc->instance); INSTANCE_WR(ramfc, 0x88/4, 0x3d520); /* some vram addy >> 10 */ INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12); } - if ((ret = nv50_fifo_channel_enable(dev, channel))) { - DRM_ERROR("error enabling ch%d: %d\n", channel, ret); + if ((ret = nv50_fifo_channel_enable(dev, chan->id))) { + DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret); nouveau_gpuobj_ref_del(dev, &chan->ramfc); return ret; } @@ -283,25 +283,24 @@ nv50_fifo_create_context(struct drm_device *dev, int channel) } void -nv50_fifo_destroy_context(struct drm_device *dev, int channel) +nv50_fifo_destroy_context(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; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); - nv50_fifo_channel_disable(dev, channel, 0); + nv50_fifo_channel_disable(dev, chan->id, 0); nouveau_gpuobj_ref_del(dev, &chan->ramfc); } int -nv50_fifo_load_context(struct drm_device *dev, int channel) +nv50_fifo_load_context(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 *ramfc = chan->ramfc->gpuobj; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); /*XXX: incomplete, only touches the regs that NV does */ @@ -319,14 +318,14 @@ nv50_fifo_load_context(struct drm_device *dev, int channel) NV_WRITE(0x3410, INSTANCE_RD(ramfc, 0x98/4)); } - NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, channel | (1<<16)); + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); return 0; } int -nv50_fifo_save_context(struct drm_device *dev, int channel) +nv50_fifo_save_context(struct nouveau_channel *chan) { - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); DRM_ERROR("stub!\n"); return 0; } diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c index 8df5df25..59c8cfeb 100644 --- a/shared-core/nv50_graph.c +++ b/shared-core/nv50_graph.c @@ -188,17 +188,17 @@ nv50_graph_takedown(struct drm_device *dev) } int -nv50_graph_create_context(struct drm_device *dev, int channel) +nv50_graph_create_context(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 *ramin = chan->ramin->gpuobj; int grctx_size = 0x60000, hdr; int ret; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); - if ((ret = nouveau_gpuobj_new_ref(dev, channel, -1, 0, + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, @@ -218,13 +218,13 @@ nv50_graph_create_context(struct drm_device *dev, int channel) } void -nv50_graph_destroy_context(struct drm_device *dev, int channel) +nv50_graph_destroy_context(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 i, hdr; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); hdr = IS_G80 ? 0x200 : 0x20; for (i=hdr; idev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo *chan = dev_priv->fifos[channel]; uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31)); int ret; (void)ret; - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); #if 0 if ((ret = nv50_graph_transfer_context(dev, inst, 0))) @@ -288,13 +288,12 @@ nv50_graph_load_context(struct drm_device *dev, int channel) } int -nv50_graph_save_context(struct drm_device *dev, int channel) +nv50_graph_save_context(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; uint32_t inst = ((chan->ramin->instance >> 12) | (1<<31)); - DRM_DEBUG("ch%d\n", channel); + DRM_DEBUG("ch%d\n", chan->id); return nv50_graph_transfer_context(dev, inst, 1); } -- 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. --- linux-core/drmP.h | 1 + linux-core/drm_irq.c | 3 +- shared-core/nouveau_drm.h | 33 +++++++++----- shared-core/nouveau_drv.h | 30 ++++++++++--- shared-core/nouveau_fifo.c | 47 ++++++++++++++------ shared-core/nouveau_mem.c | 8 ++-- shared-core/nouveau_notifier.c | 17 +++++++- shared-core/nouveau_object.c | 99 +++++++++++++++++++++++++++++++----------- shared-core/nouveau_state.c | 45 +++++++++++-------- shared-core/nv04_instmem.c | 10 ----- 10 files changed, 202 insertions(+), 91 deletions(-) diff --git a/linux-core/drmP.h b/linux-core/drmP.h index a61efcff..aa562225 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -1075,6 +1075,7 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev, extern int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv); extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); +extern int drm_irq_install(struct drm_device *dev); extern int drm_irq_uninstall(struct drm_device *dev); extern void drm_driver_irq_preinstall(struct drm_device *dev); extern void drm_driver_irq_postinstall(struct drm_device *dev); diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index fe4316e0..25166b6f 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -80,7 +80,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions * before and after the installation. */ -static int drm_irq_install(struct drm_device * dev) +int drm_irq_install(struct drm_device * dev) { int ret; unsigned long sh_flags = 0; @@ -140,6 +140,7 @@ static int drm_irq_install(struct drm_device * dev) return 0; } +EXPORT_SYMBOL(drm_irq_install); /** * Uninstall the IRQ handler. diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 4016f004..bfc9bd4b 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -25,9 +25,9 @@ #ifndef __NOUVEAU_DRM_H__ #define __NOUVEAU_DRM_H__ -#define NOUVEAU_DRM_HEADER_PATCHLEVEL 9 +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 10 -struct drm_nouveau_fifo_alloc { +struct drm_nouveau_channel_alloc { uint32_t fb_ctxdma_handle; uint32_t tt_ctxdma_handle; @@ -44,6 +44,10 @@ struct drm_nouveau_fifo_alloc { int notifier_size; }; +struct drm_nouveau_channel_free { + int channel; +}; + struct drm_nouveau_grobj_alloc { int channel; uint32_t handle; @@ -53,7 +57,7 @@ struct drm_nouveau_grobj_alloc { #define NOUVEAU_MEM_ACCESS_RO 1 #define NOUVEAU_MEM_ACCESS_WO 2 #define NOUVEAU_MEM_ACCESS_RW 3 -struct drm_nouveau_notifier_alloc { +struct drm_nouveau_notifierobj_alloc { int channel; uint32_t handle; int count; @@ -61,6 +65,11 @@ struct drm_nouveau_notifier_alloc { uint32_t offset; }; +struct drm_nouveau_gpuobj_free { + int channel; + uint32_t handle; +}; + #define NOUVEAU_MEM_FB 0x00000001 #define NOUVEAU_MEM_AGP 0x00000002 #define NOUVEAU_MEM_FB_ACCEPTABLE 0x00000004 @@ -95,6 +104,7 @@ struct drm_nouveau_mem_free { #define NOUVEAU_GETPARAM_FB_SIZE 8 #define NOUVEAU_GETPARAM_AGP_SIZE 9 #define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 +#define NOUVEAU_GETPARAM_CHIPSET_ID 11 struct drm_nouveau_getparam { uint64_t param; uint64_t value; @@ -141,13 +151,16 @@ struct drm_nouveau_sarea { unsigned int nbox; }; -#define DRM_NOUVEAU_FIFO_ALLOC 0x00 -#define DRM_NOUVEAU_GROBJ_ALLOC 0x01 -#define DRM_NOUVEAU_NOTIFIER_ALLOC 0x02 -#define DRM_NOUVEAU_MEM_ALLOC 0x03 -#define DRM_NOUVEAU_MEM_FREE 0x04 -#define DRM_NOUVEAU_GETPARAM 0x05 -#define DRM_NOUVEAU_SETPARAM 0x06 +#define DRM_NOUVEAU_CARD_INIT 0x00 +#define DRM_NOUVEAU_GETPARAM 0x01 +#define DRM_NOUVEAU_SETPARAM 0x02 +#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03 +#define DRM_NOUVEAU_CHANNEL_FREE 0x04 +#define DRM_NOUVEAU_GROBJ_ALLOC 0x05 +#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06 +#define DRM_NOUVEAU_GPUOBJ_FREE 0x07 +#define DRM_NOUVEAU_MEM_ALLOC 0x08 +#define DRM_NOUVEAU_MEM_FREE 0x09 #endif /* __NOUVEAU_DRM_H__ */ diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 8ec91898..0b173b76 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -34,7 +34,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 9 +#define DRIVER_PATCHLEVEL 10 #define NOUVEAU_FAMILY 0x0000FFFF #define NOUVEAU_FLAGS 0xFFFF0000 @@ -67,8 +67,7 @@ enum nouveau_flags { #define NVOBJ_FLAG_ZERO_FREE (1 << 2) #define NVOBJ_FLAG_FAKE (1 << 3) struct nouveau_gpuobj { - struct nouveau_gpuobj *next; - struct nouveau_gpuobj *prev; + struct list_head list; int im_channel; struct mem_block *im_pramin; @@ -80,10 +79,13 @@ struct nouveau_gpuobj { uint32_t engine; uint32_t class; + + void (*dtor)(struct drm_device *, struct nouveau_gpuobj *); + void *priv; }; struct nouveau_gpuobj_ref { - struct nouveau_gpuobj_ref *next; + struct list_head list; struct nouveau_gpuobj *gpuobj; uint32_t instance; @@ -129,7 +131,7 @@ struct nouveau_channel struct nouveau_gpuobj_ref *ramin; /* Private instmem */ struct mem_block *ramin_heap; /* Private PRAMIN heap */ struct nouveau_gpuobj_ref *ramht; /* Hash table */ - struct nouveau_gpuobj_ref *ramht_refs; /* Objects referenced by RAMHT */ + struct list_head ramht_refs; /* Objects referenced by RAMHT */ }; struct nouveau_config { @@ -269,9 +271,17 @@ struct drm_nouveau_private { struct nouveau_config config; - struct nouveau_gpuobj *gpuobj_all; + struct list_head gpuobj_list; }; +#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \ + struct drm_nouveau_private *nv = dev->dev_private; \ + if (nv->init_state != NOUVEAU_CARD_INIT_DONE) { \ + DRM_ERROR("called without init\n"); \ + return -EINVAL; \ + } \ +} while(0) + #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id,cl,ch) do { \ struct drm_nouveau_private *nv = dev->dev_private; \ if (!nouveau_fifo_owner(dev, (cl), (id))) { \ @@ -293,6 +303,7 @@ extern int nouveau_ioctl_getparam(struct drm_device *, void *data, extern int nouveau_ioctl_setparam(struct drm_device *, void *data, struct drm_file *); extern void nouveau_wait_for_idle(struct drm_device *); +extern int nouveau_card_init(struct drm_device *); extern int nouveau_ioctl_card_init(struct drm_device *, void *data, struct drm_file *); @@ -324,6 +335,8 @@ extern int nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, int cout, uint32_t *offset); extern int nouveau_ioctl_notifier_alloc(struct drm_device *, void *data, struct drm_file *); +extern int nouveau_ioctl_notifier_free(struct drm_device *, void *data, + struct drm_file *); /* nouveau_fifo.c */ extern int nouveau_fifo_init(struct drm_device *); @@ -335,6 +348,7 @@ extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, extern void nouveau_fifo_free(struct nouveau_channel *); /* nouveau_object.c */ +extern int nouveau_gpuobj_init(struct drm_device *); extern void nouveau_gpuobj_takedown(struct drm_device *); extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, uint32_t vram_h, uint32_t tt_h); @@ -348,6 +362,8 @@ extern int nouveau_gpuobj_ref_add(struct drm_device *, struct nouveau_channel *, struct nouveau_gpuobj_ref **); extern int nouveau_gpuobj_ref_del(struct drm_device *, struct nouveau_gpuobj_ref **); +extern int nouveau_gpuobj_ref_find(struct nouveau_channel *, uint32_t handle, + struct nouveau_gpuobj_ref **ref_ret); extern int nouveau_gpuobj_new_ref(struct drm_device *, struct nouveau_channel *alloc_chan, struct nouveau_channel *ref_chan, @@ -368,6 +384,8 @@ extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, struct nouveau_gpuobj **); extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, struct drm_file *); +extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, + struct drm_file *); /* nouveau_irq.c */ extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index c7ce1d8d..152b669a 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -302,22 +302,22 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, DRM_INFO("Allocating FIFO number %d\n", channel); - /* Setup channel's default objects */ - ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); + /* Allocate space for per-channel fixed notifier memory */ + ret = nouveau_notifier_init_channel(chan); if (ret) { nouveau_fifo_free(chan); return ret; } - /* allocate a command buffer, and create a dma object for the gpu */ - ret = nouveau_fifo_cmdbuf_alloc(chan); + /* Setup channel's default objects */ + ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); if (ret) { nouveau_fifo_free(chan); return ret; } - /* Allocate space for per-channel fixed notifier memory */ - ret = nouveau_notifier_init_channel(chan); + /* allocate a command buffer, and create a dma object for the gpu */ + ret = nouveau_fifo_cmdbuf_alloc(chan); if (ret) { nouveau_fifo_free(chan); return ret; @@ -426,11 +426,11 @@ void nouveau_fifo_free(struct nouveau_channel *chan) chan->pushbuf_mem = NULL; } - nouveau_notifier_takedown_channel(chan); - /* Destroy objects belonging to the channel */ nouveau_gpuobj_channel_takedown(chan); + nouveau_notifier_takedown_channel(chan); + dev_priv->fifos[chan->id] = NULL; dev_priv->fifo_alloc_count--; drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER); @@ -468,14 +468,17 @@ nouveau_fifo_owner(struct drm_device *dev, struct drm_file *file_priv, * ioctls wrapping the functions ***********************************/ -static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_fifo_alloc *init = data; + struct drm_nouveau_channel_alloc *init = data; struct drm_map_list *entry; struct nouveau_channel *chan; int res; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) return -EINVAL; @@ -519,18 +522,34 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct d return 0; } +static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_nouveau_channel_free *cfree = data; + struct nouveau_channel *chan; + + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); + + nouveau_fifo_free(chan); + return 0; +} + /*********************************** * finally, the ioctl table ***********************************/ struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF(DRM_NOUVEAU_FIFO_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIER_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_ALLOC, nouveau_ioctl_mem_alloc, DRM_AUTH), DRM_IOCTL_DEF(DRM_NOUVEAU_MEM_FREE, nouveau_ioctl_mem_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index a7044c94..981af8a6 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -549,14 +549,10 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_mem_alloc *alloc = data; struct mem_block *block; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; - } + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size, alloc->flags, file_priv); @@ -575,6 +571,8 @@ int nouveau_ioctl_mem_free(struct drm_device *dev, void *data, struct drm_file * struct drm_nouveau_mem_free *memfree = data; struct mem_block *block; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + block=NULL; if (memfree->flags & NOUVEAU_MEM_FB) block = find_block(dev_priv->fb_heap, memfree->offset); 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); 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; +} + diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 26ba8fbf..4fb53291 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -267,12 +267,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) return 0; } -static int nouveau_card_init(struct drm_device *dev) +int +nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; int ret; + if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) + return 0; + /* Map any PCI resources we need on the card */ ret = nouveau_init_card_mappings(dev); if (ret) return ret; @@ -290,6 +294,9 @@ static int nouveau_card_init(struct drm_device *dev) engine = &dev_priv->Engine; dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; + ret = drm_irq_install(dev); + if (ret) return ret; + /* Initialise instance memory, must happen before mem_init so we * know exactly how much VRAM we're able to use for "normal" * purposes. @@ -301,6 +308,9 @@ static int nouveau_card_init(struct drm_device *dev) ret = nouveau_mem_init(dev); if (ret) return ret; + ret = nouveau_gpuobj_init(dev); + if (ret) return ret; + /* Parse BIOS tables / Run init tables? */ /* PMC */ @@ -349,6 +359,8 @@ static void nouveau_card_takedown(struct drm_device *dev) nouveau_mem_close(dev); engine->instmem.takedown(dev); + drm_irq_uninstall(dev); + dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; } } @@ -368,14 +380,6 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) /* first module load, setup the mmio/fb mapping */ int nouveau_firstopen(struct drm_device *dev) { - int ret; - - ret = nouveau_card_init(dev); - if (ret) { - DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret); - return ret; - } - return 0; } @@ -395,15 +399,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; dev->dev_private = (void *)dev_priv; - -#if 0 - ret = nouveau_card_init(dev); - if (ret) { - DRM_ERROR("nouveau_card_init() failed! (%d)\n", ret); - return ret; - } -#endif - return 0; } @@ -427,12 +422,24 @@ int nouveau_unload(struct drm_device *dev) return 0; } +int +nouveau_ioctl_card_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return nouveau_card_init(dev); +} + int nouveau_ioctl_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_getparam *getparam = data; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + switch (getparam->param) { + case NOUVEAU_GETPARAM_CHIPSET_ID: + getparam->value = dev_priv->chipset; + break; case NOUVEAU_GETPARAM_PCI_VENDOR: getparam->value=dev->pci_vendor; break; @@ -481,6 +488,8 @@ int nouveau_ioctl_setparam(struct drm_device *dev, void *data, struct drm_file * struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_setparam *setparam = data; + NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + switch (setparam->param) { case NOUVEAU_SETPARAM_CMDBUF_LOCATION: switch (setparam->value) { diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c index 35b20abd..36aa6200 100644 --- a/shared-core/nv04_instmem.c +++ b/shared-core/nv04_instmem.c @@ -93,13 +93,6 @@ int nv04_instmem_init(struct drm_device *dev) nv04_instmem_determine_amount(dev); nv04_instmem_configure_fixed_tables(dev); - 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; - /* Create a heap to manage RAMIN allocations, we don't allocate * the space that was reserved for RAMHT/FC/RO. */ @@ -117,9 +110,6 @@ int nv04_instmem_init(struct drm_device *dev) void nv04_instmem_takedown(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - nouveau_gpuobj_del(dev, &dev_priv->ramht); } int -- cgit v1.2.3 From 51f24be578025e3f1eae859288adf5232afc898d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2007 21:46:55 +1000 Subject: nouveau: Determine trapped channel id from active grctx on >=NV40 --- shared-core/nouveau_irq.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index f7baf89e..2ee77d83 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -301,6 +301,61 @@ nouveau_print_bitfield_names(uint32_t value, printk(" (unknown bits 0x%08x)", value); } +static int +nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int channel; + + if (dev_priv->card_type < NV_40) { + channel = (NV_READ(0x400704) >> 20) & 0x1f; + } else + if (dev_priv->card_type < NV_50) { + uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 4; + + /* 0x400704 *sometimes* contains a sensible channel ID, but + * mostly not.. for now lookup which channel owns the active + * PGRAPH context. Probably a better way, but this'll do + * for now. + */ + for (channel = 0; channel < 32; channel++) { + if (dev_priv->fifos[channel] == NULL) + continue; + if (cur_grctx == + dev_priv->fifos[channel]->ramin_grctx->instance) + break; + } + if (channel == 32) { + DRM_ERROR("AIII, unable to determine active channel " + "from PGRAPH context 0x%08x\n", cur_grctx); + return -EINVAL; + } + } else { + uint32_t cur_grctx = (NV_READ(0x40032C) & 0xfffff) << 12; + + for (channel = 0; channel < 128; channel++) { + if (dev_priv->fifos[channel] == NULL) + continue; + if (cur_grctx == + dev_priv->fifos[channel]->ramin_grctx->instance) + break; + } + if (channel == 128) { + DRM_ERROR("AIII, unable to determine active channel " + "from PGRAPH context 0x%08x\n", cur_grctx); + return -EINVAL; + } + } + + if (channel > nouveau_fifo_number(dev) || + dev_priv->fifos[channel] == NULL) { + DRM_ERROR("AIII, invalid/inactive channel id %d\n", channel); + return -EINVAL; + } + + return 0; +} + static void nouveau_graph_dump_trap_info(struct drm_device *dev) { @@ -310,8 +365,10 @@ nouveau_graph_dump_trap_info(struct drm_device *dev) uint32_t method, subc, data; uint32_t nsource, nstatus; + if (nouveau_graph_trapped_channel(dev, &channel)) + channel = -1; + address = NV_READ(0x400704); - channel = (address >> 20) & 0x1F; subc = (address >> 16) & 0x7; method = address & 0x1FFC; data = NV_READ(0x400708); -- cgit v1.2.3 From cf04641bc61c8bc18101713a8d95ef98e6afae7f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2007 22:05:31 +1000 Subject: nouveau: Give DRM its own gpu channel If your card doesn't have working context switching, it is now broken. --- linux-core/Makefile.kernel | 2 +- linux-core/nouveau_sgdma.c | 2 +- shared-core/nouveau_drv.h | 26 ++++++++++++++++++++++++++ shared-core/nouveau_fifo.c | 14 +++++++------- shared-core/nouveau_state.c | 9 +++++++++ shared-core/nv04_instmem.c | 1 - 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 5aa589cd..3d00cbe6 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -22,7 +22,7 @@ i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \ i915_buffer.o nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o nouveau_notifier.o \ - nouveau_sgdma.o \ + nouveau_sgdma.o nouveau_dma.o \ nv04_timer.o \ nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_fb.o nv10_fb.o nv40_fb.o \ diff --git a/linux-core/nouveau_sgdma.c b/linux-core/nouveau_sgdma.c index 6393a469..df970d11 100644 --- a/linux-core/nouveau_sgdma.c +++ b/linux-core/nouveau_sgdma.c @@ -69,7 +69,7 @@ nouveau_sgdma_clear(struct drm_ttm_backend *be) if (nvbe->is_bound) be->func->unbind(be); - for (d = 0; d < nvbe->pages_populated; d--) { + for (d = 0; d < nvbe->pages_populated; d++) { pci_unmap_page(nvbe->dev->pdev, nvbe->pagelist[d], NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 0b173b76..10f9149e 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -134,6 +134,22 @@ struct nouveau_channel struct list_head ramht_refs; /* Objects referenced by RAMHT */ }; +struct nouveau_drm_channel { + struct nouveau_channel *chan; + + /* DMA state */ + int max, put, cur, free; + int push_free; + volatile uint32_t *pushbuf; + + /* Notifiers */ + uint32_t notify0_offset; + + /* Buffer moves */ + uint32_t m2mf_dma_source; + uint32_t m2mf_dma_destin; +}; + struct nouveau_config { struct { int location; @@ -222,6 +238,7 @@ struct drm_nouveau_private { struct nouveau_channel *fifos[NV_MAX_FIFO_NUMBER]; struct nouveau_engine Engine; + struct nouveau_drm_channel channel; /* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */ struct nouveau_gpuobj *ramht; @@ -345,6 +362,10 @@ extern int nouveau_fifo_ctx_size(struct drm_device *); extern void nouveau_fifo_cleanup(struct drm_device *, struct drm_file *); extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, int channel); +extern int nouveau_fifo_alloc(struct drm_device *dev, + struct nouveau_channel **chan, + struct drm_file *file_priv, + uint32_t fb_ctxdma, uint32_t tt_ctxdma); extern void nouveau_fifo_free(struct nouveau_channel *); /* nouveau_object.c */ @@ -400,6 +421,11 @@ extern struct drm_ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); extern int nouveau_sgdma_nottm_hack_init(struct drm_device *); extern void nouveau_sgdma_nottm_hack_takedown(struct drm_device *); +/* nouveau_dma.c */ +extern int nouveau_dma_channel_init(struct drm_device *); +extern void nouveau_dma_channel_takedown(struct drm_device *); +extern int nouveau_dma_wait(struct drm_device *, int size); + /* nv04_fb.c */ extern int nv04_fb_init(struct drm_device *); extern void nv04_fb_takedown(struct drm_device *); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 152b669a..823801f9 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -261,9 +261,10 @@ nouveau_fifo_cmdbuf_alloc(struct nouveau_channel *chan) } /* allocates and initializes a fifo for user space consumption */ -int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, - struct drm_file *file_priv, - uint32_t vram_handle, uint32_t tt_handle) +int +nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, + struct drm_file *file_priv, + uint32_t vram_handle, uint32_t tt_handle) { int ret; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -288,7 +289,6 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, /* no more fifos. you lost. */ if (channel==nouveau_fifo_number(dev)) return -EINVAL; - (*chan_ret) = channel; dev_priv->fifos[channel] = drm_calloc(1, sizeof(struct nouveau_channel), DRM_MEM_DRIVER); @@ -394,6 +394,7 @@ int nouveau_fifo_alloc(struct drm_device *dev, int *chan_ret, NV_WRITE(NV03_PFIFO_CACHES, 1); DRM_INFO("%s: initialised FIFO %d\n", __func__, channel); + *chan_ret = chan; return 0; } @@ -482,13 +483,12 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) return -EINVAL; - res = nouveau_fifo_alloc(dev, &init->channel, file_priv, + res = nouveau_fifo_alloc(dev, &chan, file_priv, init->fb_ctxdma_handle, init->tt_ctxdma_handle); if (res) return res; - chan = dev_priv->fifos[init->channel]; - + init->channel = chan->id; init->put_base = chan->pushbuf_base; /* make the fifo available to user space */ diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 4fb53291..9dab34cc 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -274,6 +274,8 @@ nouveau_card_init(struct drm_device *dev) struct nouveau_engine *engine; int ret; + DRM_DEBUG("prev state = %d\n", dev_priv->init_state); + if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE) return 0; @@ -335,6 +337,9 @@ nouveau_card_init(struct drm_device *dev) /* what about PVIDEO/PCRTC/PRAMDAC etc? */ + ret = nouveau_dma_channel_init(dev); + if (ret) return ret; + dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; return 0; } @@ -344,7 +349,11 @@ static void nouveau_card_takedown(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->Engine; + DRM_DEBUG("prev state = %d\n", dev_priv->init_state); + if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) { + nouveau_dma_channel_takedown(dev); + engine->fifo.takedown(dev); engine->graph.takedown(dev); engine->fb.takedown(dev); diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c index 36aa6200..5e0f6f4e 100644 --- a/shared-core/nv04_instmem.c +++ b/shared-core/nv04_instmem.c @@ -129,7 +129,6 @@ nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) if (gpuobj && gpuobj->im_backing) { if (gpuobj->im_bound) dev_priv->Engine.instmem.unbind(dev, gpuobj); - nouveau_mem_free(dev, gpuobj->im_backing); gpuobj->im_backing = NULL; } } -- cgit v1.2.3 From 7a0a812ea42d80eed89b7b9993eae42c7c1b1613 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2007 22:06:52 +1000 Subject: nouveau: Remove PGRAPH_SURFACE hack, it wont work now anyway. Need to find another way of doing this, ideally someone'd hunt down which object/method controls it! The Xv blit adaptor is likely now broken on cards that have pNv->WaitVSyncPossible enabled. --- shared-core/nouveau_fifo.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 823801f9..fd21d2f3 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -369,19 +369,6 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, nouveau_fifo_free(chan); return ret; } - - /* Temporary hack, to avoid breaking Xv on cards where the - * initial context value for 0x400710 doesn't have these bits - * set. Proper fix would be to find which object+method is - * responsible for modifying this state. - */ - if (dev_priv->chipset >= 0x10 && dev_priv->chipset < 0x50) { - uint32_t tmp; - tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00; - NV_WRITE(NV10_PGRAPH_SURFACE, tmp); - tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100; - NV_WRITE(NV10_PGRAPH_SURFACE, tmp); - } } NV_WRITE(NV04_PFIFO_CACHE1_DMA_PUSH, -- cgit v1.2.3 From 92084c6e056a738308ff65f3fcd7411fd7d2995a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2007 22:11:18 +1000 Subject: Export some useful ttm functions to drivers. --- linux-core/drm_bo.c | 10 ++++++---- linux-core/drm_bo_move.c | 1 + linux-core/drm_objects.h | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 467d03ff..4c2b1541 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -517,7 +517,7 @@ static void drm_bo_base_deref_locked(struct drm_file * file_priv, drm_bo_usage_deref_locked(&bo); } -static void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo) +void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo) { struct drm_buffer_object *tmp_bo = *bo; struct drm_device *dev = tmp_bo->dev; @@ -530,6 +530,7 @@ static void drm_bo_usage_deref_unlocked(struct drm_buffer_object ** bo) mutex_unlock(&dev->struct_mutex); } } +EXPORT_SYMBOL(drm_bo_usage_deref_unlocked); /* * Note. The caller has to register (if applicable) @@ -1672,10 +1673,10 @@ int drm_buffer_object_create(struct drm_device *dev, drm_bo_usage_deref_unlocked(&bo); return ret; } +EXPORT_SYMBOL(drm_buffer_object_create); -static int drm_bo_add_user_object(struct drm_file *file_priv, - struct drm_buffer_object *bo, - int shareable) +int drm_bo_add_user_object(struct drm_file *file_priv, + struct drm_buffer_object *bo, int shareable) { struct drm_device *dev = file_priv->head->dev; int ret; @@ -1694,6 +1695,7 @@ static int drm_bo_add_user_object(struct drm_file *file_priv, mutex_unlock(&dev->struct_mutex); return ret; } +EXPORT_SYMBOL(drm_bo_add_user_object); static int drm_bo_lock_test(struct drm_device * dev, struct drm_file *file_priv) { diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c index 5e21173c..1a613916 100644 --- a/linux-core/drm_bo_move.c +++ b/linux-core/drm_bo_move.c @@ -128,6 +128,7 @@ int drm_mem_reg_ioremap(struct drm_device * dev, struct drm_bo_mem_reg * mem, *virtual = addr; return 0; } +EXPORT_SYMBOL(drm_mem_reg_ioremap); /** * \c Unmap mapping obtained using drm_bo_ioremap diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index e5f2b69c..e34fdbc4 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -483,6 +483,17 @@ extern int drm_bo_mem_space(struct drm_buffer_object * bo, struct drm_bo_mem_reg * mem, int no_wait); extern int drm_bo_move_buffer(struct drm_buffer_object * bo, uint32_t new_mem_flags, int no_wait, int move_unfenced); +extern int drm_buffer_object_create(struct drm_device *dev, unsigned long size, + enum drm_bo_type type, uint64_t mask, + uint32_t hint, uint32_t page_alignment, + unsigned long buffer_start, + struct drm_buffer_object **bo); +extern int drm_bo_init_mm(struct drm_device *dev, unsigned type, + unsigned long p_offset, unsigned long p_size); +extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type); +extern int drm_bo_add_user_object(struct drm_file *file_priv, + struct drm_buffer_object *bo, int sharable); +extern void drm_bo_usage_deref_unlocked(struct drm_buffer_object **bo); /* * Buffer object memory move helpers. @@ -502,6 +513,11 @@ extern int drm_bo_move_accel_cleanup(struct drm_buffer_object * bo, uint32_t fence_flags, struct drm_bo_mem_reg * new_mem); +extern int drm_mem_reg_ioremap(struct drm_device *dev, + struct drm_bo_mem_reg *mem, void **virtual); +extern void drm_mem_reg_iounmap(struct drm_device *dev, + struct drm_bo_mem_reg *mem, void *virtual); + #ifdef CONFIG_DEBUG_MUTEXES #define DRM_ASSERT_LOCKED(_mutex) \ BUG_ON(!mutex_is_locked(_mutex) || \ -- cgit v1.2.3 From 8d5a8ebc316028f14666697cff33daddbe384bcd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 6 Aug 2007 22:32:36 +1000 Subject: nouveau: ouch, add nouveau_dma.[ch] files.. --- linux-core/nouveau_dma.c | 1 + linux-core/nouveau_dma.h | 1 + shared-core/nouveau_dma.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++ shared-core/nouveau_dma.h | 98 +++++++++++++++++++++++++++ 4 files changed, 268 insertions(+) create mode 120000 linux-core/nouveau_dma.c create mode 120000 linux-core/nouveau_dma.h create mode 100644 shared-core/nouveau_dma.c create mode 100644 shared-core/nouveau_dma.h diff --git a/linux-core/nouveau_dma.c b/linux-core/nouveau_dma.c new file mode 120000 index 00000000..f8e0bdc3 --- /dev/null +++ b/linux-core/nouveau_dma.c @@ -0,0 +1 @@ +../shared-core/nouveau_dma.c \ No newline at end of file diff --git a/linux-core/nouveau_dma.h b/linux-core/nouveau_dma.h new file mode 120000 index 00000000..a545e387 --- /dev/null +++ b/linux-core/nouveau_dma.h @@ -0,0 +1 @@ +../shared-core/nouveau_dma.h \ No newline at end of file diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c new file mode 100644 index 00000000..ce5b6299 --- /dev/null +++ b/shared-core/nouveau_dma.c @@ -0,0 +1,168 @@ +/* + * 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" +#include "nouveau_dma.h" + +#define SKIPS 8 + +int +nouveau_dma_channel_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + struct nouveau_gpuobj *gpuobj = NULL; + int grclass, ret, i; + + DRM_DEBUG("\n"); + + /* Allocate channel */ + ret = nouveau_fifo_alloc(dev, &dchan->chan, (struct drm_file *)-2, + NvDmaFB, NvDmaTT); + if (ret) { + DRM_ERROR("Error allocating GPU channel: %d\n", ret); + return ret; + } + DRM_DEBUG("Using FIFO channel %d\n", dchan->chan->id); + + /* Map push buffer */ + drm_core_ioremap(dchan->chan->pushbuf_mem->map, dev); + if (!dchan->chan->pushbuf_mem->map->handle) { + DRM_ERROR("Failed to ioremap push buffer\n"); + return -EINVAL; + } + dchan->pushbuf = (void*)dchan->chan->pushbuf_mem->map->handle; + + /* Initialise DMA vars */ + dchan->max = (dchan->chan->pushbuf_mem->size >> 2) - 2; + dchan->put = dchan->chan->pushbuf_base >> 2; + dchan->cur = dchan->put; + dchan->free = dchan->max - dchan->cur; + + /* Insert NOPS for SKIPS */ + dchan->free -= SKIPS; + dchan->push_free = SKIPS; + for (i=0; ichan, NvNotify0, 1, + &dchan->notify0_offset))) { + DRM_ERROR("Error allocating NvNotify0: %d\n", ret); + return ret; + } + + /* We use NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ + if (dev_priv->card_type < NV_50) grclass = NV_MEMORY_TO_MEMORY_FORMAT; + else grclass = NV50_MEMORY_TO_MEMORY_FORMAT; + if ((ret = nouveau_gpuobj_gr_new(dchan->chan, grclass, &gpuobj))) { + DRM_ERROR("Error creating NvM2MF: %d\n", ret); + return ret; + } + + if ((ret = nouveau_gpuobj_ref_add(dev, dchan->chan, NvM2MF, + gpuobj, NULL))) { + DRM_ERROR("Error referencing NvM2MF: %d\n", ret); + return ret; + } + dchan->m2mf_dma_source = NvDmaFB; + dchan->m2mf_dma_destin = NvDmaFB; + + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1); + OUT_RING (NvM2MF); + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY, 1); + OUT_RING (NvNotify0); + BEGIN_RING(NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE, 2); + OUT_RING (dchan->m2mf_dma_source); + OUT_RING (dchan->m2mf_dma_destin); + FIRE_RING(); + + return 0; +} + +void +nouveau_dma_channel_takedown(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + + DRM_DEBUG("\n"); + + if (dchan->chan) { + nouveau_fifo_free(dchan->chan); + dchan->chan = NULL; + } +} + +#define RING_SKIPS 8 + +#define READ_GET() ((NV_READ(NV03_FIFO_REGS_DMAGET(dchan->chan->id)) - \ + dchan->chan->pushbuf_base) >> 2) +#define WRITE_PUT(val) do { \ + NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \ + ((val) << 2) + dchan->chan->pushbuf_base); \ +} while(0) + +int +nouveau_dma_wait(struct drm_device *dev, int size) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_drm_channel *dchan = &dev_priv->channel; + uint32_t get; + + while (dchan->free < size) { + get = READ_GET(); + + if (dchan->put >= get) { + dchan->free = dchan->max - dchan->cur; + + if (dchan->free < size) { + dchan->push_free = 1; + OUT_RING(0x20000000|dchan->chan->pushbuf_base); + if (get <= RING_SKIPS) { + /*corner case - will be idle*/ + if (dchan->put <= RING_SKIPS) + WRITE_PUT(RING_SKIPS + 1); + + do { + get = READ_GET(); + } while (get <= RING_SKIPS); + } + + WRITE_PUT(RING_SKIPS); + dchan->cur = dchan->put = RING_SKIPS; + dchan->free = get - (RING_SKIPS + 1); + } + } else { + dchan->free = get - dchan->cur - 1; + } + } + + return 0; +} + diff --git a/shared-core/nouveau_dma.h b/shared-core/nouveau_dma.h new file mode 100644 index 00000000..5e51c1c4 --- /dev/null +++ b/shared-core/nouveau_dma.h @@ -0,0 +1,98 @@ +/* + * 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. + * + */ + +#ifndef __NOUVEAU_DMA_H__ +#define __NOUVEAU_DMA_H__ + +typedef enum { + NvSubM2MF = 0, +} nouveau_subchannel_id_t; + +typedef enum { + NvM2MF = 0x80039001, + NvDmaFB = 0x8003d001, + NvDmaTT = 0x8003d002, + NvNotify0 = 0x8003d003 +} nouveau_object_handle_t; + +#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 +#define NV_MEMORY_TO_MEMORY_FORMAT_NAME 0x00000000 +#define NV_MEMORY_TO_MEMORY_FORMAT_SET_REF 0x00000050 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOP 0x00000100 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE 0x00000000 +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY_STYLE_WRITE_LE_AWAKEN 0x00000001 +#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_NOTIFY 0x00000180 +#define NV_MEMORY_TO_MEMORY_FORMAT_SET_DMA_SOURCE 0x00000184 +#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c + +#define NV50_MEMORY_TO_MEMORY_FORMAT 0x00005039 +#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK200 0x00000200 +#define NV50_MEMORY_TO_MEMORY_FORMAT_UNK21C 0x0000021c +#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH 0x00000238 +#define NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_OUT_HIGH 0x0000023c + +#define BEGIN_RING(subc, mthd, cnt) do { \ + int push_size = (cnt) + 1; \ + if (dchan->push_free) { \ + DRM_ERROR("prior packet incomplete: %d\n", dchan->push_free); \ + break; \ + } \ + if (dchan->free < push_size) { \ + if (nouveau_dma_wait(dev, push_size)) { \ + DRM_ERROR("FIFO timeout\n"); \ + break; \ + } \ + } \ + dchan->free -= push_size; \ + dchan->push_free = push_size; \ + OUT_RING(((cnt)<<18) | ((subc)<<15) | mthd); \ +} while(0) + +#define OUT_RING(data) do { \ + if (dchan->push_free == 0) { \ + DRM_ERROR("no space left in packet\n"); \ + break; \ + } \ + dchan->pushbuf[dchan->cur++] = (data); \ + dchan->push_free--; \ +} while(0) + +#define FIRE_RING() do { \ + if (dchan->push_free) { \ + DRM_ERROR("packet incomplete: %d\n", dchan->push_free); \ + break; \ + } \ + if (dchan->cur != dchan->put) { \ + DRM_MEMORYBARRIER(); \ + dchan->put = dchan->cur; \ + NV_WRITE(NV03_FIFO_REGS_DMAPUT(dchan->chan->id), \ + (dchan->put<<2)); \ + } \ +} while(0) + +#endif + -- cgit v1.2.3 From ac24f328ec8954f78b1025db716abdd5b25b3dd9 Mon Sep 17 00:00:00 2001 From: Stephane Marchesin Date: Mon, 6 Aug 2007 17:14:26 +0200 Subject: nouveau: Bump PCI GART to 16MB --- shared-core/nouveau_mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 981af8a6..419522f4 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -411,7 +411,7 @@ int nouveau_mem_init(struct drm_device *dev) struct drm_scatter_gather sgreq; DRM_DEBUG("Allocating sg memory for PCI DMA\n"); - sgreq.size = 4 << 20; //4MB of PCI scatter-gather zone + sgreq.size = 16 << 20; //4MB of PCI scatter-gather zone if (drm_sg_alloc(dev, &sgreq)) { DRM_ERROR("Unable to allocate 4MB of scatter-gather" -- 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 -- shared-core/nouveau_state.c | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) 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, diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index 9dab34cc..a23d6001 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -299,6 +299,8 @@ nouveau_card_init(struct drm_device *dev) ret = drm_irq_install(dev); if (ret) return ret; + INIT_LIST_HEAD(&dev_priv->gpuobj_list); + /* Initialise instance memory, must happen before mem_init so we * know exactly how much VRAM we're able to use for "normal" * purposes. -- cgit v1.2.3 From d749cc9ae8c50157a1588369222a591410002c26 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 6 Aug 2007 15:45:37 -0700 Subject: Initialize the AGP structure's base address at init rather than enable. Not all drivers call enable (intel), but they would still like to use this member in driver code. --- linux-core/drm_agpsupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-core/drm_agpsupport.c b/linux-core/drm_agpsupport.c index df54360d..4618823c 100644 --- a/linux-core/drm_agpsupport.c +++ b/linux-core/drm_agpsupport.c @@ -183,7 +183,6 @@ int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode) #else agp_enable(dev->agp->bridge, mode.mode); #endif - dev->agp->base = dev->agp->agp_info.aper_base; dev->agp->enabled = 1; return 0; } @@ -441,6 +440,7 @@ struct drm_agp_head *drm_agp_init(struct drm_device *dev) INIT_LIST_HEAD(&head->memory); head->cant_use_aperture = head->agp_info.cant_use_aperture; head->page_mask = head->agp_info.page_mask; + head->base = head->agp_info.aper_base; return head; } -- cgit v1.2.3 From a4759b85139dd8d81de25e170777309b770f5316 Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Tue, 7 Aug 2007 23:09:44 +0200 Subject: nouveau : fix enable irq (in the previous code all irq were masked by engine init after irq_postinstall) --- shared-core/nouveau_irq.c | 3 +++ shared-core/nouveau_state.c | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 2ee77d83..84a37040 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -39,6 +39,9 @@ void nouveau_irq_preinstall(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + /* TODO this should be removed as this stuff is done in + * engine.*init + */ DRM_DEBUG("IRQ: preinst\n"); diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index a23d6001..e80e77a5 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -296,9 +296,6 @@ nouveau_card_init(struct drm_device *dev) engine = &dev_priv->Engine; dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; - ret = drm_irq_install(dev); - if (ret) return ret; - INIT_LIST_HEAD(&dev_priv->gpuobj_list); /* Initialise instance memory, must happen before mem_init so we @@ -337,6 +334,12 @@ nouveau_card_init(struct drm_device *dev) ret = engine->fifo.init(dev); if (ret) return ret; + /* this call irq_preinstall, register irq handler and + * call irq_postinstall + */ + ret = drm_irq_install(dev); + if (ret) return ret; + /* what about PVIDEO/PCRTC/PRAMDAC etc? */ ret = nouveau_dma_channel_init(dev); -- cgit v1.2.3 From 4ad487190d5b79947c65e238330506db6b77e523 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 8 Aug 2007 10:42:12 +1000 Subject: nouveau: enable/disable engine-specific interrupts in _init()/_takedown() All interrupts are still masked by PMC until init is finished. --- shared-core/nouveau_fifo.c | 4 +++ shared-core/nouveau_irq.c | 81 ---------------------------------------------- shared-core/nv04_graph.c | 4 +++ shared-core/nv04_mc.c | 2 -- shared-core/nv10_graph.c | 2 +- shared-core/nv20_graph.c | 2 +- shared-core/nv30_graph.c | 2 +- shared-core/nv40_graph.c | 2 +- shared-core/nv40_mc.c | 2 -- shared-core/nv50_fifo.c | 12 +++++++ shared-core/nv50_graph.c | 12 ++++++- shared-core/nv50_mc.c | 1 + 12 files changed, 36 insertions(+), 90 deletions(-) diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index fd21d2f3..f9677514 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -120,6 +120,10 @@ int nouveau_fifo_init(struct drm_device *dev) NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | NV_PMC_ENABLE_PFIFO); + /* Enable PFIFO error reporting */ + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_CACHES, 0x00000000); ret = nouveau_fifo_instmem_configure(dev); diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 84a37040..f110340b 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -39,37 +39,7 @@ void nouveau_irq_preinstall(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - /* TODO this should be removed as this stuff is done in - * engine.*init - */ - DRM_DEBUG("IRQ: preinst\n"); - - if (!dev_priv) { - DRM_ERROR("AIII, no dev_priv\n"); - return; - } - if (!dev_priv->mmio) { - DRM_ERROR("AIII, no dev_priv->mmio\n"); - return; - } - - /* Disable/Clear PFIFO interrupts */ - NV_WRITE(NV03_PFIFO_INTR_EN_0, 0); - NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); - /* Disable/Clear PGRAPH interrupts */ - if (dev_priv->card_typedev_private; - if (!dev_priv) { - DRM_ERROR("AIII, no dev_priv\n"); - return; - } - if (!dev_priv->mmio) { - DRM_ERROR("AIII, no dev_priv->mmio\n"); - return; - } - - DRM_DEBUG("IRQ: postinst\n"); - - /* Enable PFIFO error reporting */ - NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); - NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); - - /* Enable PGRAPH interrupts */ - if (dev_priv->card_typedev_private; - if (!dev_priv) { - DRM_ERROR("AIII, no dev_priv\n"); - return; - } - if (!dev_priv->mmio) { - DRM_ERROR("AIII, no dev_priv->mmio\n"); - return; - } - - DRM_DEBUG("IRQ: uninst\n"); - - /* Disable PFIFO interrupts */ - NV_WRITE(NV03_PFIFO_INTR_EN_0, 0); - /* Disable PGRAPH interrupts */ - if (dev_priv->card_typectx_table->instance >> 4); - NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000); NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000); diff --git a/shared-core/nv40_graph.c b/shared-core/nv40_graph.c index c79b63cc..c1464bc2 100644 --- a/shared-core/nv40_graph.c +++ b/shared-core/nv40_graph.c @@ -1636,8 +1636,8 @@ nv40_graph_init(struct drm_device *dev) /* No context present currently */ NV_WRITE(NV40_PGRAPH_CTXCTL_CUR, 0x00000000); - NV_WRITE(NV03_PGRAPH_INTR_EN, 0x00000000); NV_WRITE(NV03_PGRAPH_INTR , 0xFFFFFFFF); + NV_WRITE(NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF); NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000); diff --git a/shared-core/nv40_mc.c b/shared-core/nv40_mc.c index 8bb6b083..c7db9023 100644 --- a/shared-core/nv40_mc.c +++ b/shared-core/nv40_mc.c @@ -14,8 +14,6 @@ nv40_mc_init(struct drm_device *dev) */ NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); - NV_WRITE(NV03_PMC_INTR_EN_0, 0); - switch (dev_priv->chipset) { case 0x44: case 0x46: /* G72 */ diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c index a5e79260..f915d332 100644 --- a/shared-core/nv50_fifo.c +++ b/shared-core/nv50_fifo.c @@ -119,6 +119,17 @@ nv50_fifo_init_reset(struct drm_device *dev) NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PFIFO); } +static void +nv50_fifo_init_intr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + + NV_WRITE(NV03_PFIFO_INTR_0, 0xFFFFFFFF); + NV_WRITE(NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); +} + static void nv50_fifo_init_context_table(struct drm_device *dev) { @@ -190,6 +201,7 @@ nv50_fifo_init(struct drm_device *dev) dev_priv->Engine.fifo.priv = priv; nv50_fifo_init_reset(dev); + nv50_fifo_init_intr(dev); if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, (128+2)*4, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c index 59c8cfeb..f98fe601 100644 --- a/shared-core/nv50_graph.c +++ b/shared-core/nv50_graph.c @@ -44,6 +44,16 @@ nv50_graph_init_reset(struct drm_device *dev) NV_WRITE(NV03_PMC_ENABLE, pmc_e | NV_PMC_ENABLE_PGRAPH); } +static void +nv50_graph_init_intr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + DRM_DEBUG("\n"); + NV_WRITE(NV03_PGRAPH_INTR, 0xffffffff); + NV_WRITE(NV40_PGRAPH_INTR_EN, 0xffffffff); +} + static void nv50_graph_init_regs__nv(struct drm_device *dev) { @@ -59,7 +69,6 @@ nv50_graph_init_regs__nv(struct drm_device *dev) NV_WRITE(0x402000, 0xc0000000); NV_WRITE(0x400108, 0xffffffff); - NV_WRITE(0x400100, 0xffffffff); NV_WRITE(0x400824, 0x00004000); NV_WRITE(0x400500, 0x00010001); @@ -174,6 +183,7 @@ nv50_graph_init(struct drm_device *dev) DRM_DEBUG("\n"); nv50_graph_init_reset(dev); + nv50_graph_init_intr(dev); nv50_graph_init_regs__nv(dev); nv50_graph_init_regs(dev); nv50_graph_init_ctxctl(dev); diff --git a/shared-core/nv50_mc.c b/shared-core/nv50_mc.c index 952dea9f..b111826b 100644 --- a/shared-core/nv50_mc.c +++ b/shared-core/nv50_mc.c @@ -34,6 +34,7 @@ nv50_mc_init(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); + return 0; } -- cgit v1.2.3 From 296050eee6ca7b496e8702ceca9628de803d79f8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 8 Aug 2007 13:01:29 +1000 Subject: nouveau/nv50: hack up initial channel context from current state We really should be providing static values like the nv40 PGRAPH code does, however, this will do for now to keep X at least working. --- shared-core/nv50_graph.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shared-core/nv50_graph.c b/shared-core/nv50_graph.c index f98fe601..e5bbf65e 100644 --- a/shared-core/nv50_graph.c +++ b/shared-core/nv50_graph.c @@ -202,6 +202,7 @@ nv50_graph_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; struct nouveau_gpuobj *ramin = chan->ramin->gpuobj; int grctx_size = 0x60000, hdr; int ret; @@ -224,6 +225,11 @@ nv50_graph_create_context(struct nouveau_channel *chan) INSTANCE_WR(ramin, (hdr + 0x10)/4, 0); INSTANCE_WR(ramin, (hdr + 0x14)/4, 0x00010000); + if ((ret = engine->graph.load_context(chan))) { + DRM_ERROR("Error hacking up initial context: %d\n", ret); + return ret; + } + return 0; } -- cgit v1.2.3 From 40f21563564332786ca2b9ffc7d7ba9c7e6f7f1a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 8 Aug 2007 16:11:28 +1000 Subject: nouveau: return channel id --- shared-core/nouveau_irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index f110340b..03c466de 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -275,6 +275,7 @@ nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) return -EINVAL; } + *channel_ret = channel; return 0; } -- cgit v1.2.3 From 05633ca3708f48cfbbb77518da4e791d7e1613c2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 8 Aug 2007 16:37:55 +1000 Subject: nouveau: Always allocate drm's push buffer in VRAM Fixes #11868 --- shared-core/nouveau_dma.c | 11 ++++++- shared-core/nouveau_drv.h | 1 + shared-core/nouveau_fifo.c | 78 +++++++++++++++++++++++++--------------------- 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c index ce5b6299..ab502e6a 100644 --- a/shared-core/nouveau_dma.c +++ b/shared-core/nouveau_dma.c @@ -37,13 +37,22 @@ nouveau_dma_channel_init(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_drm_channel *dchan = &dev_priv->channel; struct nouveau_gpuobj *gpuobj = NULL; + struct mem_block *pushbuf; int grclass, ret, i; DRM_DEBUG("\n"); + pushbuf = nouveau_mem_alloc(dev, 0, 0x8000, + NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED, + (struct drm_file *)-2); + if (!pushbuf) { + DRM_ERROR("Failed to allocate DMA push buffer\n"); + return -ENOMEM; + } + /* Allocate channel */ ret = nouveau_fifo_alloc(dev, &dchan->chan, (struct drm_file *)-2, - NvDmaFB, NvDmaTT); + pushbuf, NvDmaFB, NvDmaTT); if (ret) { DRM_ERROR("Error allocating GPU channel: %d\n", ret); return ret; diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 10f9149e..572df46e 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -365,6 +365,7 @@ extern int nouveau_fifo_owner(struct drm_device *, struct drm_file *, extern int nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan, struct drm_file *file_priv, + struct mem_block *pushbuf, uint32_t fb_ctxdma, uint32_t tt_ctxdma); extern void nouveau_fifo_free(struct nouveau_channel *); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index f9677514..22bced14 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -190,46 +190,30 @@ int nouveau_fifo_init(struct drm_device *dev) } static int -nouveau_fifo_cmdbuf_alloc(struct nouveau_channel *chan) +nouveau_fifo_pushbuf_ctxdma_init(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_config *config = &dev_priv->config; - struct mem_block *cb; - int cb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE); + struct mem_block *pb = chan->pushbuf_mem; struct nouveau_gpuobj *pushbuf = NULL; int ret; - /* Defaults for unconfigured values */ - if (!config->cmdbuf.location) - config->cmdbuf.location = NOUVEAU_MEM_FB; - if (!config->cmdbuf.size || config->cmdbuf.size < cb_min_size) - config->cmdbuf.size = cb_min_size; - - cb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size, - config->cmdbuf.location | NOUVEAU_MEM_MAPPED, - (struct drm_file *)-2); - if (!cb) { - DRM_ERROR("Couldn't allocate DMA command buffer.\n"); - return -ENOMEM; - } - - if (cb->flags & NOUVEAU_MEM_AGP) { - ret = nouveau_gpuobj_gart_dma_new(chan, cb->start, cb->size, + if (pb->flags & NOUVEAU_MEM_AGP) { + ret = nouveau_gpuobj_gart_dma_new(chan, pb->start, pb->size, NV_DMA_ACCESS_RO, &pushbuf, &chan->pushbuf_base); } else - if (cb->flags & NOUVEAU_MEM_PCI) { + if (pb->flags & NOUVEAU_MEM_PCI) { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - cb->start, cb->size, + pb->start, pb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI_NONLINEAR, &pushbuf); chan->pushbuf_base = 0; } else if (dev_priv->card_type != NV_04) { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - cb->start, cb->size, + pb->start, pb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_VIDMEM, &pushbuf); chan->pushbuf_base = 0; @@ -239,19 +223,13 @@ nouveau_fifo_cmdbuf_alloc(struct nouveau_channel *chan) * VRAM. */ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - cb->start + + pb->start + drm_get_resource_start(dev, 1), - cb->size, NV_DMA_ACCESS_RO, + pb->size, NV_DMA_ACCESS_RO, NV_DMA_TARGET_PCI, &pushbuf); chan->pushbuf_base = 0; } - if (ret) { - nouveau_mem_free(dev, cb); - DRM_ERROR("Error creating push buffer ctxdma: %d\n", ret); - return ret; - } - if ((ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf))) { DRM_ERROR("Error referencing push buffer ctxdma: %d\n", ret); @@ -260,14 +238,36 @@ nouveau_fifo_cmdbuf_alloc(struct nouveau_channel *chan) return ret; } - chan->pushbuf_mem = cb; return 0; } +static struct mem_block * +nouveau_fifo_user_pushbuf_alloc(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_config *config = &dev_priv->config; + struct mem_block *pb; + int pb_min_size = max(NV03_FIFO_SIZE,PAGE_SIZE); + + /* Defaults for unconfigured values */ + if (!config->cmdbuf.location) + config->cmdbuf.location = NOUVEAU_MEM_FB; + if (!config->cmdbuf.size || config->cmdbuf.size < pb_min_size) + config->cmdbuf.size = pb_min_size; + + pb = nouveau_mem_alloc(dev, 0, config->cmdbuf.size, + config->cmdbuf.location | NOUVEAU_MEM_MAPPED, + (struct drm_file *)-2); + if (!pb) + DRM_ERROR("Couldn't allocate DMA push buffer.\n"); + + return pb; +} + /* allocates and initializes a fifo for user space consumption */ int nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, - struct drm_file *file_priv, + struct drm_file *file_priv, struct mem_block *pushbuf, uint32_t vram_handle, uint32_t tt_handle) { int ret; @@ -303,6 +303,7 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, chan->dev = dev; chan->id = channel; chan->file_priv = file_priv; + chan->pushbuf_mem = pushbuf; DRM_INFO("Allocating FIFO number %d\n", channel); @@ -320,8 +321,8 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, return ret; } - /* allocate a command buffer, and create a dma object for the gpu */ - ret = nouveau_fifo_cmdbuf_alloc(chan); + /* Create a dma object for the push buffer */ + ret = nouveau_fifo_pushbuf_ctxdma_init(chan); if (ret) { nouveau_fifo_free(chan); return ret; @@ -467,6 +468,7 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, struct drm_nouveau_channel_alloc *init = data; struct drm_map_list *entry; struct nouveau_channel *chan; + struct mem_block *pushbuf; int res; NOUVEAU_CHECK_INITIALISED_WITH_RETURN; @@ -474,7 +476,11 @@ static int nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) return -EINVAL; - res = nouveau_fifo_alloc(dev, &chan, file_priv, + pushbuf = nouveau_fifo_user_pushbuf_alloc(dev); + if (!pushbuf) + return -ENOMEM; + + res = nouveau_fifo_alloc(dev, &chan, file_priv, pushbuf, init->fb_ctxdma_handle, init->tt_ctxdma_handle); if (res) -- cgit v1.2.3 From e326acf5493a7193954d3dd794855e2a11dc1782 Mon Sep 17 00:00:00 2001 From: Matthieu Castet Date: Wed, 8 Aug 2007 22:55:32 +0200 Subject: nouveau : nv10, nv20, nv30 : don't save all channel in the same RAMFC entry This should improve multi fifo --- shared-core/nv10_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c index 47af0ff0..a056460d 100644 --- a/shared-core/nv10_fifo.c +++ b/shared-core/nv10_fifo.c @@ -33,7 +33,7 @@ NV10_RAMFC_##offset/4, (val)) #define RAMFC_RD(offset) INSTANCE_RD(chan->ramfc->gpuobj, \ NV10_RAMFC_##offset/4) -#define NV10_RAMFC(c) (dev_priv->ramfc_offset + NV10_RAMFC__SIZE) +#define NV10_RAMFC(c) (dev_priv->ramfc_offset + ((c) * NV10_RAMFC__SIZE)) #define NV10_RAMFC__SIZE ((dev_priv->chipset) >= 0x17 ? 64 : 32) int -- cgit v1.2.3 From 7281463f8d5d45a26f4cdff3fb67d896e0e74f74 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 9 Aug 2007 10:23:36 +1000 Subject: nouveau/nv40: add some missing pciids. --- shared-core/drm_pciids.txt | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index 126974d0..4bd690b2 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -510,8 +510,9 @@ 0x10de 0x0091 NV_40 "GeForce 7800 GTX" 0x10de 0x0092 NV_40 "GeForce 7800 GT" 0x10de 0x0093 NV_40 "GeForce 7800 GS" +0x10de 0x0095 NV_40 "GeForce 7800 SLI" 0x10de 0x0098 NV_40 "GeForce Go 7800" -0x10de 0x0099 NV_40 "GE Force Go 7800 GTX" +0x10de 0x0099 NV_40 "GeForce Go 7800 GTX" 0x10de 0x009d NV_40 "Quadro FX4500" 0x10de 0x00a0 NV_04 "Aladdin TNT2" 0x10de 0x00c0 NV_40 "GeForce 6800 GS" @@ -547,13 +548,16 @@ 0x10de 0x0113 NV_11 "Quadro2 MXR/EX/Go" 0x10de 0x0140 NV_40 "GeForce 6600 GT" 0x10de 0x0141 NV_40 "GeForce 6600" -0x10de 0x0142 NV_40 "GeForce 6600 PCIe" +0x10de 0x0142 NV_40 "GeForce 6600 LE" +0x10de 0x0143 NV_40 "GeForce 6600 VE" 0x10de 0x0144 NV_40 "GeForce Go 6600" 0x10de 0x0145 NV_40 "GeForce 6610 XL" 0x10de 0x0146 NV_40 "Geforce Go 6600TE/6200TE" +0x10de 0x0147 NV_40 "GeForce 6700 XL" 0x10de 0x0148 NV_40 "GeForce Go 6600" 0x10de 0x0149 NV_40 "GeForce Go 6600 GT" 0x10de 0x014a NV_40 "Quadro NVS 440" +0x10de 0x014c NV_40 "Quadro FX 550" 0x10de 0x014d NV_17 "Quadro FX 550" 0x10de 0x014e NV_40 "Quadro FX 540" 0x10de 0x014f NV_40 "GeForce 6200" @@ -561,6 +565,7 @@ 0x10de 0x0151 NV_15 "GeForce2 Ti" 0x10de 0x0152 NV_15 "GeForce2 Ultra, Bladerunner" 0x10de 0x0153 NV_15 "Quadro2 Pro" +0x10de 0x0160 NV_44 "GeForce 6500" 0x10de 0x0161 NV_44 "GeForce 6200 TurboCache(TM)" 0x10de 0x0162 NV_44 "GeForce 6200 SE TurboCache (TM)" 0x10de 0x0163 NV_44 "GeForce 6200 LE" @@ -569,6 +574,7 @@ 0x10de 0x0166 NV_44 "GeForce Go 6400" 0x10de 0x0167 NV_44 "GeForce Go 6200 TurboCache" 0x10de 0x0168 NV_44 "GeForce Go 6200 TurboCache" +0x10de 0x0169 NV_44 "GeForce 6250" 0x10de 0x0170 NV_17 "GeForce4 MX 460" 0x10de 0x0171 NV_17 "GeForce4 MX 440" 0x10de 0x0172 NV_17 "GeForce4 MX 420" @@ -601,11 +607,16 @@ 0x10de 0x019e NV_50 "Quadro FX 4600" 0x10de 0x01a0 NV_11|NV_NFORCE "GeForce2 MX Integrated Graphics" 0x10de 0x01d1 NV_44 "GeForce 7300 LE" +0x10de 0x01d3 NV_44 "Geforce 7300 SE" 0x10de 0x01d6 NV_44 "GeForce Go 7200" 0x10de 0x01d7 NV_44 "Quadro NVS 110M / GeForce Go 7300" 0x10de 0x01d8 NV_44 "GeForce Go 7400" +0x10de 0x01d9 NV_44 "GeForce Go 7400 GS" 0x10de 0x01da NV_44 "Quadro NVS 110M" +0x10de 0x01db NV_44 "Quadro NVS 120M" 0x10de 0x01dc NV_44 "Quadro FX 350M" +0x10de 0x01dd NV_44 "GeForce 7500 LE" +0x10de 0x01de NV_44 "Quadro FX 350" 0x10de 0x01df NV_44 "GeForce 7300 GS" 0x10de 0x01f0 NV_17|NV_NFORCE2 "GeForce4 MX - nForce GPU" 0x10de 0x0200 NV_20 "GeForce3" @@ -617,9 +628,12 @@ 0x10de 0x0215 NV_40 "GeForce 6800 GT" 0x10de 0x0218 NV_40 "GeForce 6800 XT" 0x10de 0x0221 NV_44 "GeForce 6200" +0x10de 0x0222 NV_44 "GeForce 6200 A-LE" 0x10de 0x0240 NV_44 "GeForce 6150" +0x10de 0x0241 NV_44 "GeForce 6150 LE" 0x10de 0x0242 NV_44 "GeForce 6100" -0x10de 0x0244 NV_44 "GeForce 6150 Go" +0x10de 0x0244 NV_44 "GeForce Go 6150" +0x10de 0x0247 NV_44 "GeForce Go 6100" 0x10de 0x0250 NV_25 "GeForce4 Ti 4600" 0x10de 0x0251 NV_25 "GeForce4 Ti 4400" 0x10de 0x0252 NV_25 "GeForce4 Ti" @@ -700,7 +714,15 @@ 0x10de 0x0391 NV_40 "GeForce 7600 GT" 0x10de 0x0392 NV_40 "GeForce 7600 GS" 0x10de 0x0393 NV_40 "GeForce 7300 GT" +0x10de 0x0394 NV_40 "GeForce 7600 LE" +0x10de 0x0395 NV_40 "GeForce 7300 GT" +0x10de 0x0397 NV_40 "GeForce Go 7700" 0x10de 0x0398 NV_40 "GeForce Go 7600" +0x10de 0x0399 NV_40 "GeForce Go 7600 GT" +0x10de 0x039a NV_40 "Quadro NVS 300M" +0x10de 0x039b NV_40 "GeForce Go 7900 SE" +0x10de 0x039c NV_40 "Quadro FX 550M" +0x10de 0x039e NV_40 "Quadro FX 560" 0x10de 0x03d0 NV_44 "GeForce 6100 nForce 430" 0x10de 0x03d1 NV_44 "GeForce 6100 nForce 405" 0x10de 0x03d2 NV_44 "GeForce 6100 nForce 400" -- cgit v1.2.3 From 7784e8c6e74b93ffb39d82e3385bd3268a55507c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 9 Aug 2007 11:12:13 +1000 Subject: nouveau: silence irq handler a bit --- shared-core/nouveau_irq.c | 87 +++++++++++------------------------------------ 1 file changed, 20 insertions(+), 67 deletions(-) diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 03c466de..d8a2c1b8 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -72,12 +72,10 @@ static void nouveau_fifo_irq_handler(struct drm_device *dev) chstat = NV_READ(NV04_PFIFO_DMA); channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); - DRM_DEBUG("NV: PFIFO interrupt! Channel=%d, INTSTAT=0x%08x/MODE=0x%08x/PEND=0x%08x\n", channel, status, chmode, chstat); - if (status & NV_PFIFO_INTR_CACHE_ERROR) { uint32_t c1get, c1method, c1data; - DRM_ERROR("NV: PFIFO error interrupt\n"); + DRM_ERROR("PFIFO error interrupt\n"); c1get = NV_READ(NV03_PFIFO_CACHE1_GET) >> 2; if (dev_priv->card_type < NV_40) { @@ -89,17 +87,17 @@ static void nouveau_fifo_irq_handler(struct drm_device *dev) c1data = NV_READ(NV40_PFIFO_CACHE1_DATA(c1get)); } - DRM_ERROR("NV: Channel %d/%d - Method 0x%04x, Data 0x%08x\n", - channel, (c1method >> 13) & 7, - c1method & 0x1ffc, c1data - ); + DRM_ERROR("Channel %d/%d - Method 0x%04x, Data 0x%08x\n", + channel, (c1method >> 13) & 7, c1method & 0x1ffc, + c1data); status &= ~NV_PFIFO_INTR_CACHE_ERROR; NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); } if (status & NV_PFIFO_INTR_DMA_PUSHER) { - DRM_INFO("NV: PFIFO DMA pusher interrupt\n"); + DRM_ERROR("PFIFO DMA pusher interrupt: ch%d, 0x%08x\n", + channel, NV_READ(NV04_PFIFO_CACHE1_DMA_GET)); status &= ~NV_PFIFO_INTR_DMA_PUSHER; NV_WRITE(NV03_PFIFO_INTR_0, NV_PFIFO_INTR_DMA_PUSHER); @@ -113,7 +111,7 @@ static void nouveau_fifo_irq_handler(struct drm_device *dev) } if (status) { - DRM_INFO("NV: unknown PFIFO interrupt. status=0x%08x\n", status); + DRM_ERROR("Unhandled PFIFO interrupt: status=0x%08x\n", status); NV_WRITE(NV03_PFIFO_INTR_0, status); } @@ -311,77 +309,31 @@ nouveau_graph_dump_trap_info(struct drm_device *dev) ARRAY_SIZE(nouveau_nstatus_names)); printk("\n"); - DRM_ERROR("NV: Channel %d/%d (class 0x%04x) - " - "Method 0x%04x, Data 0x%08x\n", - channel, subc, class, method, data - ); + DRM_ERROR("Channel %d/%d (class 0x%04x) - Method 0x%04x, Data 0x%08x\n", + channel, subc, class, method, data); } static void nouveau_pgraph_irq_handler(struct drm_device *dev) { - uint32_t status; struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t status, nsource; status = NV_READ(NV03_PGRAPH_INTR); if (!status) return; + nsource = NV_READ(NV03_PGRAPH_NSOURCE); if (status & NV_PGRAPH_INTR_NOTIFY) { - uint32_t nsource, nstatus, instance, notify; - DRM_DEBUG("NV: PGRAPH notify interrupt\n"); + DRM_DEBUG("PGRAPH notify interrupt\n"); - nstatus = NV_READ(NV03_PGRAPH_NSTATUS); - nsource = NV_READ(NV03_PGRAPH_NSOURCE); - DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus); - - /* if this wasn't NOTIFICATION_PENDING, dump extra trap info */ - if (nsource & ~(1<<0)) { - nouveau_graph_dump_trap_info(dev); - } else { - instance = NV_READ(0x00400158); - notify = NV_READ(0x00400150) >> 16; - DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", - instance, notify); - } + nouveau_graph_dump_trap_info(dev); status &= ~NV_PGRAPH_INTR_NOTIFY; NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); } - if (status & NV_PGRAPH_INTR_BUFFER_NOTIFY) { - uint32_t nsource, nstatus, instance, notify; - DRM_DEBUG("NV: PGRAPH buffer notify interrupt\n"); - - nstatus = NV_READ(NV03_PGRAPH_NSTATUS); - nsource = NV_READ(NV03_PGRAPH_NSOURCE); - DRM_DEBUG("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus); - - instance = NV_READ(0x00400158); - notify = NV_READ(0x00400150) >> 16; - DRM_DEBUG("instance:0x%08x\tnotify:0x%08x\n", instance, notify); - - status &= ~NV_PGRAPH_INTR_BUFFER_NOTIFY; - NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_BUFFER_NOTIFY); - } - - if (status & NV_PGRAPH_INTR_MISSING_HW) { - DRM_ERROR("NV: PGRAPH missing hw interrupt\n"); - - status &= ~NV_PGRAPH_INTR_MISSING_HW; - NV_WRITE(NV03_PGRAPH_INTR, NV_PGRAPH_INTR_MISSING_HW); - } - if (status & NV_PGRAPH_INTR_ERROR) { - uint32_t nsource, nstatus, instance; - - DRM_ERROR("NV: PGRAPH error interrupt\n"); - - nstatus = NV_READ(NV03_PGRAPH_NSTATUS); - nsource = NV_READ(NV03_PGRAPH_NSOURCE); - DRM_ERROR("nsource:0x%08x\tnstatus:0x%08x\n", nsource, nstatus); - - instance = NV_READ(0x00400158); - DRM_ERROR("instance:0x%08x\n", instance); + DRM_ERROR("PGRAPH error interrupt\n"); nouveau_graph_dump_trap_info(dev); @@ -391,7 +343,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev) if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { uint32_t channel=NV_READ(NV03_PFIFO_CACHE1_PUSH1)&(nouveau_fifo_number(dev)-1); - DRM_INFO("NV: PGRAPH context switch interrupt channel %x\n",channel); + DRM_DEBUG("PGRAPH context switch interrupt channel %x\n",channel); switch(dev_priv->card_type) { case NV_04: @@ -408,7 +360,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev) nouveau_nv20_context_switch(dev); break; default: - DRM_INFO("NV: Context switch not implemented\n"); + DRM_ERROR("Context switch not implemented\n"); break; } @@ -417,7 +369,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev) } if (status) { - DRM_INFO("NV: Unknown PGRAPH interrupt! STAT=0x%08x\n", status); + DRM_ERROR("Unhandled PGRAPH interrupt: STAT=0x%08x\n", status); NV_WRITE(NV03_PGRAPH_INTR, status); } @@ -427,6 +379,7 @@ static void nouveau_pgraph_irq_handler(struct drm_device *dev) static void nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) { struct drm_nouveau_private *dev_priv = dev->dev_private; + if (crtc&1) { NV_WRITE(NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); } @@ -446,16 +399,16 @@ irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS) if (!status) return IRQ_NONE; - DRM_DEBUG("PMC INTSTAT: 0x%08x\n", status); - if (status & NV_PMC_INTR_0_PFIFO_PENDING) { nouveau_fifo_irq_handler(dev); status &= ~NV_PMC_INTR_0_PFIFO_PENDING; } + if (status & NV_PMC_INTR_0_PGRAPH_PENDING) { nouveau_pgraph_irq_handler(dev); status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; } + if (status & NV_PMC_INTR_0_CRTCn_PENDING) { nouveau_crtc_irq_handler(dev, (status>>24)&3); status &= ~NV_PMC_INTR_0_CRTCn_PENDING; -- 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_drv.h | 2 ++ shared-core/nouveau_object.c | 26 ++++++++++++++++++++++++-- shared-core/nouveau_state.c | 5 ++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 572df46e..4d5c7f7e 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -370,8 +370,10 @@ extern int nouveau_fifo_alloc(struct drm_device *dev, extern void nouveau_fifo_free(struct nouveau_channel *); /* nouveau_object.c */ +extern int nouveau_gpuobj_early_init(struct drm_device *); extern int nouveau_gpuobj_init(struct drm_device *); extern void nouveau_gpuobj_takedown(struct drm_device *); +extern void nouveau_gpuobj_late_takedown(struct drm_device *); extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, uint32_t vram_h, uint32_t tt_h); extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); 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); diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index e80e77a5..eac38060 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -296,7 +296,8 @@ nouveau_card_init(struct drm_device *dev) engine = &dev_priv->Engine; dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; - INIT_LIST_HEAD(&dev_priv->gpuobj_list); + ret = nouveau_gpuobj_early_init(dev); + if (ret) return ret; /* Initialise instance memory, must happen before mem_init so we * know exactly how much VRAM we're able to use for "normal" @@ -375,6 +376,8 @@ static void nouveau_card_takedown(struct drm_device *dev) drm_irq_uninstall(dev); + nouveau_gpuobj_late_takedown(dev); + dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN; } } -- 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_drv.h | 3 +- shared-core/nouveau_fifo.c | 2 - shared-core/nouveau_object.c | 50 ++++++--- shared-core/nouveau_reg.h | 10 ++ shared-core/nv04_fifo.c | 2 +- shared-core/nv10_fifo.c | 2 +- shared-core/nv40_fifo.c | 2 +- shared-core/nv50_fifo.c | 37 +++---- shared-core/nv50_instmem.c | 246 ++++++++++++++++++++++++++----------------- 9 files changed, 217 insertions(+), 137 deletions(-) diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index 4d5c7f7e..e3d0ff4c 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -393,7 +393,8 @@ extern int nouveau_gpuobj_new_ref(struct drm_device *, struct nouveau_channel *ref_chan, uint32_t handle, int size, int align, uint32_t flags, struct nouveau_gpuobj_ref **); -extern int nouveau_gpuobj_new_fake(struct drm_device *, uint32_t offset, +extern int nouveau_gpuobj_new_fake(struct drm_device *, + uint32_t p_offset, uint32_t b_offset, uint32_t size, uint32_t flags, struct nouveau_gpuobj **, struct nouveau_gpuobj_ref**); diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 22bced14..f0c2a556 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -285,8 +285,6 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, * When there are no more contexts, you lost */ for(channel=0; channelcard_type == NV_50) && (channel == 0)) - continue; if (dev_priv->fifos[channel] == NULL) break; } 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) { diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 47d54b2a..65614627 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -80,6 +80,16 @@ #define NV40_PMC_1708 0x00001708 #define NV40_PMC_170C 0x0000170C +/* probably PMC ? */ +#define NV50_PUNK_BAR0_PRAMIN 0x00001700 +#define NV50_PUNK_BAR_CFG_BASE 0x00001704 +#define NV50_PUNK_BAR_CFG_BASE_VALID (1<<30) +#define NV50_PUNK_BAR1_CTXDMA 0x00001708 +#define NV50_PUNK_BAR1_CTXDMA_VALID (1<<31) +#define NV50_PUNK_BAR3_CTXDMA 0x0000170C +#define NV50_PUNK_BAR3_CTXDMA_VALID (1<<31) +#define NV50_PUNK_UNK1710 0x00001710 + #define NV04_PTIMER_INTR_0 0x00009100 #define NV04_PTIMER_INTR_EN_0 0x00009140 #define NV04_PTIMER_NUMERATOR 0x00009200 diff --git a/shared-core/nv04_fifo.c b/shared-core/nv04_fifo.c index 4d61f4fe..d750ced8 100644 --- a/shared-core/nv04_fifo.c +++ b/shared-core/nv04_fifo.c @@ -42,7 +42,7 @@ nv04_fifo_create_context(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; - if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), + if ((ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0, NV04_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, diff --git a/shared-core/nv10_fifo.c b/shared-core/nv10_fifo.c index a056460d..c86725d2 100644 --- a/shared-core/nv10_fifo.c +++ b/shared-core/nv10_fifo.c @@ -43,7 +43,7 @@ nv10_fifo_create_context(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; - if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), + if ((ret = nouveau_gpuobj_new_fake(dev, NV10_RAMFC(chan->id), ~0, NV10_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c index f04c2882..eb160ee2 100644 --- a/shared-core/nv40_fifo.c +++ b/shared-core/nv40_fifo.c @@ -43,7 +43,7 @@ nv40_fifo_create_context(struct nouveau_channel *chan) struct drm_nouveau_private *dev_priv = dev->dev_private; int ret; - if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), + if ((ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0, NV40_RAMFC__SIZE, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c index f915d332..71b89d6d 100644 --- a/shared-core/nv50_fifo.c +++ b/shared-core/nv50_fifo.c @@ -30,7 +30,6 @@ typedef struct { struct nouveau_gpuobj_ref *thingo; - struct nouveau_gpuobj_ref *dummyctx; } nv50_fifo_priv; #define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50) @@ -47,7 +46,7 @@ nv50_fifo_init_thingo(struct drm_device *dev) INSTANCE_WR(thingo->gpuobj, 0, 0x7e); INSTANCE_WR(thingo->gpuobj, 1, 0x7e); - for (i = 0; i fifos[i]) { INSTANCE_WR(thingo->gpuobj, fi, i); fi++; @@ -60,7 +59,7 @@ nv50_fifo_init_thingo(struct drm_device *dev) } static int -nv50_fifo_channel_enable(struct drm_device *dev, int channel) +nv50_fifo_channel_enable(struct drm_device *dev, int channel, int nt) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->fifos[channel]; @@ -83,7 +82,7 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel) NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED); } - nv50_fifo_init_thingo(dev); + if (!nt) nv50_fifo_init_thingo(dev); return 0; } @@ -156,18 +155,9 @@ static int nv50_fifo_init_regs(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - nv50_fifo_priv *priv = dev_priv->Engine.fifo.priv; - int ret; DRM_DEBUG("\n"); - if ((ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, 0x1000, - 0x1000, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, - &priv->dummyctx))) - return ret; - NV_WRITE(0x2500, 0); NV_WRITE(0x3250, 0); NV_WRITE(0x3220, 0); @@ -175,13 +165,9 @@ nv50_fifo_init_regs(struct drm_device *dev) NV_WRITE(0x3210, 0); NV_WRITE(0x3270, 0); - if (IS_G80) { - NV_WRITE(0x2600, (priv->dummyctx->instance>>8) | (1<<31)); - NV_WRITE(0x27fc, (priv->dummyctx->instance>>8) | (1<<31)); - } else { - NV_WRITE(0x2600, (priv->dummyctx->instance>>12) | (1<<31)); - NV_WRITE(0x27fc, (priv->dummyctx->instance>>12) | (1<<31)); - } + /* Enable dummy channels setup by nv50_instmem.c */ + nv50_fifo_channel_enable(dev, 0, 1); + nv50_fifo_channel_enable(dev, 127, 1); return 0; } @@ -209,6 +195,7 @@ nv50_fifo_init(struct drm_device *dev) DRM_ERROR("error creating thingo: %d\n", ret); return ret; } + nv50_fifo_init_context_table(dev); nv50_fifo_init_regs__nv(dev); @@ -230,7 +217,6 @@ nv50_fifo_takedown(struct drm_device *dev) return; nouveau_gpuobj_ref_del(dev, &priv->thingo); - nouveau_gpuobj_ref_del(dev, &priv->dummyctx); dev_priv->Engine.fifo.priv = NULL; drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER); @@ -248,7 +234,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) if (IS_G80) { uint32_t ramfc_offset = chan->ramin->gpuobj->im_pramin->start; - if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, 0x100, + if ((ret = nouveau_gpuobj_new_fake(dev, ramfc_offset, ~0, 0x100, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &ramfc, &chan->ramfc))) @@ -285,7 +271,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) INSTANCE_WR(ramfc, 0x98/4, chan->ramin->instance >> 12); } - if ((ret = nv50_fifo_channel_enable(dev, chan->id))) { + if ((ret = nv50_fifo_channel_enable(dev, chan->id, 0))) { DRM_ERROR("error enabling ch%d: %d\n", chan->id, ret); nouveau_gpuobj_ref_del(dev, &chan->ramfc); return ret; @@ -302,6 +288,11 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) DRM_DEBUG("ch%d\n", chan->id); nv50_fifo_channel_disable(dev, chan->id, 0); + + /* Dummy channel, also used on ch 127 */ + if (chan->id == 0) + nv50_fifo_channel_disable(dev, 127, 0); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); } diff --git a/shared-core/nv50_instmem.c b/shared-core/nv50_instmem.c index c26b1db5..1eeb54df 100644 --- a/shared-core/nv50_instmem.c +++ b/shared-core/nv50_instmem.c @@ -31,118 +31,162 @@ typedef struct { uint32_t save1700[5]; /* 0x1700->0x1710 */ + + struct nouveau_gpuobj_ref *pramin_pt; + struct nouveau_gpuobj_ref *pramin_bar; } nv50_instmem_priv; #define NV50_INSTMEM_PAGE_SHIFT 12 #define NV50_INSTMEM_PAGE_SIZE (1 << NV50_INSTMEM_PAGE_SHIFT) -#define NV50_INSTMEM_RSVD_SIZE (64 * 1024) #define NV50_INSTMEM_PT_SIZE(a) (((a) >> 12) << 3) +/*NOTE: - Assumes 0x1700 already covers the correct MiB of PRAMIN + */ +#define BAR0_WI32(g,o,v) do { \ + uint32_t offset; \ + if ((g)->im_backing) { \ + offset = (g)->im_backing->start; \ + } else { \ + offset = chan->ramin->gpuobj->im_backing->start; \ + offset += (g)->im_pramin->start; \ + } \ + offset += (o); \ + NV_WRITE(NV_RAMIN + (offset & 0xfffff), (v)); \ +} while(0) + int nv50_instmem_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size; nv50_instmem_priv *priv; - uint32_t rv, pt, pts, cb, cb0, cb1, unk, as; - uint32_t i, v; - int ret; + int ret, i; + uint32_t v; priv = drm_calloc(1, sizeof(*priv), DRM_MEM_DRIVER); if (!priv) return -ENOMEM; dev_priv->Engine.instmem.priv = priv; - /* Save current state */ - for (i = 0x1700; i <= 0x1710; i+=4) - priv->save1700[(i-0x1700)/4] = NV_READ(i); - - as = dev_priv->ramin->size; - rv = nouveau_mem_fb_amount(dev) - (1*1024*1024); - pt = rv + 0xd0000; - pts = NV50_INSTMEM_PT_SIZE(as); - cb = rv + 0xc8000; - if ((dev_priv->chipset & 0xf0) != 0x50) { - unk = cb + 0x4200; - cb0 = cb + 0x4240; - cb1 = cb + 0x278; - } else { - unk = cb + 0x5400; - cb0 = cb + 0x5440; - cb1 = cb + 0x1478; - } - - DRM_DEBUG("PRAMIN config:\n"); - DRM_DEBUG(" Rsvd VRAM base: 0x%08x\n", rv); - DRM_DEBUG(" Aperture size: %i MiB\n", as >> 20); - DRM_DEBUG(" PT base: 0x%08x\n", pt); - DRM_DEBUG(" PT size: %d KiB\n", pts >> 10); - DRM_DEBUG(" BIOS image: 0x%08x\n", (NV_READ(0x619f04)&~0xff)<<8); - DRM_DEBUG(" Config base: 0x%08x\n", cb); - DRM_DEBUG(" ctxdma Config0: 0x%08x\n", cb0); - DRM_DEBUG(" Config1: 0x%08x\n", cb1); - - /* Map first MiB of reserved vram into BAR0 PRAMIN aperture */ - NV_WRITE(0x1700, (rv>>16)); - /* Poke some regs.. */ - NV_WRITE(0x1704, (cb>>12)); - NV_WRITE(0x1710, (((unk-cb)>>4))|(1<<31)); - NV_WRITE(0x1704, (cb>>12)|(1<<30)); - - /* CB0, some DMA object, NFI what it points at... Needed however, - * or the PRAMIN aperture doesn't operate as expected. + /* Reserve the last MiB of VRAM, we should probably try to avoid + * setting up the below tables over the top of the VBIOS image at + * some point. */ - NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x00, 0x7fc00000); - NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x04, 0xe1ffffff); - NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x08, 0xe0000000); - NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x0c, 0x01000001); - NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x10, 0x00000000); - NV_WRITE(NV_RAMIN + (cb0 - rv) + 0x14, 0x00000000); - - /* CB1, points at PRAMIN PT */ - NV_WRITE(NV_RAMIN + (cb1 - rv) + 0, pt | 0x63); - NV_WRITE(NV_RAMIN + (cb1 - rv) + 4, 0x00000000); - - /* Zero PRAMIN page table */ - v = NV_RAMIN + (pt - rv); - for (i = v; i < v + pts; i += 8) { - NV_WRITE(i + 0x00, 0x00000009); - NV_WRITE(i + 0x04, 0x00000000); - } + dev_priv->ramin_rsvd_vram = 1 << 20; + c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram; + c_size = 128 << 10; + c_vmpd = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200; + c_ramfc = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20; + c_base = c_vmpd + 0x4000; + pt_size = NV50_INSTMEM_PT_SIZE(dev_priv->ramin->size); + + DRM_DEBUG(" Rsvd VRAM base: 0x%08x\n", c_offset); + DRM_DEBUG(" VBIOS image: 0x%08x\n", (NV_READ(0x619f04)&~0xff)<<8); + DRM_DEBUG(" Aperture size: %d MiB\n", + (uint32_t)dev_priv->ramin->size >> 20); + DRM_DEBUG(" PT size: %d KiB\n", pt_size >> 10); + + NV_WRITE(NV50_PUNK_BAR0_PRAMIN, (c_offset >> 16)); + + /* Create a fake channel, and use it as our "dummy" channels 0/127. + * The main reason for creating a channel is so we can use the gpuobj + * code. However, it's probably worth noting that NVIDIA also setup + * their channels 0/127 with the same values they configure here. + * So, there may be some other reason for doing this. + * + * Have to create the entire channel manually, as the real channel + * creation code assumes we have PRAMIN access, and we don't until + * we're done here. + */ + chan = drm_calloc(1, sizeof(*chan), DRM_MEM_DRIVER); + if (!chan) + return -ENOMEM; + chan->id = 0; + chan->dev = dev; + chan->file_priv = (struct drm_file *)-2; + dev_priv->fifos[0] = dev_priv->fifos[127] = chan; - /* Map page table into PRAMIN aperture */ - for (i = pt; i < pt + pts; i += 0x1000) { - uint32_t pte = NV_RAMIN + (pt-rv) + (((i-pt) >> 12) << 3); - DRM_DEBUG("PRAMIN PTE = 0x%08x @ 0x%08x\n", i, pte); - NV_WRITE(pte + 0x00, i | 1); - NV_WRITE(pte + 0x04, 0x00000000); - } + /* Channel's PRAMIN object + heap */ + if ((ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, 128<<10, 0, + NULL, &chan->ramin))) + return ret; - /* Points at CB0 */ - NV_WRITE(0x170c, (((cb0 - cb)>>4)|(1<<31))); + if (nouveau_mem_init_heap(&chan->ramin_heap, c_base, c_size - c_base)) + return -ENOMEM; + + /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ + if ((ret = nouveau_gpuobj_new_fake(dev, c_ramfc, c_offset + c_ramfc, + 0x4000, 0, NULL, &chan->ramfc))) + return ret; + + for (i = 0; i < c_vmpd; i += 4) + BAR0_WI32(chan->ramin->gpuobj, i, 0); + + /* VM page directory */ + if ((ret = nouveau_gpuobj_new_fake(dev, c_vmpd, c_offset + c_vmpd, + 0x4000, 0, &chan->vm_pd, NULL))) + return ret; + for (i = 0; i < 0x4000; i += 8) { + BAR0_WI32(chan->vm_pd, i + 0x00, 0x00000000); + BAR0_WI32(chan->vm_pd, i + 0x04, 0x00000000); + } - /* Confirm it all worked, should be able to read back the page table's - * PTEs from the PRAMIN BAR + /* PRAMIN page table, cheat and map into VM at 0x0000000000. + * We map the entire fake channel into the start of the PRAMIN BAR */ - NV_WRITE(0x1700, pt >> 16); - if (NV_READ(0x700000) != NV_RI32(0)) { - DRM_ERROR("Failed to init PRAMIN page table\n"); - return -EINVAL; + if ((ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pt_size, 0x1000, + 0, &priv->pramin_pt))) + return ret; + + for (i = 0, v = c_offset; i < pt_size; i+=8, v+=0x1000) { + if (v < (c_offset + c_size)) + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v | 1); + else + BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, 0x00000009); + BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); } - /* Create a heap to manage PRAMIN aperture allocations */ - ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, pts, as-pts); - if (ret) { - DRM_ERROR("Failed to init PRAMIN heap\n"); - return -ENOMEM; + BAR0_WI32(chan->vm_pd, 0x00, priv->pramin_pt->instance | 0x63); + BAR0_WI32(chan->vm_pd, 0x04, 0x00000000); + + /* DMA object for PRAMIN BAR */ + if ((ret = nouveau_gpuobj_new_ref(dev, chan, chan, 0, 6*4, 16, 0, + &priv->pramin_bar))) + return ret; + BAR0_WI32(priv->pramin_bar->gpuobj, 0x00, 0x7fc00000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x04, dev_priv->ramin->size - 1); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x08, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x0c, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x10, 0x00000000); + BAR0_WI32(priv->pramin_bar->gpuobj, 0x14, 0x00000000); + + /* Poke the relevant regs, and pray it works :) */ + NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12)); + NV_WRITE(NV50_PUNK_UNK1710, 0); + NV_WRITE(NV50_PUNK_BAR_CFG_BASE, (chan->ramin->instance >> 12) | + NV50_PUNK_BAR_CFG_BASE_VALID); + NV_WRITE(NV50_PUNK_BAR1_CTXDMA, 0); + NV_WRITE(NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->instance >> 4) | + NV50_PUNK_BAR3_CTXDMA_VALID); + + /* Assume that praying isn't enough, check that we can re-read the + * entire fake channel back from the PRAMIN BAR */ + for (i = 0; i < c_size; i+=4) { + if (NV_READ(NV_RAMIN + i) != NV_RI32(i)) { + DRM_ERROR("Error reading back PRAMIN at 0x%08x\n", i); + return -EINVAL; + } } - DRM_DEBUG("NV50: PRAMIN setup ok\n"); - /* Don't alloc the last MiB of VRAM, probably too much, but be safe - * at least for now. - */ - dev_priv->ramin_rsvd_vram = 1*1024*1024; + /* Global PRAMIN heap */ + if (nouveau_mem_init_heap(&dev_priv->ramin_heap, + c_size, dev_priv->ramin->size - c_size)) { + dev_priv->ramin_heap = NULL; + DRM_ERROR("Failed to init RAMIN heap\n"); + } - /*XXX: probably incorrect, but needed to make hash func "work" */ + /*XXX: incorrect, but needed to make hash func "work" */ dev_priv->ramht_offset = 0x10000; dev_priv->ramht_bits = 9; dev_priv->ramht_size = (1 << dev_priv->ramht_bits); @@ -154,8 +198,11 @@ nv50_instmem_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv; + struct nouveau_channel *chan = dev_priv->fifos[0]; int i; + DRM_DEBUG("\n"); + if (!priv) return; @@ -163,6 +210,20 @@ nv50_instmem_takedown(struct drm_device *dev) for (i = 0x1700; i <= 0x1710; i+=4) NV_WRITE(i, priv->save1700[(i-0x1700)/4]); + nouveau_gpuobj_ref_del(dev, &priv->pramin_bar); + nouveau_gpuobj_ref_del(dev, &priv->pramin_pt); + + /* Destroy dummy channel */ + if (chan) { + nouveau_gpuobj_del(dev, &chan->vm_pd); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); + nouveau_gpuobj_ref_del(dev, &chan->ramin); + nouveau_mem_takedown(&chan->ramin_heap); + + dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; + drm_free(chan, sizeof(*chan), DRM_MEM_DRIVER); + } + dev_priv->Engine.instmem.priv = NULL; drm_free(priv, sizeof(*priv), DRM_MEM_DRIVER); } @@ -205,6 +266,7 @@ int nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) { struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv; uint32_t pte, pte_end, vram; if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) @@ -217,19 +279,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; vram = gpuobj->im_backing->start; - if (pte == pte_end) { - DRM_ERROR("WARNING: badness in bind() pte calc\n"); - pte_end++; - } - DRM_DEBUG("pramin=0x%llx, pte=%d, pte_end=%d\n", gpuobj->im_pramin->start, pte, pte_end); DRM_DEBUG("first vram page: 0x%llx\n", gpuobj->im_backing->start); while (pte < pte_end) { - NV_WI32(pte + 0, vram | 1); - NV_WI32(pte + 4, 0x00000000); + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, vram | 1); + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); pte += 8; vram += NV50_INSTMEM_PAGE_SIZE; @@ -243,6 +300,7 @@ int nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) { struct drm_nouveau_private *dev_priv = dev->dev_private; + nv50_instmem_priv *priv = dev_priv->Engine.instmem.priv; uint32_t pte, pte_end; if (gpuobj->im_bound == 0) @@ -251,8 +309,8 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) pte = (gpuobj->im_pramin->start >> 12) << 3; pte_end = ((gpuobj->im_pramin->size >> 12) << 3) + pte; while (pte < pte_end) { - NV_WI32(pte + 0, 0x00000000); - NV_WI32(pte + 4, 0x00000000); + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 0)/4, 0x00000009); + INSTANCE_WR(priv->pramin_pt->gpuobj, (pte + 4)/4, 0x00000000); pte += 8; } -- cgit v1.2.3 From da279868706cc799bdf25cdd5523d11fda64d4cc Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 6 Aug 2007 18:33:29 +1000 Subject: i915: i965 non-secure batchbuffer bit has moved. --- shared-core/i915_dma.c | 10 ++++++++-- shared-core/i915_drv.h | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 5d227d8b..9f18feee 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -546,9 +546,15 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, if (dev_priv->use_mi_batchbuffer_start) { BEGIN_LP_RING(2); - OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); - OUT_RING(batch->start | MI_BATCH_NON_SECURE); + if (IS_I965G(dev)) { + OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); + OUT_RING(batch->start); + } else { + OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); + OUT_RING(batch->start | MI_BATCH_NON_SECURE); + } ADVANCE_LP_RING(); + } else { BEGIN_LP_RING(4); OUT_RING(MI_BATCH_BUFFER); diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index e641fdc6..528f7b3a 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -364,6 +364,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define MI_BATCH_BUFFER_END (0xA<<23) #define MI_BATCH_NON_SECURE (1) +#define MI_BATCH_NON_SECURE_I965 (1<<8) + #define MI_WAIT_FOR_EVENT ((0x3<<23)) #define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) #define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) -- cgit v1.2.3 From 263775c454f381fffc8f5d4f309b4e1b131c3734 Mon Sep 17 00:00:00 2001 From: vehemens Date: Mon, 13 Aug 2007 10:24:39 -0700 Subject: Fix drm_auth.c locking to not recurse on dev_lock. --- bsd-core/drm_auth.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/bsd-core/drm_auth.c b/bsd-core/drm_auth.c index 964f9a42..14cfc225 100644 --- a/bsd-core/drm_auth.c +++ b/bsd-core/drm_auth.c @@ -43,6 +43,8 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic) drm_magic_entry_t *pt; int hash = drm_hash_magic(magic); + DRM_SPINLOCK_ASSERT(&dev->dev_lock); + for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { if (pt->magic == magic) { return pt->priv; @@ -59,6 +61,8 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) DRM_DEBUG("%d\n", magic); + DRM_SPINLOCK_ASSERT(&dev->dev_lock); + hash = drm_hash_magic(magic); entry = malloc(sizeof(*entry), M_DRM, M_ZERO | M_NOWAIT); if (!entry) return ENOMEM; @@ -85,10 +89,11 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) drm_magic_entry_t *pt; int hash; + DRM_SPINLOCK_ASSERT(&dev->dev_lock); + DRM_DEBUG("%d\n", magic); hash = drm_hash_magic(magic); - DRM_LOCK(); for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { if (pt->magic == magic) { if (dev->magiclist[hash].head == pt) { @@ -100,11 +105,9 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) if (prev) { prev->next = pt->next; } - DRM_UNLOCK(); return 0; } } - DRM_UNLOCK(); free(pt, M_DRM); return EINVAL; @@ -129,8 +132,8 @@ int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv) continue; } while (drm_find_file(dev, auth->magic)); file_priv->magic = auth->magic; - DRM_UNLOCK(); drm_add_magic(dev, file_priv, auth->magic); + DRM_UNLOCK(); } DRM_DEBUG("%u\n", auth->magic); -- cgit v1.2.3 From 3b07a37a48ca6dc22d538221b59b430dd72c6203 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 13 Aug 2007 10:50:25 -0700 Subject: Add doxygen and fix whitespace for drm_auth.c --- bsd-core/drm_auth.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/bsd-core/drm_auth.c b/bsd-core/drm_auth.c index 14cfc225..9b5f4f74 100644 --- a/bsd-core/drm_auth.c +++ b/bsd-core/drm_auth.c @@ -1,4 +1,4 @@ -/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*- +/* drm_auth.c -- IOCTLs for authentication -*- linux-c -*- * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com */ /*- @@ -38,6 +38,9 @@ static int drm_hash_magic(drm_magic_t magic) return magic & (DRM_HASH_SIZE-1); } +/** + * Returns the file private associated with the given magic number. + */ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic) { drm_magic_entry_t *pt; @@ -54,6 +57,10 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic) return NULL; } +/** + * Inserts the given magic number into the hash table of used magic number + * lists. + */ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) { int hash; @@ -83,6 +90,10 @@ static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) return 0; } +/** + * Removes the given magic number from the hash table of used magic number + * lists. + */ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) { drm_magic_entry_t *prev = NULL; @@ -113,6 +124,14 @@ static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) return EINVAL; } +/** + * Called by the client, this returns a unique magic number to be authorized + * by the master. + * + * The master may use its own knowledge of the client (such as the X + * connection that the magic is passed over) to determine if the magic number + * should be authenticated. + */ int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv) { static drm_magic_t sequence = 0; @@ -125,9 +144,9 @@ int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv) DRM_LOCK(); do { int old = sequence; - + auth->magic = old+1; - + if (!atomic_cmpset_int(&sequence, old, auth->magic)) continue; } while (drm_find_file(dev, auth->magic)); @@ -141,6 +160,9 @@ int drm_getmagic(drm_device_t *dev, void *data, struct drm_file *file_priv) return 0; } +/** + * Marks the client associated with the given magic number as authenticated. + */ int drm_authmagic(drm_device_t *dev, void *data, struct drm_file *file_priv) { drm_auth_t *auth = data; -- cgit v1.2.3 From d6a45ebf0ee47c31f560f3072a4b70c4039e454a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 13 Aug 2007 11:27:46 -0700 Subject: Add a regression test for authentication. --- .gitignore | 1 + tests/Makefile.am | 3 +- tests/auth.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/auth.c diff --git a/.gitignore b/.gitignore index 8447db2b..f63c1532 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ sis.kld stamp-h1 tdfx.kld via.kld +tests/auth tests/dristat tests/drmstat tests/getclient diff --git a/tests/Makefile.am b/tests/Makefile.am index 38a07a35..e846efbe 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -15,7 +15,8 @@ libdrmtest_la_LIBADD = \ LDADD = libdrmtest.la -TESTS = openclose \ +TESTS = auth \ + openclose \ getversion \ getclient \ updatedraw diff --git a/tests/auth.c b/tests/auth.c new file mode 100644 index 00000000..45265d6c --- /dev/null +++ b/tests/auth.c @@ -0,0 +1,137 @@ +/* + * Copyright © 2007 Intel Corporation + * + * 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 AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Eric Anholt + * + */ + +#include +#include "drmtest.h" + +enum auth_event { + SERVER_READY, + CLIENT_MAGIC, + CLIENT_DONE, +}; + +int commfd[2]; + +static void wait_event(int pipe, enum auth_event expected_event) +{ + int ret; + enum auth_event event; + unsigned char in; + + ret = read(commfd[pipe], &in, 1); + if (ret == -1) + err(1, "read error"); + event = in; + + if (event != expected_event) + errx(1, "unexpected event: %d\n", event); +} + +static void +send_event(int pipe, enum auth_event send_event) +{ + int ret; + unsigned char event; + + event = send_event; + ret = write(commfd[pipe], &event, 1); + if (ret == -1) + err(1, "failed to send event %d", event); +} + +static void client() +{ + struct drm_auth auth; + int drmfd, ret; + + /* XXX: Should make sure we open the same DRM as the master */ + drmfd = drm_open_any(); + + wait_event(0, SERVER_READY); + + /* Get a client magic number and pass it to the master for auth. */ + auth.magic = 0; /* Quiet valgrind */ + ret = ioctl(drmfd, DRM_IOCTL_GET_MAGIC, &auth); + if (ret == -1) + err(1, "Couldn't get client magic"); + send_event(0, CLIENT_MAGIC); + ret = write(commfd[0], &auth.magic, sizeof(auth.magic)); + if (ret == -1) + err(1, "Couldn't write auth data"); + + /* Signal that the client is completely done. */ + send_event(0, CLIENT_DONE); +} + +static void server() +{ + int drmfd, ret; + struct drm_auth auth; + + drmfd = drm_open_any_master(); + + auth.magic = 0xd0d0d0d0; + ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth); + if (ret != -1 || errno != EINVAL) + errx(1, "Authenticating bad magic succeeded\n"); + + send_event(1, SERVER_READY); + + wait_event(1, CLIENT_MAGIC); + ret = read(commfd[1], &auth.magic, sizeof(auth.magic)); + if (ret == -1) + err(1, "Failure to read client magic"); + + ret = ioctl(drmfd, DRM_IOCTL_AUTH_MAGIC, &auth); + if (ret == -1) + err(1, "Authenticating bad magic succeeded\n"); + + wait_event(1, CLIENT_DONE); +} + +/** + * Checks DRM authentication mechanisms. + */ +int main(int argc, char **argv) +{ + int ret; + + ret = pipe(commfd); + if (ret == -1) + err(1, "Couldn't create pipe"); + + ret = fork(); + if (ret == -1) + err(1, "failure to fork client"); + if (ret == 0) + client(); + else + server(); + + return 0; +} + -- cgit v1.2.3 From 4340f49bf79a5421886363e08501ad347973b083 Mon Sep 17 00:00:00 2001 From: vehemens Date: Mon, 13 Aug 2007 10:17:47 -0700 Subject: Bug #11951: Fix an errno sign inversion on pre-FreeBSD 5. Also, annotate where signs change, to hopefully remind the reader of these issues in the future. --- bsd-core/drmP.h | 4 +++- bsd-core/drm_dma.c | 1 + bsd-core/drm_fops.c | 1 + bsd-core/drm_irq.c | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 73342d09..8a768f0c 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -377,6 +377,7 @@ do { \ } while (0) #if defined(__FreeBSD__) && __FreeBSD_version > 500000 +/* Returns -errno to shared code */ #define DRM_WAIT_ON( ret, queue, timeout, condition ) \ for ( ret = 0 ; !ret && !(condition) ; ) { \ DRM_UNLOCK(); \ @@ -388,11 +389,12 @@ for ( ret = 0 ; !ret && !(condition) ; ) { \ DRM_LOCK(); \ } #else +/* Returns -errno to shared code */ #define DRM_WAIT_ON( ret, queue, timeout, condition ) \ for ( ret = 0 ; !ret && !(condition) ; ) { \ int s = spldrm(); \ if (!(condition)) \ - ret = tsleep( &(queue), PZERO | PCATCH, \ + ret = -tsleep( &(queue), PZERO | PCATCH, \ "drmwtq", (timeout) ); \ splx(s); \ } diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index fc1e1250..4896cf22 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -121,6 +121,7 @@ int drm_dma(drm_device_t *dev, void *data, struct drm_file *file_priv) { if (dev->driver.dma_ioctl) { + /* shared code returns -errno */ return -dev->driver.dma_ioctl(dev, data, file_priv); } else { DRM_DEBUG("DMA ioctl on driver with no dma handler\n"); diff --git a/bsd-core/drm_fops.c b/bsd-core/drm_fops.c index 870e4d29..2d037ea5 100644 --- a/bsd-core/drm_fops.c +++ b/bsd-core/drm_fops.c @@ -93,6 +93,7 @@ int drm_open_helper(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p, priv->authenticated = DRM_SUSER(p); if (dev->driver.open) { + /* shared code returns -errno */ retcode = -dev->driver.open(dev, priv); if (retcode != 0) { free(priv, M_DRM); diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c index 1ab532fe..9c437e9d 100644 --- a/bsd-core/drm_irq.c +++ b/bsd-core/drm_irq.c @@ -241,6 +241,7 @@ int drm_wait_vblank(drm_device_t *dev, void *data, struct drm_file *file_priv) ret = EINVAL; } else { DRM_LOCK(); + /* shared code returns -errno */ ret = -dev->driver.vblank_wait(dev, &vblwait->request.sequence); DRM_UNLOCK(); -- cgit v1.2.3 From 3ee211f4f7435792752c1dbcd3a60e2e7abfba09 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 13 Aug 2007 16:29:24 -0700 Subject: Bug #11895: Only add the AGP base to map offset if the caller didn't. The i830 and newer intel 2D code adds the AGP base to map offsets already, because it wasn't doing the AGP enable which used to set dev->agp->base. Credit goes to Zhenyu for finding the issue. --- linux-core/drm_bufs.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index f9987ca6..f0b28fa1 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -223,11 +223,17 @@ static int drm_addmap_core(struct drm_device *dev, unsigned int offset, #ifdef __alpha__ map->offset += dev->hose->mem_space->start; #endif - /* Note: dev->agp->base may actually be 0 when the DRM - * is not in control of AGP space. But if user space is - * it should already have added the AGP base itself. + /* In some cases (i810 driver), user space may have already + * added the AGP base itself, because dev->agp->base previously + * only got set during AGP enable. So, only add the base + * address if the map's offset isn't already within the + * aperture. */ - map->offset += dev->agp->base; + if (map->offset < dev->agp->base || + map->offset > dev->agp->base + + dev->agp->agp_info.aper_size * 1024 * 1024) { + map->offset += dev->agp->base; + } map->mtrr = dev->agp->agp_mtrr; /* for getmap */ /* This assumes the DRM is in total control of AGP space. -- cgit v1.2.3 From 02c4e0e757b69cd6ae38b8ab2c078b3f06fea661 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 15 Aug 2007 00:56:24 +1000 Subject: nouveau/nv40: Fix channel scheduling. Ensure NV_PFIFO_DMA_TIMESLICE_TIMEOUT_ENABLE gets set, otherwise channels will appear to "freeze" in some circumstances. --- shared-core/nouveau_drv.h | 1 + shared-core/nouveau_state.c | 2 +- shared-core/nv40_fifo.c | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index e3d0ff4c..b7459b1b 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -455,6 +455,7 @@ extern int nv10_fifo_load_context(struct nouveau_channel *); extern int nv10_fifo_save_context(struct nouveau_channel *); /* nv40_fifo.c */ +extern int nv40_fifo_init(struct drm_device *); extern int nv40_fifo_create_context(struct nouveau_channel *); extern void nv40_fifo_destroy_context(struct nouveau_channel *); extern int nv40_fifo_load_context(struct nouveau_channel *); diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index eac38060..d885f7c6 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -224,7 +224,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.load_context = nv40_graph_load_context; engine->graph.save_context = nv40_graph_save_context; - engine->fifo.init = nouveau_fifo_init; + engine->fifo.init = nv40_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; engine->fifo.create_context = nv40_fifo_create_context; engine->fifo.destroy_context = nv40_fifo_destroy_context; diff --git a/shared-core/nv40_fifo.c b/shared-core/nv40_fifo.c index eb160ee2..ce3f8fdd 100644 --- a/shared-core/nv40_fifo.c +++ b/shared-core/nv40_fifo.c @@ -193,3 +193,16 @@ nv40_fifo_save_context(struct nouveau_channel *chan) return 0; } +int +nv40_fifo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if ((ret = nouveau_fifo_init(dev))) + return ret; + + NV_WRITE(NV04_PFIFO_DMA_TIMESLICE, 0x2101ffff); + return 0; +} + -- cgit v1.2.3