drm/nouveau/pageflip: kick flip handling out of engsw and into fence
authorBen Skeggs <bskeggs@redhat.com>
Sun, 22 Jul 2012 01:55:54 +0000 (11:55 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 3 Oct 2012 03:12:55 +0000 (13:12 +1000)
This is all very much a policy thing, and hence will not belong in SW
after the rework.

engsw now only handles receiving the event to say "can flip now" and makes
a callback to perform the actual work.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
17 files changed:
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_fence.h
drivers/gpu/drm/nouveau/nouveau_software.h
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv04_software.c
drivers/gpu/drm/nouveau/nv10_fence.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_fence.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nv50_software.c
drivers/gpu/drm/nouveau/nv84_fence.c
drivers/gpu/drm/nouveau/nvc0_fence.c
drivers/gpu/drm/nouveau/nvc0_software.c
drivers/gpu/drm/nouveau/nvd0_display.c

index 9a86ae3e68073f5ff95e9b8ec07de5936b7f368b..1855699a1ef17f039735c9390235daaa4b95c21f 100644 (file)
@@ -132,7 +132,7 @@ nouveau-y += nouveau_drm.o nouveau_compat.o \
             nouveau_mxm.o nouveau_agp.o \
             nouveau_abi16.o \
             nouveau_bios.o \
-             nv04_fence.o nv10_fence.o nv84_fence.o nvc0_fence.o \
+             nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o \
              nv04_software.o nv50_software.o nvc0_software.o \
              nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
              nv04_crtc.o nv04_display.o nv04_cursor.o \
index 6535a999015d2e830e42c9a8cb89a15f0df3e3fa..b99d976011d15396c9b482400125bc80c3e96558 100644 (file)
@@ -27,6 +27,7 @@
 #include "nouveau_drv.h"
 #include <core/mm.h>
 #include <engine/fifo.h>
+#include "nouveau_software.h"
 
 static void nvc0_fifo_isr(struct drm_device *);
 
@@ -323,8 +324,11 @@ nvc0_fifo_page_flip(struct drm_device *dev, u32 chid)
        spin_lock_irqsave(&dev_priv->channels.lock, flags);
        if (likely(chid >= 0 && chid < priv->base.channels)) {
                chan = dev_priv->channels.ptr[chid];
-               if (likely(chan))
-                       ret = nouveau_finish_page_flip(chan, NULL);
+               if (likely(chan)) {
+                       struct nouveau_software_chan *swch =
+                               chan->engctx[NVOBJ_ENGINE_SW];
+                       ret = swch->flip(swch->flip_data);
+               }
        }
        spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
        return ret;
index 461fbf62492dfce891f4e0b4f2f31d3d71d3ae09..0b356f1b68646792d6dccd08c4277b05636d22d2 100644 (file)
@@ -27,6 +27,7 @@
 #include "nouveau_drv.h"
 #include <core/mm.h>
 #include <engine/fifo.h>
+#include "nouveau_software.h"
 
 #define NVE0_FIFO_ENGINE_NUM 32
 
@@ -302,8 +303,11 @@ nve0_fifo_page_flip(struct drm_device *dev, u32 chid)
        spin_lock_irqsave(&dev_priv->channels.lock, flags);
        if (likely(chid >= 0 && chid < priv->base.channels)) {
                chan = dev_priv->channels.ptr[chid];
-               if (likely(chan))
-                       ret = nouveau_finish_page_flip(chan, NULL);
+               if (likely(chan)) {
+                       struct nouveau_software_chan *swch =
+                               chan->engctx[NVOBJ_ENGINE_SW];
+                       ret = swch->flip(swch->flip_data);
+               }
        }
        spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
        return ret;
@@ -315,7 +319,7 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
        u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000));
        u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000));
        u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000));
-       u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f;
+       u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0xfff;
        u32 subc = (addr & 0x00070000);
        u32 mthd = (addr & 0x00003ffc);
        u32 show = stat;
index 44835c4649576009aeb5762d173094555adbadb2..e0a56b27788400209543f8daf051552af3f3c6c5 100644 (file)
@@ -435,7 +435,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
                       struct nouveau_page_flip_state *s,
                       struct nouveau_fence **pfence)
 {
-       struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
+       struct nouveau_fence_chan *fctx = chan->fence;
        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
        struct drm_device *dev = chan->dev;
        unsigned long flags;
@@ -443,7 +443,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
 
        /* Queue it to the pending list */
        spin_lock_irqsave(&dev->event_lock, flags);
-       list_add_tail(&s->head, &swch->flip);
+       list_add_tail(&s->head, &fctx->flip);
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        /* Synchronize with the old framebuffer */
@@ -553,20 +553,20 @@ int
 nouveau_finish_page_flip(struct nouveau_channel *chan,
                         struct nouveau_page_flip_state *ps)
 {
-       struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
+       struct nouveau_fence_chan *fctx = chan->fence;
        struct drm_device *dev = chan->dev;
        struct nouveau_page_flip_state *s;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->event_lock, flags);
 
-       if (list_empty(&swch->flip)) {
+       if (list_empty(&fctx->flip)) {
                NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id);
                spin_unlock_irqrestore(&dev->event_lock, flags);
                return -EINVAL;
        }
 
-       s = list_first_entry(&swch->flip, struct nouveau_page_flip_state, head);
+       s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
        if (s->event) {
                struct drm_pending_vblank_event *e = s->event;
                struct timeval now;
@@ -588,6 +588,25 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
        return 0;
 }
 
+int
+nouveau_flip_complete(void *data)
+{
+       struct nouveau_channel *chan = data;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_page_flip_state state;
+
+       if (!nouveau_finish_page_flip(chan, &state)) {
+               if (dev_priv->card_type < NV_50) {
+                       nv_set_crtc_base(dev, state.crtc, state.offset +
+                                        state.y * state.pitch +
+                                        state.x * state.bpp / 8);
+               }
+       }
+
+       return 0;
+}
+
 int
 nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
                            struct drm_mode_create_dumb *args)
index 9775458aff48409774cff591a4b4e9df6cd274e0..a1835d710f73539184603feb6e56a94881177444 100644 (file)
@@ -54,6 +54,7 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
 void
 nouveau_fence_context_new(struct nouveau_fence_chan *fctx)
 {
+       INIT_LIST_HEAD(&fctx->flip);
        INIT_LIST_HEAD(&fctx->pending);
        spin_lock_init(&fctx->lock);
 }
index 690f46536a707dfe977eb1100f200f1add175111..8ee65758f24fdcce995d4144af1f8ab839947887 100644 (file)
@@ -27,6 +27,8 @@ void nouveau_fence_update(struct nouveau_channel *);
 
 struct nouveau_fence_chan {
        struct list_head pending;
+       struct list_head flip;
+
        spinlock_t lock;
        u32 sequence;
 };
@@ -49,8 +51,19 @@ void nouveau_fence_context_del(struct nouveau_fence_chan *);
 int nv04_fence_create(struct drm_device *dev);
 int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32);
 
-int nv10_fence_create(struct drm_device *dev);
+int  nv10_fence_emit(struct nouveau_fence *);
+int  nv17_fence_sync(struct nouveau_fence *, struct nouveau_channel *,
+                    struct nouveau_channel *);
+u32  nv10_fence_read(struct nouveau_channel *);
+void nv10_fence_context_del(struct nouveau_channel *);
+void nv10_fence_destroy(struct drm_device *);
+int  nv10_fence_create(struct drm_device *dev);
+
+int nv50_fence_create(struct drm_device *dev);
 int nv84_fence_create(struct drm_device *dev);
 int nvc0_fence_create(struct drm_device *dev);
+u64 nvc0_fence_crtc(struct nouveau_channel *, int crtc);
+
+int nouveau_flip_complete(void *chan);
 
 #endif
index 709e5ac680ec8356ea5b5c4b4ba61bf5ae9c4480..2105a9eef52c28857b3895035285ebe556c186f1 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __NOUVEAU_SOFTWARE_H__
 #define __NOUVEAU_SOFTWARE_H__
 
+#include "nouveau_fence.h"
+
 struct nouveau_software_priv {
        struct nouveau_exec_engine base;
        struct list_head vblank;
@@ -8,7 +10,9 @@ struct nouveau_software_priv {
 };
 
 struct nouveau_software_chan {
-       struct list_head flip;
+       int (*flip)(void *data);
+       void *flip_data;
+
        struct {
                struct list_head list;
                u32 channel;
@@ -20,10 +24,11 @@ struct nouveau_software_chan {
 };
 
 static inline void
-nouveau_software_context_new(struct nouveau_software_chan *pch)
+nouveau_software_context_new(struct nouveau_channel *chan,
+                            struct nouveau_software_chan *pch)
 {
-       INIT_LIST_HEAD(&pch->flip);
-       INIT_LIST_HEAD(&pch->vblank.list);
+       pch->flip = nouveau_flip_complete;
+       pch->flip_data = chan;
 }
 
 static inline void
@@ -51,6 +56,5 @@ nouveau_software_class(struct drm_device *dev)
 int nv04_software_create(struct drm_device *);
 int nv50_software_create(struct drm_device *);
 int nvc0_software_create(struct drm_device *);
-u64 nvc0_software_crtc(struct nouveau_channel *, int crtc);
 
 #endif
index 1cdabdc790835a94755fb8e8cf102aa1d2ae370a..5c2836fbf01a4bc63a097c0457d383b786cc8a6f 100644 (file)
@@ -394,7 +394,7 @@ nouveau_card_init(struct drm_device *dev)
                case NV_40:
                case NV_50:
                        if (dev_priv->chipset < 0x84)
-                               nv10_fence_create(dev);
+                               nv50_fence_create(dev);
                        else
                                nv84_fence_create(dev);
                        break;
index 06c316b386ac8402232ca23e389d21f2793beeb9..ceeb868c7c29d6d3d2c839b81d8b7a732cb22e79 100644 (file)
@@ -41,16 +41,8 @@ struct nv04_software_chan {
 static int
 mthd_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
 {
-
-       struct nouveau_page_flip_state state;
-
-       if (!nouveau_finish_page_flip(chan, &state)) {
-               nv_set_crtc_base(chan->dev, state.crtc, state.offset +
-                                state.y * state.pitch +
-                                state.x * state.bpp / 8);
-       }
-
-       return 0;
+       struct nv04_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
+       return pch->base.flip(pch->base.flip_data);
 }
 
 static int
@@ -62,7 +54,7 @@ nv04_software_context_new(struct nouveau_channel *chan, int engine)
        if (!pch)
                return -ENOMEM;
 
-       nouveau_software_context_new(&pch->base);
+       nouveau_software_context_new(chan, &pch->base);
        chan->engctx[engine] = pch;
        return 0;
 }
index 4dac16a9c7f7c0ff7c6db2d9711484403d03a597..dd7f17dd9903644666591c4e462196c758ed7f07 100644 (file)
@@ -39,7 +39,7 @@ struct nv10_fence_priv {
        u32 sequence;
 };
 
-static int
+int
 nv10_fence_emit(struct nouveau_fence *fence)
 {
        struct nouveau_channel *chan = fence->channel;
@@ -60,7 +60,7 @@ nv10_fence_sync(struct nouveau_fence *fence,
        return -ENODEV;
 }
 
-static int
+int
 nv17_fence_sync(struct nouveau_fence *fence,
                struct nouveau_channel *prev, struct nouveau_channel *chan)
 {
@@ -100,13 +100,13 @@ nv17_fence_sync(struct nouveau_fence *fence,
        return 0;
 }
 
-static u32
+u32
 nv10_fence_read(struct nouveau_channel *chan)
 {
        return nvchan_rd32(chan, 0x0048);
 }
 
-static void
+void
 nv10_fence_context_del(struct nouveau_channel *chan)
 {
        struct nv10_fence_chan *fctx = chan->fence;
@@ -148,7 +148,7 @@ nv10_fence_context_new(struct nouveau_channel *chan)
        return ret;
 }
 
-static void
+void
 nv10_fence_destroy(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
index 9c0bb20b0dc3a0733bd70c870293cb088c6014e6..83419a2daa0bb6a306046c9c6e6b7d49f19dcd45 100644 (file)
@@ -32,8 +32,8 @@
 #include "nouveau_fb.h"
 #include "nouveau_fbcon.h"
 #include <core/ramht.h>
-#include "nouveau_software.h"
 #include "drm_crtc_helper.h"
+#include "nouveau_fence.h"
 
 static void nv50_display_isr(struct drm_device *);
 static void nv50_display_bh(unsigned long);
@@ -446,7 +446,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                        else
                                OUT_RING  (chan, chan->vram_handle);
                } else {
-                       u64 offset = nvc0_software_crtc(chan, nv_crtc->index);
+                       u64 offset = nvc0_fence_crtc(chan, nv_crtc->index);
                        offset += dispc->sem.offset;
                        BEGIN_NVC0(chan, 0, 0x0010, 4);
                        OUT_RING  (chan, upper_32_bits(offset));
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c
new file mode 100644 (file)
index 0000000..10aa04f
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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 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 HOLDER(S) OR AUTHOR(S) 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: Ben Skeggs <bskeggs@redhat.com>
+ */
+
+#include "drmP.h"
+#include "nouveau_drv.h"
+#include "nouveau_dma.h"
+#include <core/ramht.h>
+#include "nouveau_fence.h"
+#include "nv50_display.h"
+
+struct nv50_fence_chan {
+       struct nouveau_fence_chan base;
+};
+
+struct nv50_fence_priv {
+       struct nouveau_fence_priv base;
+       struct nouveau_bo *bo;
+       spinlock_t lock;
+       u32 sequence;
+};
+
+static int
+nv50_fence_context_new(struct nouveau_channel *chan)
+{
+       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+       struct nv50_fence_priv *priv = dev_priv->fence.func;
+       struct nv50_fence_chan *fctx;
+       struct ttm_mem_reg *mem = &priv->bo->bo.mem;
+       struct nouveau_gpuobj *obj;
+       int ret = 0, i;
+
+       fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
+       if (!fctx)
+               return -ENOMEM;
+
+       nouveau_fence_context_new(&fctx->base);
+
+       ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY,
+                                    mem->start * PAGE_SIZE, mem->size,
+                                    NV_MEM_ACCESS_RW,
+                                    NV_MEM_TARGET_VRAM, &obj);
+       if (!ret) {
+               ret = nouveau_ramht_insert(chan, NvSema, obj);
+               nouveau_gpuobj_ref(NULL, &obj);
+       }
+
+       /* dma objects for display sync channel semaphore blocks */
+       for (i = 0; i < chan->dev->mode_config.num_crtc; i++) {
+               struct nv50_display *pdisp = nv50_display(chan->dev);
+               struct nv50_display_crtc *dispc = &pdisp->crtc[i];
+               struct nouveau_gpuobj *obj = NULL;
+
+               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                            dispc->sem.bo->bo.offset, 0x1000,
+                                            NV_MEM_ACCESS_RW,
+                                            NV_MEM_TARGET_VRAM, &obj);
+               if (ret)
+                       break;
+
+               ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj);
+               nouveau_gpuobj_ref(NULL, &obj);
+       }
+
+       if (ret)
+               nv10_fence_context_del(chan);
+       return ret;
+}
+
+int
+nv50_fence_create(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nv50_fence_priv *priv;
+       int ret = 0;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->base.dtor = nv10_fence_destroy;
+       priv->base.context_new = nv50_fence_context_new;
+       priv->base.context_del = nv10_fence_context_del;
+       priv->base.emit = nv10_fence_emit;
+       priv->base.read = nv10_fence_read;
+       priv->base.sync = nv17_fence_sync;
+       dev_priv->fence.func = &priv->base;
+       spin_lock_init(&priv->lock);
+
+       ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
+                            0, 0x0000, NULL, &priv->bo);
+       if (!ret) {
+               ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
+               if (!ret)
+                       ret = nouveau_bo_map(priv->bo);
+               if (ret)
+                       nouveau_bo_ref(NULL, &priv->bo);
+       }
+
+       if (ret == 0)
+               nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
+       else
+               nv10_fence_destroy(dev);
+       return ret;
+}
index a1c06d44eeb53fdd4dad45d287d8ebf2df39367f..7c9dbe862c44a6b41b79901315908667b0546c0a 100644 (file)
@@ -88,45 +88,23 @@ mthd_vblsem_release(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
 static int
 mthd_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
 {
-       nouveau_finish_page_flip(chan, NULL);
-       return 0;
+       struct nv50_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
+       return pch->base.flip(pch->base.flip_data);
 }
 
 static int
 nv50_software_context_new(struct nouveau_channel *chan, int engine)
 {
-       struct nv50_software_priv *psw = nv_engine(chan->dev, NVOBJ_ENGINE_SW);
-       struct nv50_display *pdisp = nv50_display(chan->dev);
        struct nv50_software_chan *pch;
-       int ret = 0, i;
 
        pch = kzalloc(sizeof(*pch), GFP_KERNEL);
        if (!pch)
                return -ENOMEM;
 
-       nouveau_software_context_new(&pch->base);
+       nouveau_software_context_new(chan, &pch->base);
        pch->base.vblank.channel = chan->ramin->addr >> 12;
        chan->engctx[engine] = pch;
-
-       /* dma objects for display sync channel semaphore blocks */
-       for (i = 0; i < chan->dev->mode_config.num_crtc; i++) {
-               struct nv50_display_crtc *dispc = &pdisp->crtc[i];
-               struct nouveau_gpuobj *obj = NULL;
-
-               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-                                            dispc->sem.bo->bo.offset, 0x1000,
-                                            NV_MEM_ACCESS_RW,
-                                            NV_MEM_TARGET_VRAM, &obj);
-               if (ret)
-                       break;
-
-               ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj);
-               nouveau_gpuobj_ref(NULL, &obj);
-       }
-
-       if (ret)
-               psw->base.base.context_del(chan, engine);
-       return ret;
+       return 0;
 }
 
 static void
index a1812cab19dc1b7b89f588124c880cf4f0c5a532..5ef87edb878d87a937eacdffb23a51b13e81c14e 100644 (file)
@@ -28,6 +28,7 @@
 #include <engine/fifo.h>
 #include <core/ramht.h>
 #include "nouveau_fence.h"
+#include "nv50_display.h"
 
 struct nv84_fence_chan {
        struct nouveau_fence_chan base;
@@ -99,7 +100,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
        struct nv84_fence_priv *priv = dev_priv->fence.func;
        struct nv84_fence_chan *fctx;
        struct nouveau_gpuobj *obj;
-       int ret;
+       int ret, i;
 
        fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
        if (!fctx)
@@ -117,6 +118,23 @@ nv84_fence_context_new(struct nouveau_channel *chan)
                nv_wo32(priv->mem, chan->id * 16, 0x00000000);
        }
 
+       /* dma objects for display sync channel semaphore blocks */
+       for (i = 0; i < chan->dev->mode_config.num_crtc; i++) {
+               struct nv50_display *pdisp = nv50_display(chan->dev);
+               struct nv50_display_crtc *dispc = &pdisp->crtc[i];
+               struct nouveau_gpuobj *obj = NULL;
+
+               ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
+                                            dispc->sem.bo->bo.offset, 0x1000,
+                                            NV_MEM_ACCESS_RW,
+                                            NV_MEM_TARGET_VRAM, &obj);
+               if (ret)
+                       break;
+
+               ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, obj);
+               nouveau_gpuobj_ref(NULL, &obj);
+       }
+
        if (ret)
                nv84_fence_context_del(chan);
        return ret;
index d53ae32caea3570a6e843305015ceda5e7a1e0de..779c5ff4ed7014502c47357f09df74f903c91514 100644 (file)
@@ -28,6 +28,7 @@
 #include <engine/fifo.h>
 #include <core/ramht.h>
 #include "nouveau_fence.h"
+#include "nv50_display.h"
 
 struct nvc0_fence_priv {
        struct nouveau_fence_priv base;
@@ -38,8 +39,16 @@ struct nvc0_fence_priv {
 struct nvc0_fence_chan {
        struct nouveau_fence_chan base;
        struct nouveau_vma vma;
+       struct nouveau_vma dispc_vma[4];
 };
 
+u64
+nvc0_fence_crtc(struct nouveau_channel *chan, int crtc)
+{
+       struct nvc0_fence_chan *fctx = chan->fence;
+       return fctx->dispc_vma[crtc].offset;
+}
+
 static int
 nvc0_fence_emit(struct nouveau_fence *fence)
 {
@@ -94,9 +103,25 @@ nvc0_fence_read(struct nouveau_channel *chan)
 static void
 nvc0_fence_context_del(struct nouveau_channel *chan)
 {
-       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvc0_fence_priv *priv = dev_priv->fence.func;
        struct nvc0_fence_chan *fctx = chan->fence;
+       int i;
+
+       if (dev_priv->card_type >= NV_D0) {
+               for (i = 0; i < dev->mode_config.num_crtc; i++) {
+                       struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i);
+                       nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
+               }
+       } else
+       if (dev_priv->card_type >= NV_50) {
+               struct nv50_display *disp = nv50_display(dev);
+               for (i = 0; i < dev->mode_config.num_crtc; i++) {
+                       struct nv50_display_crtc *dispc = &disp->crtc[i];
+                       nouveau_bo_vma_del(dispc->sem.bo, &fctx->dispc_vma[i]);
+               }
+       }
 
        nouveau_bo_vma_del(priv->bo, &fctx->vma);
        nouveau_fence_context_del(&fctx->base);
@@ -107,10 +132,11 @@ nvc0_fence_context_del(struct nouveau_channel *chan)
 static int
 nvc0_fence_context_new(struct nouveau_channel *chan)
 {
-       struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+       struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvc0_fence_priv *priv = dev_priv->fence.func;
        struct nvc0_fence_chan *fctx;
-       int ret;
+       int ret, i;
 
        fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
        if (!fctx)
@@ -122,6 +148,17 @@ nvc0_fence_context_new(struct nouveau_channel *chan)
        if (ret)
                nvc0_fence_context_del(chan);
 
+       /* map display semaphore buffers into channel's vm */
+       for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
+               struct nouveau_bo *bo;
+               if (dev_priv->card_type >= NV_D0)
+                       bo = nvd0_display_crtc_sema(dev, i);
+               else
+                       bo = nv50_display(dev)->crtc[i].sem.bo;
+
+               ret = nouveau_bo_vma_add(bo, chan->vm, &fctx->dispc_vma[i]);
+       }
+
        nouveau_bo_wr32(priv->bo, chan->id * 16/4, 0x00000000);
        return ret;
 }
index 22527682ec58c16ab2aab9ca467d8cc97168fa36..eaaa5768f4f777c00002bc4d7c0d7ef875505ed6 100644 (file)
@@ -36,70 +36,26 @@ struct nvc0_software_priv {
 
 struct nvc0_software_chan {
        struct nouveau_software_chan base;
-       struct nouveau_vma dispc_vma[4];
 };
 
-u64
-nvc0_software_crtc(struct nouveau_channel *chan, int crtc)
-{
-       struct nvc0_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
-       return pch->dispc_vma[crtc].offset;
-}
-
 static int
 nvc0_software_context_new(struct nouveau_channel *chan, int engine)
 {
-       struct drm_device *dev = chan->dev;
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct nvc0_software_priv *psw = nv_engine(dev, NVOBJ_ENGINE_SW);
        struct nvc0_software_chan *pch;
-       int ret = 0, i;
 
        pch = kzalloc(sizeof(*pch), GFP_KERNEL);
        if (!pch)
                return -ENOMEM;
 
-       nouveau_software_context_new(&pch->base);
+       nouveau_software_context_new(chan, &pch->base);
        chan->engctx[engine] = pch;
-
-       /* map display semaphore buffers into channel's vm */
-       for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
-               struct nouveau_bo *bo;
-               if (dev_priv->card_type >= NV_D0)
-                       bo = nvd0_display_crtc_sema(dev, i);
-               else
-                       bo = nv50_display(dev)->crtc[i].sem.bo;
-
-               ret = nouveau_bo_vma_add(bo, chan->vm, &pch->dispc_vma[i]);
-       }
-
-       if (ret)
-               psw->base.base.context_del(chan, engine);
-       return ret;
+       return 0;
 }
 
 static void
 nvc0_software_context_del(struct nouveau_channel *chan, int engine)
 {
-       struct drm_device *dev = chan->dev;
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nvc0_software_chan *pch = chan->engctx[engine];
-       int i;
-
-       if (dev_priv->card_type >= NV_D0) {
-               for (i = 0; i < dev->mode_config.num_crtc; i++) {
-                       struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i);
-                       nouveau_bo_vma_del(bo, &pch->dispc_vma[i]);
-               }
-       } else
-       if (dev_priv->card_type >= NV_50) {
-               struct nv50_display *disp = nv50_display(dev);
-               for (i = 0; i < dev->mode_config.num_crtc; i++) {
-                       struct nv50_display_crtc *dispc = &disp->crtc[i];
-                       nouveau_bo_vma_del(dispc->sem.bo, &pch->dispc_vma[i]);
-               }
-       }
-
        chan->engctx[engine] = NULL;
        kfree(pch);
 }
index 715359ef9211da18ea22d4136b5b3595dfa0511a..2da4927b5e064ed1b61c236767cbb592154ddb3a 100644 (file)
@@ -33,7 +33,7 @@
 #include "nouveau_crtc.h"
 #include "nouveau_dma.h"
 #include "nouveau_fb.h"
-#include "nouveau_software.h"
+#include "nouveau_fence.h"
 #include "nv50_display.h"
 
 #define EVO_DMA_NR 9
@@ -300,7 +300,7 @@ nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                        return ret;
 
 
-               offset  = nvc0_software_crtc(chan, nv_crtc->index);
+               offset  = nvc0_fence_crtc(chan, nv_crtc->index);
                offset += evo->sem.offset;
 
                BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);