From 56c2da8338d5cdfc0695eeed96ebe03cf2ac0321 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 11 May 2015 11:50:03 -0400 Subject: [PATCH] drm/msm: fix timeout calculation The 'timeout' value comes from userspace (CLOCK_MONOTONIC), but converting this directly to jiffies doesn't take into account the initial jiffies count at boot, which may differ from the base time of CLOCK_MONOTONIC. TODO: add ktime_delta_jiffies() when rebasing on 4.1 and use that instead of ktime_sub/ktime_to_timespec/timespec_to_jiffies combo (as suggested by Arnd) v2: switch over from 'struct timespec' to ktime_t throughout, since 'struct timespec' will be deprecated (as suggested by Arnd) v3: minor cosmetic tweaks Cc: Arnd Bergmann Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_atomic.c | 4 ++-- drivers/gpu/drm/msm/msm_drv.c | 26 ++++++++++++++++---------- drivers/gpu/drm/msm/msm_drv.h | 4 ++-- drivers/gpu/drm/msm/msm_gem.c | 3 +-- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index b421c843c9df..1b22d8bfe142 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -204,7 +204,7 @@ int msm_atomic_commit(struct drm_device *dev, { int nplanes = dev->mode_config.num_total_plane; int ncrtcs = dev->mode_config.num_crtc; - struct timespec timeout; + ktime_t timeout; struct msm_commit *c; int i, ret; @@ -281,7 +281,7 @@ int msm_atomic_commit(struct drm_device *dev, return 0; } - jiffies_to_timespec(jiffies + msecs_to_jiffies(1000), &timeout); + timeout = ktime_add_ms(ktime_get(), 1000); ret = msm_wait_fence_interruptable(dev, c->fence, &timeout); if (ret) { diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 7efd3071481d..b7ef56ed8d1c 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -638,7 +638,7 @@ static void msm_debugfs_cleanup(struct drm_minor *minor) */ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, - struct timespec *timeout) + ktime_t *timeout) { struct msm_drm_private *priv = dev->dev_private; int ret; @@ -656,14 +656,16 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, /* no-wait: */ ret = fence_completed(dev, fence) ? 0 : -EBUSY; } else { - unsigned long timeout_jiffies = timespec_to_jiffies(timeout); - unsigned long start_jiffies = jiffies; + ktime_t now = ktime_get(); unsigned long remaining_jiffies; - if (time_after(start_jiffies, timeout_jiffies)) + if (ktime_compare(*timeout, now) < 0) { remaining_jiffies = 0; - else - remaining_jiffies = timeout_jiffies - start_jiffies; + } else { + ktime_t rem = ktime_sub(*timeout, now); + struct timespec ts = ktime_to_timespec(rem); + remaining_jiffies = timespec_to_jiffies(&ts); + } ret = wait_event_interruptible_timeout(priv->fence_event, fence_completed(dev, fence), @@ -772,13 +774,17 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data, args->flags, &args->handle); } -#define TS(t) ((struct timespec){ .tv_sec = (t).tv_sec, .tv_nsec = (t).tv_nsec }) +static inline ktime_t to_ktime(struct drm_msm_timespec timeout) +{ + return ktime_set(timeout.tv_sec, timeout.tv_nsec); +} static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_msm_gem_cpu_prep *args = data; struct drm_gem_object *obj; + ktime_t timeout = to_ktime(args->timeout); int ret; if (args->op & ~MSM_PREP_FLAGS) { @@ -790,7 +796,7 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, if (!obj) return -ENOENT; - ret = msm_gem_cpu_prep(obj, args->op, &TS(args->timeout)); + ret = msm_gem_cpu_prep(obj, args->op, &timeout); drm_gem_object_unreference_unlocked(obj); @@ -840,14 +846,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_msm_wait_fence *args = data; + ktime_t timeout = to_ktime(args->timeout); if (args->pad) { DRM_ERROR("invalid pad: %08x\n", args->pad); return -EINVAL; } - return msm_wait_fence_interruptable(dev, args->fence, - &TS(args->timeout)); + return msm_wait_fence_interruptable(dev, args->fence, &timeout); } static const struct drm_ioctl_desc msm_ioctls[] = { diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 04db4bd1b5b6..e7c5ea125d45 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -165,7 +165,7 @@ int msm_atomic_commit(struct drm_device *dev, int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu); int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, - struct timespec *timeout); + ktime_t *timeout); int msm_queue_fence_cb(struct drm_device *dev, struct msm_fence_cb *cb, uint32_t fence); void msm_update_fence(struct drm_device *dev, uint32_t fence); @@ -205,7 +205,7 @@ void msm_gem_move_to_active(struct drm_gem_object *obj, struct msm_gpu *gpu, bool write, uint32_t fence); void msm_gem_move_to_inactive(struct drm_gem_object *obj); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, - struct timespec *timeout); + ktime_t *timeout); int msm_gem_cpu_fini(struct drm_gem_object *obj); void msm_gem_free_object(struct drm_gem_object *obj); int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index dfc74a5736a3..f211b80e3a1e 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -448,8 +448,7 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj) list_add_tail(&msm_obj->mm_list, &priv->inactive_list); } -int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, - struct timespec *timeout) +int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) { struct drm_device *dev = obj->dev; struct msm_gem_object *msm_obj = to_msm_bo(obj); -- 2.34.1