From 9d1e07ca184869eb0082b418d0d1cf6e62af3a40 Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Tue, 14 Apr 2020 16:28:53 +0530 Subject: gpu: nvgpu: change system suspend's implementation Currently, for platforms with canRailgate device characteristics disabled, suspend can block as deterministic channels hold busy references. This patch makes the change to first hold off any new jobs for deterministic channels and then reverts back the busy references taken by those channels. Following this, suspend also waits for the device to get idle by waiting (with timeout) for the nvgpu's internal usage counter to be come zero. This ensures there are no further jobs in progress and allows the system to go into a suspend state. Bug 200598228 Bug 2930266 Change-Id: Id02b4d41a9c2dd64303b2e2449dbed48c12aea4c Signed-off-by: Debarshi Dutta Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2328489 Reviewed-by: automaticguardword Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Konsta Holtta Reviewed-by: Shashank Singh Reviewed-by: Sami Kiminki Reviewed-by: Alex Waterman Reviewed-by: Bibek Basu Reviewed-by: mobile promotions Tested-by: mobile promotions GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/os/linux/module.c | 39 +++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 5627abfd..807df2ca 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -1,7 +1,7 @@ /* * GK20A Graphics * - * Copyright (c) 2011-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2020, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -1058,11 +1058,13 @@ static int gk20a_pm_suspend(struct device *dev) struct gk20a_platform *platform = dev_get_drvdata(dev); struct gk20a *g = get_gk20a(dev); int ret = 0; - int idle_usage_count = 0; + int usage_count; + struct nvgpu_timeout timeout; if (!g->power_on) { if (platform->suspend) ret = platform->suspend(dev); + if (ret) return ret; @@ -1072,20 +1074,43 @@ static int gk20a_pm_suspend(struct device *dev) return ret; } - if (nvgpu_atomic_read(&g->usage_count) > idle_usage_count) - return -EBUSY; + nvgpu_timeout_init(g, &timeout, GK20A_WAIT_FOR_IDLE_MS, + NVGPU_TIMER_CPU_TIMER); + /* + * Hold back deterministic submits and changes to deterministic + * channels - this must be outside the power busy locks. + */ + gk20a_channel_deterministic_idle(g); + + /* check and wait until GPU is idle (with a timeout) */ + do { + nvgpu_usleep_range(1000, 1100); + usage_count = nvgpu_atomic_read(&g->usage_count); + } while (usage_count != 0 && !nvgpu_timeout_expired(&timeout)); + + if (usage_count != 0) { + nvgpu_err(g, "failed to idle - usage_count %d", usage_count); + ret = -EINVAL; + goto fail_idle; + } ret = gk20a_pm_runtime_suspend(dev); if (ret) - return ret; + goto fail_idle; if (platform->suspend) ret = platform->suspend(dev); if (ret) - return ret; + goto fail_suspend; g->suspended = true; + return 0; + +fail_suspend: + gk20a_pm_runtime_resume(dev); +fail_idle: + gk20a_channel_deterministic_unidle(g); return ret; } @@ -1118,6 +1143,8 @@ static int gk20a_pm_resume(struct device *dev) g->suspended = false; + gk20a_channel_deterministic_unidle(g); + return ret; } -- cgit v1.2.2