Commit d375e7d5 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau/fence: minor api changes for an upcoming rework

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 875ac34a
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_mm.h" #include "nouveau_mm.h"
#include "nouveau_vm.h" #include "nouveau_vm.h"
#include "nouveau_fence.h"
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -478,7 +479,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, ...@@ -478,7 +479,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
struct nouveau_fence *fence = NULL; struct nouveau_fence *fence = NULL;
int ret; int ret;
ret = nouveau_fence_new(chan, &fence, true); ret = nouveau_fence_new(chan, &fence);
if (ret) if (ret)
return ret; return ret;
...@@ -1196,7 +1197,7 @@ nouveau_bo_fence_ref(void *sync_obj) ...@@ -1196,7 +1197,7 @@ nouveau_bo_fence_ref(void *sync_obj)
static bool static bool
nouveau_bo_fence_signalled(void *sync_obj, void *sync_arg) nouveau_bo_fence_signalled(void *sync_obj, void *sync_arg)
{ {
return nouveau_fence_signalled(sync_obj); return nouveau_fence_done(sync_obj);
} }
static int static int
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_ramht.h" #include "nouveau_ramht.h"
#include "nouveau_fence.h"
#include "nouveau_software.h" #include "nouveau_software.h"
static int static int
...@@ -369,7 +370,7 @@ nouveau_channel_idle(struct nouveau_channel *chan) ...@@ -369,7 +370,7 @@ nouveau_channel_idle(struct nouveau_channel *chan)
nouveau_fence_update(chan); nouveau_fence_update(chan);
if (chan->fence.sequence != chan->fence.sequence_ack) { if (chan->fence.sequence != chan->fence.sequence_ack) {
ret = nouveau_fence_new(chan, &fence, true); ret = nouveau_fence_new(chan, &fence);
if (!ret) { if (!ret) {
ret = nouveau_fence_wait(fence, false, false); ret = nouveau_fence_wait(fence, false, false);
nouveau_fence_unref(&fence); nouveau_fence_unref(&fence);
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "nouveau_connector.h" #include "nouveau_connector.h"
#include "nouveau_software.h" #include "nouveau_software.h"
#include "nouveau_gpio.h" #include "nouveau_gpio.h"
#include "nouveau_fence.h"
#include "nv50_display.h" #include "nv50_display.h"
static void static void
...@@ -465,7 +466,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, ...@@ -465,7 +466,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
} }
FIRE_RING (chan); FIRE_RING (chan);
ret = nouveau_fence_new(chan, pfence, true); ret = nouveau_fence_new(chan, pfence);
if (ret) if (ret)
goto fail; goto fail;
...@@ -486,7 +487,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -486,7 +487,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
struct nouveau_page_flip_state *s; struct nouveau_page_flip_state *s;
struct nouveau_channel *chan; struct nouveau_channel *chan = NULL;
struct nouveau_fence *fence; struct nouveau_fence *fence;
int ret; int ret;
...@@ -509,7 +510,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -509,7 +510,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
new_bo->bo.offset }; new_bo->bo.offset };
/* Choose the channel the flip will be handled in */ /* Choose the channel the flip will be handled in */
chan = nouveau_fence_channel(new_bo->bo.sync_obj); fence = new_bo->bo.sync_obj;
if (fence)
chan = nouveau_channel_get_unlocked(fence->channel);
if (!chan) if (!chan)
chan = nouveau_channel_get_unlocked(dev_priv->channel); chan = nouveau_channel_get_unlocked(dev_priv->channel);
mutex_lock(&chan->mutex); mutex_lock(&chan->mutex);
......
...@@ -1444,26 +1444,12 @@ extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *, ...@@ -1444,26 +1444,12 @@ extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *,
extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *); extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *);
/* nouveau_fence.c */ /* nouveau_fence.c */
struct nouveau_fence; int nouveau_fence_init(struct drm_device *);
extern int nouveau_fence_init(struct drm_device *); void nouveau_fence_fini(struct drm_device *);
extern void nouveau_fence_fini(struct drm_device *); int nouveau_fence_channel_init(struct nouveau_channel *);
extern int nouveau_fence_channel_init(struct nouveau_channel *); void nouveau_fence_channel_fini(struct nouveau_channel *);
extern void nouveau_fence_channel_fini(struct nouveau_channel *); void nouveau_fence_work(struct nouveau_fence *fence,
extern void nouveau_fence_update(struct nouveau_channel *); void (*work)(void *priv, bool signalled), void *priv);
extern int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **,
bool emit);
extern int nouveau_fence_emit(struct nouveau_fence *);
extern void nouveau_fence_work(struct nouveau_fence *fence,
void (*work)(void *priv, bool signalled),
void *priv);
struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *);
extern bool nouveau_fence_signalled(struct nouveau_fence *);
extern int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
extern void nouveau_fence_unref(struct nouveau_fence **);
extern struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *);
extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *);
/* nouveau_gem.c */ /* nouveau_gem.c */
extern int nouveau_gem_new(struct drm_device *, int size, int align, extern int nouveau_gem_new(struct drm_device *, int size, int align,
uint32_t domain, uint32_t tile_mode, uint32_t domain, uint32_t tile_mode,
......
...@@ -32,47 +32,13 @@ ...@@ -32,47 +32,13 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_ramht.h" #include "nouveau_ramht.h"
#include "nouveau_fence.h"
#include "nouveau_software.h" #include "nouveau_software.h"
#include "nouveau_dma.h" #include "nouveau_dma.h"
#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10) #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17) #define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17)
struct nouveau_fence {
struct nouveau_channel *channel;
struct kref refcount;
struct list_head entry;
uint32_t sequence;
bool signalled;
unsigned long timeout;
void (*work)(void *priv, bool signalled);
void *priv;
};
struct nouveau_semaphore {
struct kref ref;
struct drm_device *dev;
struct drm_mm_node *mem;
};
static inline struct nouveau_fence *
nouveau_fence(void *sync_obj)
{
return (struct nouveau_fence *)sync_obj;
}
static void
nouveau_fence_del(struct kref *ref)
{
struct nouveau_fence *fence =
container_of(ref, struct nouveau_fence, refcount);
nouveau_channel_ref(NULL, &fence->channel);
kfree(fence);
}
void void
nouveau_fence_update(struct nouveau_channel *chan) nouveau_fence_update(struct nouveau_channel *chan)
{ {
...@@ -94,16 +60,16 @@ nouveau_fence_update(struct nouveau_channel *chan) ...@@ -94,16 +60,16 @@ nouveau_fence_update(struct nouveau_channel *chan)
chan->fence.sequence_ack = sequence; chan->fence.sequence_ack = sequence;
} }
list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { list_for_each_entry_safe(fence, tmp, &chan->fence.pending, head) {
if (fence->sequence > chan->fence.sequence_ack) if (fence->sequence > chan->fence.sequence_ack)
break; break;
fence->signalled = true; fence->channel = NULL;
list_del(&fence->entry); list_del(&fence->head);
if (fence->work) if (fence->work)
fence->work(fence->priv, true); fence->work(fence->priv, true);
kref_put(&fence->refcount, nouveau_fence_del); nouveau_fence_unref(&fence);
} }
out: out:
...@@ -111,37 +77,8 @@ nouveau_fence_update(struct nouveau_channel *chan) ...@@ -111,37 +77,8 @@ nouveau_fence_update(struct nouveau_channel *chan)
} }
int int
nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence, nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
bool emit)
{
struct nouveau_fence *fence;
int ret = 0;
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
if (!fence)
return -ENOMEM;
kref_init(&fence->refcount);
nouveau_channel_ref(chan, &fence->channel);
if (emit)
ret = nouveau_fence_emit(fence);
if (ret)
nouveau_fence_unref(&fence);
*pfence = fence;
return ret;
}
struct nouveau_channel *
nouveau_fence_channel(struct nouveau_fence *fence)
{
return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
}
int
nouveau_fence_emit(struct nouveau_fence *fence)
{ {
struct nouveau_channel *chan = fence->channel;
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
int ret; int ret;
...@@ -158,10 +95,11 @@ nouveau_fence_emit(struct nouveau_fence *fence) ...@@ -158,10 +95,11 @@ nouveau_fence_emit(struct nouveau_fence *fence)
} }
fence->sequence = ++chan->fence.sequence; fence->sequence = ++chan->fence.sequence;
fence->channel = chan;
kref_get(&fence->refcount); kref_get(&fence->kref);
spin_lock(&chan->fence.lock); spin_lock(&chan->fence.lock);
list_add_tail(&fence->entry, &chan->fence.pending); list_add_tail(&fence->head, &chan->fence.pending);
spin_unlock(&chan->fence.lock); spin_unlock(&chan->fence.lock);
if (USE_REFCNT(dev)) { if (USE_REFCNT(dev)) {
...@@ -179,50 +117,12 @@ nouveau_fence_emit(struct nouveau_fence *fence) ...@@ -179,50 +117,12 @@ nouveau_fence_emit(struct nouveau_fence *fence)
return 0; return 0;
} }
void
nouveau_fence_work(struct nouveau_fence *fence,
void (*work)(void *priv, bool signalled),
void *priv)
{
BUG_ON(fence->work);
spin_lock(&fence->channel->fence.lock);
if (fence->signalled) {
work(priv, true);
} else {
fence->work = work;
fence->priv = priv;
}
spin_unlock(&fence->channel->fence.lock);
}
void
nouveau_fence_unref(struct nouveau_fence **pfence)
{
if (*pfence)
kref_put(&(*pfence)->refcount, nouveau_fence_del);
*pfence = NULL;
}
struct nouveau_fence *
nouveau_fence_ref(struct nouveau_fence *fence)
{
kref_get(&fence->refcount);
return fence;
}
bool bool
nouveau_fence_signalled(struct nouveau_fence *fence) nouveau_fence_done(struct nouveau_fence *fence)
{ {
struct nouveau_channel *chan = fence->channel; if (fence->channel)
nouveau_fence_update(fence->channel);
if (fence->signalled) return !fence->channel;
return true;
nouveau_fence_update(chan);
return fence->signalled;
} }
int int
...@@ -232,8 +132,8 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) ...@@ -232,8 +132,8 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
ktime_t t; ktime_t t;
int ret = 0; int ret = 0;
while (!nouveau_fence_signalled(fence)) { while (!nouveau_fence_done(fence)) {
if (time_after_eq(jiffies, fence->timeout)) { if (fence->timeout && time_after_eq(jiffies, fence->timeout)) {
ret = -EBUSY; ret = -EBUSY;
break; break;
} }
...@@ -255,10 +155,71 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) ...@@ -255,10 +155,71 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
} }
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
return ret;
}
static void
nouveau_fence_del(struct kref *kref)
{
struct nouveau_fence *fence = container_of(kref, typeof(*fence), kref);
kfree(fence);
}
void
nouveau_fence_unref(struct nouveau_fence **pfence)
{
if (*pfence)
kref_put(&(*pfence)->kref, nouveau_fence_del);
*pfence = NULL;
}
struct nouveau_fence *
nouveau_fence_ref(struct nouveau_fence *fence)
{
kref_get(&fence->kref);
return fence;
}
int
nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence)
{
struct nouveau_fence *fence;
int ret = 0;
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
if (!fence)
return -ENOMEM;
kref_init(&fence->kref);
if (chan) {
ret = nouveau_fence_emit(fence, chan);
if (ret)
nouveau_fence_unref(&fence);
}
*pfence = fence;
return ret; return ret;
} }
struct nouveau_semaphore {
struct kref ref;
struct drm_device *dev;
struct drm_mm_node *mem;
};
void
nouveau_fence_work(struct nouveau_fence *fence,
void (*work)(void *priv, bool signalled),
void *priv)
{
if (!fence->channel) {
work(priv, true);
} else {
fence->work = work;
fence->priv = priv;
}
}
static struct nouveau_semaphore * static struct nouveau_semaphore *
semaphore_alloc(struct drm_device *dev) semaphore_alloc(struct drm_device *dev)
{ {
...@@ -367,7 +328,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) ...@@ -367,7 +328,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
} }
/* Delay semaphore destruction until its work is done */ /* Delay semaphore destruction until its work is done */
ret = nouveau_fence_new(chan, &fence, true); ret = nouveau_fence_new(chan, &fence);
if (ret) if (ret)
return ret; return ret;
...@@ -421,7 +382,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) ...@@ -421,7 +382,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
} }
/* Delay semaphore destruction until its work is done */ /* Delay semaphore destruction until its work is done */
ret = nouveau_fence_new(chan, &fence, true); ret = nouveau_fence_new(chan, &fence);
if (ret) if (ret)
return ret; return ret;
...@@ -435,13 +396,13 @@ int ...@@ -435,13 +396,13 @@ int
nouveau_fence_sync(struct nouveau_fence *fence, nouveau_fence_sync(struct nouveau_fence *fence,
struct nouveau_channel *wchan) struct nouveau_channel *wchan)
{ {
struct nouveau_channel *chan = nouveau_fence_channel(fence); struct nouveau_channel *chan;
struct drm_device *dev = wchan->dev; struct drm_device *dev = wchan->dev;
struct nouveau_semaphore *sema; struct nouveau_semaphore *sema;
int ret = 0; int ret = 0;
if (likely(!chan || chan == wchan || chan = fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
nouveau_fence_signalled(fence))) if (likely(!chan || chan == wchan || nouveau_fence_done(fence)))
goto out; goto out;
sema = semaphore_alloc(dev); sema = semaphore_alloc(dev);
...@@ -479,12 +440,6 @@ nouveau_fence_sync(struct nouveau_fence *fence, ...@@ -479,12 +440,6 @@ nouveau_fence_sync(struct nouveau_fence *fence,
return ret; return ret;
} }
int
__nouveau_fence_flush(void *sync_obj, void *sync_arg)
{
return 0;
}
int int
nouveau_fence_channel_init(struct nouveau_channel *chan) nouveau_fence_channel_init(struct nouveau_channel *chan)
{ {
...@@ -538,14 +493,14 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan) ...@@ -538,14 +493,14 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
struct nouveau_fence *tmp, *fence; struct nouveau_fence *tmp, *fence;
spin_lock(&chan->fence.lock); spin_lock(&chan->fence.lock);
list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { list_for_each_entry_safe(fence, tmp, &chan->fence.pending, head) {
fence->signalled = true; fence->channel = NULL;
list_del(&fence->entry); list_del(&fence->head);
if (unlikely(fence->work)) if (unlikely(fence->work))
fence->work(fence->priv, false); fence->work(fence->priv, false);
kref_put(&fence->refcount, nouveau_fence_del); kref_put(&fence->kref, nouveau_fence_del);
} }
spin_unlock(&chan->fence.lock); spin_unlock(&chan->fence.lock);
......
#ifndef __NOUVEAU_FENCE_H__
#define __NOUVEAU_FENCE_H__
struct nouveau_fence {
struct list_head head;
struct kref kref;
struct nouveau_channel *channel;
unsigned long timeout;
u32 sequence;
void (*work)(void *priv, bool signalled);
void *priv;
};
int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **);
struct nouveau_fence *
nouveau_fence_ref(struct nouveau_fence *);
void nouveau_fence_unref(struct nouveau_fence **);
int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *);
bool nouveau_fence_done(struct nouveau_fence *);
int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *);
void nouveau_fence_idle(struct nouveau_channel *);
void nouveau_fence_update(struct nouveau_channel *);
#endif
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_fence.h"
#define nouveau_gem_pushbuf_sync(chan) 0 #define nouveau_gem_pushbuf_sync(chan) 0
...@@ -778,7 +779,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -778,7 +779,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
} }
} }
ret = nouveau_fence_new(chan, &fence, true); ret = nouveau_fence_new(chan, &fence);
if (ret) { if (ret) {
NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
WIND_RING(chan); WIND_RING(chan);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "nouveau_pm.h" #include "nouveau_pm.h"
#include "nouveau_mm.h" #include "nouveau_mm.h"
#include "nouveau_vm.h" #include "nouveau_vm.h"
#include "nouveau_fence.h"
/* /*
* NV10-NV40 tiling helpers * NV10-NV40 tiling helpers
...@@ -89,7 +90,7 @@ nv10_mem_get_tile_region(struct drm_device *dev, int i) ...@@ -89,7 +90,7 @@ nv10_mem_get_tile_region(struct drm_device *dev, int i)
spin_lock(&dev_priv->tile.lock); spin_lock(&dev_priv->tile.lock);
if (!tile->used && if (!tile->used &&
(!tile->fence || nouveau_fence_signalled(tile->fence))) (!tile->fence || nouveau_fence_done(tile->fence)))
tile->used = true; tile->used = true;
else else
tile = NULL; tile = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment