drm: Branch 'master' - 3 commits
[email protected] (Rob Clark)
| Newsgroups | gmane.comp.video.dri.patches |
|---|---|
| Message-ID | <[email protected]> |
Makefile.sources | 1 freedreno/freedreno_drmif.h | 1 freedreno/freedreno_priv.h | 3 freedreno/freedreno_ringbuffer.c | 11 ++ freedreno/freedreno_ringbuffer.h | 5 + freedreno/kgsl/kgsl_ringbuffer.c | 6 + freedreno/msm/msm_drm.h | 22 +++++ freedreno/msm/msm_ringbuffer.c | 18 ++++ libsync.h | 148 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 207 insertions(+), 8 deletions(-) New commits: commit e9eb44b45b8d4a2f06ef83365b28eca55c0f3fb4 Author: Rob Clark <[email protected]> Date: Mon Aug 15 13:26:18 2016 -0400 freedreno: add fence fd support Signed-off-by: Rob Clark <[email protected]> diff --git a/freedreno/freedreno_drmif.h b/freedreno/freedreno_drmif.h index 2d913e6..7a8073f 100644 --- a/freedreno/freedreno_drmif.h +++ b/freedreno/freedreno_drmif.h @@ -92,6 +92,7 @@ int fd_device_fd(struct fd_device *dev); enum fd_version { FD_VERSION_MADVISE = 1, /* kernel supports madvise */ FD_VERSION_UNLIMITED_CMDS = 1, /* submits w/ >4 cmd buffers (growable ringbuffer) */ + FD_VERSION_FENCE_FD = 2, /* submit command supports in/out fences */ }; enum fd_version fd_device_version(struct fd_device *dev); diff --git a/freedreno/freedreno_priv.h b/freedreno/freedreno_priv.h index cdfdbe8..86da83b 100644 --- a/freedreno/freedreno_priv.h +++ b/freedreno/freedreno_priv.h @@ -133,7 +133,8 @@ struct fd_ringmarker { struct fd_ringbuffer_funcs { void * (*hostptr)(struct fd_ringbuffer *ring); - int (*flush)(struct fd_ringbuffer *ring, uint32_t *last_start); + int (*flush)(struct fd_ringbuffer *ring, uint32_t *last_start, + int in_fence_fd, int *out_fence_fd); void (*grow)(struct fd_ringbuffer *ring, uint32_t size); void (*reset)(struct fd_ringbuffer *ring); void (*emit_reloc)(struct fd_ringbuffer *ring, diff --git a/freedreno/freedreno_ringbuffer.c b/freedreno/freedreno_ringbuffer.c index 22dafb3..c132145 100644 --- a/freedreno/freedreno_ringbuffer.c +++ b/freedreno/freedreno_ringbuffer.c @@ -80,10 +80,15 @@ void fd_ringbuffer_reset(struct fd_ringbuffer *ring) ring->funcs->reset(ring); } -/* maybe get rid of this and use fd_ringmarker_flush() from DDX too? */ int fd_ringbuffer_flush(struct fd_ringbuffer *ring) { - return ring->funcs->flush(ring, ring->last_start); + return ring->funcs->flush(ring, ring->last_start, -1, NULL); +} + +int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd, + int *out_fence_fd) +{ + return ring->funcs->flush(ring, ring->last_start, in_fence_fd, out_fence_fd); } void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords) @@ -177,5 +182,5 @@ uint32_t fd_ringmarker_dwords(struct fd_ringmarker *start, int fd_ringmarker_flush(struct fd_ringmarker *marker) { struct fd_ringbuffer *ring = marker->ring; - return ring->funcs->flush(ring, marker->cur); + return ring->funcs->flush(ring, marker->cur, -1, NULL); } diff --git a/freedreno/freedreno_ringbuffer.h b/freedreno/freedreno_ringbuffer.h index 8899b5d..108d5a6 100644 --- a/freedreno/freedreno_ringbuffer.h +++ b/freedreno/freedreno_ringbuffer.h @@ -56,6 +56,11 @@ void fd_ringbuffer_set_parent(struct fd_ringbuffer *ring, struct fd_ringbuffer *parent); void fd_ringbuffer_reset(struct fd_ringbuffer *ring); int fd_ringbuffer_flush(struct fd_ringbuffer *ring); +/* in_fence_fd: -1 for no in-fence, else fence fd + * out_fence_fd: NULL for no output-fence requested, else ptr to return out-fence + */ +int fd_ringbuffer_flush2(struct fd_ringbuffer *ring, int in_fence_fd, + int *out_fence_fd); void fd_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t ndwords); uint32_t fd_ringbuffer_timestamp(struct fd_ringbuffer *ring); diff --git a/freedreno/kgsl/kgsl_ringbuffer.c b/freedreno/kgsl/kgsl_ringbuffer.c index 7b3298a..e4696b1 100644 --- a/freedreno/kgsl/kgsl_ringbuffer.c +++ b/freedreno/kgsl/kgsl_ringbuffer.c @@ -113,7 +113,8 @@ static void * kgsl_ringbuffer_hostptr(struct fd_ringbuffer *ring) return kgsl_ring->bo->hostptr; } -static int kgsl_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start) +static int kgsl_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start, + int in_fence_fd, int *out_fence_fd) { struct kgsl_ringbuffer *kgsl_ring = to_kgsl_ringbuffer(ring); struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(ring->pipe); @@ -131,6 +132,9 @@ static int kgsl_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_star }; int ret; + assert(in_fence_fd == -1); + assert(out_fence_fd == NULL); + kgsl_pipe_pre_submit(kgsl_pipe); /* z180_cmdstream_issueibcmds() is made of fail: */ diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index 60f0315..5117df1 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -395,7 +395,8 @@ static void dump_submit(struct msm_ringbuffer *msm_ring) } } -static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start) +static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start, + int in_fence_fd, int *out_fence_fd) { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); struct drm_msm_gem_submit req = { @@ -404,6 +405,15 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start uint32_t i; int ret; + if (in_fence_fd != -1) { + req.flags |= MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_NO_IMPLICIT; + req.fence_fd = in_fence_fd; + } + + if (out_fence_fd) { + req.flags |= MSM_SUBMIT_FENCE_FD_OUT; + } + finalize_current_cmd(ring, last_start); /* needs to be after get_cmd() as that could create bos/cmds table: */ @@ -435,6 +445,10 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start struct msm_cmd *msm_cmd = msm_ring->cmds[i]; msm_cmd->ring->last_timestamp = req.fence; } + + if (out_fence_fd) { + *out_fence_fd = req.fence_fd; + } } flush_reset(ring); commit 9270d984cde31a8abc5f9ec31cbd86a10b883864 Author: Rob Clark <[email protected]> Date: Mon Aug 15 12:52:31 2016 -0400 freedreno: sync uapi header Signed-off-by: Rob Clark <[email protected]> diff --git a/freedreno/msm/msm_drm.h b/freedreno/msm/msm_drm.h index cbf75c3..ed4c8d4 100644 --- a/freedreno/msm/msm_drm.h +++ b/freedreno/msm/msm_drm.h @@ -50,6 +50,15 @@ extern "C" { #define MSM_PIPE_2D1 0x02 #define MSM_PIPE_3D0 0x10 +/* The pipe-id just uses the lower bits, so can be OR'd with flags in + * the upper 16 bits (which could be extended further, if needed, maybe + * we extend/overload the pipe-id some day to deal with multiple rings, + * but even then I don't think we need the full lower 16 bits). + */ +#define MSM_PIPE_ID_MASK 0xffff +#define MSM_PIPE_ID(x) ((x) & MSM_PIPE_ID_MASK) +#define MSM_PIPE_FLAGS(x) ((x) & ~MSM_PIPE_ID_MASK) + /* timeouts are specified in clock-monotonic absolute times (to simplify * restarting interrupted ioctls). The following struct is logically the * same as 'struct timespec' but 32/64b ABI safe. @@ -183,17 +192,28 @@ struct drm_msm_gem_submit_bo { __u64 presumed; /* in/out, presumed buffer address */ }; +/* Valid submit ioctl flags: */ +#define MSM_SUBMIT_NO_IMPLICIT 0x80000000 /* disable implicit sync */ +#define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */ +#define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */ +#define MSM_SUBMIT_FLAGS ( \ + MSM_SUBMIT_NO_IMPLICIT | \ + MSM_SUBMIT_FENCE_FD_IN | \ + MSM_SUBMIT_FENCE_FD_OUT | \ + 0) + /* Each cmdstream submit consists of a table of buffers involved, and * one or more cmdstream buffers. This allows for conditional execution * (context-restore), and IB buffers needed for per tile/bin draw cmds. */ struct drm_msm_gem_submit { - __u32 pipe; /* in, MSM_PIPE_x */ + __u32 flags; /* MSM_PIPE_x | MSM_SUBMIT_x */ __u32 fence; /* out */ __u32 nr_bos; /* in, number of submit_bo's */ __u32 nr_cmds; /* in, number of submit_cmd's */ __u64 __user bos; /* in, ptr to array of submit_bo's */ __u64 __user cmds; /* in, ptr to array of submit_cmd's */ + __s32 fence_fd; /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */ }; /* The normal way to synchronize with the GPU is just to CPU_PREP on diff --git a/freedreno/msm/msm_ringbuffer.c b/freedreno/msm/msm_ringbuffer.c index a78806c..60f0315 100644 --- a/freedreno/msm/msm_ringbuffer.c +++ b/freedreno/msm/msm_ringbuffer.c @@ -399,7 +399,7 @@ static int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start { struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); struct drm_msm_gem_submit req = { - .pipe = to_msm_pipe(ring->pipe)->pipe, + .flags = to_msm_pipe(ring->pipe)->pipe, }; uint32_t i; int ret; commit f803a45e744272190aaaab1ad7c702641190d002 Author: Rob Clark <[email protected]> Date: Mon Aug 15 14:45:35 2016 -0400 add libsync.h helper Rather than cut/pasting these couple ioctl wrappers everywhere, just stuff them as static-inline into a header. This is probably mostly used from mesa, but some drivers, test apps, etc may also want to use it from libdrm. v2: handle EINTR, add sync_accumulate() based on #dri-devel discussion, etc Signed-off-by: Rob Clark <[email protected]> Reviewed-by: Chris Wilson <[email protected]> diff --git a/Makefile.sources b/Makefile.sources index a57036a..10aa1d0 100644 --- a/Makefile.sources +++ b/Makefile.sources @@ -13,6 +13,7 @@ LIBDRM_FILES := \ util_math.h LIBDRM_H_FILES := \ + libsync.h \ xf86drm.h \ xf86drmMode.h diff --git a/libsync.h b/libsync.h new file mode 100644 index 0000000..f1a2f96 --- /dev/null +++ b/libsync.h @@ -0,0 +1,148 @@ +/* + * sync abstraction + * Copyright 2015-2016 Collabora Ltd. + * + * Based on the implementation from the Android Open Source Project, + * + * Copyright 2012 Google, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _LIBSYNC_H +#define _LIBSYNC_H + +#include <assert.h> +#include <errno.h> +#include <stdint.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/poll.h> +#include <unistd.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef SYNC_IOC_MERGE +/* duplicated from linux/sync_file.h to avoid build-time dependency + * on new (v4.7) kernel headers. Once distro's are mostly using + * something newer than v4.7 drop this and #include <linux/sync_file.h> + * instead. + */ +struct sync_merge_data { + char name[32]; + int32_t fd2; + int32_t fence; + uint32_t flags; + uint32_t pad; +}; +#define SYNC_IOC_MAGIC '>' +#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) +#endif + + +static inline int sync_wait(int fd, int timeout) +{ + struct pollfd fds = {0}; + int ret; + + fds.fd = fd; + fds.events = POLLIN; + + do { + ret = poll(&fds, 1, timeout); + if (ret > 0) { + if (fds.revents & (POLLERR | POLLNVAL)) { + errno = EINVAL; + return -1; + } + return 0; + } else if (ret == 0) { + errno = ETIME; + return -1; + } + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + return ret; +} + +static inline int sync_merge(const char *name, int fd1, int fd2) +{ + struct sync_merge_data data = {0}; + int ret; + + data.fd2 = fd2; + strncpy(data.name, name, sizeof(data.name)); + + do { + ret = ioctl(fd1, SYNC_IOC_MERGE, &data); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + if (ret < 0) + return ret; + + return data.fence; +} + +/* accumulate fd2 into fd1. If *fd1 is not a valid fd then dup fd2, + * otherwise sync_merge() and close the old *fd1. This can be used + * to implement the pattern: + * + * init() + * { + * batch.fence_fd = -1; + * } + * + * // does *NOT* take ownership of fd + * server_sync(int fd) + * { + * if (sync_accumulate("foo", &batch.fence_fd, fd)) { + * ... error ... + * } + * } + */ +static inline int sync_accumulate(const char *name, int *fd1, int fd2) +{ + int ret; + + assert(fd2 >= 0); + + if (*fd1 < 0) { + *fd1 = dup(fd2); + return 0; + } + + ret = sync_merge(name, *fd1, fd2); + if (ret < 0) { + /* leave *fd1 as it is */ + return ret; + } + + close(*fd1); + *fd1 = ret; + + return 0; +} + +#if defined(__cplusplus) +} +#endif + +#endif ------------------------------------------------------------------------------ Developer Access Program for Intel Xeon Phi Processors Access to Intel Xeon Phi processor-based developer platforms. With one year of Intel Parallel Studio XE. Training and support from Colfax. Order your platform today. http://sdm.link/xeonphi --