Commit 56c2da83 authored by Rob Clark's avatar Rob Clark

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 <arnd@arndb.de>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 865807d0
...@@ -204,7 +204,7 @@ int msm_atomic_commit(struct drm_device *dev, ...@@ -204,7 +204,7 @@ int msm_atomic_commit(struct drm_device *dev,
{ {
int nplanes = dev->mode_config.num_total_plane; int nplanes = dev->mode_config.num_total_plane;
int ncrtcs = dev->mode_config.num_crtc; int ncrtcs = dev->mode_config.num_crtc;
struct timespec timeout; ktime_t timeout;
struct msm_commit *c; struct msm_commit *c;
int i, ret; int i, ret;
...@@ -281,7 +281,7 @@ int msm_atomic_commit(struct drm_device *dev, ...@@ -281,7 +281,7 @@ int msm_atomic_commit(struct drm_device *dev,
return 0; 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); ret = msm_wait_fence_interruptable(dev, c->fence, &timeout);
if (ret) { if (ret) {
......
...@@ -638,7 +638,7 @@ static void msm_debugfs_cleanup(struct drm_minor *minor) ...@@ -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, 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; struct msm_drm_private *priv = dev->dev_private;
int ret; int ret;
...@@ -656,14 +656,16 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, ...@@ -656,14 +656,16 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
/* no-wait: */ /* no-wait: */
ret = fence_completed(dev, fence) ? 0 : -EBUSY; ret = fence_completed(dev, fence) ? 0 : -EBUSY;
} else { } else {
unsigned long timeout_jiffies = timespec_to_jiffies(timeout); ktime_t now = ktime_get();
unsigned long start_jiffies = jiffies;
unsigned long remaining_jiffies; unsigned long remaining_jiffies;
if (time_after(start_jiffies, timeout_jiffies)) if (ktime_compare(*timeout, now) < 0) {
remaining_jiffies = 0; remaining_jiffies = 0;
else } else {
remaining_jiffies = timeout_jiffies - start_jiffies; 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, ret = wait_event_interruptible_timeout(priv->fence_event,
fence_completed(dev, fence), fence_completed(dev, fence),
...@@ -772,13 +774,17 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data, ...@@ -772,13 +774,17 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data,
args->flags, &args->handle); 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, static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
struct drm_file *file) struct drm_file *file)
{ {
struct drm_msm_gem_cpu_prep *args = data; struct drm_msm_gem_cpu_prep *args = data;
struct drm_gem_object *obj; struct drm_gem_object *obj;
ktime_t timeout = to_ktime(args->timeout);
int ret; int ret;
if (args->op & ~MSM_PREP_FLAGS) { if (args->op & ~MSM_PREP_FLAGS) {
...@@ -790,7 +796,7 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, ...@@ -790,7 +796,7 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
if (!obj) if (!obj)
return -ENOENT; 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); drm_gem_object_unreference_unlocked(obj);
...@@ -840,14 +846,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, ...@@ -840,14 +846,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
struct drm_file *file) struct drm_file *file)
{ {
struct drm_msm_wait_fence *args = data; struct drm_msm_wait_fence *args = data;
ktime_t timeout = to_ktime(args->timeout);
if (args->pad) { if (args->pad) {
DRM_ERROR("invalid pad: %08x\n", args->pad); DRM_ERROR("invalid pad: %08x\n", args->pad);
return -EINVAL; return -EINVAL;
} }
return msm_wait_fence_interruptable(dev, args->fence, return msm_wait_fence_interruptable(dev, args->fence, &timeout);
&TS(args->timeout));
} }
static const struct drm_ioctl_desc msm_ioctls[] = { static const struct drm_ioctl_desc msm_ioctls[] = {
......
...@@ -165,7 +165,7 @@ int msm_atomic_commit(struct drm_device *dev, ...@@ -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_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, 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, int msm_queue_fence_cb(struct drm_device *dev,
struct msm_fence_cb *cb, uint32_t fence); struct msm_fence_cb *cb, uint32_t fence);
void msm_update_fence(struct drm_device *dev, 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, ...@@ -205,7 +205,7 @@ void msm_gem_move_to_active(struct drm_gem_object *obj,
struct msm_gpu *gpu, bool write, uint32_t fence); struct msm_gpu *gpu, bool write, uint32_t fence);
void msm_gem_move_to_inactive(struct drm_gem_object *obj); void msm_gem_move_to_inactive(struct drm_gem_object *obj);
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, 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); int msm_gem_cpu_fini(struct drm_gem_object *obj);
void msm_gem_free_object(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, int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
......
...@@ -448,8 +448,7 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj) ...@@ -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); list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
} }
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
struct timespec *timeout)
{ {
struct drm_device *dev = obj->dev; struct drm_device *dev = obj->dev;
struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_object *msm_obj = to_msm_bo(obj);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment