diff options
author | Sachit Kadle <skadle@nvidia.com> | 2016-06-28 01:53:42 -0400 |
---|---|---|
committer | Vijayakumar Subbu <vsubbu@nvidia.com> | 2016-07-27 00:09:11 -0400 |
commit | 6ac44d2813f5ab1873eb5148f26746a8f9dbd4a8 (patch) | |
tree | 50603804f0e0518db87bb9cde02e4e7189db9d2d /drivers/gpu/nvgpu | |
parent | 823f00d4849c57760b0f87f05c253924f50eec9e (diff) |
gpu: nvgpu: take platform power ref at power on
Currently, host1x power refcount may decrement
to 0, while GPU is still powered on and we're still
servicing IRQs. So to prevent this situation,,
take a ref while GPU is being powered on, and
decrement it during power off. Since we are always
holding one reference while GPU is powered on,
we can remove this handling from gk20a_busy/idle()
Bug 200187507
Change-Id: I249a4527178537c1dc53d769411f53c4451352c3
Signed-off-by: Sachit Kadle <skadle@nvidia.com>
Reviewed-on: http://git-master/r/1172320
(cherry picked from commit 3e27e6a5820f5c1ad05596553d75e8979b71f1bd)
Reviewed-on: http://git-master/r/1172607
(cherry picked from commit 1e01a49fdc139b8cdf5164b4a6767d22ef4ad1d3)
Reviewed-on: http://git-master/r/1185175
GVS: Gerrit_Virtual_Submit
Reviewed-by: Thomas Fleury <tfleury@nvidia.com>
Reviewed-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 33 |
1 files changed, 14 insertions, 19 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index bb8cb33f..caa1583e 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -813,6 +813,10 @@ static int gk20a_pm_prepare_poweroff(struct device *dev) | |||
813 | 813 | ||
814 | g->power_on = false; | 814 | g->power_on = false; |
815 | 815 | ||
816 | /* Decrement platform power refcount */ | ||
817 | if (platform->idle) | ||
818 | platform->idle(dev); | ||
819 | |||
816 | /* Stop CPU from accessing the GPU registers. */ | 820 | /* Stop CPU from accessing the GPU registers. */ |
817 | gk20a_lockout_registers(g); | 821 | gk20a_lockout_registers(g); |
818 | 822 | ||
@@ -859,6 +863,16 @@ int gk20a_pm_finalize_poweron(struct device *dev) | |||
859 | 863 | ||
860 | trace_gk20a_finalize_poweron(dev_name(dev)); | 864 | trace_gk20a_finalize_poweron(dev_name(dev)); |
861 | 865 | ||
866 | /* Increment platform power refcount */ | ||
867 | if (platform->busy) { | ||
868 | err = platform->busy(dev); | ||
869 | if (err < 0) { | ||
870 | dev_err(dev, "%s: failed to poweron platform dependency\n", | ||
871 | __func__); | ||
872 | goto done; | ||
873 | } | ||
874 | } | ||
875 | |||
862 | err = gk20a_restore_registers(g); | 876 | err = gk20a_restore_registers(g); |
863 | if (err) | 877 | if (err) |
864 | return err; | 878 | return err; |
@@ -1787,25 +1801,12 @@ int gk20a_busy(struct device *dev) | |||
1787 | { | 1801 | { |
1788 | int ret = 0; | 1802 | int ret = 0; |
1789 | struct gk20a *g = get_gk20a(dev); | 1803 | struct gk20a *g = get_gk20a(dev); |
1790 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
1791 | 1804 | ||
1792 | down_read(&g->busy_lock); | 1805 | down_read(&g->busy_lock); |
1793 | |||
1794 | if (pm_runtime_enabled(dev)) { | 1806 | if (pm_runtime_enabled(dev)) { |
1795 | if (platform->busy) { | ||
1796 | ret = platform->busy(dev); | ||
1797 | if (ret < 0) { | ||
1798 | dev_err(dev, "%s: failed to poweron platform dependency\n", | ||
1799 | __func__); | ||
1800 | goto fail; | ||
1801 | } | ||
1802 | } | ||
1803 | |||
1804 | ret = pm_runtime_get_sync(dev); | 1807 | ret = pm_runtime_get_sync(dev); |
1805 | if (ret < 0) { | 1808 | if (ret < 0) { |
1806 | pm_runtime_put_noidle(dev); | 1809 | pm_runtime_put_noidle(dev); |
1807 | if (platform->idle) | ||
1808 | platform->idle(dev); | ||
1809 | goto fail; | 1810 | goto fail; |
1810 | } | 1811 | } |
1811 | } else { | 1812 | } else { |
@@ -1818,8 +1819,6 @@ int gk20a_busy(struct device *dev) | |||
1818 | } | 1819 | } |
1819 | } | 1820 | } |
1820 | 1821 | ||
1821 | gk20a_scale_notify_busy(dev); | ||
1822 | |||
1823 | fail: | 1822 | fail: |
1824 | up_read(&g->busy_lock); | 1823 | up_read(&g->busy_lock); |
1825 | 1824 | ||
@@ -1828,8 +1827,6 @@ fail: | |||
1828 | 1827 | ||
1829 | void gk20a_idle(struct device *dev) | 1828 | void gk20a_idle(struct device *dev) |
1830 | { | 1829 | { |
1831 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
1832 | |||
1833 | if (pm_runtime_enabled(dev)) { | 1830 | if (pm_runtime_enabled(dev)) { |
1834 | #ifdef CONFIG_PM | 1831 | #ifdef CONFIG_PM |
1835 | if (atomic_read(&dev->power.usage_count) == 1) | 1832 | if (atomic_read(&dev->power.usage_count) == 1) |
@@ -1839,8 +1836,6 @@ void gk20a_idle(struct device *dev) | |||
1839 | pm_runtime_mark_last_busy(dev); | 1836 | pm_runtime_mark_last_busy(dev); |
1840 | pm_runtime_put_sync_autosuspend(dev); | 1837 | pm_runtime_put_sync_autosuspend(dev); |
1841 | 1838 | ||
1842 | if (platform->idle) | ||
1843 | platform->idle(dev); | ||
1844 | } else { | 1839 | } else { |
1845 | gk20a_scale_notify_idle(dev); | 1840 | gk20a_scale_notify_idle(dev); |
1846 | } | 1841 | } |