diff options
author | Nitin Kumbhar <nkumbhar@nvidia.com> | 2018-09-17 05:48:28 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-09-18 13:34:41 -0400 |
commit | fbc5296e7d8a7eeceba9a904dd4736373c4c6d4e (patch) | |
tree | b382453159410f2f9fef0dabcbe292b44c97afd4 /drivers/gpu/nvgpu | |
parent | 1982d050cc8c90ef269476bec87778e8c3ade5f7 (diff) |
gpu: nvgpu: use single lock for gpu power on-off
Using two separate locks (poweron_lock and poweroff_lock)
allows concurrent gpu power-on and power-off. This shall
not happen as driver won't be able to maintain correct
gpu state.
Use a single power_lock to manage gpu power state. This
lock will be used to manage gpu power state from multiple
triggers like gpu idle, gpu gc-off, etc.
JIRA NVGPU-1100
Change-Id: Ia9b4aeda024a5844ae9f182d453cd6341876680a
Signed-off-by: Nitin Kumbhar <nkumbhar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1827812
Reviewed-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-by: svc-misra-checker <svc-misra-checker@nvidia.com>
Reviewed-by: Debarshi Dutta <ddutta@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/driver_common.c | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/module.c | 40 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c | 22 |
4 files changed, 36 insertions, 32 deletions
diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index 0230709c..1ca6be0d 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h | |||
@@ -1446,8 +1446,7 @@ struct gk20a { | |||
1446 | unsigned int ch_wdt_timeout_ms; | 1446 | unsigned int ch_wdt_timeout_ms; |
1447 | u32 fifo_eng_timeout_us; | 1447 | u32 fifo_eng_timeout_us; |
1448 | 1448 | ||
1449 | struct nvgpu_mutex poweron_lock; | 1449 | struct nvgpu_mutex power_lock; |
1450 | struct nvgpu_mutex poweroff_lock; | ||
1451 | 1450 | ||
1452 | /* Channel priorities */ | 1451 | /* Channel priorities */ |
1453 | u32 timeslice_low_priority_us; | 1452 | u32 timeslice_low_priority_us; |
diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index 6375030b..ebd0b40b 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c | |||
@@ -61,8 +61,7 @@ static void nvgpu_init_vars(struct gk20a *g) | |||
61 | nvgpu_mutex_init(&platform->railgate_lock); | 61 | nvgpu_mutex_init(&platform->railgate_lock); |
62 | nvgpu_mutex_init(&g->dbg_sessions_lock); | 62 | nvgpu_mutex_init(&g->dbg_sessions_lock); |
63 | nvgpu_mutex_init(&g->client_lock); | 63 | nvgpu_mutex_init(&g->client_lock); |
64 | nvgpu_mutex_init(&g->poweron_lock); | 64 | nvgpu_mutex_init(&g->power_lock); |
65 | nvgpu_mutex_init(&g->poweroff_lock); | ||
66 | nvgpu_mutex_init(&g->ctxsw_disable_lock); | 65 | nvgpu_mutex_init(&g->ctxsw_disable_lock); |
67 | nvgpu_mutex_init(&g->tpc_pg_lock); | 66 | nvgpu_mutex_init(&g->tpc_pg_lock); |
68 | nvgpu_mutex_init(&g->clk_arb_enable_lock); | 67 | nvgpu_mutex_init(&g->clk_arb_enable_lock); |
diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 0d4cd7f1..9d84cc2f 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c | |||
@@ -129,18 +129,13 @@ int gk20a_busy(struct gk20a *g) | |||
129 | goto fail; | 129 | goto fail; |
130 | } | 130 | } |
131 | } else { | 131 | } else { |
132 | nvgpu_mutex_acquire(&g->poweron_lock); | 132 | ret = gk20a_gpu_is_virtual(dev) ? |
133 | if (!g->power_on) { | 133 | vgpu_pm_finalize_poweron(dev) : |
134 | ret = gk20a_gpu_is_virtual(dev) ? | 134 | gk20a_pm_finalize_poweron(dev); |
135 | vgpu_pm_finalize_poweron(dev) | 135 | if (ret) { |
136 | : gk20a_pm_finalize_poweron(dev); | 136 | atomic_dec(&g->usage_count.atomic_var); |
137 | if (ret) { | 137 | goto fail; |
138 | atomic_dec(&g->usage_count.atomic_var); | ||
139 | nvgpu_mutex_release(&g->poweron_lock); | ||
140 | goto fail; | ||
141 | } | ||
142 | } | 138 | } |
143 | nvgpu_mutex_release(&g->poweron_lock); | ||
144 | } | 139 | } |
145 | 140 | ||
146 | fail: | 141 | fail: |
@@ -240,12 +235,14 @@ int gk20a_pm_finalize_poweron(struct device *dev) | |||
240 | struct gk20a *g = get_gk20a(dev); | 235 | struct gk20a *g = get_gk20a(dev); |
241 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | 236 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); |
242 | struct gk20a_platform *platform = gk20a_get_platform(dev); | 237 | struct gk20a_platform *platform = gk20a_get_platform(dev); |
243 | int err; | 238 | int err = 0; |
244 | 239 | ||
245 | nvgpu_log_fn(g, " "); | 240 | nvgpu_log_fn(g, " "); |
246 | 241 | ||
242 | nvgpu_mutex_acquire(&g->power_lock); | ||
243 | |||
247 | if (g->power_on) | 244 | if (g->power_on) |
248 | return 0; | 245 | goto done; |
249 | 246 | ||
250 | trace_gk20a_finalize_poweron(dev_name(dev)); | 247 | trace_gk20a_finalize_poweron(dev_name(dev)); |
251 | 248 | ||
@@ -254,13 +251,13 @@ int gk20a_pm_finalize_poweron(struct device *dev) | |||
254 | err = platform->busy(dev); | 251 | err = platform->busy(dev); |
255 | if (err < 0) { | 252 | if (err < 0) { |
256 | nvgpu_err(g, "failed to poweron platform dependency"); | 253 | nvgpu_err(g, "failed to poweron platform dependency"); |
257 | return err; | 254 | goto done; |
258 | } | 255 | } |
259 | } | 256 | } |
260 | 257 | ||
261 | err = gk20a_restore_registers(g); | 258 | err = gk20a_restore_registers(g); |
262 | if (err) | 259 | if (err) |
263 | return err; | 260 | goto done; |
264 | 261 | ||
265 | /* Enable interrupt workqueue */ | 262 | /* Enable interrupt workqueue */ |
266 | if (!l->nonstall_work_queue) { | 263 | if (!l->nonstall_work_queue) { |
@@ -271,7 +268,7 @@ int gk20a_pm_finalize_poweron(struct device *dev) | |||
271 | 268 | ||
272 | err = gk20a_detect_chip(g); | 269 | err = gk20a_detect_chip(g); |
273 | if (err) | 270 | if (err) |
274 | return err; | 271 | goto done; |
275 | 272 | ||
276 | if (g->sim) { | 273 | if (g->sim) { |
277 | if (g->sim->sim_init_late) | 274 | if (g->sim->sim_init_late) |
@@ -319,7 +316,7 @@ int gk20a_pm_finalize_poweron(struct device *dev) | |||
319 | err = gk20a_sched_ctrl_init(g); | 316 | err = gk20a_sched_ctrl_init(g); |
320 | if (err) { | 317 | if (err) { |
321 | nvgpu_err(g, "failed to init sched control"); | 318 | nvgpu_err(g, "failed to init sched control"); |
322 | return err; | 319 | goto done; |
323 | } | 320 | } |
324 | 321 | ||
325 | g->sw_ready = true; | 322 | g->sw_ready = true; |
@@ -328,6 +325,7 @@ done: | |||
328 | if (err) | 325 | if (err) |
329 | g->power_on = false; | 326 | g->power_on = false; |
330 | 327 | ||
328 | nvgpu_mutex_release(&g->power_lock); | ||
331 | return err; | 329 | return err; |
332 | } | 330 | } |
333 | 331 | ||
@@ -356,13 +354,13 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
356 | #ifdef CONFIG_NVGPU_SUPPORT_CDE | 354 | #ifdef CONFIG_NVGPU_SUPPORT_CDE |
357 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | 355 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); |
358 | #endif | 356 | #endif |
359 | int ret = 0; | ||
360 | struct gk20a_platform *platform = gk20a_get_platform(dev); | 357 | struct gk20a_platform *platform = gk20a_get_platform(dev); |
361 | bool irqs_enabled; | 358 | bool irqs_enabled; |
359 | int ret = 0; | ||
362 | 360 | ||
363 | nvgpu_log_fn(g, " "); | 361 | nvgpu_log_fn(g, " "); |
364 | 362 | ||
365 | nvgpu_mutex_acquire(&g->poweroff_lock); | 363 | nvgpu_mutex_acquire(&g->power_lock); |
366 | 364 | ||
367 | if (!g->power_on) | 365 | if (!g->power_on) |
368 | goto done; | 366 | goto done; |
@@ -393,7 +391,7 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
393 | /* Stop CPU from accessing the GPU registers. */ | 391 | /* Stop CPU from accessing the GPU registers. */ |
394 | gk20a_lockout_registers(g); | 392 | gk20a_lockout_registers(g); |
395 | 393 | ||
396 | nvgpu_mutex_release(&g->poweroff_lock); | 394 | nvgpu_mutex_release(&g->power_lock); |
397 | return 0; | 395 | return 0; |
398 | 396 | ||
399 | error: | 397 | error: |
@@ -407,7 +405,7 @@ error: | |||
407 | 405 | ||
408 | gk20a_scale_resume(dev); | 406 | gk20a_scale_resume(dev); |
409 | done: | 407 | done: |
410 | nvgpu_mutex_release(&g->poweroff_lock); | 408 | nvgpu_mutex_release(&g->power_lock); |
411 | 409 | ||
412 | return ret; | 410 | return ret; |
413 | } | 411 | } |
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c index 3fd944f4..7cf22d9d 100644 --- a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c +++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c | |||
@@ -72,8 +72,7 @@ static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform) | |||
72 | { | 72 | { |
73 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | 73 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); |
74 | 74 | ||
75 | nvgpu_mutex_init(&g->poweron_lock); | 75 | nvgpu_mutex_init(&g->power_lock); |
76 | nvgpu_mutex_init(&g->poweroff_lock); | ||
77 | nvgpu_mutex_init(&g->ctxsw_disable_lock); | 76 | nvgpu_mutex_init(&g->ctxsw_disable_lock); |
78 | l->regs_saved = l->regs; | 77 | l->regs_saved = l->regs; |
79 | l->bar1_saved = l->bar1; | 78 | l->bar1_saved = l->bar1; |
@@ -142,16 +141,19 @@ int vgpu_pm_prepare_poweroff(struct device *dev) | |||
142 | 141 | ||
143 | nvgpu_log_fn(g, " "); | 142 | nvgpu_log_fn(g, " "); |
144 | 143 | ||
144 | nvgpu_mutex_acquire(&g->power_lock); | ||
145 | |||
145 | if (!g->power_on) | 146 | if (!g->power_on) |
146 | return 0; | 147 | goto done; |
147 | 148 | ||
148 | if (g->ops.fifo.channel_suspend) | 149 | if (g->ops.fifo.channel_suspend) |
149 | ret = g->ops.fifo.channel_suspend(g); | 150 | ret = g->ops.fifo.channel_suspend(g); |
150 | |||
151 | if (ret) | 151 | if (ret) |
152 | return ret; | 152 | goto done; |
153 | 153 | ||
154 | g->power_on = false; | 154 | g->power_on = false; |
155 | done: | ||
156 | nvgpu_mutex_release(&g->power_lock); | ||
155 | 157 | ||
156 | return ret; | 158 | return ret; |
157 | } | 159 | } |
@@ -160,12 +162,14 @@ int vgpu_pm_finalize_poweron(struct device *dev) | |||
160 | { | 162 | { |
161 | struct gk20a *g = get_gk20a(dev); | 163 | struct gk20a *g = get_gk20a(dev); |
162 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); | 164 | struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); |
163 | int err; | 165 | int err = 0; |
164 | 166 | ||
165 | nvgpu_log_fn(g, " "); | 167 | nvgpu_log_fn(g, " "); |
166 | 168 | ||
169 | nvgpu_mutex_acquire(&g->power_lock); | ||
170 | |||
167 | if (g->power_on) | 171 | if (g->power_on) |
168 | return 0; | 172 | goto done; |
169 | 173 | ||
170 | g->power_on = true; | 174 | g->power_on = true; |
171 | 175 | ||
@@ -220,6 +224,10 @@ int vgpu_pm_finalize_poweron(struct device *dev) | |||
220 | g->sw_ready = true; | 224 | g->sw_ready = true; |
221 | 225 | ||
222 | done: | 226 | done: |
227 | if (err) | ||
228 | g->power_on = false; | ||
229 | |||
230 | nvgpu_mutex_release(&g->power_lock); | ||
223 | return err; | 231 | return err; |
224 | } | 232 | } |
225 | 233 | ||