diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2016-10-12 05:44:15 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-10-18 14:08:01 -0400 |
commit | c284516ead33708e135eeaa53672d835849f25fb (patch) | |
tree | e7ca4a1c6402f50bd1e783b78c00d92848dfc5e8 /drivers/gpu/nvgpu/gk20a/gk20a.c | |
parent | 8b051f34fc10caa7309c0ae964fbc708d6a679a2 (diff) |
gpu: nvgpu: support suspend/resume with user disabled railgating
We take an extra power refcount when we disable railgating
through railgate_enable sysfs
And that breaks suspend/resume since we check for power
refcount first in gk20a_pm_suspend()
Fix this with following :
- set a flag user_railgate_disabled when User
disables railgating through sysfs railgate_enable
- in gk20a_pm_suspend(), drop one power refcount
if flag is set
- in gk20a_pm_resume(), take one refcount again
if flag is set
Fix __gk20a_do_idle() to consider this extra refcount as well.
Add new variable target_ref_cnt and use it instead of
assuming target refcount of 1
In case User has disabled rail gating, set this target
refcount as 2
Also, export gk20a_idle_nosuspend() which drop power refcount
without triggering suspend
Bug 200233570
Change-Id: Ic0e35c73eb74ffefea1cd90d1b152650d9d2043d
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/1236047
(cherry picked from commit 6e002d57da4b5c58ed79889728bb678d3aa1f1b1)
Reviewed-on: http://git-master/r/1235219
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 721c44e3..ff87edc2 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -1395,9 +1395,14 @@ static int gk20a_pm_suspend(struct device *dev) | |||
1395 | struct gk20a *g = get_gk20a(dev); | 1395 | struct gk20a *g = get_gk20a(dev); |
1396 | int ret = 0; | 1396 | int ret = 0; |
1397 | 1397 | ||
1398 | if (platform->user_railgate_disabled) | ||
1399 | gk20a_idle_nosuspend(dev); | ||
1400 | |||
1398 | #ifdef CONFIG_PM | 1401 | #ifdef CONFIG_PM |
1399 | if (atomic_read(&dev->power.usage_count) > 1) | 1402 | if (atomic_read(&dev->power.usage_count) > 1) { |
1400 | return -EBUSY; | 1403 | ret = -EBUSY; |
1404 | goto fail; | ||
1405 | } | ||
1401 | #endif | 1406 | #endif |
1402 | 1407 | ||
1403 | if (!g->power_on) | 1408 | if (!g->power_on) |
@@ -1405,7 +1410,7 @@ static int gk20a_pm_suspend(struct device *dev) | |||
1405 | 1410 | ||
1406 | ret = gk20a_pm_runtime_suspend(dev); | 1411 | ret = gk20a_pm_runtime_suspend(dev); |
1407 | if (ret) | 1412 | if (ret) |
1408 | return ret; | 1413 | goto fail; |
1409 | 1414 | ||
1410 | if (platform->suspend) | 1415 | if (platform->suspend) |
1411 | platform->suspend(dev); | 1416 | platform->suspend(dev); |
@@ -1413,13 +1418,23 @@ static int gk20a_pm_suspend(struct device *dev) | |||
1413 | g->suspended = true; | 1418 | g->suspended = true; |
1414 | 1419 | ||
1415 | return 0; | 1420 | return 0; |
1421 | |||
1422 | fail: | ||
1423 | if (platform->user_railgate_disabled) | ||
1424 | gk20a_busy_noresume(dev); | ||
1425 | |||
1426 | return ret; | ||
1416 | } | 1427 | } |
1417 | 1428 | ||
1418 | static int gk20a_pm_resume(struct device *dev) | 1429 | static int gk20a_pm_resume(struct device *dev) |
1419 | { | 1430 | { |
1420 | struct gk20a *g = get_gk20a(dev); | 1431 | struct gk20a *g = get_gk20a(dev); |
1432 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
1421 | int ret = 0; | 1433 | int ret = 0; |
1422 | 1434 | ||
1435 | if (platform->user_railgate_disabled) | ||
1436 | gk20a_busy_noresume(dev); | ||
1437 | |||
1423 | if (!g->suspended) | 1438 | if (!g->suspended) |
1424 | return 0; | 1439 | return 0; |
1425 | 1440 | ||
@@ -1711,6 +1726,11 @@ fail: | |||
1711 | return ret < 0 ? ret : 0; | 1726 | return ret < 0 ? ret : 0; |
1712 | } | 1727 | } |
1713 | 1728 | ||
1729 | void gk20a_idle_nosuspend(struct device *dev) | ||
1730 | { | ||
1731 | pm_runtime_put_noidle(dev); | ||
1732 | } | ||
1733 | |||
1714 | void gk20a_idle(struct device *dev) | 1734 | void gk20a_idle(struct device *dev) |
1715 | { | 1735 | { |
1716 | if (pm_runtime_enabled(dev)) { | 1736 | if (pm_runtime_enabled(dev)) { |
@@ -1783,6 +1803,7 @@ int __gk20a_do_idle(struct device *dev, bool force_reset) | |||
1783 | unsigned long timeout = jiffies + | 1803 | unsigned long timeout = jiffies + |
1784 | msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS); | 1804 | msecs_to_jiffies(GK20A_WAIT_FOR_IDLE_MS); |
1785 | int ref_cnt; | 1805 | int ref_cnt; |
1806 | int target_ref_cnt = 0; | ||
1786 | bool is_railgated; | 1807 | bool is_railgated; |
1787 | int err = 0; | 1808 | int err = 0; |
1788 | 1809 | ||
@@ -1802,15 +1823,25 @@ int __gk20a_do_idle(struct device *dev, bool force_reset) | |||
1802 | */ | 1823 | */ |
1803 | mutex_unlock(&platform->railgate_lock); | 1824 | mutex_unlock(&platform->railgate_lock); |
1804 | pm_runtime_get_sync(dev); | 1825 | pm_runtime_get_sync(dev); |
1826 | |||
1827 | /* | ||
1828 | * One refcount taken in this API | ||
1829 | * If User disables rail gating, we take one more | ||
1830 | * extra refcount | ||
1831 | */ | ||
1832 | if (platform->user_railgate_disabled) | ||
1833 | target_ref_cnt = 2; | ||
1834 | else | ||
1835 | target_ref_cnt = 1; | ||
1805 | mutex_lock(&platform->railgate_lock); | 1836 | mutex_lock(&platform->railgate_lock); |
1806 | 1837 | ||
1807 | /* check and wait until GPU is idle (with a timeout) */ | 1838 | /* check and wait until GPU is idle (with a timeout) */ |
1808 | do { | 1839 | do { |
1809 | msleep(1); | 1840 | msleep(1); |
1810 | ref_cnt = atomic_read(&dev->power.usage_count); | 1841 | ref_cnt = atomic_read(&dev->power.usage_count); |
1811 | } while (ref_cnt != 1 && time_before(jiffies, timeout)); | 1842 | } while (ref_cnt != target_ref_cnt && time_before(jiffies, timeout)); |
1812 | 1843 | ||
1813 | if (ref_cnt != 1) { | 1844 | if (ref_cnt != target_ref_cnt) { |
1814 | gk20a_err(dev, "failed to idle - refcount %d != 1\n", | 1845 | gk20a_err(dev, "failed to idle - refcount %d != 1\n", |
1815 | ref_cnt); | 1846 | ref_cnt); |
1816 | goto fail_drop_usage_count; | 1847 | goto fail_drop_usage_count; |