From 66729149802aa6d0a07dbb4f9bff4950f67810ab Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Wed, 28 Apr 2021 12:30:52 +0530 Subject: [PATCH] gpu: nvgpu: create timed wait functions for stall and nonstall interrupts completion In order to process stalling interrupts during TSG unbind, we need a API to wait for the stalling interrupts to complete within certain duration. Prepare these APIs for stalling and non-stalling interrupts. Bug 200711183 Change-Id: I0b7a64c0f3761bbd0ca0843aea28a591ed23739f Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2521970 Tested-by: mobile promotions Reviewed-by: Deepak Nibade Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/common/mc/mc_intr.c | 28 ++++++++++++--- drivers/gpu/nvgpu/include/nvgpu/mc.h | 52 ++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/nvgpu/common/mc/mc_intr.c b/drivers/gpu/nvgpu/common/mc/mc_intr.c index 86d801ccb..e00b456c3 100644 --- a/drivers/gpu/nvgpu/common/mc/mc_intr.c +++ b/drivers/gpu/nvgpu/common/mc/mc_intr.c @@ -28,17 +28,35 @@ #include #include -void nvgpu_wait_for_deferred_interrupts(struct gk20a *g) +int nvgpu_wait_for_stall_interrupts(struct gk20a *g, u32 timeout) { /* wait until all stalling irqs are handled */ - NVGPU_COND_WAIT(&g->mc.sw_irq_stall_last_handled_cond, + return NVGPU_COND_WAIT(&g->mc.sw_irq_stall_last_handled_cond, nvgpu_atomic_read(&g->mc.sw_irq_stall_pending) == 0, - 0U); + timeout); +} +int nvgpu_wait_for_nonstall_interrupts(struct gk20a *g, u32 timeout) +{ /* wait until all non-stalling irqs are handled */ - NVGPU_COND_WAIT(&g->mc.sw_irq_nonstall_last_handled_cond, + return NVGPU_COND_WAIT(&g->mc.sw_irq_nonstall_last_handled_cond, nvgpu_atomic_read(&g->mc.sw_irq_nonstall_pending) == 0, - 0U); + timeout); +} + +void nvgpu_wait_for_deferred_interrupts(struct gk20a *g) +{ + int ret; + + ret = nvgpu_wait_for_stall_interrupts(g, 0U); + if (ret != 0) { + nvgpu_err(g, "wait for stall interrupts failed %d", ret); + } + + ret = nvgpu_wait_for_nonstall_interrupts(g, 0U); + if (ret != 0) { + nvgpu_err(g, "wait for nonstall interrupts failed %d", ret); + } } void nvgpu_mc_intr_mask(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/include/nvgpu/mc.h b/drivers/gpu/nvgpu/include/nvgpu/mc.h index e8f0511bd..0c1bf4a97 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/mc.h +++ b/drivers/gpu/nvgpu/include/nvgpu/mc.h @@ -325,7 +325,7 @@ struct nvgpu_mc { * One of the condition variables needed to keep track of deferred * interrupts. * The condition variable that is signalled upon handling of the - * stalling interrupt. Function #nvgpu_wait_for_deferred_interrupts + * stalling interrupt. Function #nvgpu_wait_for_stall_interrupts * waits on this condition variable. */ struct nvgpu_cond sw_irq_stall_last_handled_cond; @@ -341,7 +341,7 @@ struct nvgpu_mc { * One of the condition variables needed to keep track of deferred * interrupts. * The condition variable that is signalled upon handling of the - * non-stalling interrupt. Function #nvgpu_wait_for_deferred_interrupts + * non-stalling interrupt. Function #nvgpu_wait_for_nonstall_interrupts * waits on this condition variable. */ struct nvgpu_cond sw_irq_nonstall_last_handled_cond; @@ -361,6 +361,45 @@ struct nvgpu_mc { /** @endcond DOXYGEN_SHOULD_SKIP_THIS */ }; +/** + * @brief Wait for the stalling interrupts to complete. + * + * @param g [in] The GPU driver struct. + * @param timeout [in] Timeout + * + * Steps: + * - Get the stalling interrupts atomic count. + * - Wait for #timeout duration on the condition variable + * #sw_irq_stall_last_handled_cond until #sw_irq_stall_last_handled + * becomes greater than or equal to previously read stalling + * interrupt atomic count. + * + * @retval 0 if wait completes successfully. + * @retval -ETIMEDOUT if wait completes without stalling interrupts + * completing. + */ +int nvgpu_wait_for_stall_interrupts(struct gk20a *g, u32 timeout); + + +/** + * @brief Wait for the non-stalling interrupts to complete. + * + * @param g [in] The GPU driver struct. + * @param timeout [in] Timeout + * + * Steps: + * - Get the non-stalling interrupts atomic count. + * - Wait for #timeout duration on the condition variable + * #sw_irq_nonstall_last_handled_cond until #sw_irq_nonstall_last_handled + * becomes greater than or equal to previously read non-stalling + * interrupt atomic count. + * + * @retval 0 if wait completes successfully. + * @retval -ETIMEDOUT if wait completes without nonstalling interrupts + * completing. + */ +int nvgpu_wait_for_nonstall_interrupts(struct gk20a *g, u32 timeout); + /** * @brief Wait for the interrupts to complete. * @@ -370,13 +409,8 @@ struct nvgpu_mc { * to wait until all scheduled interrupt handlers have completed. This is * because the interrupt handlers could access data structures after freeing. * Steps: - * - Get the stalling and non-stalling interrupts atomic count. - * - Wait on the condition variable #sw_irq_stall_last_handled_cond until - * #sw_irq_stall_last_handled becomes greater than or equal to previously - * read stalling interrupt atomic count. - * - Wait on the condition variable #sw_irq_nonstall_last_handled_cond until - * #sw_irq_nonstall_last_handled becomes greater than or equal to previously - * read non-stalling interrupt atomic count. + * - Wait for stalling interrupts to complete with timeout disabled. + * - Wait for non-stalling interrupts to complete with timeout disabled. */ void nvgpu_wait_for_deferred_interrupts(struct gk20a *g);