diff options
author | Lauri Peltonen <lpeltonen@nvidia.com> | 2015-02-16 16:31:46 +0900 |
---|---|---|
committer | Alexandre Courbot <acourbot@nvidia.com> | 2015-03-27 16:06:56 +0900 |
commit | 0b69b0ecbb0eb739bb71b25fbafd8cb6f7a6f04a (patch) | |
tree | 222686edb58d77ed0a2b2bbf21b2532891a673e0 | |
parent | 81b36f87549f87d61ca1433f64c3b86ea2f1f942 (diff) | |
download | nouveau-0b69b0ecbb0eb739bb71b25fbafd8cb6f7a6f04a.tar.gz |
drm/nouveau: Add fence fd helpers
Add nouveau_fence_install, which installs a drm fence as a file
descriptor that can be returned to user space.
Add nouveau_fence_sync_fd, which pushes semaphore wait commands for
each Nouveau fence contained within the sync fd. If the sync fd
contains non-Nouveau fences, those are waited on the CPU.
Add missing fence_value_str and timeline_value_str callbacks to
nouveau fence_ops.
Signed-off-by: Lauri Peltonen <lpeltonen@nvidia.com>
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
-rw-r--r-- | drm/nouveau/nouveau_fence.c | 77 | ||||
-rw-r--r-- | drm/nouveau/nouveau_fence.h | 2 |
2 files changed, 78 insertions, 1 deletions
diff --git a/drm/nouveau/nouveau_fence.c b/drm/nouveau/nouveau_fence.c index b504e8031..f2a5466b3 100644 --- a/drm/nouveau/nouveau_fence.c +++ b/drm/nouveau/nouveau_fence.c @@ -37,6 +37,8 @@ #include "nouveau_dma.h" #include "nouveau_fence.h" +#include "../drivers/staging/android/sync.h" + static const struct fence_ops nouveau_fence_ops_uevent; static const struct fence_ops nouveau_fence_ops_legacy; @@ -539,11 +541,84 @@ static bool nouveau_fence_enable_signaling(struct fence *f) return ret; } +static void nouveau_fence_timeline_value_str(struct fence *fence, char *str, + int size) +{ + struct nouveau_fence *f = from_fence(fence); + struct nouveau_fence_chan *fctx = nouveau_fctx(f); + u32 cur; + + cur = f->channel ? fctx->read(f->channel) : 0; + snprintf(str, size, "%d", cur); +} + +static void +nouveau_fence_value_str(struct fence *fence, char *str, int size) +{ + snprintf(str, size, "%d", fence->seqno); +} + static const struct fence_ops nouveau_fence_ops_uevent = { .get_driver_name = nouveau_fence_get_get_driver_name, .get_timeline_name = nouveau_fence_get_timeline_name, .enable_signaling = nouveau_fence_enable_signaling, .signaled = nouveau_fence_is_signaled, .wait = fence_default_wait, - .release = NULL + .release = NULL, + .fence_value_str = nouveau_fence_value_str, + .timeline_value_str = nouveau_fence_timeline_value_str, }; + +int +nouveau_fence_install(struct fence *fence, const char *name, int *fd_out) +{ +#ifdef CONFIG_SYNC + struct sync_fence *f; + int fd; + + f = sync_fence_create(name, &fence, 1); + + if (!f) + return -ENOMEM; + + fd = get_unused_fd_flags(0); + + if (fd < 0) { + sync_fence_put(f); + return fd; + } + + sync_fence_install(f, fd); + *fd_out = fd; + return 0; +#else + return -ENODEV; +#endif +} + +int +nouveau_fence_sync_fd(int fence_fd, struct nouveau_channel *chan, bool intr) +{ +#ifdef CONFIG_SYNC + int i, ret = 0; + struct sync_fence *fence; + + fence = sync_fence_fdget(fence_fd); + + if (!fence) + return -EINVAL; + + for (i = 0; i < fence->num_fences; ++i) { + struct fence *pt = fence->cbs[i].sync_pt; + + ret = nouveau_fence_sync(pt, chan, intr); + + if (ret) + break; + } + + return ret; +#else + return -ENODEV; +#endif +} diff --git a/drm/nouveau/nouveau_fence.h b/drm/nouveau/nouveau_fence.h index 4610fdf58..aca5966b4 100644 --- a/drm/nouveau/nouveau_fence.h +++ b/drm/nouveau/nouveau_fence.h @@ -27,6 +27,8 @@ bool nouveau_fence_done(struct nouveau_fence *); void nouveau_fence_work(struct fence *, void (*)(void *), void *); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_sync(struct fence *, struct nouveau_channel *, bool intr); +int nouveau_fence_sync_fd(int, struct nouveau_channel *, bool intr); +int nouveau_fence_install(struct fence *, const char *name, int *); struct nouveau_fence_chan { spinlock_t lock; |