Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+75 -2
+73 -2
drivers/gpu/drm/drm_syncobj.c
··· 45 45 #include <linux/file.h> 46 46 #include <linux/fs.h> 47 47 #include <linux/anon_inodes.h> 48 + #include <linux/sync_file.h> 48 49 49 50 #include "drm_internal.h" 50 51 #include <drm/drm_syncobj.h> ··· 277 276 return 0; 278 277 } 279 278 279 + int drm_syncobj_import_sync_file_fence(struct drm_file *file_private, 280 + int fd, int handle) 281 + { 282 + struct dma_fence *fence = sync_file_get_fence(fd); 283 + struct drm_syncobj *syncobj; 284 + 285 + if (!fence) 286 + return -EINVAL; 287 + 288 + syncobj = drm_syncobj_find(file_private, handle); 289 + if (!syncobj) { 290 + dma_fence_put(fence); 291 + return -ENOENT; 292 + } 293 + 294 + drm_syncobj_replace_fence(file_private, syncobj, fence); 295 + dma_fence_put(fence); 296 + drm_syncobj_put(syncobj); 297 + return 0; 298 + } 299 + 300 + int drm_syncobj_export_sync_file(struct drm_file *file_private, 301 + int handle, int *p_fd) 302 + { 303 + int ret; 304 + struct dma_fence *fence; 305 + struct sync_file *sync_file; 306 + int fd = get_unused_fd_flags(O_CLOEXEC); 307 + 308 + if (fd < 0) 309 + return fd; 310 + 311 + ret = drm_syncobj_fence_get(file_private, handle, &fence); 312 + if (ret) 313 + goto err_put_fd; 314 + 315 + sync_file = sync_file_create(fence); 316 + 317 + dma_fence_put(fence); 318 + 319 + if (!sync_file) { 320 + ret = -EINVAL; 321 + goto err_put_fd; 322 + } 323 + 324 + fd_install(fd, sync_file->file); 325 + 326 + *p_fd = fd; 327 + return 0; 328 + err_put_fd: 329 + put_unused_fd(fd); 330 + return ret; 331 + } 280 332 /** 281 333 * drm_syncobj_open - initalizes syncobj file-private structures at devnode open time 282 334 * @dev: drm_device which is being opened by userspace ··· 412 358 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 413 359 return -ENODEV; 414 360 415 - if (args->pad || args->flags) 361 + if (args->pad) 416 362 return -EINVAL; 363 + 364 + if (args->flags != 0 && 365 + args->flags != DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) 366 + return -EINVAL; 367 + 368 + if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) 369 + return drm_syncobj_export_sync_file(file_private, args->handle, 370 + &args->fd); 417 371 418 372 return drm_syncobj_handle_to_fd(file_private, args->handle, 419 373 &args->fd); ··· 436 374 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 437 375 return -ENODEV; 438 376 439 - if (args->pad || args->flags) 377 + if (args->pad) 440 378 return -EINVAL; 379 + 380 + if (args->flags != 0 && 381 + args->flags != DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) 382 + return -EINVAL; 383 + 384 + if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) 385 + return drm_syncobj_import_sync_file_fence(file_private, 386 + args->fd, 387 + args->handle); 441 388 442 389 return drm_syncobj_fd_to_handle(file_private, args->fd, 443 390 &args->handle);
+2
include/uapi/drm/drm.h
··· 708 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 713 struct drm_syncobj_handle { 712 714 __u32 handle; 713 715 __u32 flags;