gpu: nvgpu: force idle if railgate not supported

Add a way to force idle and reset the GPU in case where GPU
rail gating is not supported
(i.e. platform->can_railgate = false)

In this case, we follow below sequence :
- once GPU is idle, get runtime reference which enables the clocks
- call prepare_poweroff() to save the state explicitly
- perform explicit reset assert/deassert
- call finalize_poweron() to restore the state
- drop the runtime reference taken earlier

Bug 1525284

Change-Id: Id5f3ec152093acd585631dfbf785d8e0561f9048
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/435620
GVS: Gerrit_Virtual_Submit
Reviewed-by: Arto Merilainen <amerilainen@nvidia.com>
Tested-by: Arto Merilainen <amerilainen@nvidia.com>
This commit is contained in:
Deepak Nibade
2014-07-08 18:00:18 +05:30
committed by Dan Willemsen
parent 597083eaba
commit fec60b6e6e
2 changed files with 36 additions and 15 deletions

View File

@@ -1743,9 +1743,6 @@ int gk20a_do_idle(void)
int ref_cnt; int ref_cnt;
bool is_railgated; bool is_railgated;
if (!platform->can_railgate)
return -ENOSYS;
/* acquire busy lock to block other busy() calls */ /* acquire busy lock to block other busy() calls */
down_write(&g->busy_lock); down_write(&g->busy_lock);
@@ -1772,10 +1769,14 @@ int gk20a_do_idle(void)
/* /*
* if GPU is now idle, we will have only one ref count * if GPU is now idle, we will have only one ref count
* drop this ref which will rail gate the GPU * drop this ref which will rail gate the GPU (if GPU
* railgate is supported)
* if GPU railgate is not supported then we need to
* explicitly reset it
*/ */
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
if (platform->can_railgate) {
/* add sufficient delay to allow GPU to rail gate */ /* add sufficient delay to allow GPU to rail gate */
msleep(platform->railgate_delay); msleep(platform->railgate_delay);
@@ -1791,6 +1792,16 @@ int gk20a_do_idle(void)
return 0; return 0;
else else
goto fail_timeout; goto fail_timeout;
} else {
pm_runtime_get_sync(&pdev->dev);
gk20a_pm_prepare_poweroff(&pdev->dev);
tegra_periph_reset_assert(platform->clk[0]);
udelay(10);
g->forced_reset = true;
return 0;
}
fail: fail:
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
@@ -1811,6 +1822,15 @@ int gk20a_do_unidle(void)
struct gk20a *g = get_gk20a(pdev); struct gk20a *g = get_gk20a(pdev);
struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev); struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev);
if (g->forced_reset) {
tegra_periph_reset_deassert(platform->clk[0]);
gk20a_pm_finalize_poweron(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
g->forced_reset = false;
}
/* release the lock and open up all other busy() calls */ /* release the lock and open up all other busy() calls */
mutex_unlock(&platform->railgate_lock); mutex_unlock(&platform->railgate_lock);
up_write(&g->busy_lock); up_write(&g->busy_lock);

View File

@@ -271,6 +271,7 @@ struct gk20a {
bool elpg_enabled; bool elpg_enabled;
bool aelpg_enabled; bool aelpg_enabled;
bool forced_idle; bool forced_idle;
bool forced_reset;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
spinlock_t debugfs_lock; spinlock_t debugfs_lock;