mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 12:43:55 +08:00
drm/nouveau/fence: minor api changes for an upcoming rework
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
875ac34aad
commit
d375e7d56d
@ -35,6 +35,7 @@
|
||||
#include "nouveau_dma.h"
|
||||
#include "nouveau_mm.h"
|
||||
#include "nouveau_vm.h"
|
||||
#include "nouveau_fence.h"
|
||||
|
||||
#include <linux/log2.h>
|
||||
#include <linux/slab.h>
|
||||
@ -478,7 +479,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
|
||||
struct nouveau_fence *fence = NULL;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_fence_new(chan, &fence, true);
|
||||
ret = nouveau_fence_new(chan, &fence);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1196,7 +1197,7 @@ nouveau_bo_fence_ref(void *sync_obj)
|
||||
static bool
|
||||
nouveau_bo_fence_signalled(void *sync_obj, void *sync_arg)
|
||||
{
|
||||
return nouveau_fence_signalled(sync_obj);
|
||||
return nouveau_fence_done(sync_obj);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "nouveau_drm.h"
|
||||
#include "nouveau_dma.h"
|
||||
#include "nouveau_ramht.h"
|
||||
#include "nouveau_fence.h"
|
||||
#include "nouveau_software.h"
|
||||
|
||||
static int
|
||||
@ -369,7 +370,7 @@ nouveau_channel_idle(struct nouveau_channel *chan)
|
||||
nouveau_fence_update(chan);
|
||||
|
||||
if (chan->fence.sequence != chan->fence.sequence_ack) {
|
||||
ret = nouveau_fence_new(chan, &fence, true);
|
||||
ret = nouveau_fence_new(chan, &fence);
|
||||
if (!ret) {
|
||||
ret = nouveau_fence_wait(fence, false, false);
|
||||
nouveau_fence_unref(&fence);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "nouveau_connector.h"
|
||||
#include "nouveau_software.h"
|
||||
#include "nouveau_gpio.h"
|
||||
#include "nouveau_fence.h"
|
||||
#include "nv50_display.h"
|
||||
|
||||
static void
|
||||
@ -465,7 +466,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
|
||||
}
|
||||
FIRE_RING (chan);
|
||||
|
||||
ret = nouveau_fence_new(chan, pfence, true);
|
||||
ret = nouveau_fence_new(chan, pfence);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
@ -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 *new_bo = nouveau_framebuffer(fb)->nvbo;
|
||||
struct nouveau_page_flip_state *s;
|
||||
struct nouveau_channel *chan;
|
||||
struct nouveau_channel *chan = NULL;
|
||||
struct nouveau_fence *fence;
|
||||
int ret;
|
||||
|
||||
@ -509,7 +510,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
new_bo->bo.offset };
|
||||
|
||||
/* 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)
|
||||
chan = nouveau_channel_get_unlocked(dev_priv->channel);
|
||||
mutex_lock(&chan->mutex);
|
||||
|
@ -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 *);
|
||||
|
||||
/* nouveau_fence.c */
|
||||
struct nouveau_fence;
|
||||
extern int nouveau_fence_init(struct drm_device *);
|
||||
extern void nouveau_fence_fini(struct drm_device *);
|
||||
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);
|
||||
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 *);
|
||||
|
||||
int nouveau_fence_init(struct drm_device *);
|
||||
void nouveau_fence_fini(struct drm_device *);
|
||||
int nouveau_fence_channel_init(struct nouveau_channel *);
|
||||
void nouveau_fence_channel_fini(struct nouveau_channel *);
|
||||
void nouveau_fence_work(struct nouveau_fence *fence,
|
||||
void (*work)(void *priv, bool signalled), void *priv);
|
||||
/* nouveau_gem.c */
|
||||
extern int nouveau_gem_new(struct drm_device *, int size, int align,
|
||||
uint32_t domain, uint32_t tile_mode,
|
||||
|
@ -32,47 +32,13 @@
|
||||
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_ramht.h"
|
||||
#include "nouveau_fence.h"
|
||||
#include "nouveau_software.h"
|
||||
#include "nouveau_dma.h"
|
||||
|
||||
#define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
|
||||
#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
|
||||
nouveau_fence_update(struct nouveau_channel *chan)
|
||||
{
|
||||
@ -94,16 +60,16 @@ nouveau_fence_update(struct nouveau_channel *chan)
|
||||
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)
|
||||
break;
|
||||
|
||||
fence->signalled = true;
|
||||
list_del(&fence->entry);
|
||||
fence->channel = NULL;
|
||||
list_del(&fence->head);
|
||||
if (fence->work)
|
||||
fence->work(fence->priv, true);
|
||||
|
||||
kref_put(&fence->refcount, nouveau_fence_del);
|
||||
nouveau_fence_unref(&fence);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -111,37 +77,8 @@ out:
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence,
|
||||
bool emit)
|
||||
nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
|
||||
{
|
||||
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_nouveau_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
@ -158,10 +95,11 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
}
|
||||
|
||||
fence->sequence = ++chan->fence.sequence;
|
||||
fence->channel = chan;
|
||||
|
||||
kref_get(&fence->refcount);
|
||||
kref_get(&fence->kref);
|
||||
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);
|
||||
|
||||
if (USE_REFCNT(dev)) {
|
||||
@ -179,50 +117,12 @@ nouveau_fence_emit(struct nouveau_fence *fence)
|
||||
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
|
||||
nouveau_fence_signalled(struct nouveau_fence *fence)
|
||||
nouveau_fence_done(struct nouveau_fence *fence)
|
||||
{
|
||||
struct nouveau_channel *chan = fence->channel;
|
||||
|
||||
if (fence->signalled)
|
||||
return true;
|
||||
|
||||
nouveau_fence_update(chan);
|
||||
return fence->signalled;
|
||||
if (fence->channel)
|
||||
nouveau_fence_update(fence->channel);
|
||||
return !fence->channel;
|
||||
}
|
||||
|
||||
int
|
||||
@ -232,8 +132,8 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
|
||||
ktime_t t;
|
||||
int ret = 0;
|
||||
|
||||
while (!nouveau_fence_signalled(fence)) {
|
||||
if (time_after_eq(jiffies, fence->timeout)) {
|
||||
while (!nouveau_fence_done(fence)) {
|
||||
if (fence->timeout && time_after_eq(jiffies, fence->timeout)) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
@ -255,10 +155,71 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
|
||||
}
|
||||
|
||||
__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;
|
||||
}
|
||||
|
||||
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 *
|
||||
semaphore_alloc(struct drm_device *dev)
|
||||
{
|
||||
@ -367,7 +328,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
|
||||
}
|
||||
|
||||
/* Delay semaphore destruction until its work is done */
|
||||
ret = nouveau_fence_new(chan, &fence, true);
|
||||
ret = nouveau_fence_new(chan, &fence);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -421,7 +382,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
|
||||
}
|
||||
|
||||
/* Delay semaphore destruction until its work is done */
|
||||
ret = nouveau_fence_new(chan, &fence, true);
|
||||
ret = nouveau_fence_new(chan, &fence);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -435,13 +396,13 @@ int
|
||||
nouveau_fence_sync(struct nouveau_fence *fence,
|
||||
struct nouveau_channel *wchan)
|
||||
{
|
||||
struct nouveau_channel *chan = nouveau_fence_channel(fence);
|
||||
struct nouveau_channel *chan;
|
||||
struct drm_device *dev = wchan->dev;
|
||||
struct nouveau_semaphore *sema;
|
||||
int ret = 0;
|
||||
|
||||
if (likely(!chan || chan == wchan ||
|
||||
nouveau_fence_signalled(fence)))
|
||||
chan = fence ? nouveau_channel_get_unlocked(fence->channel) : NULL;
|
||||
if (likely(!chan || chan == wchan || nouveau_fence_done(fence)))
|
||||
goto out;
|
||||
|
||||
sema = semaphore_alloc(dev);
|
||||
@ -479,12 +440,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
__nouveau_fence_flush(void *sync_obj, void *sync_arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_fence_channel_init(struct nouveau_channel *chan)
|
||||
{
|
||||
@ -538,14 +493,14 @@ nouveau_fence_channel_fini(struct nouveau_channel *chan)
|
||||
struct nouveau_fence *tmp, *fence;
|
||||
|
||||
spin_lock(&chan->fence.lock);
|
||||
list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) {
|
||||
fence->signalled = true;
|
||||
list_del(&fence->entry);
|
||||
list_for_each_entry_safe(fence, tmp, &chan->fence.pending, head) {
|
||||
fence->channel = NULL;
|
||||
list_del(&fence->head);
|
||||
|
||||
if (unlikely(fence->work))
|
||||
fence->work(fence->priv, false);
|
||||
|
||||
kref_put(&fence->refcount, nouveau_fence_del);
|
||||
kref_put(&fence->kref, nouveau_fence_del);
|
||||
}
|
||||
spin_unlock(&chan->fence.lock);
|
||||
|
||||
|
28
drivers/gpu/drm/nouveau/nouveau_fence.h
Normal file
28
drivers/gpu/drm/nouveau/nouveau_fence.h
Normal file
@ -0,0 +1,28 @@
|
||||
#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 @@
|
||||
#include "nouveau_drv.h"
|
||||
#include "nouveau_drm.h"
|
||||
#include "nouveau_dma.h"
|
||||
#include "nouveau_fence.h"
|
||||
|
||||
#define nouveau_gem_pushbuf_sync(chan) 0
|
||||
|
||||
@ -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) {
|
||||
NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
|
||||
WIND_RING(chan);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "nouveau_pm.h"
|
||||
#include "nouveau_mm.h"
|
||||
#include "nouveau_vm.h"
|
||||
#include "nouveau_fence.h"
|
||||
|
||||
/*
|
||||
* NV10-NV40 tiling helpers
|
||||
@ -89,7 +90,7 @@ nv10_mem_get_tile_region(struct drm_device *dev, int i)
|
||||
spin_lock(&dev_priv->tile.lock);
|
||||
|
||||
if (!tile->used &&
|
||||
(!tile->fence || nouveau_fence_signalled(tile->fence)))
|
||||
(!tile->fence || nouveau_fence_done(tile->fence)))
|
||||
tile->used = true;
|
||||
else
|
||||
tile = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user