From f589be88caf32501a734e531180d5df5d6089ef3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 22 Jul 2012 11:55:54 +1000 Subject: [PATCH] drm/nouveau/pageflip: kick flip handling out of engsw and into fence 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 --- drivers/gpu/drm/nouveau/Makefile | 2 +- .../gpu/drm/nouveau/core/engine/fifo/nvc0.c | 8 +- .../gpu/drm/nouveau/core/engine/fifo/nve0.c | 10 +- drivers/gpu/drm/nouveau/nouveau_display.c | 29 +++- drivers/gpu/drm/nouveau/nouveau_fence.c | 1 + drivers/gpu/drm/nouveau/nouveau_fence.h | 15 ++- drivers/gpu/drm/nouveau/nouveau_software.h | 14 +- drivers/gpu/drm/nouveau/nouveau_state.c | 2 +- drivers/gpu/drm/nouveau/nv04_software.c | 14 +- drivers/gpu/drm/nouveau/nv10_fence.c | 10 +- drivers/gpu/drm/nouveau/nv50_display.c | 4 +- drivers/gpu/drm/nouveau/nv50_fence.c | 125 ++++++++++++++++++ drivers/gpu/drm/nouveau/nv50_software.c | 30 +---- drivers/gpu/drm/nouveau/nv84_fence.c | 20 ++- drivers/gpu/drm/nouveau/nvc0_fence.c | 43 +++++- drivers/gpu/drm/nouveau/nvc0_software.c | 48 +------ drivers/gpu/drm/nouveau/nvd0_display.c | 4 +- 17 files changed, 265 insertions(+), 114 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nv50_fence.c diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 9a86ae3e6807..1855699a1ef1 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -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 \ diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 6535a999015d..b99d976011d1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -27,6 +27,7 @@ #include "nouveau_drv.h" #include #include +#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; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 461fbf62492d..0b356f1b6864 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -27,6 +27,7 @@ #include "nouveau_drv.h" #include #include +#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; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 44835c464957..e0a56b277884 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -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) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 9775458aff48..a1835d710f73 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 690f46536a70..8ee65758f24f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/nouveau_software.h b/drivers/gpu/drm/nouveau/nouveau_software.h index 709e5ac680ec..2105a9eef52c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_software.h +++ b/drivers/gpu/drm/nouveau/nouveau_software.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 1cdabdc79083..5c2836fbf01a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nv04_software.c b/drivers/gpu/drm/nouveau/nv04_software.c index 06c316b386ac..ceeb868c7c29 100644 --- a/drivers/gpu/drm/nouveau/nv04_software.c +++ b/drivers/gpu/drm/nouveau/nv04_software.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 4dac16a9c7f7..dd7f17dd9903 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 9c0bb20b0dc3..83419a2daa0b 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -32,8 +32,8 @@ #include "nouveau_fb.h" #include "nouveau_fbcon.h" #include -#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 index 000000000000..10aa04f26b83 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_fence.c @@ -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 + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_dma.h" +#include +#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; +} diff --git a/drivers/gpu/drm/nouveau/nv50_software.c b/drivers/gpu/drm/nouveau/nv50_software.c index a1c06d44eeb5..7c9dbe862c44 100644 --- a/drivers/gpu/drm/nouveau/nv50_software.c +++ b/drivers/gpu/drm/nouveau/nv50_software.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index a1812cab19dc..5ef87edb878d 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -28,6 +28,7 @@ #include #include #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; diff --git a/drivers/gpu/drm/nouveau/nvc0_fence.c b/drivers/gpu/drm/nouveau/nvc0_fence.c index d53ae32caea3..779c5ff4ed70 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/drivers/gpu/drm/nouveau/nvc0_fence.c @@ -28,6 +28,7 @@ #include #include #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; } diff --git a/drivers/gpu/drm/nouveau/nvc0_software.c b/drivers/gpu/drm/nouveau/nvc0_software.c index 22527682ec58..eaaa5768f4f7 100644 --- a/drivers/gpu/drm/nouveau/nvc0_software.c +++ b/drivers/gpu/drm/nouveau/nvc0_software.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 715359ef9211..2da4927b5e06 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -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);