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 <ddutta@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2328489
(cherry picked from commit 9d1e07ca18)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2330159
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Debarshi Dutta
2020-04-14 16:28:53 +05:30
committed by Alex Waterman
parent e9747d5477
commit c1521a7bba

View File

@@ -1338,11 +1338,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 (nvgpu_is_powered_off(g)) {
if (platform->suspend)
ret = platform->suspend(dev);
if (ret)
return ret;
@@ -1352,20 +1354,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.
*/
nvgpu_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:
nvgpu_channel_deterministic_unidle(g);
return ret;
}
@@ -1398,6 +1423,8 @@ static int gk20a_pm_resume(struct device *dev)
g->suspended = false;
nvgpu_channel_deterministic_unidle(g);
return ret;
}