gpu: nvgpu: poweron host1x explicitly

Currently gk20a gets reference of host1x via phandle in
Device Tree. But runtime PM does not seem to be handling power
dependencies too well in this case and hence some times host1x
is off when we need it.

To fix this, exlicitly power on host1x while powering gpu up.
Do this via "busy" and "idle" callbacks from gk20a_platform

Bug 1534272
Bug 200022536

Change-Id: Ia562ee19722cfc8edc5626a5a058ab8edfe3d206
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
This commit is contained in:
Deepak Nibade
2014-07-28 16:21:10 +05:30
committed by Dan Willemsen
parent cc30ac4395
commit d0ce4807d0
3 changed files with 53 additions and 1 deletions

View File

@@ -1604,16 +1604,30 @@ int gk20a_busy(struct platform_device *pdev)
{ {
int ret = 0; int ret = 0;
struct gk20a *g = get_gk20a(pdev); struct gk20a *g = get_gk20a(pdev);
struct gk20a_platform *platform = gk20a_get_platform(pdev);
down_read(&g->busy_lock); down_read(&g->busy_lock);
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
if (platform->busy) {
ret = platform->busy(pdev);
if (ret < 0) {
dev_err(&pdev->dev, "%s: failed to poweron platform dependency\n",
__func__);
goto fail;
}
}
ret = pm_runtime_get_sync(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) if (ret < 0) {
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
if (platform->idle)
platform->idle(pdev);
}
#endif #endif
gk20a_scale_notify_busy(pdev); gk20a_scale_notify_busy(pdev);
fail:
up_read(&g->busy_lock); up_read(&g->busy_lock);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
@@ -1621,11 +1635,15 @@ int gk20a_busy(struct platform_device *pdev)
void gk20a_idle(struct platform_device *pdev) void gk20a_idle(struct platform_device *pdev)
{ {
struct gk20a_platform *platform = gk20a_get_platform(pdev);
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME
if (atomic_read(&pdev->dev.power.usage_count) == 1) if (atomic_read(&pdev->dev.power.usage_count) == 1)
gk20a_scale_notify_idle(pdev); gk20a_scale_notify_idle(pdev);
pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_sync_autosuspend(&pdev->dev); pm_runtime_put_sync_autosuspend(&pdev->dev);
if (platform->idle)
platform->idle(pdev);
#else #else
gk20a_scale_notify_idle(pdev); gk20a_scale_notify_idle(pdev);
#endif #endif

View File

@@ -94,6 +94,12 @@ struct gk20a_platform {
*/ */
int (*late_probe)(struct platform_device *dev); int (*late_probe)(struct platform_device *dev);
/* Poweron platform dependencies */
int (*busy)(struct platform_device *dev);
/* Powerdown platform dependencies */
void (*idle)(struct platform_device *dev);
/* This function is called to allocate secure memory (memory that the /* This function is called to allocate secure memory (memory that the
* CPU cannot see). The function should fill the context buffer * CPU cannot see). The function should fill the context buffer
* descriptor (especially fields destroy, sgt, size). * descriptor (especially fields destroy, sgt, size).

View File

@@ -449,6 +449,25 @@ static void gk20a_tegra_debug_dump(struct platform_device *pdev)
nvhost_debug_dump_device(g->host1x_dev); nvhost_debug_dump_device(g->host1x_dev);
} }
static int gk20a_tegra_busy(struct platform_device *dev)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
if (g->host1x_dev)
return nvhost_module_busy_ext(g->host1x_dev);
return 0;
}
static void gk20a_tegra_idle(struct platform_device *dev)
{
struct gk20a_platform *platform = gk20a_get_platform(dev);
struct gk20a *g = platform->g;
if (g->host1x_dev)
nvhost_module_idle_ext(g->host1x_dev);
}
static int gk20a_tegra_probe(struct platform_device *dev) static int gk20a_tegra_probe(struct platform_device *dev)
{ {
struct gk20a_platform *platform = gk20a_get_platform(dev); struct gk20a_platform *platform = gk20a_get_platform(dev);
@@ -554,6 +573,9 @@ struct gk20a_platform t132_gk20a_tegra_platform = {
.unrailgate = gk20a_tegra_unrailgate, .unrailgate = gk20a_tegra_unrailgate,
.is_railgated = gk20a_tegra_is_railgated, .is_railgated = gk20a_tegra_is_railgated,
.busy = gk20a_tegra_busy,
.idle = gk20a_tegra_idle,
/* frequency scaling configuration */ /* frequency scaling configuration */
.prescale = gk20a_tegra_prescale, .prescale = gk20a_tegra_prescale,
.postscale = gk20a_tegra_postscale, .postscale = gk20a_tegra_postscale,
@@ -587,6 +609,9 @@ struct gk20a_platform gk20a_tegra_platform = {
.unrailgate = gk20a_tegra_unrailgate, .unrailgate = gk20a_tegra_unrailgate,
.is_railgated = gk20a_tegra_is_railgated, .is_railgated = gk20a_tegra_is_railgated,
.busy = gk20a_tegra_busy,
.idle = gk20a_tegra_idle,
/* frequency scaling configuration */ /* frequency scaling configuration */
.prescale = gk20a_tegra_prescale, .prescale = gk20a_tegra_prescale,
.postscale = gk20a_tegra_postscale, .postscale = gk20a_tegra_postscale,
@@ -618,6 +643,9 @@ struct gk20a_platform gm20b_tegra_platform = {
/* power management callbacks */ /* power management callbacks */
.suspend = gk20a_tegra_suspend, .suspend = gk20a_tegra_suspend,
.busy = gk20a_tegra_busy,
.idle = gk20a_tegra_idle,
/* frequency scaling configuration */ /* frequency scaling configuration */
.prescale = gk20a_tegra_prescale, .prescale = gk20a_tegra_prescale,
.postscale = gk20a_tegra_postscale, .postscale = gk20a_tegra_postscale,