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: Rob Clark <robdclark@gmail.com>
This commit is contained in:
Родитель
865807d0a9
Коммит
56c2da8338
|
@ -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) {
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче