diff options
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 | ||