summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2016-06-09 09:16:21 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2016-07-08 03:58:53 -0400
commite27c72446bf09196d6d66f28389f00565273a13f (patch)
tree473530a0f10eee8d9dcae29afdc35c72b7a6a0ad /drivers/gpu
parent8417698b519be9dc8c1bd04714fc72ce4e0bc38f (diff)
gpu: nvgpu: simplify power management
We currenlty initialize both runtime PM and pm_domains frameworks and use pm_domain to control runtime power management of NvGPU But since GPU has a separate rail, using pm_domain is not strictly required Hence remove pm_domain support and use runtime PM only for all the power management This also simplifies the code a lot Initialization in gk20a_pm_init() - if railgate_delay is set, set autosuspend delay of runtime PM - try enabling runtime PM - if runtime PM is now enabled, keep GPU railgated - if runtime PM is not enabled, keep GPU unrailgated - if can_railgate = false, disable runtime PM and keep GPU unrailgated Set gk20a_pm_ops with below callbacks for runtime PM static const struct dev_pm_ops gk20a_pm_ops = { .runtime_resume = gk20a_pm_runtime_resume, .runtime_suspend = gk20a_pm_runtime_suspend, .resume = gk20a_pm_resume, .suspend = gk20a_pm_suspend, } Move gk20a_busy() to use runtime checks of pm_runtime_enabled() instead of using compile time checks on CONFIG_PM Clean up some pm_domain related code Remove use of gk20a_pm_enable/disable_clk() since this should be already done in platform specific unrailgate()/ railgate() APIs Fix "railgate_delay" and "railgate_enable" sysfs to use runtime PM calls For VGPU, disable runtime PM during vgpu_pm_init() With this, we will initialize vgpu with vgpu_pm_finalize_poweron() upon first call to gk20a_busy() Jira DNVGPU-57 Change-Id: I6013e33ae9bd28f35c25271af1239942a4fa0919 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-on: http://git-master/r/1163216 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c378
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h7
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c40
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a.h1
-rw-r--r--drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c7
-rw-r--r--drivers/gpu/nvgpu/vgpu/vgpu.c42
6 files changed, 123 insertions, 352 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index 2ca89e9f..bcde6df3 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -36,7 +36,6 @@
36#include <linux/debugfs.h> 36#include <linux/debugfs.h>
37#include <linux/spinlock.h> 37#include <linux/spinlock.h>
38#include <linux/tegra-powergate.h> 38#include <linux/tegra-powergate.h>
39#include <linux/tegra_pm_domains.h>
40#include <linux/clk/tegra.h> 39#include <linux/clk/tegra.h>
41#include <linux/kthread.h> 40#include <linux/kthread.h>
42#include <linux/platform/tegra/common.h> 41#include <linux/platform/tegra/common.h>
@@ -1130,41 +1129,31 @@ struct channel_gk20a *gk20a_get_channel_from_file(int fd)
1130 return ch; 1129 return ch;
1131} 1130}
1132 1131
1133static int gk20a_pm_enable_clk(struct device *dev) 1132static int gk20a_pm_railgate(struct device *dev)
1134{ 1133{
1135 int index = 0; 1134 struct gk20a_platform *platform = dev_get_drvdata(dev);
1136 struct gk20a_platform *platform; 1135 int ret = 0;
1137
1138 platform = dev_get_drvdata(dev);
1139 if (!platform)
1140 return -EINVAL;
1141 1136
1142 for (index = 0; index < platform->num_clks; index++) { 1137 if (platform->railgate)
1143 int err = 0; 1138 ret = platform->railgate(dev);
1144 if (platform->clk[index])
1145 err = clk_prepare_enable(platform->clk[index]);
1146 if (err)
1147 return -EINVAL;
1148 }
1149 1139
1150 return 0; 1140 return ret;
1151} 1141}
1152 1142
1153static int gk20a_pm_disable_clk(struct device *dev) 1143static int gk20a_pm_unrailgate(struct device *dev)
1154{ 1144{
1155 int index = 0; 1145 struct gk20a_platform *platform = dev_get_drvdata(dev);
1156 struct gk20a_platform *platform; 1146 int ret = 0;
1157 1147
1158 platform = dev_get_drvdata(dev); 1148 trace_gk20a_pm_unrailgate(dev_name(dev));
1159 if (!platform)
1160 return -EINVAL;
1161 1149
1162 for (index = 0; index < platform->num_clks; index++) { 1150 if (platform->unrailgate) {
1163 if (platform->clk[index]) 1151 mutex_lock(&platform->railgate_lock);
1164 clk_disable_unprepare(platform->clk[index]); 1152 ret = platform->unrailgate(dev);
1153 mutex_unlock(&platform->railgate_lock);
1165 } 1154 }
1166 1155
1167 return 0; 1156 return ret;
1168} 1157}
1169 1158
1170static void gk20a_pm_shutdown(struct platform_device *pdev) 1159static void gk20a_pm_shutdown(struct platform_device *pdev)
@@ -1176,17 +1165,12 @@ static void gk20a_pm_shutdown(struct platform_device *pdev)
1176 /* If GPU is already railgated, 1165 /* If GPU is already railgated,
1177 * just prevent more requests, and return */ 1166 * just prevent more requests, and return */
1178 if (platform->is_railgated && platform->is_railgated(&pdev->dev)) { 1167 if (platform->is_railgated && platform->is_railgated(&pdev->dev)) {
1179#ifdef CONFIG_PM
1180 __pm_runtime_disable(&pdev->dev, false); 1168 __pm_runtime_disable(&pdev->dev, false);
1181#endif
1182 return; 1169 return;
1183 } 1170 }
1184 1171
1185
1186#ifdef CONFIG_PM
1187 /* Prevent more requests by disabling Runtime PM */ 1172 /* Prevent more requests by disabling Runtime PM */
1188 __pm_runtime_disable(&pdev->dev, false); 1173 __pm_runtime_disable(&pdev->dev, false);
1189#endif
1190 1174
1191 /* Be ready for rail-gate after this point */ 1175 /* Be ready for rail-gate after this point */
1192 if (gk20a_gpu_is_virtual(&pdev->dev)) 1176 if (gk20a_gpu_is_virtual(&pdev->dev))
@@ -1194,63 +1178,55 @@ static void gk20a_pm_shutdown(struct platform_device *pdev)
1194 else 1178 else
1195 gk20a_pm_prepare_poweroff(&pdev->dev); 1179 gk20a_pm_prepare_poweroff(&pdev->dev);
1196 1180
1181 gk20a_pm_railgate(&pdev->dev);
1182
1197 dev_info(&pdev->dev, "shut down complete\n"); 1183 dev_info(&pdev->dev, "shut down complete\n");
1198} 1184}
1199 1185
1200#ifdef CONFIG_PM 1186static int gk20a_pm_runtime_resume(struct device *dev)
1201static const struct dev_pm_ops gk20a_pm_ops = {
1202#if defined(CONFIG_PM) && !defined(CONFIG_PM_GENERIC_DOMAINS)
1203 .runtime_resume = gk20a_pm_enable_clk,
1204 .runtime_suspend = gk20a_pm_disable_clk,
1205#endif
1206};
1207#endif
1208
1209static int _gk20a_pm_railgate(struct device *dev)
1210{ 1187{
1211 struct gk20a_platform *platform = dev_get_drvdata(dev); 1188 int err = 0;
1212 int ret = 0;
1213 if (platform->railgate)
1214 ret = platform->railgate(dev);
1215 return ret;
1216}
1217 1189
1218static int gk20a_pm_railgate(struct generic_pm_domain *domain) 1190 err = gk20a_pm_unrailgate(dev);
1219{ 1191 if (err)
1220 struct gk20a_domain_data *gk20a_domain = container_of(domain, 1192 goto fail;
1221 struct gk20a_domain_data, gpd); 1193
1222 struct gk20a *g = gk20a_domain->gk20a; 1194 err = gk20a_pm_finalize_poweron(dev);
1195 if (err)
1196 goto fail_poweron;
1223 1197
1224 return _gk20a_pm_railgate(g->dev); 1198 return 0;
1199
1200fail_poweron:
1201 gk20a_pm_railgate(dev);
1202fail:
1203 return err;
1225} 1204}
1226 1205
1227static int _gk20a_pm_unrailgate(struct device *dev) 1206static int gk20a_pm_runtime_suspend(struct device *dev)
1228{ 1207{
1229 struct gk20a_platform *platform = dev_get_drvdata(dev); 1208 int err = 0;
1230 int ret = 0;
1231 1209
1232 if (platform->unrailgate) { 1210 err = gk20a_pm_prepare_poweroff(dev);
1233 mutex_lock(&platform->railgate_lock); 1211 if (err)
1234 ret = platform->unrailgate(dev); 1212 goto fail;
1235 mutex_unlock(&platform->railgate_lock);
1236 }
1237 1213
1238 return ret; 1214 err = gk20a_pm_railgate(dev);
1239} 1215 if (err)
1216 goto fail_railgate;
1240 1217
1241static int gk20a_pm_unrailgate(struct generic_pm_domain *domain) 1218 return 0;
1242{
1243 struct gk20a_domain_data *gk20a_domain = container_of(domain,
1244 struct gk20a_domain_data, gpd);
1245 struct gk20a *g = gk20a_domain->gk20a;
1246 trace_gk20a_pm_unrailgate(dev_name(g->dev));
1247 1219
1248 return _gk20a_pm_unrailgate(g->dev); 1220fail_railgate:
1221 gk20a_pm_finalize_poweron(dev);
1222fail:
1223 return err;
1249} 1224}
1250 1225
1251static int gk20a_pm_suspend(struct device *dev) 1226static int gk20a_pm_suspend(struct device *dev)
1252{ 1227{
1253 struct gk20a_platform *platform = dev_get_drvdata(dev); 1228 struct gk20a_platform *platform = dev_get_drvdata(dev);
1229 struct gk20a *g = get_gk20a(dev);
1254 int ret = 0; 1230 int ret = 0;
1255 1231
1256#ifdef CONFIG_PM 1232#ifdef CONFIG_PM
@@ -1258,86 +1234,43 @@ static int gk20a_pm_suspend(struct device *dev)
1258 return -EBUSY; 1234 return -EBUSY;
1259#endif 1235#endif
1260 1236
1261 ret = gk20a_pm_prepare_poweroff(dev); 1237 if (!g->power_on)
1238 return 0;
1239
1240 ret = gk20a_pm_runtime_suspend(dev);
1262 if (ret) 1241 if (ret)
1263 return ret; 1242 return ret;
1264 1243
1265 if (platform->suspend) 1244 if (platform->suspend)
1266 platform->suspend(dev); 1245 platform->suspend(dev);
1267 1246
1247 g->suspended = true;
1248
1268 return 0; 1249 return 0;
1269} 1250}
1270 1251
1271static int gk20a_pm_resume(struct device *dev) 1252static int gk20a_pm_resume(struct device *dev)
1272{ 1253{
1273 return gk20a_pm_finalize_poweron(dev); 1254 struct gk20a *g = get_gk20a(dev);
1274} 1255 int ret = 0;
1275
1276#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
1277static int gk20a_pm_initialise_domain(struct device *dev)
1278{
1279 struct gk20a_platform *platform = dev_get_drvdata(dev);
1280 struct dev_power_governor *pm_domain_gov = NULL;
1281 struct generic_pm_domain *domain = dev_to_genpd(dev);
1282 1256
1283 if (IS_ERR(domain)) 1257 if (!g->suspended)
1284 return 0; 1258 return 0;
1285 1259
1286#ifdef CONFIG_PM 1260 ret = gk20a_pm_runtime_resume(dev);
1287 if (!platform->can_railgate)
1288 pm_domain_gov = &pm_domain_always_on_gov;
1289#endif
1290 domain->gov = pm_domain_gov;
1291 1261
1292 if (platform->railgate_delay) 1262 g->suspended = false;
1293 pm_genpd_set_poweroff_delay(domain, platform->railgate_delay);
1294 1263
1295 device_set_wakeup_capable(dev, 0); 1264 return ret;
1296 return 0;
1297} 1265}
1298 1266
1299#else
1300static int gk20a_pm_initialise_domain(struct device *dev)
1301{
1302 struct gk20a_platform *platform = dev_get_drvdata(dev);
1303 struct dev_power_governor *pm_domain_gov = NULL;
1304 struct generic_pm_domain *domain = NULL;
1305 int ret = 0;
1306 struct gk20a_domain_data *gpu_gpd_data = (struct gk20a_domain_data *)
1307 kzalloc(sizeof(struct gk20a_domain_data), GFP_KERNEL);
1308
1309 if (!gpu_gpd_data)
1310 return -ENOMEM;
1311
1312 gpu_gpd_data->gk20a = platform->g;
1313 domain = &gpu_gpd_data->gpd;
1314
1315 domain->name = "gpu";
1316
1317#ifdef CONFIG_PM 1267#ifdef CONFIG_PM
1318 if (!platform->can_railgate) 1268static const struct dev_pm_ops gk20a_pm_ops = {
1319 pm_domain_gov = &pm_domain_always_on_gov; 1269 .runtime_resume = gk20a_pm_runtime_resume,
1320#endif 1270 .runtime_suspend = gk20a_pm_runtime_suspend,
1321 1271 .resume = gk20a_pm_resume,
1322 pm_genpd_init(domain, pm_domain_gov, true); 1272 .suspend = gk20a_pm_suspend,
1323 1273};
1324 domain->power_off = gk20a_pm_railgate;
1325 domain->power_on = gk20a_pm_unrailgate;
1326 domain->dev_ops.start = gk20a_pm_enable_clk;
1327 domain->dev_ops.stop = gk20a_pm_disable_clk;
1328 domain->dev_ops.save_state = gk20a_pm_prepare_poweroff;
1329 domain->dev_ops.restore_state = gk20a_pm_finalize_poweron;
1330 domain->dev_ops.suspend = gk20a_pm_suspend;
1331 domain->dev_ops.resume = gk20a_pm_resume;
1332
1333 device_set_wakeup_capable(dev, 0);
1334 ret = pm_genpd_add_device(domain, dev);
1335
1336 if (platform->railgate_delay)
1337 pm_genpd_set_poweroff_delay(domain, platform->railgate_delay);
1338
1339 return ret;
1340}
1341#endif 1274#endif
1342 1275
1343int gk20a_pm_init(struct device *dev) 1276int gk20a_pm_init(struct device *dev)
@@ -1350,24 +1283,20 @@ int gk20a_pm_init(struct device *dev)
1350 /* Initialise pm runtime */ 1283 /* Initialise pm runtime */
1351 if (platform->railgate_delay) { 1284 if (platform->railgate_delay) {
1352 pm_runtime_set_autosuspend_delay(dev, 1285 pm_runtime_set_autosuspend_delay(dev,
1353 platform->railgate_delay); 1286 platform->railgate_delay);
1354 pm_runtime_use_autosuspend(dev); 1287 pm_runtime_use_autosuspend(dev);
1355 } 1288 }
1356 1289
1357 pm_runtime_enable(dev); 1290 if (platform->can_railgate) {
1358 if (!pm_runtime_enabled(dev)) 1291 pm_runtime_enable(dev);
1359 gk20a_pm_enable_clk(dev); 1292 if (!pm_runtime_enabled(dev))
1360 1293 gk20a_pm_unrailgate(dev);
1361 /* Enable runtime railgating if possible. If not, 1294 else
1362 * turn on the rail now. */ 1295 gk20a_pm_railgate(dev);
1363 if (platform->can_railgate && IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) 1296 } else {
1364 _gk20a_pm_railgate(dev); 1297 __pm_runtime_disable(dev, false);
1365 else if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) 1298 gk20a_pm_unrailgate(dev);
1366 _gk20a_pm_unrailgate(dev); 1299 }
1367
1368 /* genpd will take care of runtime power management if it is enabled */
1369 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
1370 err = gk20a_pm_initialise_domain(dev);
1371 1300
1372 return err; 1301 return err;
1373} 1302}
@@ -1386,24 +1315,12 @@ static int gk20a_secure_page_alloc(struct platform_device *pdev)
1386 return err; 1315 return err;
1387} 1316}
1388 1317
1389static struct of_device_id tegra_gpu_domain_match[] = {
1390 {.compatible = "nvidia,tegra124-gpu-pd"},
1391 {.compatible = "nvidia,tegra132-gpu-pd"},
1392 {.compatible = "nvidia,tegra210-gpu-pd"},
1393 {.compatible = "nvidia,tegra186-gpu-pd"},
1394 {},
1395};
1396
1397static int gk20a_probe(struct platform_device *dev) 1318static int gk20a_probe(struct platform_device *dev)
1398{ 1319{
1399 struct gk20a *gk20a; 1320 struct gk20a *gk20a;
1400 int err; 1321 int err;
1401 struct gk20a_platform *platform = NULL; 1322 struct gk20a_platform *platform = NULL;
1402 1323
1403#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
1404 struct gk20a_domain_data *gk20a_domain;
1405#endif
1406
1407 if (dev->dev.of_node) { 1324 if (dev->dev.of_node) {
1408 const struct of_device_id *match; 1325 const struct of_device_id *match;
1409 1326
@@ -1434,12 +1351,6 @@ static int gk20a_probe(struct platform_device *dev)
1434 init_waitqueue_head(&gk20a->sw_irq_stall_last_handled_wq); 1351 init_waitqueue_head(&gk20a->sw_irq_stall_last_handled_wq);
1435 init_waitqueue_head(&gk20a->sw_irq_nonstall_last_handled_wq); 1352 init_waitqueue_head(&gk20a->sw_irq_nonstall_last_handled_wq);
1436 1353
1437#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
1438 gk20a_domain = container_of(dev_to_genpd(&dev->dev),
1439 struct gk20a_domain_data, gpd);
1440 gk20a_domain->gk20a = gk20a;
1441#endif
1442
1443 set_gk20a(dev, gk20a); 1354 set_gk20a(dev, gk20a);
1444 gk20a->dev = &dev->dev; 1355 gk20a->dev = &dev->dev;
1445 1356
@@ -1636,7 +1547,6 @@ static int __exit gk20a_remove(struct platform_device *pdev)
1636 struct device *dev = &pdev->dev; 1547 struct device *dev = &pdev->dev;
1637 struct gk20a *g = get_gk20a(dev); 1548 struct gk20a *g = get_gk20a(dev);
1638 struct gk20a_platform *platform = gk20a_get_platform(dev); 1549 struct gk20a_platform *platform = gk20a_get_platform(dev);
1639 struct gk20a_domain_data *gk20a_gpd;
1640 1550
1641 gk20a_dbg_fn(""); 1551 gk20a_dbg_fn("");
1642 1552
@@ -1665,14 +1575,8 @@ static int __exit gk20a_remove(struct platform_device *pdev)
1665 platform->secure_buffer.destroy(dev, 1575 platform->secure_buffer.destroy(dev,
1666 &platform->secure_buffer); 1576 &platform->secure_buffer);
1667 1577
1668 gk20a_gpd = container_of(&g, struct gk20a_domain_data, gk20a);
1669 gk20a_gpd->gk20a = NULL;
1670 kfree(gk20a_gpd);
1671
1672 if (pm_runtime_enabled(dev)) 1578 if (pm_runtime_enabled(dev))
1673 pm_runtime_disable(dev); 1579 pm_runtime_disable(dev);
1674 else
1675 gk20a_pm_disable_clk(dev);
1676 1580
1677 if (platform->remove) 1581 if (platform->remove)
1678 platform->remove(dev); 1582 platform->remove(dev);
@@ -1704,63 +1608,6 @@ static struct platform_driver gk20a_driver = {
1704 } 1608 }
1705}; 1609};
1706 1610
1707#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
1708
1709
1710static int _gk20a_init_domain(struct device_node *np,
1711 struct generic_pm_domain *gpd)
1712{
1713 bool is_off = false;
1714
1715 gpd->name = (char *)np->name;
1716
1717 if (of_property_read_bool(np, "is_off"))
1718 is_off = true;
1719
1720 pm_genpd_init(gpd, NULL, is_off);
1721
1722 gpd->power_on = gk20a_pm_unrailgate;
1723 gpd->power_off = gk20a_pm_railgate;
1724 gpd->dev_ops.start = gk20a_pm_enable_clk;
1725 gpd->dev_ops.stop = gk20a_pm_disable_clk;
1726 gpd->dev_ops.save_state = gk20a_pm_prepare_poweroff;
1727 gpd->dev_ops.restore_state = gk20a_pm_finalize_poweron;
1728 gpd->dev_ops.suspend = gk20a_pm_suspend;
1729 gpd->dev_ops.resume = gk20a_pm_resume;
1730
1731 of_genpd_add_provider_simple(np, gpd);
1732 gpd->of_node = of_node_get(np);
1733
1734 genpd_pm_subdomain_attach(gpd);
1735 return 0;
1736}
1737
1738static int gk20a_domain_init(struct of_device_id *matches)
1739{
1740 int ret = 0;
1741 struct device_node *np;
1742 struct gk20a_domain_data *gk20a_domain;
1743
1744 np = of_find_matching_node(NULL, matches);
1745 if (!np)
1746 return -ENOENT;
1747
1748 gk20a_domain = (struct gk20a_domain_data *)kzalloc
1749 (sizeof(struct gk20a_domain_data), GFP_KERNEL);
1750 if (!gk20a_domain)
1751 return -ENOMEM;
1752
1753 ret = _gk20a_init_domain(np, &gk20a_domain->gpd);
1754
1755 return ret;
1756}
1757#else
1758static int gk20a_domain_init(struct of_device_id *matches)
1759{
1760 return 0;
1761}
1762#endif
1763
1764struct class nvgpu_class = { 1611struct class nvgpu_class = {
1765 .owner = THIS_MODULE, 1612 .owner = THIS_MODULE,
1766 .name = CLASS_NAME, 1613 .name = CLASS_NAME,
@@ -1775,10 +1622,6 @@ static int __init gk20a_init(void)
1775 if (ret) 1622 if (ret)
1776 return ret; 1623 return ret;
1777 1624
1778 ret = gk20a_domain_init(tegra_gpu_domain_match);
1779 if (ret)
1780 return ret;
1781
1782 ret = nvgpu_pci_init(); 1625 ret = nvgpu_pci_init();
1783 if (ret) 1626 if (ret)
1784 return ret; 1627 return ret;
@@ -1802,38 +1645,37 @@ int gk20a_busy(struct device *dev)
1802{ 1645{
1803 int ret = 0; 1646 int ret = 0;
1804 struct gk20a *g = get_gk20a(dev); 1647 struct gk20a *g = get_gk20a(dev);
1805#ifdef CONFIG_PM
1806 struct gk20a_platform *platform = gk20a_get_platform(dev); 1648 struct gk20a_platform *platform = gk20a_get_platform(dev);
1807#endif
1808 1649
1809 down_read(&g->busy_lock); 1650 down_read(&g->busy_lock);
1810 1651
1811#ifdef CONFIG_PM 1652 if (pm_runtime_enabled(dev)) {
1812 if (platform->busy) { 1653 if (platform->busy) {
1813 ret = platform->busy(dev); 1654 ret = platform->busy(dev);
1655 if (ret < 0) {
1656 dev_err(dev, "%s: failed to poweron platform dependency\n",
1657 __func__);
1658 goto fail;
1659 }
1660 }
1661
1662 ret = pm_runtime_get_sync(dev);
1814 if (ret < 0) { 1663 if (ret < 0) {
1815 dev_err(dev, "%s: failed to poweron platform dependency\n", 1664 pm_runtime_put_noidle(dev);
1816 __func__); 1665 if (platform->idle)
1666 platform->idle(dev);
1817 goto fail; 1667 goto fail;
1818 } 1668 }
1669 } else {
1670 if (!g->power_on) {
1671 ret = gk20a_gpu_is_virtual(dev) ?
1672 vgpu_pm_finalize_poweron(dev)
1673 : gk20a_pm_finalize_poweron(dev);
1674 if (ret)
1675 goto fail;
1676 }
1819 } 1677 }
1820 1678
1821 ret = pm_runtime_get_sync(dev);
1822 if (ret < 0) {
1823 pm_runtime_put_noidle(dev);
1824 if (platform->idle)
1825 platform->idle(dev);
1826 goto fail;
1827 }
1828#else
1829 if (!g->power_on) {
1830 ret = gk20a_gpu_is_virtual(dev) ?
1831 vgpu_pm_finalize_poweron(dev)
1832 : gk20a_pm_finalize_poweron(dev);
1833 if (ret)
1834 goto fail;
1835 }
1836#endif
1837 gk20a_scale_notify_busy(dev); 1679 gk20a_scale_notify_busy(dev);
1838 1680
1839fail: 1681fail:
@@ -1844,18 +1686,22 @@ fail:
1844 1686
1845void gk20a_idle(struct device *dev) 1687void gk20a_idle(struct device *dev)
1846{ 1688{
1847#ifdef CONFIG_PM
1848 struct gk20a_platform *platform = gk20a_get_platform(dev); 1689 struct gk20a_platform *platform = gk20a_get_platform(dev);
1849 if (atomic_read(&dev->power.usage_count) == 1)
1850 gk20a_scale_notify_idle(dev);
1851 pm_runtime_mark_last_busy(dev);
1852 pm_runtime_put_sync_autosuspend(dev);
1853 1690
1854 if (platform->idle) 1691 if (pm_runtime_enabled(dev)) {
1855 platform->idle(dev); 1692#ifdef CONFIG_PM
1856#else 1693 if (atomic_read(&dev->power.usage_count) == 1)
1857 gk20a_scale_notify_idle(dev); 1694 gk20a_scale_notify_idle(dev);
1858#endif 1695#endif
1696
1697 pm_runtime_mark_last_busy(dev);
1698 pm_runtime_put_sync_autosuspend(dev);
1699
1700 if (platform->idle)
1701 platform->idle(dev);
1702 } else {
1703 gk20a_scale_notify_idle(dev);
1704 }
1859} 1705}
1860 1706
1861void gk20a_disable(struct gk20a *g, u32 units) 1707void gk20a_disable(struct gk20a *g, u32 units)
@@ -1991,8 +1837,6 @@ int __gk20a_do_idle(struct device *dev, bool force_reset)
1991 /* Save the GPU state */ 1837 /* Save the GPU state */
1992 gk20a_pm_prepare_poweroff(dev); 1838 gk20a_pm_prepare_poweroff(dev);
1993 1839
1994 gk20a_pm_disable_clk(dev);
1995
1996 /* railgate GPU */ 1840 /* railgate GPU */
1997 platform->railgate(dev); 1841 platform->railgate(dev);
1998 1842
@@ -2044,8 +1888,6 @@ int __gk20a_do_unidle(struct device *dev)
2044 */ 1888 */
2045 platform->unrailgate(dev); 1889 platform->unrailgate(dev);
2046 1890
2047 gk20a_pm_enable_clk(dev);
2048
2049 /* restore the GPU state */ 1891 /* restore the GPU state */
2050 gk20a_pm_finalize_poweron(dev); 1892 gk20a_pm_finalize_poweron(dev);
2051 1893
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index b8a2fc3e..949cd4a5 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -664,6 +664,7 @@ struct gk20a {
664 struct device *dev; 664 struct device *dev;
665 struct platform_device *host1x_dev; 665 struct platform_device *host1x_dev;
666 666
667
667 struct resource *reg_mem; 668 struct resource *reg_mem;
668 void __iomem *regs; 669 void __iomem *regs;
669 void __iomem *regs_saved; 670 void __iomem *regs_saved;
@@ -673,6 +674,7 @@ struct gk20a {
673 void __iomem *bar1_saved; 674 void __iomem *bar1_saved;
674 675
675 bool power_on; 676 bool power_on;
677 bool suspended;
676 678
677 struct rw_semaphore busy_lock; 679 struct rw_semaphore busy_lock;
678 680
@@ -882,11 +884,6 @@ struct gk20a_cyclestate_buffer_elem {
882 u64 data; 884 u64 data;
883}; 885};
884 886
885struct gk20a_domain_data {
886 struct generic_pm_domain gpd;
887 struct gk20a *gk20a;
888};
889
890/* debug accessories */ 887/* debug accessories */
891 888
892#ifdef CONFIG_DEBUG_FS 889#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
index 127d0258..38d5a842 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c
@@ -276,49 +276,33 @@ static DEVICE_ATTR(ptimer_src_freq,
276 NULL); 276 NULL);
277 277
278 278
279#if defined(CONFIG_PM) && defined(CONFIG_PM_GENERIC_DOMAINS) 279#if defined(CONFIG_PM)
280static ssize_t railgate_enable_store(struct device *dev, 280static ssize_t railgate_enable_store(struct device *dev,
281 struct device_attribute *attr, const char *buf, size_t count) 281 struct device_attribute *attr, const char *buf, size_t count)
282{ 282{
283 struct gk20a_platform *platform = dev_get_drvdata(dev); 283 struct gk20a_platform *platform = dev_get_drvdata(dev);
284 struct generic_pm_domain *genpd = dev_to_genpd(dev);
285 struct gk20a *g = get_gk20a(dev);
286 unsigned long railgate_enable = 0; 284 unsigned long railgate_enable = 0;
287 int err = 0; 285 int err = 0;
288 286
289 if (kstrtoul(buf, 10, &railgate_enable) < 0) 287 if (kstrtoul(buf, 10, &railgate_enable) < 0)
290 return -EINVAL; 288 return -EINVAL;
289
291 if (railgate_enable && !platform->can_railgate) { 290 if (railgate_enable && !platform->can_railgate) {
292 mutex_lock(&platform->railgate_lock); 291 /* release extra ref count */
292 gk20a_idle(dev);
293 platform->can_railgate = true; 293 platform->can_railgate = true;
294 genpd->gov = NULL;
295 pm_genpd_set_poweroff_delay(genpd, platform->railgate_delay);
296 /* release extra ref count:if power domains not enabled */
297 if ((platform->railgate) && \
298 !IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
299 err = platform->railgate(dev);
300 mutex_unlock(&platform->railgate_lock);
301 } else if (railgate_enable == 0 && platform->can_railgate) { 294 } else if (railgate_enable == 0 && platform->can_railgate) {
302 mutex_lock(&platform->railgate_lock); 295 /* take extra ref count */
296 err = gk20a_busy(dev);
297 if (err)
298 return err;
303 platform->can_railgate = false; 299 platform->can_railgate = false;
304 genpd->gov = &pm_domain_always_on_gov;
305 pm_genpd_set_poweroff_delay(genpd, platform->railgate_delay);
306 /* take extra ref count - incase of power domains not enabled */
307 if ((platform->unrailgate) && \
308 !IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
309 err = platform->unrailgate(dev);
310 mutex_unlock(&platform->railgate_lock);
311 } 300 }
312 if (err) 301 if (err)
313 return err; 302 return err;
314 303
315 dev_info(dev, "railgate is %s.\n", platform->can_railgate ? 304 dev_info(dev, "railgate is %s.\n", platform->can_railgate ?
316 "enabled" : "disabled"); 305 "enabled" : "disabled");
317 /* wake-up system to make railgating_enable effective immediately */
318 err = gk20a_busy(g->dev);
319 if (err)
320 return err;
321 gk20a_idle(g->dev);
322 306
323 return count; 307 return count;
324} 308}
@@ -351,11 +335,11 @@ static ssize_t railgate_delay_store(struct device *dev,
351 335
352 ret = sscanf(buf, "%d", &railgate_delay); 336 ret = sscanf(buf, "%d", &railgate_delay);
353 if (ret == 1 && railgate_delay >= 0) { 337 if (ret == 1 && railgate_delay >= 0) {
354 struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain);
355 platform->railgate_delay = railgate_delay; 338 platform->railgate_delay = railgate_delay;
356 pm_genpd_set_poweroff_delay(genpd, platform->railgate_delay); 339 pm_runtime_set_autosuspend_delay(dev, platform->railgate_delay);
357 } else 340 } else
358 dev_err(dev, "Invalid powergate delay\n"); 341 dev_err(dev, "Invalid powergate delay\n");
342
359 /* wake-up system to make rail-gating delay effective immediately */ 343 /* wake-up system to make rail-gating delay effective immediately */
360 err = gk20a_busy(g->dev); 344 err = gk20a_busy(g->dev);
361 if (err) 345 if (err)
@@ -782,10 +766,8 @@ void gk20a_remove_sysfs(struct device *dev)
782 device_remove_file(dev, &dev_attr_is_railgated); 766 device_remove_file(dev, &dev_attr_is_railgated);
783#ifdef CONFIG_PM 767#ifdef CONFIG_PM
784 device_remove_file(dev, &dev_attr_force_idle); 768 device_remove_file(dev, &dev_attr_force_idle);
785#if defined(CONFIG_PM_GENERIC_DOMAINS)
786 device_remove_file(dev, &dev_attr_railgate_enable); 769 device_remove_file(dev, &dev_attr_railgate_enable);
787#endif 770#endif
788#endif
789 device_remove_file(dev, &dev_attr_aelpg_param); 771 device_remove_file(dev, &dev_attr_aelpg_param);
790 device_remove_file(dev, &dev_attr_aelpg_enable); 772 device_remove_file(dev, &dev_attr_aelpg_enable);
791 device_remove_file(dev, &dev_attr_allow_all); 773 device_remove_file(dev, &dev_attr_allow_all);
@@ -823,10 +805,8 @@ void gk20a_create_sysfs(struct device *dev)
823 error |= device_create_file(dev, &dev_attr_is_railgated); 805 error |= device_create_file(dev, &dev_attr_is_railgated);
824#ifdef CONFIG_PM 806#ifdef CONFIG_PM
825 error |= device_create_file(dev, &dev_attr_force_idle); 807 error |= device_create_file(dev, &dev_attr_force_idle);
826#if defined(CONFIG_PM_GENERIC_DOMAINS)
827 error |= device_create_file(dev, &dev_attr_railgate_enable); 808 error |= device_create_file(dev, &dev_attr_railgate_enable);
828#endif 809#endif
829#endif
830 error |= device_create_file(dev, &dev_attr_aelpg_param); 810 error |= device_create_file(dev, &dev_attr_aelpg_param);
831 error |= device_create_file(dev, &dev_attr_aelpg_enable); 811 error |= device_create_file(dev, &dev_attr_aelpg_enable);
832 error |= device_create_file(dev, &dev_attr_allow_all); 812 error |= device_create_file(dev, &dev_attr_allow_all);
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
index a753201b..543f9873 100644
--- a/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a.h
@@ -17,7 +17,6 @@
17#define _GK20A_PLATFORM_H_ 17#define _GK20A_PLATFORM_H_
18 18
19#include <linux/device.h> 19#include <linux/device.h>
20#include <linux/pm_domain.h>
21#include <linux/dma-attrs.h> 20#include <linux/dma-attrs.h>
22 21
23struct gk20a; 22struct gk20a;
diff --git a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
index 25f9a8dd..cea82805 100644
--- a/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
+++ b/drivers/gpu/nvgpu/gk20a/platform_gk20a_tegra.c
@@ -22,7 +22,6 @@
22#include <uapi/linux/nvgpu.h> 22#include <uapi/linux/nvgpu.h>
23#include <linux/dma-buf.h> 23#include <linux/dma-buf.h>
24#include <linux/nvmap.h> 24#include <linux/nvmap.h>
25#include <linux/tegra_pm_domains.h>
26#include <linux/tegra_soctherm.h> 25#include <linux/tegra_soctherm.h>
27#include <linux/platform/tegra/clock.h> 26#include <linux/platform/tegra/clock.h>
28#include <linux/platform/tegra/dvfs.h> 27#include <linux/platform/tegra/dvfs.h>
@@ -780,9 +779,6 @@ static int gk20a_tegra_probe(struct device *dev)
780 779
781static int gk20a_tegra_late_probe(struct device *dev) 780static int gk20a_tegra_late_probe(struct device *dev)
782{ 781{
783 /* Make gk20a power domain a subdomain of host1x */
784 nvhost_register_client_domain(dev_to_genpd(dev));
785
786 /* Initialise tegra specific scaling quirks */ 782 /* Initialise tegra specific scaling quirks */
787 gk20a_tegra_scale_init(dev); 783 gk20a_tegra_scale_init(dev);
788 784
@@ -791,9 +787,6 @@ static int gk20a_tegra_late_probe(struct device *dev)
791 787
792static int gk20a_tegra_remove(struct device *dev) 788static int gk20a_tegra_remove(struct device *dev)
793{ 789{
794 /* remove gk20a power subdomain from host1x */
795 nvhost_unregister_client_domain(dev_to_genpd(dev));
796
797 /* deinitialise tegra specific scaling quirks */ 790 /* deinitialise tegra specific scaling quirks */
798 gk20a_tegra_scale_exit(dev); 791 gk20a_tegra_scale_exit(dev);
799 792
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c
index 6393ea50..c28130f2 100644
--- a/drivers/gpu/nvgpu/vgpu/vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/vgpu.c
@@ -430,48 +430,13 @@ done:
430 return err; 430 return err;
431} 431}
432 432
433static int vgpu_pm_initialise_domain(struct device *dev)
434{
435 struct gk20a_platform *platform = dev_get_drvdata(dev);
436 struct dev_power_governor *pm_domain_gov = NULL;
437 struct gk20a_domain_data *vgpu_pd_data;
438 struct generic_pm_domain *domain;
439
440 vgpu_pd_data = (struct gk20a_domain_data *)kzalloc
441 (sizeof(struct gk20a_domain_data), GFP_KERNEL);
442
443 if (!vgpu_pd_data)
444 return -ENOMEM;
445
446 domain = &vgpu_pd_data->gpd;
447 vgpu_pd_data->gk20a = platform->g;
448
449 domain->name = "gpu";
450
451#ifdef CONFIG_PM
452 pm_domain_gov = &pm_domain_always_on_gov;
453#endif
454
455 pm_genpd_init(domain, pm_domain_gov, true);
456
457 domain->dev_ops.save_state = vgpu_pm_prepare_poweroff;
458 domain->dev_ops.restore_state = vgpu_pm_finalize_poweron;
459
460 device_set_wakeup_capable(dev, 0);
461 return pm_genpd_add_device(domain, dev);
462}
463
464static int vgpu_pm_init(struct device *dev) 433static int vgpu_pm_init(struct device *dev)
465{ 434{
466 int err = 0; 435 int err = 0;
467 436
468 gk20a_dbg_fn(""); 437 gk20a_dbg_fn("");
469 438
470 pm_runtime_enable(dev); 439 __pm_runtime_disable(dev, false);
471
472 /* genpd will take care of runtime power management if it is enabled */
473 if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
474 err = vgpu_pm_initialise_domain(dev);
475 440
476 return err; 441 return err;
477} 442}
@@ -567,16 +532,11 @@ int vgpu_remove(struct platform_device *pdev)
567{ 532{
568 struct device *dev = &pdev->dev; 533 struct device *dev = &pdev->dev;
569 struct gk20a *g = get_gk20a(dev); 534 struct gk20a *g = get_gk20a(dev);
570 struct gk20a_domain_data *vgpu_gpd;
571 gk20a_dbg_fn(""); 535 gk20a_dbg_fn("");
572 536
573 if (g->remove_support) 537 if (g->remove_support)
574 g->remove_support(dev); 538 g->remove_support(dev);
575 539
576 vgpu_gpd = container_of(&g, struct gk20a_domain_data, gk20a);
577 vgpu_gpd->gk20a = NULL;
578 kfree(vgpu_gpd);
579
580 vgpu_comm_deinit(); 540 vgpu_comm_deinit();
581 gk20a_user_deinit(dev, &nvgpu_class); 541 gk20a_user_deinit(dev, &nvgpu_class);
582 gk20a_get_platform(dev)->g = NULL; 542 gk20a_get_platform(dev)->g = NULL;