nouveau: Give DRM its own gpu channel
authorBen Skeggs <skeggsb@gmail.com>
Mon, 6 Aug 2007 12:05:31 +0000 (22:05 +1000)
committerBen Skeggs <skeggsb@gmail.com>
Mon, 6 Aug 2007 12:05:31 +0000 (22:05 +1000)
If your card doesn't have working context switching, it is now broken.

linux-core/Makefile.kernel
linux-core/nouveau_sgdma.c
shared-core/nouveau_drv.h
shared-core/nouveau_fifo.c
shared-core/nouveau_state.c
shared-core/nv04_instmem.c

index 5aa589c..3d00cbe 100644 (file)
@@ -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 \
index 6393a46..df970d1 100644 (file)
@@ -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);
index 0b173b7..10f9149 100644 (file)
@@ -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 *);
index 152b669..823801f 100644 (file)
@@ -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 */
index 4fb5329..9dab34c 100644 (file)
@@ -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);
index 36aa620..5e0f6f4 100644 (file)
@@ -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;
        }       
 }