aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-08-06 22:05:31 +1000
committerBen Skeggs <skeggsb@gmail.com>2007-08-06 22:05:31 +1000
commitcf04641bc61c8bc18101713a8d95ef98e6afae7f (patch)
treebd05e99d8404347729654c9bfe2d815eceaf9a3d
parent51f24be578025e3f1eae859288adf5232afc898d (diff)
nouveau: Give DRM its own gpu channel
If your card doesn't have working context switching, it is now broken.
-rw-r--r--linux-core/Makefile.kernel2
-rw-r--r--linux-core/nouveau_sgdma.c2
-rw-r--r--shared-core/nouveau_drv.h26
-rw-r--r--shared-core/nouveau_fifo.c14
-rw-r--r--shared-core/nouveau_state.c9
-rw-r--r--shared-core/nv04_instmem.c1
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;
}
}