diff options
Diffstat (limited to 'tegra/fence.c')
-rw-r--r-- | tegra/fence.c | 95 |
1 files changed, 69 insertions, 26 deletions
diff --git a/tegra/fence.c b/tegra/fence.c index a2dd394e..7e3dc432 100644 --- a/tegra/fence.c +++ b/tegra/fence.c @@ -1,7 +1,5 @@ /* - * Copyright © 2012, 2013 Thierry Reding - * Copyright © 2013 Erik Faye-Lund - * Copyright © 2014 NVIDIA Corporation + * Copyright © 2018 NVIDIA Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,44 +25,89 @@ #endif #include <errno.h> +#include <stdbool.h> +#include <stdio.h> /* XXX remove */ #include <string.h> +#include <unistd.h> #include <sys/ioctl.h> +#include <sys/poll.h> #include "private.h" -int drm_tegra_fence_wait_timeout(struct drm_tegra_fence *fence, - unsigned long timeout) +static int drm_tegra_syncobj_destroy(struct drm_tegra *drm, uint32_t handle) { - struct drm_tegra_syncpt_wait args; + struct drm_syncobj_destroy args; int err; memset(&args, 0, sizeof(args)); - args.id = fence->syncpt; - args.thresh = fence->value; - args.timeout = timeout; + args.handle = handle; - while (true) { - err = ioctl(fence->drm->fd, DRM_IOCTL_TEGRA_SYNCPT_WAIT, &args); - if (err < 0) { - if (errno == EINTR) - continue; - - return -errno; - } - - break; - } + err = ioctl(drm->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args); + if (err < 0) + return -errno; return 0; } -int drm_tegra_fence_wait(struct drm_tegra_fence *fence) +int drm_tegra_fence_wait(struct drm_tegra *drm, struct drm_tegra_fence *fence) { - return drm_tegra_fence_wait_timeout(fence, -1); -} + int err; -void drm_tegra_fence_free(struct drm_tegra_fence *fence) -{ - free(fence); + if ((fence->flags & DRM_TEGRA_FENCE_EMIT) == 0) + return 0; + + printf("fence: %p\n", fence); + printf(" handle: %u\n", fence->handle); + printf(" flags: %x\n", fence->flags); + printf(" offset: %x\n", fence->offset); + printf(" index: %u\n", fence->index); + printf(" value: %u\n", fence->value); + + if (fence->flags & DRM_TEGRA_FENCE_FD) { + while (true) { + struct pollfd fds = { + .fd = fence->handle, + .events = POLLIN, + }; + + err = poll(&fds, 1, -1); + if (err > 0) { + if (fds.revents & (POLLERR | POLLNVAL)) + err = -EINVAL; + else + err = 0; + + break; + } + + if (err == 0) { + err = -ETIMEDOUT; + break; + } + + if (errno != EINTR && errno != EAGAIN) { + err = -errno; + break; + } + } + + close(fence->handle); + } else { + struct drm_syncobj_wait args; + + memset(&args, 0, sizeof(args)); + args.handles = (uintptr_t)&fence->handle; + args.count_handles = 1; + args.timeout_nsec = -1; + args.flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL; + + err = ioctl(drm->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); + if (err < 0) + err = -errno; + + drm_tegra_syncobj_destroy(drm, fence->handle); + } + + return err; } |