diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2016-06-09 09:16:21 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-07-08 03:58:53 -0400 |
commit | e27c72446bf09196d6d66f28389f00565273a13f (patch) | |
tree | 473530a0f10eee8d9dcae29afdc35c72b7a6a0ad /drivers/gpu/nvgpu/gk20a/gk20a.c | |
parent | 8417698b519be9dc8c1bd04714fc72ce4e0bc38f (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/nvgpu/gk20a/gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 378 |
1 files changed, 110 insertions, 268 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 | ||
1133 | static int gk20a_pm_enable_clk(struct device *dev) | 1132 | static 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 | ||
1153 | static int gk20a_pm_disable_clk(struct device *dev) | 1143 | static 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 | ||
1170 | static void gk20a_pm_shutdown(struct platform_device *pdev) | 1159 | static 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 | 1186 | static int gk20a_pm_runtime_resume(struct device *dev) |
1201 | static 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 | |||
1209 | static 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 | ||
1218 | static 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 | |||
1200 | fail_poweron: | ||
1201 | gk20a_pm_railgate(dev); | ||
1202 | fail: | ||
1203 | return err; | ||
1225 | } | 1204 | } |
1226 | 1205 | ||
1227 | static int _gk20a_pm_unrailgate(struct device *dev) | 1206 | static 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 | ||
1241 | static 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); | 1220 | fail_railgate: |
1221 | gk20a_pm_finalize_poweron(dev); | ||
1222 | fail: | ||
1223 | return err; | ||
1249 | } | 1224 | } |
1250 | 1225 | ||
1251 | static int gk20a_pm_suspend(struct device *dev) | 1226 | static 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 | ||
1271 | static int gk20a_pm_resume(struct device *dev) | 1252 | static 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 | ||
1277 | static 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 | ||
1300 | static 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) | 1268 | static 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 | ||
1343 | int gk20a_pm_init(struct device *dev) | 1276 | int 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 | ||
1389 | static 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 | |||
1397 | static int gk20a_probe(struct platform_device *dev) | 1318 | static 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 | |||
1710 | static 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 | |||
1738 | static 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 | ||
1758 | static int gk20a_domain_init(struct of_device_id *matches) | ||
1759 | { | ||
1760 | return 0; | ||
1761 | } | ||
1762 | #endif | ||
1763 | |||
1764 | struct class nvgpu_class = { | 1611 | struct 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 | ||
1839 | fail: | 1681 | fail: |
@@ -1844,18 +1686,22 @@ fail: | |||
1844 | 1686 | ||
1845 | void gk20a_idle(struct device *dev) | 1687 | void 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 | ||
1861 | void gk20a_disable(struct gk20a *g, u32 units) | 1707 | void 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 | ||