diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 629423c0..64be9398 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -1281,8 +1281,13 @@ static int _gk20a_pm_unrailgate(struct platform_device *pdev) | |||
1281 | { | 1281 | { |
1282 | struct gk20a_platform *platform = platform_get_drvdata(pdev); | 1282 | struct gk20a_platform *platform = platform_get_drvdata(pdev); |
1283 | int ret = 0; | 1283 | int ret = 0; |
1284 | if (platform->unrailgate) | 1284 | |
1285 | if (platform->unrailgate) { | ||
1286 | mutex_lock(&platform->railgate_lock); | ||
1285 | ret = platform->unrailgate(pdev); | 1287 | ret = platform->unrailgate(pdev); |
1288 | mutex_unlock(&platform->railgate_lock); | ||
1289 | } | ||
1290 | |||
1286 | return ret; | 1291 | return ret; |
1287 | } | 1292 | } |
1288 | 1293 | ||
@@ -1362,6 +1367,8 @@ static int gk20a_pm_init(struct platform_device *dev) | |||
1362 | 1367 | ||
1363 | gk20a_dbg_fn(""); | 1368 | gk20a_dbg_fn(""); |
1364 | 1369 | ||
1370 | mutex_init(&platform->railgate_lock); | ||
1371 | |||
1365 | /* Initialise pm runtime */ | 1372 | /* Initialise pm runtime */ |
1366 | if (platform->clockgate_delay) { | 1373 | if (platform->clockgate_delay) { |
1367 | pm_runtime_set_autosuspend_delay(&dev->dev, | 1374 | pm_runtime_set_autosuspend_delay(&dev->dev, |
@@ -1739,6 +1746,13 @@ int gk20a_do_idle(void) | |||
1739 | /* acquire busy lock to block other busy() calls */ | 1746 | /* acquire busy lock to block other busy() calls */ |
1740 | down_write(&g->busy_lock); | 1747 | down_write(&g->busy_lock); |
1741 | 1748 | ||
1749 | /* acquire railgate lock to prevent unrailgate in midst of do_idle() */ | ||
1750 | mutex_lock(&platform->railgate_lock); | ||
1751 | |||
1752 | /* check if it is already railgated ? */ | ||
1753 | if (platform->is_railgated(pdev)) | ||
1754 | return 0; | ||
1755 | |||
1742 | /* prevent suspend by incrementing usage counter */ | 1756 | /* prevent suspend by incrementing usage counter */ |
1743 | pm_runtime_get_noresume(&pdev->dev); | 1757 | pm_runtime_get_noresume(&pdev->dev); |
1744 | 1758 | ||
@@ -1776,11 +1790,12 @@ int gk20a_do_idle(void) | |||
1776 | } | 1790 | } |
1777 | 1791 | ||
1778 | /* GPU is not rail gated by now, return error */ | 1792 | /* GPU is not rail gated by now, return error */ |
1779 | up_write(&g->busy_lock); | 1793 | goto fail_timeout; |
1780 | return -EBUSY; | ||
1781 | 1794 | ||
1782 | fail: | 1795 | fail: |
1783 | pm_runtime_put_noidle(&pdev->dev); | 1796 | pm_runtime_put_noidle(&pdev->dev); |
1797 | fail_timeout: | ||
1798 | mutex_unlock(&platform->railgate_lock); | ||
1784 | up_write(&g->busy_lock); | 1799 | up_write(&g->busy_lock); |
1785 | return -EBUSY; | 1800 | return -EBUSY; |
1786 | } | 1801 | } |
@@ -1794,8 +1809,10 @@ int gk20a_do_unidle(void) | |||
1794 | bus_find_device_by_name(&platform_bus_type, | 1809 | bus_find_device_by_name(&platform_bus_type, |
1795 | NULL, "gk20a.0")); | 1810 | NULL, "gk20a.0")); |
1796 | struct gk20a *g = get_gk20a(pdev); | 1811 | struct gk20a *g = get_gk20a(pdev); |
1812 | struct gk20a_platform *platform = dev_get_drvdata(&pdev->dev); | ||
1797 | 1813 | ||
1798 | /* release the lock and open up all other busy() calls */ | 1814 | /* release the lock and open up all other busy() calls */ |
1815 | mutex_unlock(&platform->railgate_lock); | ||
1799 | up_write(&g->busy_lock); | 1816 | up_write(&g->busy_lock); |
1800 | 1817 | ||
1801 | return 0; | 1818 | return 0; |