diff options
author | Dave Airlie <airlied@redhat.com> | 2017-04-25 23:09:02 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-06-13 22:11:04 -0400 |
commit | 3ee45a3b533a20ed9fcc11ddb880fc4b30d28f51 (patch) | |
tree | 9cece82033c4a5d5ca25ad68a4fe69390df25eb8 | |
parent | e9083420bbacce27e43d418064d0d2dfb4b37aaa (diff) |
drm/syncobj: add sync_file interaction. (v1.2)
This interface allows importing the fence from a sync_file into
an existing drm sync object, or exporting the fence attached to
an existing drm sync object into a new sync file object.
This should only be used to interact with sync files where necessary.
v1.1: fence put fixes (Chris), drop fence from ioctl names (Chris)
fixup for new fence replace API.
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/drm_syncobj.c | 75 | ||||
-rw-r--r-- | include/uapi/drm/drm.h | 2 |
2 files changed, 75 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 7144825d45f2..89441bc78591 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/file.h> | 45 | #include <linux/file.h> |
46 | #include <linux/fs.h> | 46 | #include <linux/fs.h> |
47 | #include <linux/anon_inodes.h> | 47 | #include <linux/anon_inodes.h> |
48 | #include <linux/sync_file.h> | ||
48 | 49 | ||
49 | #include "drm_internal.h" | 50 | #include "drm_internal.h" |
50 | #include <drm/drm_syncobj.h> | 51 | #include <drm/drm_syncobj.h> |
@@ -276,6 +277,59 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private, | |||
276 | return 0; | 277 | return 0; |
277 | } | 278 | } |
278 | 279 | ||
280 | int drm_syncobj_import_sync_file_fence(struct drm_file *file_private, | ||
281 | int fd, int handle) | ||
282 | { | ||
283 | struct dma_fence *fence = sync_file_get_fence(fd); | ||
284 | struct drm_syncobj *syncobj; | ||
285 | |||
286 | if (!fence) | ||
287 | return -EINVAL; | ||
288 | |||
289 | syncobj = drm_syncobj_find(file_private, handle); | ||
290 | if (!syncobj) { | ||
291 | dma_fence_put(fence); | ||
292 | return -ENOENT; | ||
293 | } | ||
294 | |||
295 | drm_syncobj_replace_fence(file_private, syncobj, fence); | ||
296 | dma_fence_put(fence); | ||
297 | drm_syncobj_put(syncobj); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | int drm_syncobj_export_sync_file(struct drm_file *file_private, | ||
302 | int handle, int *p_fd) | ||
303 | { | ||
304 | int ret; | ||
305 | struct dma_fence *fence; | ||
306 | struct sync_file *sync_file; | ||
307 | int fd = get_unused_fd_flags(O_CLOEXEC); | ||
308 | |||
309 | if (fd < 0) | ||
310 | return fd; | ||
311 | |||
312 | ret = drm_syncobj_fence_get(file_private, handle, &fence); | ||
313 | if (ret) | ||
314 | goto err_put_fd; | ||
315 | |||
316 | sync_file = sync_file_create(fence); | ||
317 | |||
318 | dma_fence_put(fence); | ||
319 | |||
320 | if (!sync_file) { | ||
321 | ret = -EINVAL; | ||
322 | goto err_put_fd; | ||
323 | } | ||
324 | |||
325 | fd_install(fd, sync_file->file); | ||
326 | |||
327 | *p_fd = fd; | ||
328 | return 0; | ||
329 | err_put_fd: | ||
330 | put_unused_fd(fd); | ||
331 | return ret; | ||
332 | } | ||
279 | /** | 333 | /** |
280 | * drm_syncobj_open - initalizes syncobj file-private structures at devnode open time | 334 | * drm_syncobj_open - initalizes syncobj file-private structures at devnode open time |
281 | * @dev: drm_device which is being opened by userspace | 335 | * @dev: drm_device which is being opened by userspace |
@@ -358,9 +412,17 @@ drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data, | |||
358 | if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) | 412 | if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) |
359 | return -ENODEV; | 413 | return -ENODEV; |
360 | 414 | ||
361 | if (args->pad || args->flags) | 415 | if (args->pad) |
362 | return -EINVAL; | 416 | return -EINVAL; |
363 | 417 | ||
418 | if (args->flags != 0 && | ||
419 | args->flags != DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) | ||
420 | return -EINVAL; | ||
421 | |||
422 | if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) | ||
423 | return drm_syncobj_export_sync_file(file_private, args->handle, | ||
424 | &args->fd); | ||
425 | |||
364 | return drm_syncobj_handle_to_fd(file_private, args->handle, | 426 | return drm_syncobj_handle_to_fd(file_private, args->handle, |
365 | &args->fd); | 427 | &args->fd); |
366 | } | 428 | } |
@@ -374,9 +436,18 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, | |||
374 | if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) | 436 | if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) |
375 | return -ENODEV; | 437 | return -ENODEV; |
376 | 438 | ||
377 | if (args->pad || args->flags) | 439 | if (args->pad) |
440 | return -EINVAL; | ||
441 | |||
442 | if (args->flags != 0 && | ||
443 | args->flags != DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) | ||
378 | return -EINVAL; | 444 | return -EINVAL; |
379 | 445 | ||
446 | if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) | ||
447 | return drm_syncobj_import_sync_file_fence(file_private, | ||
448 | args->fd, | ||
449 | args->handle); | ||
450 | |||
380 | return drm_syncobj_fd_to_handle(file_private, args->fd, | 451 | return drm_syncobj_fd_to_handle(file_private, args->fd, |
381 | &args->handle); | 452 | &args->handle); |
382 | } | 453 | } |
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 96c5c789e73d..101593ab10ac 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h | |||
@@ -708,6 +708,8 @@ struct drm_syncobj_destroy { | |||
708 | __u32 pad; | 708 | __u32 pad; |
709 | }; | 709 | }; |
710 | 710 | ||
711 | #define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) | ||
712 | #define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) | ||
711 | struct drm_syncobj_handle { | 713 | struct drm_syncobj_handle { |
712 | __u32 handle; | 714 | __u32 handle; |
713 | __u32 flags; | 715 | __u32 flags; |