diff options
author | Eric Anholt <eric@anholt.net> | 2015-01-18 09:19:31 +1300 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2015-06-04 14:15:31 -0700 |
commit | cf24e99f0ac4918658db934ff0ab027bc41b646b (patch) | |
tree | ef8c495016bfa67edd65d8dcc75dc40eb007ba3a | |
parent | 19d37d01bc3ff4545149cfce00992fc58b28377e (diff) | |
download | linux-cf24e99f0ac4918658db934ff0ab027bc41b646b.tar.gz |
drm/vc4: Make sure that waits that get interrupted don't wait forever.
danvet's talk recommended avoiding relative waits entirely, but his
example was of relative waits with units (vblank numbers) that were
potentially longer than the interval between signals coming in, so you
couldn't adjust the ioctl arguments appropriately.
This change also has a wait unit that might be too large (jiffies),
but given that the other argument (an emitted seqno) is guaranteed to
eventually result in a nonblocking successful return, this isn't
really a big deal.
Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_gem.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 9343f36272c0..34036c3f0f50 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -505,13 +505,31 @@ vc4_job_done_work(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } +static int +vc4_wait_for_seqno_ioctl_helper(struct drm_device *dev, + uint64_t seqno, + uint64_t *timeout_ns) +{ + unsigned long start = jiffies; + int ret = vc4_wait_for_seqno(dev, seqno, *timeout_ns); + + if (ret == -EINTR || ret == -ERESTARTSYS) { + uint64_t delta = jiffies_to_nsecs(jiffies - start); + if (*timeout_ns >= delta) + *timeout_ns -= delta; + } + + return ret; +} + int vc4_wait_seqno_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_vc4_wait_seqno *args = data; - return vc4_wait_for_seqno(dev, args->seqno, args->timeout_ns); + return vc4_wait_for_seqno_ioctl_helper(dev, args->seqno, + &args->timeout_ns); } int @@ -530,7 +548,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data, } bo = to_vc4_bo(gem_obj); - ret = vc4_wait_for_seqno(dev, bo->seqno, args->timeout_ns); + ret = vc4_wait_for_seqno_ioctl_helper(dev, bo->seqno, &args->timeout_ns); drm_gem_object_unreference(gem_obj); return ret; |