gpu: nvgpu: add user API to get a syncpoint

Add new user API NVGPU_IOCTL_CHANNEL_GET_USER_SYNCPOINT which will expose
per-channel allocated syncpoint to user space
API will also return current value of the syncpoint
On supported platforms, this API will also return a RW semaphore address
(corresponding to syncpoint shim) to user space

Add new characteristics flag NVGPU_GPU_FLAGS_SUPPORT_USER_SYNCPOINT to indicate
support for this new API
Add new flag NVGPU_SUPPORT_USER_SYNCPOINT for use of core driver

Set this flag for GV11B and GP10B for now

Add a new API (*syncpt_address) in struct gk20a_channel_sync to get GPU_VA
address of a syncpoint

Add new API nvgpu_nvhost_syncpt_read_maxval() which will read and return MAX
value of syncpoint

Bug 200326065
Jira NVGPU-179

Change-Id: I9da6f17b85996f4fc6731c0bf94fca6f3181c3e0
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1658009
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Konsta Holtta <kholtta@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Deepak Nibade
2018-02-13 04:02:38 -08:00
committed by mobile promotions
parent 180604fec0
commit 8d5536271f
10 changed files with 111 additions and 2 deletions

View File

@@ -32,6 +32,7 @@
#include <nvgpu/enabled.h>
#include <nvgpu/error_notifier.h>
#include <nvgpu/barrier.h>
#include <nvgpu/nvhost.h>
#include "gk20a/gk20a.h"
#include "gk20a/dbg_gpu_gk20a.h"
@@ -948,6 +949,60 @@ static int nvgpu_ioctl_channel_set_preemption_mode(struct channel_gk20a *ch,
return err;
}
static int nvgpu_ioctl_channel_get_user_syncpoint(struct channel_gk20a *ch,
struct nvgpu_get_user_syncpoint_args *args)
{
#ifdef CONFIG_TEGRA_GK20A_NVHOST
struct gk20a *g = ch->g;
int err;
if (!nvgpu_is_enabled(g, NVGPU_SUPPORT_USER_SYNCPOINT)) {
nvgpu_err(g, "user syncpoints not supported");
return -EINVAL;
}
if (!gk20a_platform_has_syncpoints(g)) {
nvgpu_err(g, "syncpoints not supported");
return -EINVAL;
}
if (g->aggressive_sync_destroy_thresh) {
nvgpu_err(g, "sufficient syncpoints not available");
return -EINVAL;
}
nvgpu_mutex_acquire(&ch->sync_lock);
if (ch->sync) {
nvgpu_mutex_release(&ch->sync_lock);
} else {
ch->sync = gk20a_channel_sync_create(ch);
if (!ch->sync) {
nvgpu_mutex_release(&ch->sync_lock);
return -ENOMEM;
}
nvgpu_mutex_release(&ch->sync_lock);
if (g->ops.fifo.resetup_ramfc) {
err = g->ops.fifo.resetup_ramfc(ch);
if (err)
return err;
}
}
args->syncpoint_id = ch->sync->syncpt_id(ch->sync);
args->syncpoint_max = nvgpu_nvhost_syncpt_read_maxval(g->nvhost_dev,
args->syncpoint_id);
if (nvgpu_is_enabled(g, NVGPU_SUPPORT_SYNCPOINT_ADDRESS))
args->gpu_va = ch->sync->syncpt_address(ch->sync);
else
args->gpu_va = 0;
return 0;
#else
return -EINVAL;
#endif
}
long gk20a_channel_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
@@ -1239,6 +1294,18 @@ long gk20a_channel_ioctl(struct file *filp,
err = -EINVAL;
}
break;
case NVGPU_IOCTL_CHANNEL_GET_USER_SYNCPOINT:
err = gk20a_busy(ch->g);
if (err) {
dev_err(dev,
"%s: failed to host gk20a for ioctl cmd: 0x%x",
__func__, cmd);
break;
}
err = nvgpu_ioctl_channel_get_user_syncpoint(ch,
(struct nvgpu_get_user_syncpoint_args *)buf);
gk20a_idle(ch->g);
break;
default:
dev_dbg(dev, "unrecognized ioctl cmd: 0x%x", cmd);
err = -ENOTTY;