summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Kurzinger <ekurzinger@nvidia.com>2023-08-16 09:26:05 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-11-20 11:06:57 +0100
commit876a119790e530bf1f4f92ec08d1ff5b01041f58 (patch)
tree346e651474bb62ec445a835a4a99718a2579c81e
parentb9bc1806b90772889d8ffc6f93efd87ee308c921 (diff)
downloadlinux-stable-876a119790e530bf1f4f92ec08d1ff5b01041f58.tar.gz
linux-stable-876a119790e530bf1f4f92ec08d1ff5b01041f58.tar.bz2
linux-stable-876a119790e530bf1f4f92ec08d1ff5b01041f58.zip
drm/syncobj: fix DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
[ Upstream commit 101c9f637efa1655f55876644d4439e552267527 ] If DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT is invoked with the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE flag set but no fence has yet been submitted for the given timeline point the call will fail immediately with EINVAL. This does not match the intended behavior where the call should wait until the fence has been submitted (or the timeout expires). The following small example program illustrates the issue. It should wait for 5 seconds and then print ETIME, but instead it terminates right away after printing EINVAL. #include <stdio.h> #include <fcntl.h> #include <time.h> #include <errno.h> #include <xf86drm.h> int main(void) { int fd = open("/dev/dri/card0", O_RDWR); uint32_t syncobj; drmSyncobjCreate(fd, 0, &syncobj); struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); uint64_t point = 1; if (drmSyncobjTimelineWait(fd, &syncobj, &point, 1, ts.tv_sec * 1000000000 + ts.tv_nsec + 5000000000, // 5s DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, NULL)) { printf("drmSyncobjTimelineWait failed %d\n", errno); } } Fixes: 01d6c3578379 ("drm/syncobj: add support for timeline point wait v8") Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com> Reviewed by: Simon Ser <contact@emersion.fd> Signed-off-by: Simon Ser <contact@emersion.fr> Link: https://patchwork.freedesktop.org/patch/msgid/1fac96f1-2f3f-f9f9-4eb0-340f27a8f6c0@nvidia.com Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/gpu/drm/drm_syncobj.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 993898a2c779..738e60139db9 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -983,7 +983,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
fence = drm_syncobj_fence_get(syncobjs[i]);
if (!fence || dma_fence_chain_find_seqno(&fence, points[i])) {
dma_fence_put(fence);
- if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
+ if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) {
continue;
} else {
timeout = -EINVAL;