diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2014-07-28 06:51:10 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:10:37 -0400 |
commit | d0ce4807d0f190be8fd4221bb48d543bf20473f6 (patch) | |
tree | 410936871ebba93269bf15aa7b15638be780e6cc | |
parent | cc30ac4395809580d3d7ad9b3b6ac4aea099f9ec (diff) |
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>
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 20 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a.h | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | 28 |
3 files changed, 53 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 355b2039..fa6e0cce 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -1604,16 +1604,30 @@ int gk20a_busy(struct platform_device *pdev) | |||
1604 | { | 1604 | { |
1605 | int ret = 0; | 1605 | int ret = 0; |
1606 | struct gk20a *g = get_gk20a(pdev); | 1606 | struct gk20a *g = get_gk20a(pdev); |
1607 | struct gk20a_platform *platform = gk20a_get_platform(pdev); | ||
1607 | 1608 | ||
1608 | down_read(&g->busy_lock); | 1609 | down_read(&g->busy_lock); |
1609 | 1610 | ||
1610 | #ifdef CONFIG_PM_RUNTIME | 1611 | #ifdef CONFIG_PM_RUNTIME |
1612 | if (platform->busy) { | ||
1613 | ret = platform->busy(pdev); | ||
1614 | if (ret < 0) { | ||
1615 | dev_err(&pdev->dev, "%s: failed to poweron platform dependency\n", | ||
1616 | __func__); | ||
1617 | goto fail; | ||
1618 | } | ||
1619 | } | ||
1620 | |||
1611 | ret = pm_runtime_get_sync(&pdev->dev); | 1621 | ret = pm_runtime_get_sync(&pdev->dev); |
1612 | if (ret < 0) | 1622 | if (ret < 0) { |
1613 | pm_runtime_put_noidle(&pdev->dev); | 1623 | pm_runtime_put_noidle(&pdev->dev); |
1624 | if (platform->idle) | ||
1625 | platform->idle(pdev); | ||
1626 | } | ||
1614 | #endif | 1627 | #endif |
1615 | gk20a_scale_notify_busy(pdev); | 1628 | gk20a_scale_notify_busy(pdev); |
1616 | 1629 | ||
1630 | fail: | ||
1617 | up_read(&g->busy_lock); | 1631 | up_read(&g->busy_lock); |
1618 | 1632 | ||
1619 | return ret < 0 ? ret : 0; | 1633 | return ret < 0 ? ret : 0; |
@@ -1621,11 +1635,15 @@ int gk20a_busy(struct platform_device *pdev) | |||
1621 | 1635 | ||
1622 | void gk20a_idle(struct platform_device *pdev) | 1636 | void gk20a_idle(struct platform_device *pdev) |
1623 | { | 1637 | { |
1638 | struct gk20a_platform *platform = gk20a_get_platform(pdev); | ||
1624 | #ifdef CONFIG_PM_RUNTIME | 1639 | #ifdef CONFIG_PM_RUNTIME |
1625 | if (atomic_read(&pdev->dev.power.usage_count) == 1) | 1640 | if (atomic_read(&pdev->dev.power.usage_count) == 1) |
1626 | gk20a_scale_notify_idle(pdev); | 1641 | gk20a_scale_notify_idle(pdev); |
1627 | pm_runtime_mark_last_busy(&pdev->dev); | 1642 | pm_runtime_mark_last_busy(&pdev->dev); |
1628 | pm_runtime_put_sync_autosuspend(&pdev->dev); | 1643 | pm_runtime_put_sync_autosuspend(&pdev->dev); |
1644 | |||
1645 | if (platform->idle) | ||
1646 | platform->idle(pdev); | ||
1629 | #else | 1647 | #else |
1630 | gk20a_scale_notify_idle(pdev); | 1648 | gk20a_scale_notify_idle(pdev); |
1631 | #endif | 1649 | #endif |
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h index 76e9cf6c..6dd0c0db 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h | |||
@@ -94,6 +94,12 @@ struct gk20a_platform { | |||
94 | */ | 94 | */ |
95 | int (*late_probe)(struct platform_device *dev); | 95 | int (*late_probe)(struct platform_device *dev); |
96 | 96 | ||
97 | /* Poweron platform dependencies */ | ||
98 | int (*busy)(struct platform_device *dev); | ||
99 | |||
100 | /* Powerdown platform dependencies */ | ||
101 | void (*idle)(struct platform_device *dev); | ||
102 | |||
97 | /* This function is called to allocate secure memory (memory that the | 103 | /* This function is called to allocate secure memory (memory that the |
98 | * CPU cannot see). The function should fill the context buffer | 104 | * CPU cannot see). The function should fill the context buffer |
99 | * descriptor (especially fields destroy, sgt, size). | 105 | * descriptor (especially fields destroy, sgt, size). |
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c index 148496dd..f234fdec 100644 --- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c +++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c | |||
@@ -449,6 +449,25 @@ static void gk20a_tegra_debug_dump(struct platform_device *pdev) | |||
449 | nvhost_debug_dump_device(g->host1x_dev); | 449 | nvhost_debug_dump_device(g->host1x_dev); |
450 | } | 450 | } |
451 | 451 | ||
452 | static int gk20a_tegra_busy(struct platform_device *dev) | ||
453 | { | ||
454 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
455 | struct gk20a *g = platform->g; | ||
456 | |||
457 | if (g->host1x_dev) | ||
458 | return nvhost_module_busy_ext(g->host1x_dev); | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static void gk20a_tegra_idle(struct platform_device *dev) | ||
463 | { | ||
464 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
465 | struct gk20a *g = platform->g; | ||
466 | |||
467 | if (g->host1x_dev) | ||
468 | nvhost_module_idle_ext(g->host1x_dev); | ||
469 | } | ||
470 | |||
452 | static int gk20a_tegra_probe(struct platform_device *dev) | 471 | static int gk20a_tegra_probe(struct platform_device *dev) |
453 | { | 472 | { |
454 | struct gk20a_platform *platform = gk20a_get_platform(dev); | 473 | struct gk20a_platform *platform = gk20a_get_platform(dev); |
@@ -554,6 +573,9 @@ struct gk20a_platform t132_gk20a_tegra_platform = { | |||
554 | .unrailgate = gk20a_tegra_unrailgate, | 573 | .unrailgate = gk20a_tegra_unrailgate, |
555 | .is_railgated = gk20a_tegra_is_railgated, | 574 | .is_railgated = gk20a_tegra_is_railgated, |
556 | 575 | ||
576 | .busy = gk20a_tegra_busy, | ||
577 | .idle = gk20a_tegra_idle, | ||
578 | |||
557 | /* frequency scaling configuration */ | 579 | /* frequency scaling configuration */ |
558 | .prescale = gk20a_tegra_prescale, | 580 | .prescale = gk20a_tegra_prescale, |
559 | .postscale = gk20a_tegra_postscale, | 581 | .postscale = gk20a_tegra_postscale, |
@@ -587,6 +609,9 @@ struct gk20a_platform gk20a_tegra_platform = { | |||
587 | .unrailgate = gk20a_tegra_unrailgate, | 609 | .unrailgate = gk20a_tegra_unrailgate, |
588 | .is_railgated = gk20a_tegra_is_railgated, | 610 | .is_railgated = gk20a_tegra_is_railgated, |
589 | 611 | ||
612 | .busy = gk20a_tegra_busy, | ||
613 | .idle = gk20a_tegra_idle, | ||
614 | |||
590 | /* frequency scaling configuration */ | 615 | /* frequency scaling configuration */ |
591 | .prescale = gk20a_tegra_prescale, | 616 | .prescale = gk20a_tegra_prescale, |
592 | .postscale = gk20a_tegra_postscale, | 617 | .postscale = gk20a_tegra_postscale, |
@@ -618,6 +643,9 @@ struct gk20a_platform gm20b_tegra_platform = { | |||
618 | /* power management callbacks */ | 643 | /* power management callbacks */ |
619 | .suspend = gk20a_tegra_suspend, | 644 | .suspend = gk20a_tegra_suspend, |
620 | 645 | ||
646 | .busy = gk20a_tegra_busy, | ||
647 | .idle = gk20a_tegra_idle, | ||
648 | |||
621 | /* frequency scaling configuration */ | 649 | /* frequency scaling configuration */ |
622 | .prescale = gk20a_tegra_prescale, | 650 | .prescale = gk20a_tegra_prescale, |
623 | .postscale = gk20a_tegra_postscale, | 651 | .postscale = gk20a_tegra_postscale, |