From 2730723bbc4a8b289fa536fc3555e15947da09c1 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Tue, 21 Sep 2010 18:57:11 +0200 Subject: [PATCH] drm/nouveau: Minor refactoring/cleanup of the fence code. Mainly to make room for inter-channel sync. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 15 -------- drivers/gpu/drm/nouveau/nouveau_channel.c | 4 +- drivers/gpu/drm/nouveau/nouveau_dma.c | 17 --------- drivers/gpu/drm/nouveau/nouveau_drv.h | 11 +++++- drivers/gpu/drm/nouveau/nouveau_fence.c | 63 ++++++++++++++++++++++--------- drivers/gpu/drm/nouveau/nouveau_gem.c | 4 +- 6 files changed, 59 insertions(+), 55 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 2148e2d73de3..03d842a06b04 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -36,21 +36,6 @@ #include #include -int -nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan) -{ - struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; - int ret; - - if (!prev_fence || nouveau_fence_channel(prev_fence) == chan) - return 0; - - spin_lock(&nvbo->bo.lock); - ret = ttm_bo_wait(&nvbo->bo, false, false, false); - spin_unlock(&nvbo->bo.lock); - return ret; -} - static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index e01396747f6f..5eb4c966273f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -223,7 +223,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, ret = nouveau_dma_init(chan); if (!ret) - ret = nouveau_fence_init(chan); + ret = nouveau_fence_channel_init(chan); if (ret) { nouveau_channel_free(chan); return ret; @@ -270,7 +270,7 @@ nouveau_channel_free(struct nouveau_channel *chan) * above attempts at idling were OK, but if we failed this'll tell TTM * we're done with the buffers. */ - nouveau_fence_fini(chan); + nouveau_fence_channel_fini(chan); /* This will prevent pfifo from switching channels. */ pfifo->reassign(dev, false); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index eb24e2b05193..82581e600dcd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -73,16 +73,6 @@ nouveau_dma_init(struct nouveau_channel *chan) if (ret) return ret; - /* Create an NV_SW object for various sync purposes */ - ret = nouveau_gpuobj_sw_new(chan, NV_SW, &obj); - if (ret) - return ret; - - ret = nouveau_ramht_insert(chan, NvSw, obj); - nouveau_gpuobj_ref(NULL, &obj); - if (ret) - return ret; - /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy); if (ret) @@ -110,13 +100,6 @@ nouveau_dma_init(struct nouveau_channel *chan) BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); OUT_RING(chan, NvNotify0); - /* Initialise NV_SW */ - ret = RING_SPACE(chan, 2); - if (ret) - return ret; - BEGIN_RING(chan, NvSubSw, 0, 1); - OUT_RING(chan, NvSw); - /* Sit back and pray the channel works.. */ FIRE_RING(chan); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index b209a6208757..9a9066f1fbcc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -706,6 +706,12 @@ struct drm_nouveau_private { }; static inline struct drm_nouveau_private * +nouveau_private(struct drm_device *dev) +{ + return dev->dev_private; +} + +static inline struct drm_nouveau_private * nouveau_bdev(struct ttm_bo_device *bd) { return container_of(bd, struct drm_nouveau_private, ttm.bdev); @@ -1231,8 +1237,8 @@ extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); /* nouveau_fence.c */ struct nouveau_fence; -extern int nouveau_fence_init(struct nouveau_channel *); -extern void nouveau_fence_fini(struct nouveau_channel *); +extern int nouveau_fence_channel_init(struct nouveau_channel *); +extern void nouveau_fence_channel_fini(struct nouveau_channel *); extern void nouveau_fence_update(struct nouveau_channel *); extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **, bool emit); @@ -1240,6 +1246,7 @@ extern int nouveau_fence_emit(struct nouveau_fence *); struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); extern bool nouveau_fence_signalled(void *obj, void *arg); extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); +extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); extern int nouveau_fence_flush(void *obj, void *arg); extern void nouveau_fence_unref(void **obj); extern void *nouveau_fence_ref(void *obj); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 87ac21ec23d2..62f13189698a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -30,7 +30,7 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" -#define USE_REFCNT (dev_priv->card_type >= NV_10) +#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) struct nouveau_fence { struct nouveau_channel *channel; @@ -59,14 +59,13 @@ nouveau_fence_del(struct kref *ref) void nouveau_fence_update(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct list_head *entry, *tmp; - struct nouveau_fence *fence; + struct drm_device *dev = chan->dev; + struct nouveau_fence *tmp, *fence; uint32_t sequence; spin_lock(&chan->fence.lock); - if (USE_REFCNT) + if (USE_REFCNT(dev)) sequence = nvchan_rd32(chan, 0x48); else sequence = atomic_read(&chan->fence.last_sequence_irq); @@ -75,9 +74,7 @@ nouveau_fence_update(struct nouveau_channel *chan) goto out; chan->fence.sequence_ack = sequence; - list_for_each_safe(entry, tmp, &chan->fence.pending) { - fence = list_entry(entry, struct nouveau_fence, entry); - + list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { sequence = fence->sequence; fence->signalled = true; list_del(&fence->entry); @@ -121,8 +118,8 @@ nouveau_fence_channel(struct nouveau_fence *fence) int nouveau_fence_emit(struct nouveau_fence *fence) { - struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; struct nouveau_channel *chan = fence->channel; + struct drm_device *dev = chan->dev; int ret; ret = RING_SPACE(chan, 2); @@ -143,7 +140,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) list_add_tail(&fence->entry, &chan->fence.pending); spin_unlock(&chan->fence.lock); - BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); + BEGIN_RING(chan, NvSubSw, USE_REFCNT(dev) ? 0x0050 : 0x0150, 1); OUT_RING(chan, fence->sequence); FIRE_RING(chan); @@ -214,29 +211,61 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) } int +nouveau_fence_sync(struct nouveau_fence *fence, + struct nouveau_channel *wchan) +{ + struct nouveau_channel *chan = nouveau_fence_channel(fence); + + if (likely(!fence || chan == wchan || + nouveau_fence_signalled(fence, NULL))) + return 0; + + return nouveau_fence_wait(fence, NULL, false, false); +} + +int nouveau_fence_flush(void *sync_obj, void *sync_arg) { return 0; } int -nouveau_fence_init(struct nouveau_channel *chan) +nouveau_fence_channel_init(struct nouveau_channel *chan) { + struct nouveau_gpuobj *obj = NULL; + int ret; + + /* Create an NV_SW object for various sync purposes */ + ret = nouveau_gpuobj_sw_new(chan, NV_SW, &obj); + if (ret) + return ret; + + ret = nouveau_ramht_insert(chan, NvSw, obj); + nouveau_gpuobj_ref(NULL, &obj); + if (ret) + return ret; + + ret = RING_SPACE(chan, 2); + if (ret) + return ret; + BEGIN_RING(chan, NvSubSw, 0, 1); + OUT_RING(chan, NvSw); + + FIRE_RING(chan); + INIT_LIST_HEAD(&chan->fence.pending); spin_lock_init(&chan->fence.lock); atomic_set(&chan->fence.last_sequence_irq, 0); + return 0; } void -nouveau_fence_fini(struct nouveau_channel *chan) +nouveau_fence_channel_fini(struct nouveau_channel *chan) { - struct list_head *entry, *tmp; - struct nouveau_fence *fence; - - list_for_each_safe(entry, tmp, &chan->fence.pending) { - fence = list_entry(entry, struct nouveau_fence, entry); + struct nouveau_fence *tmp, *fence; + list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { fence->signalled = true; list_del(&fence->entry); kref_put(&fence->refcount, nouveau_fence_del); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index ead7b8fc53fc..1e630987543e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -364,7 +364,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, list_for_each_entry(nvbo, list, entry) { struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; - ret = nouveau_bo_sync_gpu(nvbo, chan); + ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); if (unlikely(ret)) { NV_ERROR(dev, "fail pre-validate sync\n"); return ret; @@ -387,7 +387,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, return ret; } - ret = nouveau_bo_sync_gpu(nvbo, chan); + ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); if (unlikely(ret)) { NV_ERROR(dev, "fail post-validate sync\n"); return ret; -- 2.11.0