mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
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:
committed by
mobile promotions
parent
1982d050cc
commit
fbc5296e7d
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user