diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/channel.c | 11 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c | 115 |
2 files changed, 126 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/channel.c b/drivers/gpu/nvgpu/common/linux/channel.c index 716c5820..c295336f 100644 --- a/drivers/gpu/nvgpu/common/linux/channel.c +++ b/drivers/gpu/nvgpu/common/linux/channel.c | |||
@@ -537,6 +537,17 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
537 | if (c->deterministic) | 537 | if (c->deterministic) |
538 | nvgpu_rwsem_down_read(&g->deterministic_busy); | 538 | nvgpu_rwsem_down_read(&g->deterministic_busy); |
539 | 539 | ||
540 | if (c->deterministic && c->deterministic_railgate_allowed) { | ||
541 | /* | ||
542 | * Nope - this channel has dropped its own power ref. As | ||
543 | * deterministic submits don't hold power on per each submitted | ||
544 | * job like normal ones do, the GPU might railgate any time now | ||
545 | * and thus submit is disallowed. | ||
546 | */ | ||
547 | err = -EINVAL; | ||
548 | goto clean_up; | ||
549 | } | ||
550 | |||
540 | trace_gk20a_channel_submit_gpfifo(g->name, | 551 | trace_gk20a_channel_submit_gpfifo(g->name, |
541 | c->chid, | 552 | c->chid, |
542 | num_entries, | 553 | num_entries, |
diff --git a/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c index 73911717..08a831b9 100644 --- a/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/common/linux/ioctl_ctrl.c | |||
@@ -161,6 +161,8 @@ static struct nvgpu_flags_mapping flags_mapping[] = { | |||
161 | NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_NO_JOBTRACKING}, | 161 | NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_NO_JOBTRACKING}, |
162 | {NVGPU_GPU_FLAGS_SUPPORT_DETERMINISTIC_SUBMIT_FULL, | 162 | {NVGPU_GPU_FLAGS_SUPPORT_DETERMINISTIC_SUBMIT_FULL, |
163 | NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_FULL}, | 163 | NVGPU_SUPPORT_DETERMINISTIC_SUBMIT_FULL}, |
164 | {NVGPU_GPU_FLAGS_SUPPORT_DETERMINISTIC_OPTS, | ||
165 | NVGPU_SUPPORT_DETERMINISTIC_OPTS}, | ||
164 | {NVGPU_GPU_FLAGS_SUPPORT_IO_COHERENCE, | 166 | {NVGPU_GPU_FLAGS_SUPPORT_IO_COHERENCE, |
165 | NVGPU_SUPPORT_IO_COHERENCE}, | 167 | NVGPU_SUPPORT_IO_COHERENCE}, |
166 | {NVGPU_GPU_FLAGS_SUPPORT_RESCHEDULE_RUNLIST, | 168 | {NVGPU_GPU_FLAGS_SUPPORT_RESCHEDULE_RUNLIST, |
@@ -1319,6 +1321,114 @@ static int nvgpu_gpu_set_therm_alert_limit(struct gk20a *g, | |||
1319 | return err; | 1321 | return err; |
1320 | } | 1322 | } |
1321 | 1323 | ||
1324 | static int nvgpu_gpu_set_deterministic_ch_railgate(struct channel_gk20a *ch, | ||
1325 | u32 flags) | ||
1326 | { | ||
1327 | int err = 0; | ||
1328 | bool allow; | ||
1329 | bool disallow; | ||
1330 | |||
1331 | allow = flags & | ||
1332 | NVGPU_GPU_SET_DETERMINISTIC_OPTS_FLAGS_ALLOW_RAILGATING; | ||
1333 | |||
1334 | disallow = flags & | ||
1335 | NVGPU_GPU_SET_DETERMINISTIC_OPTS_FLAGS_DISALLOW_RAILGATING; | ||
1336 | |||
1337 | /* Can't be both at the same time */ | ||
1338 | if (allow && disallow) | ||
1339 | return -EINVAL; | ||
1340 | |||
1341 | /* Nothing to do */ | ||
1342 | if (!allow && !disallow) | ||
1343 | return 0; | ||
1344 | |||
1345 | /* | ||
1346 | * Moving into explicit idle or back from it? A call that doesn't | ||
1347 | * change the status is a no-op. | ||
1348 | */ | ||
1349 | if (!ch->deterministic_railgate_allowed && | ||
1350 | allow) { | ||
1351 | gk20a_idle(ch->g); | ||
1352 | } else if (ch->deterministic_railgate_allowed && | ||
1353 | !allow) { | ||
1354 | err = gk20a_busy(ch->g); | ||
1355 | if (err) { | ||
1356 | nvgpu_warn(ch->g, | ||
1357 | "cannot busy to restore deterministic ch"); | ||
1358 | return err; | ||
1359 | } | ||
1360 | } | ||
1361 | ch->deterministic_railgate_allowed = allow; | ||
1362 | |||
1363 | return err; | ||
1364 | } | ||
1365 | |||
1366 | static int nvgpu_gpu_set_deterministic_ch(struct channel_gk20a *ch, u32 flags) | ||
1367 | { | ||
1368 | if (!ch->deterministic) | ||
1369 | return -EINVAL; | ||
1370 | |||
1371 | return nvgpu_gpu_set_deterministic_ch_railgate(ch, flags); | ||
1372 | } | ||
1373 | |||
1374 | static int nvgpu_gpu_set_deterministic_opts(struct gk20a *g, | ||
1375 | struct nvgpu_gpu_set_deterministic_opts_args *args) | ||
1376 | { | ||
1377 | int __user *user_channels; | ||
1378 | u32 i = 0; | ||
1379 | int err = 0; | ||
1380 | |||
1381 | gk20a_dbg_fn(""); | ||
1382 | |||
1383 | user_channels = (int __user *)(uintptr_t)args->channels; | ||
1384 | |||
1385 | /* Upper limit; prevent holding deterministic_busy for long */ | ||
1386 | if (args->num_channels > g->fifo.num_channels) { | ||
1387 | err = -EINVAL; | ||
1388 | goto out; | ||
1389 | } | ||
1390 | |||
1391 | /* Trivial sanity check first */ | ||
1392 | if (!access_ok(VERIFY_READ, user_channels, | ||
1393 | args->num_channels * sizeof(int))) { | ||
1394 | err = -EFAULT; | ||
1395 | goto out; | ||
1396 | } | ||
1397 | |||
1398 | nvgpu_rwsem_down_read(&g->deterministic_busy); | ||
1399 | |||
1400 | /* note: we exit at the first failure */ | ||
1401 | for (; i < args->num_channels; i++) { | ||
1402 | int ch_fd = 0; | ||
1403 | struct channel_gk20a *ch; | ||
1404 | |||
1405 | if (copy_from_user(&ch_fd, &user_channels[i], sizeof(int))) { | ||
1406 | /* User raced with above access_ok */ | ||
1407 | err = -EFAULT; | ||
1408 | break; | ||
1409 | } | ||
1410 | |||
1411 | ch = gk20a_get_channel_from_file(ch_fd); | ||
1412 | if (!ch) { | ||
1413 | err = -EINVAL; | ||
1414 | break; | ||
1415 | } | ||
1416 | |||
1417 | err = nvgpu_gpu_set_deterministic_ch(ch, args->flags); | ||
1418 | |||
1419 | gk20a_channel_put(ch); | ||
1420 | |||
1421 | if (err) | ||
1422 | break; | ||
1423 | } | ||
1424 | |||
1425 | nvgpu_rwsem_up_read(&g->deterministic_busy); | ||
1426 | |||
1427 | out: | ||
1428 | args->num_channels = i; | ||
1429 | return err; | ||
1430 | } | ||
1431 | |||
1322 | long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 1432 | long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
1323 | { | 1433 | { |
1324 | struct gk20a_ctrl_priv *priv = filp->private_data; | 1434 | struct gk20a_ctrl_priv *priv = filp->private_data; |
@@ -1633,6 +1743,11 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg | |||
1633 | (struct nvgpu_gpu_set_therm_alert_limit_args *)buf); | 1743 | (struct nvgpu_gpu_set_therm_alert_limit_args *)buf); |
1634 | break; | 1744 | break; |
1635 | 1745 | ||
1746 | case NVGPU_GPU_IOCTL_SET_DETERMINISTIC_OPTS: | ||
1747 | err = nvgpu_gpu_set_deterministic_opts(g, | ||
1748 | (struct nvgpu_gpu_set_deterministic_opts_args *)buf); | ||
1749 | break; | ||
1750 | |||
1636 | default: | 1751 | default: |
1637 | gk20a_dbg_info("unrecognized gpu ioctl cmd: 0x%x", cmd); | 1752 | gk20a_dbg_info("unrecognized gpu ioctl cmd: 0x%x", cmd); |
1638 | err = -ENOTTY; | 1753 | err = -ENOTTY; |