From ee25b33ca4aafbbab6e9b7cd963f9011a59037cd Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Tue, 16 May 2017 13:59:31 -0700 Subject: gpu: nvgpu: Proper timeout for NVGPU_COND_WAIT The timeout parameter to NVGPU_COND_WAIT() was passed directly to wait_event_timeout(), which takes jiffies. Also allows zero timeout to disable timeout. The return value of NVGPU_COND_WAIT() was defined in a way specific to how Linux wait_event_() calls work. Replace that with proper error reporting and change the callers to check against error codes. JIRA NVGPU-14 Change-Id: Idbd2c8fbbef7589c3ca4f4c5732852bc71217515 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/1484927 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/linux/ioctl_channel.c | 8 +--- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 10 ++--- drivers/gpu/nvgpu/gk20a/fence_gk20a.c | 9 +---- drivers/gpu/nvgpu/include/nvgpu/linux/cond.h | 51 +++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_channel.c b/drivers/gpu/nvgpu/common/linux/ioctl_channel.c index 4d4d1690..c7adb76c 100644 --- a/drivers/gpu/nvgpu/common/linux/ioctl_channel.c +++ b/drivers/gpu/nvgpu/common/linux/ioctl_channel.c @@ -392,7 +392,6 @@ static int gk20a_channel_wait_semaphore(struct channel_gk20a *ch, void *data; u32 *semaphore; int ret = 0; - long remain; /* do not wait if channel has timed out */ if (ch->has_timedout) @@ -413,16 +412,11 @@ static int gk20a_channel_wait_semaphore(struct channel_gk20a *ch, semaphore = data + (offset & ~PAGE_MASK); - remain = NVGPU_COND_WAIT_INTERRUPTIBLE( + ret = NVGPU_COND_WAIT_INTERRUPTIBLE( &ch->semaphore_wq, *semaphore == payload || ch->has_timedout, timeout); - if (remain == 0 && *semaphore != payload) - ret = -ETIMEDOUT; - else if (remain < 0) - ret = remain; - dma_buf_kunmap(dmabuf, offset >> PAGE_SHIFT, data); cleanup_put: dma_buf_put(dmabuf); diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 6cb77d67..4ee1ab43 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -409,7 +409,7 @@ static void gk20a_wait_until_counter_is_N( if (NVGPU_COND_WAIT( c, atomic_read(counter) == wait_value, - msecs_to_jiffies(5000)) > 0) + 5000) == 0) break; nvgpu_warn(ch->g, @@ -1798,14 +1798,14 @@ static int gk20a_channel_poll_worker(void *arg) start_wait = jiffies; while (!nvgpu_thread_should_stop(&worker->poll_task)) { - bool got_events; + int ret; - got_events = NVGPU_COND_WAIT( + ret = NVGPU_COND_WAIT( &worker->wq, __gk20a_channel_worker_pending(g, get), - timeout) > 0; + jiffies_to_msecs(timeout)) > 0; - if (got_events) + if (ret == 0) gk20a_channel_worker_process(g, &get); if (jiffies - start_wait >= timeout) { diff --git a/drivers/gpu/nvgpu/gk20a/fence_gk20a.c b/drivers/gpu/nvgpu/gk20a/fence_gk20a.c index 3964c37d..7c5d33c7 100644 --- a/drivers/gpu/nvgpu/gk20a/fence_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fence_gk20a.c @@ -203,20 +203,13 @@ void gk20a_init_fence(struct gk20a_fence *f, static int nvgpu_semaphore_fence_wait(struct gk20a_fence *f, long timeout) { - long remain; - if (!nvgpu_semaphore_is_acquired(f->semaphore)) return 0; - remain = NVGPU_COND_WAIT_INTERRUPTIBLE( + return NVGPU_COND_WAIT_INTERRUPTIBLE( f->semaphore_wq, !nvgpu_semaphore_is_acquired(f->semaphore), timeout); - if (remain == 0 && nvgpu_semaphore_is_acquired(f->semaphore)) - return -ETIMEDOUT; - else if (remain < 0) - return remain; - return 0; } static bool nvgpu_semaphore_fence_is_expired(struct gk20a_fence *f) diff --git a/drivers/gpu/nvgpu/include/nvgpu/linux/cond.h b/drivers/gpu/nvgpu/include/nvgpu/linux/cond.h index 3eb52861..01ca5291 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/linux/cond.h +++ b/drivers/gpu/nvgpu/include/nvgpu/linux/cond.h @@ -24,10 +24,57 @@ struct nvgpu_cond { wait_queue_head_t wq; }; +/** + * NVGPU_COND_WAIT - Wait for a condition to be true + * + * @c - The condition variable to sleep on + * @condition - The condition that needs to be true + * @timeout_ms - Timeout in milliseconds, or 0 for infinite wait + * + * Wait for a condition to become true. Returns -ETIMEOUT if + * the wait timed out with condition false. + */ #define NVGPU_COND_WAIT(c, condition, timeout_ms) \ - wait_event_timeout((c)->wq, condition, timeout_ms) +({\ + int ret = 0; \ + long _timeout_ms = timeout_ms;\ + if (_timeout_ms > 0) { \ + long _ret = wait_event_timeout((c)->wq, condition, \ + msecs_to_jiffies(_timeout_ms)); \ + if (_ret == 0) \ + ret = -ETIMEDOUT; \ + } else { \ + wait_event((c)->wq, condition); \ + } \ + ret;\ +}) +/** + * NVGPU_COND_WAIT_INTERRUPTIBLE - Wait for a condition to be true + * + * @c - The condition variable to sleep on + * @condition - The condition that needs to be true + * @timeout_ms - Timeout in milliseconds, or 0 for infinite wait + * + * Wait for a condition to become true. Returns -ETIMEOUT if + * the wait timed out with condition false or -ERESTARTSYS on + * signal. + */ #define NVGPU_COND_WAIT_INTERRUPTIBLE(c, condition, timeout_ms) \ - wait_event_interruptible_timeout((c)->wq, condition, timeout_ms) +({ \ + int ret = 0; \ + long _timeout_ms = timeout_ms;\ + if (_timeout_ms > 0) { \ + long _ret = wait_event_interruptible_timeout((c)->wq, condition, \ + msecs_to_jiffies(_timeout_ms)); \ + if (_ret == 0) \ + ret = -ETIMEDOUT; \ + else if (_ret == -ERESTARTSYS) \ + ret = -ERESTARTSYS; \ + } else { \ + wait_event_interruptible((c)->wq, condition); \ + } \ + ret; \ +}) #endif /* __NVGPU_LOCK_LINUX_H__ */ -- cgit v1.2.2