gpu: nvgpu: update poweroff sequence

To support concurrent UMD kickoff and railgate (due to VPR resize), It
is necessary that nvgpu immediately prevents more work submission when
it's known gpu needs to be idled. So nvgpu needs to unmap the usermode
region earliest during suspend sequence.

Otherwise, engines will not go idle before poweroff. Hence move the
call to nvgpu_hide_usermode_poweroff to the beginning of
gk20a_pm_prepare_poweorff.

Also during suspend we ensure that the channels are preempted cleanly.
IRQs should be kept enabled until after channels are suspended as the
stalling IRQ can block the preemption. Hence moved the IRQ disable
post channel_suspend call.

gk20a_prepare_poweroff unconditionally sets power_on to false. Hence
there is no need to reenable IRQs, resume scale in the failure path
of gk20a_pm_prepare_poweroff as those will be done during call to
gk20a_pm_finalize_poweron.

Bug 3789519

Change-Id: I03064e7e636252a8f3d8fe9c8c05629ce2ba5fba
Signed-off-by: Sagar Kamble <skamble@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2853584
Reviewed-by: Martin Radev <mradev@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Sagar Kamble
2023-02-06 06:52:45 +05:30
committed by mobile promotions
parent ac2dfc554f
commit 5a2ed4df76
2 changed files with 38 additions and 34 deletions

View File

@@ -1,7 +1,7 @@
/* /*
* GK20A Graphics * GK20A Graphics
* *
* Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2011-2023, NVIDIA CORPORATION. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -82,13 +82,6 @@ int gk20a_prepare_poweroff(struct gk20a *g)
nvgpu_log_fn(g, " "); nvgpu_log_fn(g, " ");
if (g->ops.fifo.channel_suspend) {
ret = g->ops.fifo.channel_suspend(g);
if (ret) {
return ret;
}
}
/* disable elpg before gr or fifo suspend */ /* disable elpg before gr or fifo suspend */
if (g->ops.pmu.is_pmu_supported(g)) { if (g->ops.pmu.is_pmu_supported(g)) {
ret |= nvgpu_pmu_destroy(g); ret |= nvgpu_pmu_destroy(g);

View File

@@ -1,7 +1,7 @@
/* /*
* GK20A Graphics * GK20A Graphics
* *
* Copyright (c) 2011-2021, NVIDIA CORPORATION. All rights reserved. * Copyright (c) 2011-2023, NVIDIA CORPORATION. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -417,14 +417,7 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
if (!g->power_on) if (!g->power_on)
goto done; goto done;
/* disable IRQs and wait for completion */ nvgpu_hide_usermode_for_poweroff(g);
irqs_enabled = g->irqs_enabled;
if (irqs_enabled) {
disable_irq(g->irq_stall);
if (g->irq_stall != g->irq_nonstall)
disable_irq(g->irq_nonstall);
g->irqs_enabled = 0;
}
gk20a_scale_suspend(dev); gk20a_scale_suspend(dev);
@@ -432,9 +425,42 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
gk20a_cde_suspend(l); gk20a_cde_suspend(l);
#endif #endif
if (g->ops.fifo.channel_suspend) {
ret = g->ops.fifo.channel_suspend(g);
if (ret) {
nvgpu_err(g, "channel suspend failed");
gk20a_scale_resume(dev);
nvgpu_restore_usermode_for_poweron(g);
goto done;
}
}
/* disable IRQs and wait for completion */
irqs_enabled = g->irqs_enabled;
if (g->irqs_enabled) {
disable_irq(g->irq_stall);
if (g->irq_stall != g->irq_nonstall)
disable_irq(g->irq_nonstall);
g->irqs_enabled = 0;
}
ret = gk20a_prepare_poweroff(g); ret = gk20a_prepare_poweroff(g);
if (ret) if (ret) {
goto error; nvgpu_err(g, "gk20a_prepare_poweroff failed %d", ret);
/* re-enabled IRQs if previously enabled */
if (irqs_enabled) {
enable_irq(g->irq_stall);
if (g->irq_stall != g->irq_nonstall) {
enable_irq(g->irq_nonstall);
}
g->irqs_enabled = 1;
}
gk20a_scale_resume(dev);
nvgpu_restore_usermode_for_poweron(g);
goto done;
}
/* Decrement platform power refcount */ /* Decrement platform power refcount */
if (platform->idle) if (platform->idle)
@@ -446,21 +472,6 @@ static int gk20a_pm_prepare_poweroff(struct device *dev)
#ifdef CONFIG_NVGPU_SUPPORT_LINUX_ECC_ERROR_REPORTING #ifdef CONFIG_NVGPU_SUPPORT_LINUX_ECC_ERROR_REPORTING
nvgpu_disable_ecc_reporting(g); nvgpu_disable_ecc_reporting(g);
#endif #endif
nvgpu_hide_usermode_for_poweroff(g);
nvgpu_mutex_release(&g->power_lock);
return 0;
error:
/* re-enabled IRQs if previously enabled */
if (irqs_enabled) {
enable_irq(g->irq_stall);
if (g->irq_stall != g->irq_nonstall)
enable_irq(g->irq_nonstall);
g->irqs_enabled = 1;
}
gk20a_scale_resume(dev);
done: done:
nvgpu_mutex_release(&g->power_lock); nvgpu_mutex_release(&g->power_lock);