diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2014-07-08 08:30:18 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:10:26 -0400 |
commit | fec60b6e6e299151d446f4bccc5fd64a23b704d2 (patch) | |
tree | 7ff144ac70c937e6a91e4f18afee64b35541d88a /drivers/gpu/nvgpu/gk20a/gk20a.c | |
parent | 597083eaba3abd3e48b3c6bfafac3ef94606c2ad (diff) |
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>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index cd104580..c69df460 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -1743,9 +1743,6 @@ int gk20a_do_idle(void) | |||
1743 | int ref_cnt; | 1743 | int ref_cnt; |
1744 | bool is_railgated; | 1744 | bool is_railgated; |
1745 | 1745 | ||
1746 | if (!platform->can_railgate) | ||
1747 | return -ENOSYS; | ||
1748 | |||
1749 | /* acquire busy lock to block other busy() calls */ | 1746 | /* acquire busy lock to block other busy() calls */ |
1750 | down_write(&g->busy_lock); | 1747 | down_write(&g->busy_lock); |
1751 | 1748 | ||
@@ -1772,25 +1769,39 @@ int gk20a_do_idle(void) | |||
1772 | 1769 | ||
1773 | /* | 1770 | /* |
1774 | * if GPU is now idle, we will have only one ref count | 1771 | * if GPU is now idle, we will have only one ref count |
1775 | * drop this ref which will rail gate the GPU | 1772 | * drop this ref which will rail gate the GPU (if GPU |
1773 | * railgate is supported) | ||
1774 | * if GPU railgate is not supported then we need to | ||
1775 | * explicitly reset it | ||
1776 | */ | 1776 | */ |
1777 | pm_runtime_put_sync(&pdev->dev); | 1777 | pm_runtime_put_sync(&pdev->dev); |
1778 | 1778 | ||
1779 | /* add sufficient delay to allow GPU to rail gate */ | 1779 | if (platform->can_railgate) { |
1780 | msleep(platform->railgate_delay); | 1780 | /* add sufficient delay to allow GPU to rail gate */ |
1781 | msleep(platform->railgate_delay); | ||
1781 | 1782 | ||
1782 | timeout = jiffies + msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS); | 1783 | timeout = jiffies + msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS); |
1783 | 1784 | ||
1784 | /* check in loop if GPU is railgated or not */ | 1785 | /* check in loop if GPU is railgated or not */ |
1785 | do { | 1786 | do { |
1786 | msleep(1); | 1787 | msleep(1); |
1787 | is_railgated = platform->is_railgated(pdev); | 1788 | is_railgated = platform->is_railgated(pdev); |
1788 | } while (!is_railgated && time_before(jiffies, timeout)); | 1789 | } while (!is_railgated && time_before(jiffies, timeout)); |
1790 | |||
1791 | if (is_railgated) | ||
1792 | return 0; | ||
1793 | else | ||
1794 | goto fail_timeout; | ||
1795 | } else { | ||
1796 | pm_runtime_get_sync(&pdev->dev); | ||
1797 | gk20a_pm_prepare_poweroff(&pdev->dev); | ||
1798 | |||
1799 | tegra_periph_reset_assert(platform->clk[0]); | ||
1800 | udelay(10); | ||
1789 | 1801 | ||
1790 | if (is_railgated) | 1802 | g->forced_reset = true; |
1791 | return 0; | 1803 | return 0; |
1792 | else | 1804 | } |
1793 | goto fail_timeout; | ||
1794 | 1805 | ||
1795 | fail: | 1806 | fail: |
1796 | pm_runtime_put_noidle(&pdev->dev); | 1807 | pm_runtime_put_noidle(&pdev->dev); |
@@ -1811,6 +1822,15 @@ int gk20a_do_unidle(void) | |||
1811 | struct gk20a *g = get_gk20a(pdev); | 1822 | struct gk20a *g = get_gk20a(pdev); |
1812 | struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev); | 1823 | struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev); |
1813 | 1824 | ||
1825 | if (g->forced_reset) { | ||
1826 | tegra_periph_reset_deassert(platform->clk[0]); | ||
1827 | |||
1828 | gk20a_pm_finalize_poweron(&pdev->dev); | ||
1829 | pm_runtime_put_sync(&pdev->dev); | ||
1830 | |||
1831 | g->forced_reset = false; | ||
1832 | } | ||
1833 | |||
1814 | /* release the lock and open up all other busy() calls */ | 1834 | /* release the lock and open up all other busy() calls */ |
1815 | mutex_unlock(&platform->railgate_lock); | 1835 | mutex_unlock(&platform->railgate_lock); |
1816 | up_write(&g->busy_lock); | 1836 | up_write(&g->busy_lock); |