diff options
author | Debarshi Dutta <ddutta@nvidia.com> | 2020-04-14 06:58:53 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2020-04-16 12:55:31 -0400 |
commit | 9d1e07ca184869eb0082b418d0d1cf6e62af3a40 (patch) | |
tree | b1a0f0ce6a872dfc9622ff3d65f967154890e509 /drivers/gpu/nvgpu/os | |
parent | 06942bd268fca1bbe37f11710cfc655708291ecc (diff) |
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
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-by: Shashank Singh <shashsingh@nvidia.com>
Reviewed-by: Sami Kiminki <skiminki@nvidia.com>
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/gpu/nvgpu/os')
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/module.c | 39 |
1 files 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 @@ | |||
1 | /* | 1 | /* |
2 | * GK20A Graphics | 2 | * GK20A Graphics |
3 | * | 3 | * |
4 | * Copyright (c) 2011-2018, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2011-2020, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -1058,11 +1058,13 @@ static int gk20a_pm_suspend(struct device *dev) | |||
1058 | struct gk20a_platform *platform = dev_get_drvdata(dev); | 1058 | struct gk20a_platform *platform = dev_get_drvdata(dev); |
1059 | struct gk20a *g = get_gk20a(dev); | 1059 | struct gk20a *g = get_gk20a(dev); |
1060 | int ret = 0; | 1060 | int ret = 0; |
1061 | int idle_usage_count = 0; | 1061 | int usage_count; |
1062 | struct nvgpu_timeout timeout; | ||
1062 | 1063 | ||
1063 | if (!g->power_on) { | 1064 | if (!g->power_on) { |
1064 | if (platform->suspend) | 1065 | if (platform->suspend) |
1065 | ret = platform->suspend(dev); | 1066 | ret = platform->suspend(dev); |
1067 | |||
1066 | if (ret) | 1068 | if (ret) |
1067 | return ret; | 1069 | return ret; |
1068 | 1070 | ||
@@ -1072,20 +1074,43 @@ static int gk20a_pm_suspend(struct device *dev) | |||
1072 | return ret; | 1074 | return ret; |
1073 | } | 1075 | } |
1074 | 1076 | ||
1075 | if (nvgpu_atomic_read(&g->usage_count) > idle_usage_count) | 1077 | nvgpu_timeout_init(g, &timeout, GK20A_WAIT_FOR_IDLE_MS, |
1076 | return -EBUSY; | 1078 | NVGPU_TIMER_CPU_TIMER); |
1079 | /* | ||
1080 | * Hold back deterministic submits and changes to deterministic | ||
1081 | * channels - this must be outside the power busy locks. | ||
1082 | */ | ||
1083 | gk20a_channel_deterministic_idle(g); | ||
1084 | |||
1085 | /* check and wait until GPU is idle (with a timeout) */ | ||
1086 | do { | ||
1087 | nvgpu_usleep_range(1000, 1100); | ||
1088 | usage_count = nvgpu_atomic_read(&g->usage_count); | ||
1089 | } while (usage_count != 0 && !nvgpu_timeout_expired(&timeout)); | ||
1090 | |||
1091 | if (usage_count != 0) { | ||
1092 | nvgpu_err(g, "failed to idle - usage_count %d", usage_count); | ||
1093 | ret = -EINVAL; | ||
1094 | goto fail_idle; | ||
1095 | } | ||
1077 | 1096 | ||
1078 | ret = gk20a_pm_runtime_suspend(dev); | 1097 | ret = gk20a_pm_runtime_suspend(dev); |
1079 | if (ret) | 1098 | if (ret) |
1080 | return ret; | 1099 | goto fail_idle; |
1081 | 1100 | ||
1082 | if (platform->suspend) | 1101 | if (platform->suspend) |
1083 | ret = platform->suspend(dev); | 1102 | ret = platform->suspend(dev); |
1084 | if (ret) | 1103 | if (ret) |
1085 | return ret; | 1104 | goto fail_suspend; |
1086 | 1105 | ||
1087 | g->suspended = true; | 1106 | g->suspended = true; |
1088 | 1107 | ||
1108 | return 0; | ||
1109 | |||
1110 | fail_suspend: | ||
1111 | gk20a_pm_runtime_resume(dev); | ||
1112 | fail_idle: | ||
1113 | gk20a_channel_deterministic_unidle(g); | ||
1089 | return ret; | 1114 | return ret; |
1090 | } | 1115 | } |
1091 | 1116 | ||
@@ -1118,6 +1143,8 @@ static int gk20a_pm_resume(struct device *dev) | |||
1118 | 1143 | ||
1119 | g->suspended = false; | 1144 | g->suspended = false; |
1120 | 1145 | ||
1146 | gk20a_channel_deterministic_unidle(g); | ||
1147 | |||
1121 | return ret; | 1148 | return ret; |
1122 | } | 1149 | } |
1123 | 1150 | ||