From fbc5296e7d8a7eeceba9a904dd4736373c4c6d4e Mon Sep 17 00:00:00 2001 From: Nitin Kumbhar Date: Mon, 17 Sep 2018 15:18:28 +0530 Subject: 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 Reviewed-on: https://git-master.nvidia.com/r/1827812 Reviewed-by: Deepak Nibade Reviewed-by: svc-misra-checker Reviewed-by: Debarshi Dutta Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Alex Waterman Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 3 +-- drivers/gpu/nvgpu/os/linux/driver_common.c | 3 +-- drivers/gpu/nvgpu/os/linux/module.c | 40 +++++++++++++--------------- 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 { unsigned int ch_wdt_timeout_ms; u32 fifo_eng_timeout_us; - struct nvgpu_mutex poweron_lock; - struct nvgpu_mutex poweroff_lock; + struct nvgpu_mutex power_lock; /* Channel priorities */ 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) nvgpu_mutex_init(&platform->railgate_lock); nvgpu_mutex_init(&g->dbg_sessions_lock); nvgpu_mutex_init(&g->client_lock); - nvgpu_mutex_init(&g->poweron_lock); - nvgpu_mutex_init(&g->poweroff_lock); + nvgpu_mutex_init(&g->power_lock); nvgpu_mutex_init(&g->ctxsw_disable_lock); nvgpu_mutex_init(&g->tpc_pg_lock); 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) goto fail; } } else { - nvgpu_mutex_acquire(&g->poweron_lock); - if (!g->power_on) { - ret = gk20a_gpu_is_virtual(dev) ? - vgpu_pm_finalize_poweron(dev) - : gk20a_pm_finalize_poweron(dev); - if (ret) { - atomic_dec(&g->usage_count.atomic_var); - nvgpu_mutex_release(&g->poweron_lock); - goto fail; - } + ret = gk20a_gpu_is_virtual(dev) ? + vgpu_pm_finalize_poweron(dev) : + gk20a_pm_finalize_poweron(dev); + if (ret) { + atomic_dec(&g->usage_count.atomic_var); + goto fail; } - nvgpu_mutex_release(&g->poweron_lock); } fail: @@ -240,12 +235,14 @@ int gk20a_pm_finalize_poweron(struct device *dev) struct gk20a *g = get_gk20a(dev); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct gk20a_platform *platform = gk20a_get_platform(dev); - int err; + int err = 0; nvgpu_log_fn(g, " "); + nvgpu_mutex_acquire(&g->power_lock); + if (g->power_on) - return 0; + goto done; trace_gk20a_finalize_poweron(dev_name(dev)); @@ -254,13 +251,13 @@ int gk20a_pm_finalize_poweron(struct device *dev) err = platform->busy(dev); if (err < 0) { nvgpu_err(g, "failed to poweron platform dependency"); - return err; + goto done; } } err = gk20a_restore_registers(g); if (err) - return err; + goto done; /* Enable interrupt workqueue */ if (!l->nonstall_work_queue) { @@ -271,7 +268,7 @@ int gk20a_pm_finalize_poweron(struct device *dev) err = gk20a_detect_chip(g); if (err) - return err; + goto done; if (g->sim) { if (g->sim->sim_init_late) @@ -319,7 +316,7 @@ int gk20a_pm_finalize_poweron(struct device *dev) err = gk20a_sched_ctrl_init(g); if (err) { nvgpu_err(g, "failed to init sched control"); - return err; + goto done; } g->sw_ready = true; @@ -328,6 +325,7 @@ done: if (err) g->power_on = false; + nvgpu_mutex_release(&g->power_lock); return err; } @@ -356,13 +354,13 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) #ifdef CONFIG_NVGPU_SUPPORT_CDE struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); #endif - int ret = 0; struct gk20a_platform *platform = gk20a_get_platform(dev); bool irqs_enabled; + int ret = 0; nvgpu_log_fn(g, " "); - nvgpu_mutex_acquire(&g->poweroff_lock); + nvgpu_mutex_acquire(&g->power_lock); if (!g->power_on) goto done; @@ -393,7 +391,7 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) /* Stop CPU from accessing the GPU registers. */ gk20a_lockout_registers(g); - nvgpu_mutex_release(&g->poweroff_lock); + nvgpu_mutex_release(&g->power_lock); return 0; error: @@ -407,7 +405,7 @@ error: gk20a_scale_resume(dev); done: - nvgpu_mutex_release(&g->poweroff_lock); + nvgpu_mutex_release(&g->power_lock); return ret; } 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) { struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - nvgpu_mutex_init(&g->poweron_lock); - nvgpu_mutex_init(&g->poweroff_lock); + nvgpu_mutex_init(&g->power_lock); nvgpu_mutex_init(&g->ctxsw_disable_lock); l->regs_saved = l->regs; l->bar1_saved = l->bar1; @@ -142,16 +141,19 @@ int vgpu_pm_prepare_poweroff(struct device *dev) nvgpu_log_fn(g, " "); + nvgpu_mutex_acquire(&g->power_lock); + if (!g->power_on) - return 0; + goto done; if (g->ops.fifo.channel_suspend) ret = g->ops.fifo.channel_suspend(g); - if (ret) - return ret; + goto done; g->power_on = false; + done: + nvgpu_mutex_release(&g->power_lock); return ret; } @@ -160,12 +162,14 @@ int vgpu_pm_finalize_poweron(struct device *dev) { struct gk20a *g = get_gk20a(dev); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); - int err; + int err = 0; nvgpu_log_fn(g, " "); + nvgpu_mutex_acquire(&g->power_lock); + if (g->power_on) - return 0; + goto done; g->power_on = true; @@ -220,6 +224,10 @@ int vgpu_pm_finalize_poweron(struct device *dev) g->sw_ready = true; done: + if (err) + g->power_on = false; + + nvgpu_mutex_release(&g->power_lock); return err; } -- cgit v1.2.2