From: Dave Airlie airlied@redhat.com
This interface will allow sync object to be used to back Vulkan fences. This API is pretty much the vulkan fence waiting API, and I've ported the code from amdgpu.
v2: accept relative timeout, pass remaining time back to userspace. v3: return to absolute timeouts. v4: absolute zero = poll, rewrite any/all code to have same operation for arrays return -EINVAL for 0 fences. v4.1: fixup fences allocation check, use u64_to_user_ptr v5: move to sec/nsec, and use timespec64 for calcs. v6: use -ETIME and drop the out status flag. (-ETIME is suggested by ickle, I can feel a shed painting) v7: talked to Daniel/Arnd, use ktime and ns everywhere.
Signed-off-by: Dave Airlie airlied@redhat.com --- drivers/gpu/drm/drm_internal.h | 2 + drivers/gpu/drm/drm_ioctl.c | 2 + drivers/gpu/drm/drm_syncobj.c | 135 +++++++++++++++++++++++++++++++++++++++++ include/uapi/drm/drm.h | 12 ++++ 4 files changed, 151 insertions(+)
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 5cecc97..d71b50d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -157,3 +157,5 @@ int drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); int drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); +int drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_private); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index f1e5681..385ce74 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -657,6 +657,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl, + DRM_UNLOCKED|DRM_RENDER_ALLOW), };
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 89441bc..d23dcc6 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1,5 +1,7 @@ /* * Copyright 2017 Red Hat + * Parts ported from amdgpu (fence wait code). + * Copyright 2016 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,6 +33,9 @@ * that contain an optional fence. The fence can be updated with a new * fence, or be NULL. * + * syncobj's can be waited upon, where it will wait for the underlying + * fence. + * * syncobj's can be export to fd's and back, these fd's are opaque and * have no other use case, except passing the syncobj between processes. * @@ -451,3 +456,133 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, return drm_syncobj_fd_to_handle(file_private, args->fd, &args->handle); } + +/** + * drm_timeout_abs_to_jiffies - calculate jiffies timeout from absolute value + * + * @timeout_sec: timeout sec component, 0 for poll + * @timeout_nsec: timeout nsec component in ns, 0 for poll + * both must be 0 for poll. + * + * Calculate the timeout in jiffies from an absolute time in sec/nsec. + */ +static unsigned long drm_timeout_abs_to_jiffies(int64_t timeout_nsec) +{ + ktime_t abs_timeout, timeout, max_jiffy_ktime; + unsigned long timeout_jiffies; + + /* make 0 timeout means poll - absolute 0 doesn't seem valid */ + if (timeout_nsec == 0) + return 0; + + abs_timeout = ns_to_ktime(timeout_nsec); + + timeout = ktime_sub(abs_timeout, ktime_get()); + + max_jiffy_ktime = ns_to_ktime(jiffies_to_nsecs(MAX_JIFFY_OFFSET)); + if (ktime_compare(timeout, max_jiffy_ktime)) + return MAX_SCHEDULE_TIMEOUT - 1; + + timeout_jiffies = nsecs_to_jiffies(ktime_to_ns(timeout)); + /* clamp timeout to avoid infinite timeout */ + if (timeout_jiffies >= MAX_SCHEDULE_TIMEOUT) + return MAX_SCHEDULE_TIMEOUT - 1; + + return timeout_jiffies + 1; +} + +static int drm_syncobj_wait_fences(struct drm_device *dev, + struct drm_file *file_private, + struct drm_syncobj_wait *wait, + struct dma_fence **fences) +{ + unsigned long timeout = drm_timeout_abs_to_jiffies(wait->timeout_nsec); + int ret = 0; + uint32_t first = ~0; + + if (wait->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL) { + int i; + for (i = 0; i < wait->count_handles; i++) { + ret = dma_fence_wait_timeout(fences[i], true, timeout); + + if (ret < 0) + return ret; + if (ret == 0) + break; + timeout = ret; + } + first = 0; + } else { + ret = dma_fence_wait_any_timeout(fences, + wait->count_handles, + true, timeout, + &first); + } + + if (ret < 0) + return ret; + + wait->first_signaled = first; + if (ret == 0) + return -ETIME; + return 0; +} + +int +drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_private) +{ + struct drm_syncobj_wait *args = data; + uint32_t *handles; + struct dma_fence **fences; + int ret = 0; + int i; + + if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) + return -ENODEV; + + if (args->flags != 0 && args->flags != DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL) + return -EINVAL; + + if (args->count_handles == 0) + return -EINVAL; + + /* Get the handles from userspace */ + handles = kmalloc_array(args->count_handles, sizeof(uint32_t), + GFP_KERNEL); + if (handles == NULL) + return -ENOMEM; + + if (copy_from_user(handles, + u64_to_user_ptr(args->handles), + sizeof(uint32_t) * args->count_handles)) { + ret = -EFAULT; + goto err_free_handles; + } + + fences = kcalloc(args->count_handles, + sizeof(struct dma_fence *), GFP_KERNEL); + if (!fences) { + ret = -ENOMEM; + goto err_free_handles; + } + + for (i = 0; i < args->count_handles; i++) { + ret = drm_syncobj_fence_get(file_private, handles[i], + &fences[i]); + if (ret) + goto err_free_fence_array; + } + + ret = drm_syncobj_wait_fences(dev, file_private, + args, fences); + +err_free_fence_array: + for (i = 0; i < args->count_handles; i++) + dma_fence_put(fences[i]); + kfree(fences); +err_free_handles: + kfree(handles); + + return ret; +} diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 101593a..0757c1a 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -718,6 +718,17 @@ struct drm_syncobj_handle { __u32 pad; };
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +struct drm_syncobj_wait { + __u64 handles; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + #if defined(__cplusplus) } #endif @@ -840,6 +851,7 @@ extern "C" { #define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) #define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) #define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait)
/** * Device specific ioctls should only be in their respective headers
Hi Dave,
[auto build test WARNING on drm/drm-next] [also build test WARNING on v4.13-rc1] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Dave-Airlie/drm-syncobj-add-sync-ob... base: git://people.freedesktop.org/~airlied/linux.git drm-next reproduce: make htmldocs
All warnings (new ones prefixed by >>):
WARNING: convert(1) not found, for SVG to PDF conversion install ImageMagick (https://www.imagemagick.org) arch/x86/include/asm/uaccess_32.h:1: warning: no structured comments found include/linux/init.h:1: warning: no structured comments found include/linux/mod_devicetable.h:687: warning: Excess struct/union/enum/typedef member 'ver_major' description in 'fsl_mc_device_id' include/linux/mod_devicetable.h:687: warning: Excess struct/union/enum/typedef member 'ver_minor' description in 'fsl_mc_device_id' kernel/sched/core.c:2088: warning: No description found for parameter 'rf' kernel/sched/core.c:2088: warning: Excess function parameter 'cookie' description in 'try_to_wake_up_local' include/linux/kthread.h:26: warning: Excess function parameter '...' description in 'kthread_create' kernel/sys.c:1: warning: no structured comments found include/linux/device.h:969: warning: No description found for parameter 'dma_ops' drivers/dma-buf/seqno-fence.c:1: warning: no structured comments found include/linux/iio/iio.h:597: warning: No description found for parameter 'trig_readonly' include/linux/iio/trigger.h:151: warning: No description found for parameter 'indio_dev' include/linux/iio/trigger.h:151: warning: No description found for parameter 'trig' include/linux/device.h:970: warning: No description found for parameter 'dma_ops' include/linux/usb/gadget.h:230: warning: No description found for parameter 'claimed' include/linux/usb/gadget.h:230: warning: No description found for parameter 'enabled' include/linux/usb/gadget.h:408: warning: No description found for parameter 'quirk_altset_not_supp' include/linux/usb/gadget.h:408: warning: No description found for parameter 'quirk_stall_not_supp' include/linux/usb/gadget.h:408: warning: No description found for parameter 'quirk_zlp_not_supp' include/drm/drm_drv.h:537: warning: No description found for parameter 'set_busid' include/drm/drm_drv.h:537: warning: No description found for parameter 'debugfs_init' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_open_object' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_close_object' include/drm/drm_drv.h:537: warning: No description found for parameter 'prime_handle_to_fd' include/drm/drm_drv.h:537: warning: No description found for parameter 'prime_fd_to_handle' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_export' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_import' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_pin' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_unpin' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_res_obj' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_get_sg_table' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_import_sg_table' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_vmap' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_vunmap' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_prime_mmap' include/drm/drm_drv.h:537: warning: No description found for parameter 'gem_vm_ops' include/drm/drm_drv.h:537: warning: No description found for parameter 'major' include/drm/drm_drv.h:537: warning: No description found for parameter 'minor' include/drm/drm_drv.h:537: warning: No description found for parameter 'patchlevel' include/drm/drm_drv.h:537: warning: No description found for parameter 'name' include/drm/drm_drv.h:537: warning: No description found for parameter 'desc' include/drm/drm_drv.h:537: warning: No description found for parameter 'date' include/drm/drm_drv.h:537: warning: No description found for parameter 'driver_features' include/drm/drm_drv.h:537: warning: No description found for parameter 'ioctls' include/drm/drm_drv.h:537: warning: No description found for parameter 'num_ioctls' include/drm/drm_drv.h:537: warning: No description found for parameter 'fops' include/drm/drm_color_mgmt.h:1: warning: no structured comments found drivers/gpu/drm/drm_syncobj.c:346: warning: Excess function parameter 'dev' description in 'drm_syncobj_open' drivers/gpu/drm/drm_syncobj.c:371: warning: Excess function parameter 'dev' description in 'drm_syncobj_release'
drivers/gpu/drm/drm_syncobj.c:468: warning: Excess function parameter 'timeout_sec' description in 'drm_timeout_abs_to_jiffies'
include/drm/drm_syncobj.h:1: warning: no structured comments found drivers/gpu/drm/drm_syncobj.c:347: warning: Excess function parameter 'dev' description in 'drm_syncobj_open' drivers/gpu/drm/drm_syncobj.c:372: warning: Excess function parameter 'dev' description in 'drm_syncobj_release' drivers/gpu/drm/drm_syncobj.c:469: warning: Excess function parameter 'timeout_sec' description in 'drm_timeout_abs_to_jiffies' drivers/gpu/host1x/bus.c:50: warning: Excess function parameter 'driver' description in 'host1x_subdev_add' Documentation/core-api/assoc_array.rst:13: WARNING: Enumerated list ends without a blank line; unexpected unindent. Documentation/doc-guide/sphinx.rst:126: ERROR: Unknown target name: "sphinx c domain". kernel/sched/fair.c:7650: WARNING: Inline emphasis start-string without end-string. kernel/time/timer.c:1200: ERROR: Unexpected indentation. kernel/time/timer.c:1202: ERROR: Unexpected indentation. kernel/time/timer.c:1203: WARNING: Block quote ends without a blank line; unexpected unindent. include/linux/wait.h:122: WARNING: Block quote ends without a blank line; unexpected unindent. include/linux/wait.h:125: ERROR: Unexpected indentation. include/linux/wait.h:127: WARNING: Block quote ends without a blank line; unexpected unindent. kernel/time/hrtimer.c:990: WARNING: Block quote ends without a blank line; unexpected unindent. kernel/signal.c:322: WARNING: Inline literal start-string without end-string. include/linux/iio/iio.h:219: ERROR: Unexpected indentation. include/linux/iio/iio.h:220: WARNING: Block quote ends without a blank line; unexpected unindent. include/linux/iio/iio.h:226: WARNING: Definition list ends without a blank line; unexpected unindent. drivers/iio/industrialio-core.c:638: ERROR: Unknown target name: "iio_val". drivers/iio/industrialio-core.c:645: ERROR: Unknown target name: "iio_val". drivers/message/fusion/mptbase.c:5051: WARNING: Definition list ends without a blank line; unexpected unindent. drivers/tty/serial/serial_core.c:1898: WARNING: Definition list ends without a blank line; unexpected unindent. drivers/pci/pci.c:3457: ERROR: Unexpected indentation. include/linux/regulator/driver.h:271: ERROR: Unknown target name: "regulator_regmap_x_voltage". include/linux/spi/spi.h:370: ERROR: Unexpected indentation. drivers/gpu/drm/drm_scdc_helper.c:203: ERROR: Unexpected indentation. drivers/gpu/drm/drm_scdc_helper.c:204: WARNING: Block quote ends without a blank line; unexpected unindent. drivers/gpu/drm/drm_ioctl.c:704: WARNING: Definition list ends without a blank line; unexpected unindent. Documentation/gpu/todo.rst:111: ERROR: Unknown target name: "drm_fb". sound/soc/soc-core.c:2671: ERROR: Unknown target name: "snd_soc_daifmt". sound/core/jack.c:312: ERROR: Unknown target name: "snd_jack_btn". Documentation/userspace-api/unshare.rst:108: WARNING: Inline emphasis start-string without end-string. Documentation/usb/typec.rst:: WARNING: document isn't included in any toctree Documentation/usb/usb3-debug-port.rst:: WARNING: document isn't included in any toctree Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 43: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 56: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 69: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 82: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 96: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 109: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 122: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 133: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 164: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 193: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 43: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 56: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 69: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 82: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 96: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 109: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 122: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 133: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 164: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 193: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 43: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 56: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 69: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 82: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 96: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 109: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 122: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 133: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 164: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 193: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 43: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 56: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 69: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 82: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 96: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 109: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 122: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 133: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 164: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 193: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 43: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 56: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 69: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 82: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 96: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 109: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 122: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 133: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 164: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 193: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 43: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 56: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 69: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 82: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 96: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 109: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 122: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 133: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 164: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "~/.fonts.conf", line 193: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 43: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 56: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 69: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 82: Having multiple values in <test> isn't supported and may not work as expected Fontconfig warning: "/home/kbuild/.config/fontconfig/fonts.conf", line 96: Having multiple values in <test> isn't supported and may not work as expected
vim +468 drivers/gpu/drm/drm_syncobj.c
303 304 int drm_syncobj_export_sync_file(struct drm_file *file_private, 305 int handle, int *p_fd) 306 { 307 int ret; 308 struct dma_fence *fence; 309 struct sync_file *sync_file; 310 int fd = get_unused_fd_flags(O_CLOEXEC); 311 312 if (fd < 0) 313 return fd; 314 315 ret = drm_syncobj_fence_get(file_private, handle, &fence); 316 if (ret) 317 goto err_put_fd; 318 319 sync_file = sync_file_create(fence); 320 321 dma_fence_put(fence); 322 323 if (!sync_file) { 324 ret = -EINVAL; 325 goto err_put_fd; 326 } 327 328 fd_install(fd, sync_file->file); 329 330 *p_fd = fd; 331 return 0; 332 err_put_fd: 333 put_unused_fd(fd); 334 return ret; 335 } 336 /** 337 * drm_syncobj_open - initalizes syncobj file-private structures at devnode open time 338 * @dev: drm_device which is being opened by userspace 339 * @file_private: drm file-private structure to set up 340 * 341 * Called at device open time, sets up the structure for handling refcounting 342 * of sync objects. 343 */ 344 void 345 drm_syncobj_open(struct drm_file *file_private)
346 {
347 idr_init(&file_private->syncobj_idr); 348 spin_lock_init(&file_private->syncobj_table_lock); 349 } 350 351 static int 352 drm_syncobj_release_handle(int id, void *ptr, void *data) 353 { 354 struct drm_syncobj *syncobj = ptr; 355 356 drm_syncobj_put(syncobj); 357 return 0; 358 } 359 360 /** 361 * drm_syncobj_release - release file-private sync object resources 362 * @dev: drm_device which is being closed by userspace 363 * @file_private: drm file-private structure to clean up 364 * 365 * Called at close time when the filp is going away. 366 * 367 * Releases any remaining references on objects by this filp. 368 */ 369 void 370 drm_syncobj_release(struct drm_file *file_private) 371 { 372 idr_for_each(&file_private->syncobj_idr, 373 &drm_syncobj_release_handle, file_private); 374 idr_destroy(&file_private->syncobj_idr); 375 } 376 377 int 378 drm_syncobj_create_ioctl(struct drm_device *dev, void *data, 379 struct drm_file *file_private) 380 { 381 struct drm_syncobj_create *args = data; 382 383 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 384 return -ENODEV; 385 386 /* no valid flags yet */ 387 if (args->flags) 388 return -EINVAL; 389 390 return drm_syncobj_create(file_private, 391 &args->handle); 392 } 393 394 int 395 drm_syncobj_destroy_ioctl(struct drm_device *dev, void *data, 396 struct drm_file *file_private) 397 { 398 struct drm_syncobj_destroy *args = data; 399 400 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 401 return -ENODEV; 402 403 /* make sure padding is empty */ 404 if (args->pad) 405 return -EINVAL; 406 return drm_syncobj_destroy(file_private, args->handle); 407 } 408 409 int 410 drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data, 411 struct drm_file *file_private) 412 { 413 struct drm_syncobj_handle *args = data; 414 415 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 416 return -ENODEV; 417 418 if (args->pad) 419 return -EINVAL; 420 421 if (args->flags != 0 && 422 args->flags != DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) 423 return -EINVAL; 424 425 if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) 426 return drm_syncobj_export_sync_file(file_private, args->handle, 427 &args->fd); 428 429 return drm_syncobj_handle_to_fd(file_private, args->handle, 430 &args->fd); 431 } 432 433 int 434 drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, 435 struct drm_file *file_private) 436 { 437 struct drm_syncobj_handle *args = data; 438 439 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 440 return -ENODEV; 441 442 if (args->pad) 443 return -EINVAL; 444 445 if (args->flags != 0 && 446 args->flags != DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) 447 return -EINVAL; 448 449 if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) 450 return drm_syncobj_import_sync_file_fence(file_private, 451 args->fd, 452 args->handle); 453 454 return drm_syncobj_fd_to_handle(file_private, args->fd, 455 &args->handle); 456 } 457 458 /** 459 * drm_timeout_abs_to_jiffies - calculate jiffies timeout from absolute value 460 * 461 * @timeout_sec: timeout sec component, 0 for poll 462 * @timeout_nsec: timeout nsec component in ns, 0 for poll 463 * both must be 0 for poll. 464 * 465 * Calculate the timeout in jiffies from an absolute time in sec/nsec. 466 */ 467 static unsigned long drm_timeout_abs_to_jiffies(int64_t timeout_nsec)
468 {
469 ktime_t abs_timeout, timeout, max_jiffy_ktime; 470 unsigned long timeout_jiffies; 471 472 /* make 0 timeout means poll - absolute 0 doesn't seem valid */ 473 if (timeout_nsec == 0) 474 return 0; 475 476 abs_timeout = ns_to_ktime(timeout_nsec); 477 478 timeout = ktime_sub(abs_timeout, ktime_get()); 479 480 max_jiffy_ktime = ns_to_ktime(jiffies_to_nsecs(MAX_JIFFY_OFFSET)); 481 if (ktime_compare(timeout, max_jiffy_ktime)) 482 return MAX_SCHEDULE_TIMEOUT - 1; 483 484 timeout_jiffies = nsecs_to_jiffies(ktime_to_ns(timeout)); 485 /* clamp timeout to avoid infinite timeout */ 486 if (timeout_jiffies >= MAX_SCHEDULE_TIMEOUT) 487 return MAX_SCHEDULE_TIMEOUT - 1; 488 489 return timeout_jiffies + 1; 490 } 491
--- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
I'm working on a VK_KHR_external_fence implementation based on this and have found some issues. :-)
On Mon, Jul 17, 2017 at 11:44 PM, Dave Airlie airlied@gmail.com wrote:
From: Dave Airlie airlied@redhat.com
This interface will allow sync object to be used to back Vulkan fences. This API is pretty much the vulkan fence waiting API, and I've ported the code from amdgpu.
v2: accept relative timeout, pass remaining time back to userspace. v3: return to absolute timeouts. v4: absolute zero = poll, rewrite any/all code to have same operation for arrays return -EINVAL for 0 fences. v4.1: fixup fences allocation check, use u64_to_user_ptr v5: move to sec/nsec, and use timespec64 for calcs. v6: use -ETIME and drop the out status flag. (-ETIME is suggested by ickle, I can feel a shed painting) v7: talked to Daniel/Arnd, use ktime and ns everywhere.
Signed-off-by: Dave Airlie airlied@redhat.com
drivers/gpu/drm/drm_internal.h | 2 + drivers/gpu/drm/drm_ioctl.c | 2 + drivers/gpu/drm/drm_syncobj.c | 135 ++++++++++++++++++++++++++++++ +++++++++++ include/uapi/drm/drm.h | 12 ++++ 4 files changed, 151 insertions(+)
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal .h index 5cecc97..d71b50d 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -157,3 +157,5 @@ int drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); int drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); +int drm_syncobj_wait_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index f1e5681..385ce74 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -657,6 +657,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl,
DRM_UNLOCKED|DRM_RENDER_ALLOW),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 89441bc..d23dcc6 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1,5 +1,7 @@ /*
- Copyright 2017 Red Hat
- Parts ported from amdgpu (fence wait code).
- Copyright 2016 Advanced Micro Devices, Inc.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the
"Software"), @@ -31,6 +33,9 @@
- that contain an optional fence. The fence can be updated with a new
- fence, or be NULL.
- syncobj's can be waited upon, where it will wait for the underlying
- fence.
- syncobj's can be export to fd's and back, these fd's are opaque and
- have no other use case, except passing the syncobj between processes.
@@ -451,3 +456,133 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, return drm_syncobj_fd_to_handle(file_private, args->fd, &args->handle); }
+/**
- drm_timeout_abs_to_jiffies - calculate jiffies timeout from absolute
value
- @timeout_sec: timeout sec component, 0 for poll
- @timeout_nsec: timeout nsec component in ns, 0 for poll
- both must be 0 for poll.
- Calculate the timeout in jiffies from an absolute time in sec/nsec.
- */
+static unsigned long drm_timeout_abs_to_jiffies(int64_t timeout_nsec) +{
ktime_t abs_timeout, timeout, max_jiffy_ktime;
unsigned long timeout_jiffies;
/* make 0 timeout means poll - absolute 0 doesn't seem valid */
if (timeout_nsec == 0)
return 0;
abs_timeout = ns_to_ktime(timeout_nsec);
timeout = ktime_sub(abs_timeout, ktime_get());
This can end you up with a negative timeout. dma_fence_wait_timeout will WARN_ON a negative timeout.
max_jiffy_ktime = ns_to_ktime(jiffies_to_nsecs(MAX_JIFFY_OFFSET));
if (ktime_compare(timeout, max_jiffy_ktime))
I think you want a > 0 here because otherwise this is a "!=" comparison which isn't what you want. Either that or use ktime_after().
return MAX_SCHEDULE_TIMEOUT - 1;
timeout_jiffies = nsecs_to_jiffies(ktime_to_ns(timeout));
/* clamp timeout to avoid infinite timeout */
if (timeout_jiffies >= MAX_SCHEDULE_TIMEOUT)
return MAX_SCHEDULE_TIMEOUT - 1;
return timeout_jiffies + 1;
+}
+static int drm_syncobj_wait_fences(struct drm_device *dev,
struct drm_file *file_private,
struct drm_syncobj_wait *wait,
struct dma_fence **fences)
+{
unsigned long timeout = drm_timeout_abs_to_jiffies(wai
t->timeout_nsec);
int ret = 0;
uint32_t first = ~0;
if (wait->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL) {
int i;
for (i = 0; i < wait->count_handles; i++) {
ret = dma_fence_wait_timeout(fences[i], true,
timeout);
Various dma_fence callbacks (including, aparently, i915) return -ENOENT to indicate that the fence has already been signaled. We need to sanitize that to 0 or else we'll return early.
if (ret < 0)
return ret;
if (ret == 0)
break;
timeout = ret;
}
first = 0;
} else {
ret = dma_fence_wait_any_timeout(fences,
wait->count_handles,
true, timeout,
&first);
}
if (ret < 0)
return ret;
wait->first_signaled = first;
if (ret == 0)
return -ETIME;
return 0;
+}
+int +drm_syncobj_wait_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_private)
+{
struct drm_syncobj_wait *args = data;
uint32_t *handles;
struct dma_fence **fences;
int ret = 0;
int i;
if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
return -ENODEV;
if (args->flags != 0 && args->flags !=
DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL)
return -EINVAL;
if (args->count_handles == 0)
return -EINVAL;
/* Get the handles from userspace */
handles = kmalloc_array(args->count_handles, sizeof(uint32_t),
GFP_KERNEL);
if (handles == NULL)
return -ENOMEM;
if (copy_from_user(handles,
u64_to_user_ptr(args->handles),
sizeof(uint32_t) * args->count_handles)) {
ret = -EFAULT;
goto err_free_handles;
}
fences = kcalloc(args->count_handles,
sizeof(struct dma_fence *), GFP_KERNEL);
if (!fences) {
ret = -ENOMEM;
goto err_free_handles;
}
for (i = 0; i < args->count_handles; i++) {
ret = drm_syncobj_fence_get(file_private, handles[i],
&fences[i]);
if (ret)
goto err_free_fence_array;
}
ret = drm_syncobj_wait_fences(dev, file_private,
args, fences);
+err_free_fence_array:
for (i = 0; i < args->count_handles; i++)
dma_fence_put(fences[i]);
kfree(fences);
+err_free_handles:
kfree(handles);
return ret;
+} diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 101593a..0757c1a 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -718,6 +718,17 @@ struct drm_syncobj_handle { __u32 pad; };
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) +struct drm_syncobj_wait {
__u64 handles;
/* absolute timeout */
__s64 timeout_nsec;
__u32 count_handles;
__u32 flags;
__u32 first_signaled; /* only valid when not waiting all */
__u32 pad;
+};
#if defined(__cplusplus) } #endif @@ -840,6 +851,7 @@ extern "C" { #define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy) #define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle) #define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle) +#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait)
/**
- Device specific ioctls should only be in their respective headers
-- 2.9.4
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel@lists.freedesktop.org