summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2014-07-03 08:29:39 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:10:24 -0400
commit0b1f9e427205190dc5e651f78ff7f8be8641037e (patch)
tree9d202f8c4a89fec720de139f28d41e58210dedef /drivers
parentd608aa53ee338922cbd47ec144cd6efb36fd0295 (diff)
gpu: nvgpu: fix race between do_idle() and unrailgate()
While we are executing do_idle() API, it is possible that unrailgate() gets invoked in midst of idling the GPU and this can result in failure of do_idle() To prevent simultaneous execution of these methods, add a mutex railgate_lock and acquire it during do_idle() and unrailgate() APIs Also, keep this lock held if do_idle() is successful. In success, lock will be released in do_unidle(), otherwise release this lock before returning Note that this lock should not be held in railgate() API since we do not want it to be blocked during do_idle() bug 1529160 Change-Id: I87114b5367eaa217376455a2699c0d21c451c889 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/434190 (cherry picked from commit 561dc8e0933ff2d72573292968b893a52f5f783a) Reviewed-on: http://git-master/r/435131 Reviewed-by: Arto Merilainen <amerilainen@nvidia.com> Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c23
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a.h1
2 files changed, 21 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
1782fail: 1795fail:
1783 pm_runtime_put_noidle(&pdev->dev); 1796 pm_runtime_put_noidle(&pdev->dev);
1797fail_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;
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
index 231f97b3..76e9cf6c 100644
--- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
@@ -118,6 +118,7 @@ struct gk20a_platform {
118 118
119 /* Called to turn on the device */ 119 /* Called to turn on the device */
120 int (*unrailgate)(struct platform_device *dev); 120 int (*unrailgate)(struct platform_device *dev);
121 struct mutex railgate_lock;
121 122
122 /* Called to check state of device */ 123 /* Called to check state of device */
123 bool (*is_railgated)(struct platform_device *dev); 124 bool (*is_railgated)(struct platform_device *dev);