Commit 29ba89b2 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Maarten Lankhorst

drm/nouveau: rework to new fence interface

Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@canonical.com>
Acked-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 2298e804
...@@ -970,7 +970,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, ...@@ -970,7 +970,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
} }
mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING); mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
ret = nouveau_fence_sync(bo->sync_obj, chan); ret = nouveau_fence_sync(nouveau_bo(bo), chan);
if (ret == 0) { if (ret == 0) {
ret = drm->ttm.move(chan, bo, &bo->mem, new_mem); ret = drm->ttm.move(chan, bo, &bo->mem, new_mem);
if (ret == 0) { if (ret == 0) {
...@@ -1464,10 +1464,12 @@ nouveau_bo_fence_unref(void **sync_obj) ...@@ -1464,10 +1464,12 @@ nouveau_bo_fence_unref(void **sync_obj)
void void
nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence)
{ {
lockdep_assert_held(&nvbo->bo.resv->lock.base); struct reservation_object *resv = nvbo->bo.resv;
nouveau_bo_fence_unref(&nvbo->bo.sync_obj); nouveau_bo_fence_unref(&nvbo->bo.sync_obj);
nvbo->bo.sync_obj = nouveau_fence_ref(fence); nvbo->bo.sync_obj = nouveau_fence_ref(fence);
reservation_object_add_excl_fence(resv, &fence->base);
} }
static void * static void *
......
...@@ -658,7 +658,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, ...@@ -658,7 +658,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
/* Synchronize with the old framebuffer */ /* Synchronize with the old framebuffer */
ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan); ret = nouveau_fence_sync(old_bo, chan);
if (ret) if (ret)
goto fail; goto fail;
...@@ -722,7 +722,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -722,7 +722,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
goto fail_unpin; goto fail_unpin;
/* synchronise rendering channel with the kernel's channel */ /* synchronise rendering channel with the kernel's channel */
ret = nouveau_fence_sync(new_bo->bo.sync_obj, chan); ret = nouveau_fence_sync(new_bo, chan);
if (ret) { if (ret) {
ttm_bo_unreserve(&new_bo->bo); ttm_bo_unreserve(&new_bo->bo);
goto fail_unpin; goto fail_unpin;
......
This diff is collapsed.
#ifndef __NOUVEAU_FENCE_H__ #ifndef __NOUVEAU_FENCE_H__
#define __NOUVEAU_FENCE_H__ #define __NOUVEAU_FENCE_H__
#include <linux/fence.h>
#include <nvif/notify.h>
struct nouveau_drm; struct nouveau_drm;
struct nouveau_bo;
struct nouveau_fence { struct nouveau_fence {
struct fence base;
struct list_head head; struct list_head head;
struct list_head work;
struct kref kref;
bool sysmem; bool sysmem;
struct nouveau_channel *channel; struct nouveau_channel *channel;
unsigned long timeout; unsigned long timeout;
u32 sequence;
}; };
int nouveau_fence_new(struct nouveau_channel *, bool sysmem, int nouveau_fence_new(struct nouveau_channel *, bool sysmem,
...@@ -25,9 +28,10 @@ int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); ...@@ -25,9 +28,10 @@ int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *);
bool nouveau_fence_done(struct nouveau_fence *); bool nouveau_fence_done(struct nouveau_fence *);
void nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *); void nouveau_fence_work(struct nouveau_fence *, void (*)(void *), void *);
int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *);
struct nouveau_fence_chan { struct nouveau_fence_chan {
spinlock_t lock;
struct list_head pending; struct list_head pending;
struct list_head flip; struct list_head flip;
...@@ -38,8 +42,12 @@ struct nouveau_fence_chan { ...@@ -38,8 +42,12 @@ struct nouveau_fence_chan {
int (*emit32)(struct nouveau_channel *, u64, u32); int (*emit32)(struct nouveau_channel *, u64, u32);
int (*sync32)(struct nouveau_channel *, u64, u32); int (*sync32)(struct nouveau_channel *, u64, u32);
spinlock_t lock;
u32 sequence; u32 sequence;
u32 context;
char name[24];
struct nvif_notify notify;
int notify_ref;
}; };
struct nouveau_fence_priv { struct nouveau_fence_priv {
...@@ -49,13 +57,13 @@ struct nouveau_fence_priv { ...@@ -49,13 +57,13 @@ struct nouveau_fence_priv {
int (*context_new)(struct nouveau_channel *); int (*context_new)(struct nouveau_channel *);
void (*context_del)(struct nouveau_channel *); void (*context_del)(struct nouveau_channel *);
wait_queue_head_t waiting; u32 contexts, context_base;
bool uevent; bool uevent;
}; };
#define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence) #define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence)
void nouveau_fence_context_new(struct nouveau_fence_chan *); void nouveau_fence_context_new(struct nouveau_channel *, struct nouveau_fence_chan *);
void nouveau_fence_context_del(struct nouveau_fence_chan *); void nouveau_fence_context_del(struct nouveau_fence_chan *);
int nv04_fence_create(struct nouveau_drm *); int nv04_fence_create(struct nouveau_drm *);
......
...@@ -425,18 +425,6 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, ...@@ -425,18 +425,6 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
return 0; return 0;
} }
static int
validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
{
struct nouveau_fence *fence = nvbo->bo.sync_obj;
int ret = 0;
if (fence)
ret = nouveau_fence_sync(fence, chan);
return ret;
}
static int static int
validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo, struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo,
...@@ -466,8 +454,9 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, ...@@ -466,8 +454,9 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
return ret; return ret;
} }
ret = validate_sync(chan, nvbo); ret = nouveau_fence_sync(nvbo, chan);
if (unlikely(ret)) { if (unlikely(ret)) {
if (ret != -ERESTARTSYS)
NV_PRINTK(error, cli, "fail post-validate sync\n"); NV_PRINTK(error, cli, "fail post-validate sync\n");
return ret; return ret;
} }
......
...@@ -41,7 +41,7 @@ nv04_fence_emit(struct nouveau_fence *fence) ...@@ -41,7 +41,7 @@ nv04_fence_emit(struct nouveau_fence *fence)
int ret = RING_SPACE(chan, 2); int ret = RING_SPACE(chan, 2);
if (ret == 0) { if (ret == 0) {
BEGIN_NV04(chan, NvSubSw, 0x0150, 1); BEGIN_NV04(chan, NvSubSw, 0x0150, 1);
OUT_RING (chan, fence->sequence); OUT_RING (chan, fence->base.seqno);
FIRE_RING (chan); FIRE_RING (chan);
} }
return ret; return ret;
...@@ -75,7 +75,7 @@ nv04_fence_context_new(struct nouveau_channel *chan) ...@@ -75,7 +75,7 @@ nv04_fence_context_new(struct nouveau_channel *chan)
{ {
struct nv04_fence_chan *fctx = kzalloc(sizeof(*fctx), GFP_KERNEL); struct nv04_fence_chan *fctx = kzalloc(sizeof(*fctx), GFP_KERNEL);
if (fctx) { if (fctx) {
nouveau_fence_context_new(&fctx->base); nouveau_fence_context_new(chan, &fctx->base);
fctx->base.emit = nv04_fence_emit; fctx->base.emit = nv04_fence_emit;
fctx->base.sync = nv04_fence_sync; fctx->base.sync = nv04_fence_sync;
fctx->base.read = nv04_fence_read; fctx->base.read = nv04_fence_read;
...@@ -105,5 +105,7 @@ nv04_fence_create(struct nouveau_drm *drm) ...@@ -105,5 +105,7 @@ nv04_fence_create(struct nouveau_drm *drm)
priv->base.dtor = nv04_fence_destroy; priv->base.dtor = nv04_fence_destroy;
priv->base.context_new = nv04_fence_context_new; priv->base.context_new = nv04_fence_context_new;
priv->base.context_del = nv04_fence_context_del; priv->base.context_del = nv04_fence_context_del;
priv->base.contexts = 15;
priv->base.context_base = fence_context_alloc(priv->base.contexts);
return 0; return 0;
} }
...@@ -33,7 +33,7 @@ nv10_fence_emit(struct nouveau_fence *fence) ...@@ -33,7 +33,7 @@ nv10_fence_emit(struct nouveau_fence *fence)
int ret = RING_SPACE(chan, 2); int ret = RING_SPACE(chan, 2);
if (ret == 0) { if (ret == 0) {
BEGIN_NV04(chan, 0, NV10_SUBCHAN_REF_CNT, 1); BEGIN_NV04(chan, 0, NV10_SUBCHAN_REF_CNT, 1);
OUT_RING (chan, fence->sequence); OUT_RING (chan, fence->base.seqno);
FIRE_RING (chan); FIRE_RING (chan);
} }
return ret; return ret;
...@@ -75,7 +75,7 @@ nv10_fence_context_new(struct nouveau_channel *chan) ...@@ -75,7 +75,7 @@ nv10_fence_context_new(struct nouveau_channel *chan)
if (!fctx) if (!fctx)
return -ENOMEM; return -ENOMEM;
nouveau_fence_context_new(&fctx->base); nouveau_fence_context_new(chan, &fctx->base);
fctx->base.emit = nv10_fence_emit; fctx->base.emit = nv10_fence_emit;
fctx->base.read = nv10_fence_read; fctx->base.read = nv10_fence_read;
fctx->base.sync = nv10_fence_sync; fctx->base.sync = nv10_fence_sync;
...@@ -106,6 +106,8 @@ nv10_fence_create(struct nouveau_drm *drm) ...@@ -106,6 +106,8 @@ nv10_fence_create(struct nouveau_drm *drm)
priv->base.dtor = nv10_fence_destroy; priv->base.dtor = nv10_fence_destroy;
priv->base.context_new = nv10_fence_context_new; priv->base.context_new = nv10_fence_context_new;
priv->base.context_del = nv10_fence_context_del; priv->base.context_del = nv10_fence_context_del;
priv->base.contexts = 31;
priv->base.context_base = fence_context_alloc(priv->base.contexts);
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
return 0; return 0;
} }
...@@ -84,7 +84,7 @@ nv17_fence_context_new(struct nouveau_channel *chan) ...@@ -84,7 +84,7 @@ nv17_fence_context_new(struct nouveau_channel *chan)
if (!fctx) if (!fctx)
return -ENOMEM; return -ENOMEM;
nouveau_fence_context_new(&fctx->base); nouveau_fence_context_new(chan, &fctx->base);
fctx->base.emit = nv10_fence_emit; fctx->base.emit = nv10_fence_emit;
fctx->base.read = nv10_fence_read; fctx->base.read = nv10_fence_read;
fctx->base.sync = nv17_fence_sync; fctx->base.sync = nv17_fence_sync;
...@@ -124,6 +124,8 @@ nv17_fence_create(struct nouveau_drm *drm) ...@@ -124,6 +124,8 @@ nv17_fence_create(struct nouveau_drm *drm)
priv->base.resume = nv17_fence_resume; priv->base.resume = nv17_fence_resume;
priv->base.context_new = nv17_fence_context_new; priv->base.context_new = nv17_fence_context_new;
priv->base.context_del = nv10_fence_context_del; priv->base.context_del = nv10_fence_context_del;
priv->base.contexts = 31;
priv->base.context_base = fence_context_alloc(priv->base.contexts);
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
......
...@@ -46,7 +46,7 @@ nv50_fence_context_new(struct nouveau_channel *chan) ...@@ -46,7 +46,7 @@ nv50_fence_context_new(struct nouveau_channel *chan)
if (!fctx) if (!fctx)
return -ENOMEM; return -ENOMEM;
nouveau_fence_context_new(&fctx->base); nouveau_fence_context_new(chan, &fctx->base);
fctx->base.emit = nv10_fence_emit; fctx->base.emit = nv10_fence_emit;
fctx->base.read = nv10_fence_read; fctx->base.read = nv10_fence_read;
fctx->base.sync = nv17_fence_sync; fctx->base.sync = nv17_fence_sync;
...@@ -95,6 +95,8 @@ nv50_fence_create(struct nouveau_drm *drm) ...@@ -95,6 +95,8 @@ nv50_fence_create(struct nouveau_drm *drm)
priv->base.resume = nv17_fence_resume; priv->base.resume = nv17_fence_resume;
priv->base.context_new = nv50_fence_context_new; priv->base.context_new = nv50_fence_context_new;
priv->base.context_del = nv10_fence_context_del; priv->base.context_del = nv10_fence_context_del;
priv->base.contexts = 127;
priv->base.context_base = fence_context_alloc(priv->base.contexts);
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
......
...@@ -82,7 +82,7 @@ nv84_fence_emit(struct nouveau_fence *fence) ...@@ -82,7 +82,7 @@ nv84_fence_emit(struct nouveau_fence *fence)
else else
addr += fctx->vma.offset; addr += fctx->vma.offset;
return fctx->base.emit32(chan, addr, fence->sequence); return fctx->base.emit32(chan, addr, fence->base.seqno);
} }
static int static int
...@@ -97,7 +97,7 @@ nv84_fence_sync(struct nouveau_fence *fence, ...@@ -97,7 +97,7 @@ nv84_fence_sync(struct nouveau_fence *fence,
else else
addr += fctx->vma.offset; addr += fctx->vma.offset;
return fctx->base.sync32(chan, addr, fence->sequence); return fctx->base.sync32(chan, addr, fence->base.seqno);
} }
static u32 static u32
...@@ -139,12 +139,13 @@ nv84_fence_context_new(struct nouveau_channel *chan) ...@@ -139,12 +139,13 @@ nv84_fence_context_new(struct nouveau_channel *chan)
if (!fctx) if (!fctx)
return -ENOMEM; return -ENOMEM;
nouveau_fence_context_new(&fctx->base); nouveau_fence_context_new(chan, &fctx->base);
fctx->base.emit = nv84_fence_emit; fctx->base.emit = nv84_fence_emit;
fctx->base.sync = nv84_fence_sync; fctx->base.sync = nv84_fence_sync;
fctx->base.read = nv84_fence_read; fctx->base.read = nv84_fence_read;
fctx->base.emit32 = nv84_fence_emit32; fctx->base.emit32 = nv84_fence_emit32;
fctx->base.sync32 = nv84_fence_sync32; fctx->base.sync32 = nv84_fence_sync32;
fctx->base.sequence = nv84_fence_read(chan);
ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma); ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
if (ret == 0) { if (ret == 0) {
...@@ -168,13 +169,12 @@ nv84_fence_context_new(struct nouveau_channel *chan) ...@@ -168,13 +169,12 @@ nv84_fence_context_new(struct nouveau_channel *chan)
static bool static bool
nv84_fence_suspend(struct nouveau_drm *drm) nv84_fence_suspend(struct nouveau_drm *drm)
{ {
struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
struct nv84_fence_priv *priv = drm->fence; struct nv84_fence_priv *priv = drm->fence;
int i; int i;
priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); priv->suspend = vmalloc(priv->base.contexts * sizeof(u32));
if (priv->suspend) { if (priv->suspend) {
for (i = 0; i <= pfifo->max; i++) for (i = 0; i < priv->base.contexts; i++)
priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
} }
...@@ -184,12 +184,11 @@ nv84_fence_suspend(struct nouveau_drm *drm) ...@@ -184,12 +184,11 @@ nv84_fence_suspend(struct nouveau_drm *drm)
static void static void
nv84_fence_resume(struct nouveau_drm *drm) nv84_fence_resume(struct nouveau_drm *drm)
{ {
struct nouveau_fifo *pfifo = nvkm_fifo(&drm->device);
struct nv84_fence_priv *priv = drm->fence; struct nv84_fence_priv *priv = drm->fence;
int i; int i;
if (priv->suspend) { if (priv->suspend) {
for (i = 0; i <= pfifo->max; i++) for (i = 0; i < priv->base.contexts; i++)
nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]); nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
vfree(priv->suspend); vfree(priv->suspend);
priv->suspend = NULL; priv->suspend = NULL;
...@@ -229,10 +228,11 @@ nv84_fence_create(struct nouveau_drm *drm) ...@@ -229,10 +228,11 @@ nv84_fence_create(struct nouveau_drm *drm)
priv->base.context_new = nv84_fence_context_new; priv->base.context_new = nv84_fence_context_new;
priv->base.context_del = nv84_fence_context_del; priv->base.context_del = nv84_fence_context_del;
init_waitqueue_head(&priv->base.waiting); priv->base.contexts = pfifo->max + 1;
priv->base.context_base = fence_context_alloc(priv->base.contexts);
priv->base.uevent = true; priv->base.uevent = true;
ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0,
TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo);
if (ret == 0) { if (ret == 0) {
ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM);
...@@ -246,7 +246,7 @@ nv84_fence_create(struct nouveau_drm *drm) ...@@ -246,7 +246,7 @@ nv84_fence_create(struct nouveau_drm *drm)
} }
if (ret == 0) if (ret == 0)
ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, ret = nouveau_bo_new(drm->dev, 16 * priv->base.contexts, 0,
TTM_PL_FLAG_TT, 0, 0, NULL, TTM_PL_FLAG_TT, 0, 0, NULL,
&priv->bo_gart); &priv->bo_gart);
if (ret == 0) { if (ret == 0) {
......
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