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>
This commit is contained in:
Nitin Kumbhar
2018-09-17 15:18:28 +05:30
committed by mobile promotions
parent 1982d050cc
commit fbc5296e7d
4 changed files with 36 additions and 32 deletions

View File

@@ -1446,8 +1446,7 @@ struct gk20a {
unsigned int ch_wdt_timeout_ms; unsigned int ch_wdt_timeout_ms;
u32 fifo_eng_timeout_us; u32 fifo_eng_timeout_us;
struct nvgpu_mutex poweron_lock; struct nvgpu_mutex power_lock;
struct nvgpu_mutex poweroff_lock;
/* Channel priorities */ /* Channel priorities */
u32 timeslice_low_priority_us; u32 timeslice_low_priority_us;

View File

@@ -61,8 +61,7 @@ static void nvgpu_init_vars(struct gk20a *g)
nvgpu_mutex_init(&platform->railgate_lock); nvgpu_mutex_init(&platform->railgate_lock);
nvgpu_mutex_init(&g->dbg_sessions_lock); nvgpu_mutex_init(&g->dbg_sessions_lock);
nvgpu_mutex_init(&g->client_lock); nvgpu_mutex_init(&g->client_lock);
nvgpu_mutex_init(&g->poweron_lock); nvgpu_mutex_init(&g->power_lock);
nvgpu_mutex_init(&g->poweroff_lock);
nvgpu_mutex_init(&g->ctxsw_disable_lock); nvgpu_mutex_init(&g->ctxsw_disable_lock);
nvgpu_mutex_init(&g->tpc_pg_lock); nvgpu_mutex_init(&g->tpc_pg_lock);
nvgpu_mutex_init(&g->clk_arb_enable_lock); nvgpu_mutex_init(&g->clk_arb_enable_lock);

View File

@@ -129,19 +129,14 @@ int gk20a_busy(struct gk20a *g)
goto fail; goto fail;
} }
} else { } else {
nvgpu_mutex_acquire(&g->poweron_lock);
if (!g->power_on) {
ret = gk20a_gpu_is_virtual(dev) ? ret = gk20a_gpu_is_virtual(dev) ?
vgpu_pm_finalize_poweron(dev) vgpu_pm_finalize_poweron(dev) :
: gk20a_pm_finalize_poweron(dev); gk20a_pm_finalize_poweron(dev);
if (ret) { if (ret) {
atomic_dec(&g->usage_count.atomic_var); atomic_dec(&g->usage_count.atomic_var);
nvgpu_mutex_release(&g->poweron_lock);
goto fail; goto fail;
} }
} }
nvgpu_mutex_release(&g->poweron_lock);
}
fail: fail:
up_read(&l->busy_lock); up_read(&l->busy_lock);
@@ -240,12 +235,14 @@ int gk20a_pm_finalize_poweron(struct device *dev)
struct gk20a *g = get_gk20a(dev); struct gk20a *g = get_gk20a(dev);
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
struct gk20a_platform *platform = gk20a_get_platform(dev); struct gk20a_platform *platform = gk20a_get_platform(dev);
int err; int err = 0;
nvgpu_log_fn(g, " "); nvgpu_log_fn(g, " ");
nvgpu_mutex_acquire(&g->power_lock);
if (g->power_on) if (g->power_on)
return 0; goto done;
trace_gk20a_finalize_poweron(dev_name(dev)); trace_gk20a_finalize_poweron(dev_name(dev));
@@ -254,13 +251,13 @@ int gk20a_pm_finalize_poweron(struct device *dev)
err = platform->busy(dev); err = platform->busy(dev);
if (err < 0) { if (err < 0) {
nvgpu_err(g, "failed to poweron platform dependency"); nvgpu_err(g, "failed to poweron platform dependency");
return err; goto done;
} }
} }
err = gk20a_restore_registers(g); err = gk20a_restore_registers(g);
if (err) if (err)
return err; goto done;
/* Enable interrupt workqueue */ /* Enable interrupt workqueue */
if (!l->nonstall_work_queue) { if (!l->nonstall_work_queue) {
@@ -271,7 +268,7 @@ int gk20a_pm_finalize_poweron(struct device *dev)
err = gk20a_detect_chip(g); err = gk20a_detect_chip(g);
if (err) if (err)
return err; goto done;
if (g->sim) { if (g->sim) {
if (g->sim->sim_init_late) if (g->sim->sim_init_late)
@@ -319,7 +316,7 @@ int gk20a_pm_finalize_poweron(struct device *dev)
err = gk20a_sched_ctrl_init(g); err = gk20a_sched_ctrl_init(g);
if (err) { if (err) {
nvgpu_err(g, "failed to init sched control"); nvgpu_err(g, "failed to init sched control");
return err; goto done;
} }
g->sw_ready = true; g->sw_ready = true;
@@ -328,6 +325,7 @@ done:
if (err) if (err)
g->power_on = false; g->power_on = false;
nvgpu_mutex_release(&g->power_lock);
return err; return err;
} }
@@ -356,13 +354,13 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
#ifdef CONFIG_NVGPU_SUPPORT_CDE #ifdef CONFIG_NVGPU_SUPPORT_CDE
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
#endif #endif
int ret = 0;
struct gk20a_platform *platform = gk20a_get_platform(dev); struct gk20a_platform *platform = gk20a_get_platform(dev);
bool irqs_enabled; bool irqs_enabled;
int ret = 0;
nvgpu_log_fn(g, " "); nvgpu_log_fn(g, " ");
nvgpu_mutex_acquire(&g->poweroff_lock); nvgpu_mutex_acquire(&g->power_lock);
if (!g->power_on) if (!g->power_on)
goto done; goto done;
@@ -393,7 +391,7 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
/* Stop CPU from accessing the GPU registers. */ /* Stop CPU from accessing the GPU registers. */
gk20a_lockout_registers(g); gk20a_lockout_registers(g);
nvgpu_mutex_release(&g->poweroff_lock); nvgpu_mutex_release(&g->power_lock);
return 0; return 0;
error: error:
@@ -407,7 +405,7 @@ error:
gk20a_scale_resume(dev); gk20a_scale_resume(dev);
done: done:
nvgpu_mutex_release(&g->poweroff_lock); nvgpu_mutex_release(&g->power_lock);
return ret; return ret;
} }

View File

@@ -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); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
nvgpu_mutex_init(&g->poweron_lock); nvgpu_mutex_init(&g->power_lock);
nvgpu_mutex_init(&g->poweroff_lock);
nvgpu_mutex_init(&g->ctxsw_disable_lock); nvgpu_mutex_init(&g->ctxsw_disable_lock);
l->regs_saved = l->regs; l->regs_saved = l->regs;
l->bar1_saved = l->bar1; l->bar1_saved = l->bar1;
@@ -142,16 +141,19 @@ int vgpu_pm_prepare_poweroff(struct device *dev)
nvgpu_log_fn(g, " "); nvgpu_log_fn(g, " ");
nvgpu_mutex_acquire(&g->power_lock);
if (!g->power_on) if (!g->power_on)
return 0; goto done;
if (g->ops.fifo.channel_suspend) if (g->ops.fifo.channel_suspend)
ret = g->ops.fifo.channel_suspend(g); ret = g->ops.fifo.channel_suspend(g);
if (ret) if (ret)
return ret; goto done;
g->power_on = false; g->power_on = false;
done:
nvgpu_mutex_release(&g->power_lock);
return ret; return ret;
} }
@@ -160,12 +162,14 @@ int vgpu_pm_finalize_poweron(struct device *dev)
{ {
struct gk20a *g = get_gk20a(dev); struct gk20a *g = get_gk20a(dev);
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
int err; int err = 0;
nvgpu_log_fn(g, " "); nvgpu_log_fn(g, " ");
nvgpu_mutex_acquire(&g->power_lock);
if (g->power_on) if (g->power_on)
return 0; goto done;
g->power_on = true; g->power_on = true;
@@ -220,6 +224,10 @@ int vgpu_pm_finalize_poweron(struct device *dev)
g->sw_ready = true; g->sw_ready = true;
done: done:
if (err)
g->power_on = false;
nvgpu_mutex_release(&g->power_lock);
return err; return err;
} }