mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
gpu: nvgpu: Move submit sync code into its own function
Move the submit synchornization code into it's own function. This should help keep the submit code path a little more readable and understandable. Bug 1732449 Reviewed-on: http://git-master/r/1203833 (cherry picked from commit f931c65c166aeca3b8fe2996dba4ea5133febc5a) Change-Id: I4111252d242a4dbffe7f9c31e397a27b66403efc Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: http://git-master/r/1221043 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
7b8cbd2be3
commit
c9bb122876
@@ -2086,6 +2086,100 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the submit synchronization - pre-fences and post-fences.
|
||||
*/
|
||||
static int gk20a_submit_prepare_syncs(struct channel_gk20a *c,
|
||||
struct nvgpu_fence *fence,
|
||||
struct priv_cmd_entry **wait_cmd,
|
||||
struct priv_cmd_entry **incr_cmd,
|
||||
struct gk20a_fence **pre_fence,
|
||||
struct gk20a_fence **post_fence,
|
||||
bool force_need_sync_fence,
|
||||
u32 flags)
|
||||
{
|
||||
struct gk20a *g = c->g;
|
||||
bool need_sync_fence = false;
|
||||
bool new_sync_created = false;
|
||||
int wait_fence_fd = -1;
|
||||
int err = 0;
|
||||
bool need_wfi = !(flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SUPPRESS_WFI);
|
||||
|
||||
/*
|
||||
* If user wants to always allocate sync_fence_fds then respect that;
|
||||
* otherwise, allocate sync_fence_fd based on user flags.
|
||||
*/
|
||||
if (force_need_sync_fence)
|
||||
need_sync_fence = true;
|
||||
|
||||
mutex_lock(&c->sync_lock);
|
||||
if (!c->sync) {
|
||||
c->sync = gk20a_channel_sync_create(c);
|
||||
if (!c->sync) {
|
||||
err = -ENOMEM;
|
||||
mutex_unlock(&c->sync_lock);
|
||||
goto fail;
|
||||
}
|
||||
new_sync_created = true;
|
||||
}
|
||||
atomic_inc(&c->sync->refcount);
|
||||
mutex_unlock(&c->sync_lock);
|
||||
|
||||
if (g->ops.fifo.resetup_ramfc && new_sync_created) {
|
||||
err = g->ops.fifo.resetup_ramfc(c);
|
||||
if (err)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionally insert syncpt wait in the beginning of gpfifo submission
|
||||
* when user requested and the wait hasn't expired. Validate that the id
|
||||
* makes sense, elide if not. The only reason this isn't being
|
||||
* unceremoniously killed is to keep running some tests which trigger
|
||||
* this condition.
|
||||
*/
|
||||
if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_WAIT) {
|
||||
if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE) {
|
||||
wait_fence_fd = fence->id;
|
||||
err = c->sync->wait_fd(c->sync, wait_fence_fd,
|
||||
wait_cmd, pre_fence);
|
||||
} else {
|
||||
err = c->sync->wait_syncpt(c->sync, fence->id,
|
||||
fence->value, wait_cmd,
|
||||
pre_fence);
|
||||
}
|
||||
}
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
if ((flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET) &&
|
||||
(flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE))
|
||||
need_sync_fence = true;
|
||||
|
||||
/*
|
||||
* Always generate an increment at the end of a GPFIFO submission. This
|
||||
* is used to keep track of method completion for idle railgating. The
|
||||
* sync_pt/semaphore PB is added to the GPFIFO later on in submit.
|
||||
*/
|
||||
if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET)
|
||||
err = c->sync->incr_user(c->sync, wait_fence_fd, incr_cmd,
|
||||
post_fence, need_wfi, need_sync_fence);
|
||||
else
|
||||
err = c->sync->incr(c->sync, incr_cmd,
|
||||
post_fence, need_sync_fence);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/*
|
||||
* Cleanup is handled by gk20a_submit_channel_gpfifo() since it is the
|
||||
* real owner of the objects we make here.
|
||||
*/
|
||||
return err;
|
||||
}
|
||||
|
||||
int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
|
||||
struct nvgpu_gpfifo *gpfifo,
|
||||
struct nvgpu_submit_gpfifo_args *args,
|
||||
@@ -2097,8 +2191,6 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
|
||||
{
|
||||
struct gk20a *g = c->g;
|
||||
struct device *d = dev_from_gk20a(g);
|
||||
int err = 0;
|
||||
int wait_fence_fd = -1;
|
||||
struct priv_cmd_entry *wait_cmd = NULL;
|
||||
struct priv_cmd_entry *incr_cmd = NULL;
|
||||
struct gk20a_fence *pre_fence = NULL;
|
||||
@@ -2106,21 +2198,12 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
|
||||
/* we might need two extra gpfifo entries - one for pre fence
|
||||
* and one for post fence. */
|
||||
const int extra_entries = 2;
|
||||
bool need_wfi = !(flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SUPPRESS_WFI);
|
||||
bool skip_buffer_refcounting = (flags &
|
||||
NVGPU_SUBMIT_GPFIFO_FLAGS_SKIP_BUFFER_REFCOUNTING);
|
||||
bool need_sync_fence = false;
|
||||
bool new_sync_created = false;
|
||||
int err = 0;
|
||||
struct nvgpu_gpfifo __user *user_gpfifo = args ?
|
||||
(struct nvgpu_gpfifo __user *)(uintptr_t)args->gpfifo : NULL;
|
||||
|
||||
/*
|
||||
* If user wants to allocate sync_fence_fd always, then respect that;
|
||||
* otherwise, allocate sync_fence_fd based on user flags only
|
||||
*/
|
||||
if (force_need_sync_fence)
|
||||
need_sync_fence = true;
|
||||
|
||||
if (c->has_timedout)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
@@ -2192,62 +2275,11 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
|
||||
}
|
||||
|
||||
|
||||
mutex_lock(&c->sync_lock);
|
||||
if (!c->sync) {
|
||||
c->sync = gk20a_channel_sync_create(c);
|
||||
if (!c->sync) {
|
||||
err = -ENOMEM;
|
||||
mutex_unlock(&c->sync_lock);
|
||||
goto clean_up;
|
||||
}
|
||||
new_sync_created = true;
|
||||
}
|
||||
atomic_inc(&c->sync->refcount);
|
||||
mutex_unlock(&c->sync_lock);
|
||||
|
||||
if (g->ops.fifo.resetup_ramfc && new_sync_created) {
|
||||
err = g->ops.fifo.resetup_ramfc(c);
|
||||
if (err) {
|
||||
goto clean_up;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* optionally insert syncpt wait in the beginning of gpfifo submission
|
||||
* when user requested and the wait hasn't expired.
|
||||
* validate that the id makes sense, elide if not
|
||||
* the only reason this isn't being unceremoniously killed is to
|
||||
* keep running some tests which trigger this condition
|
||||
*/
|
||||
if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_WAIT) {
|
||||
if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE) {
|
||||
wait_fence_fd = fence->id;
|
||||
err = c->sync->wait_fd(c->sync, wait_fence_fd,
|
||||
&wait_cmd, &pre_fence);
|
||||
} else {
|
||||
err = c->sync->wait_syncpt(c->sync, fence->id,
|
||||
fence->value, &wait_cmd, &pre_fence);
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
err = gk20a_submit_prepare_syncs(c, fence, &wait_cmd, &incr_cmd,
|
||||
&pre_fence, &post_fence,
|
||||
force_need_sync_fence, flags);
|
||||
if (err)
|
||||
goto clean_up;
|
||||
}
|
||||
|
||||
if ((flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET) &&
|
||||
(flags & NVGPU_SUBMIT_GPFIFO_FLAGS_SYNC_FENCE))
|
||||
need_sync_fence = true;
|
||||
|
||||
/* always insert syncpt increment at end of gpfifo submission
|
||||
to keep track of method completion for idle railgating */
|
||||
if (flags & NVGPU_SUBMIT_GPFIFO_FLAGS_FENCE_GET)
|
||||
err = c->sync->incr_user(c->sync, wait_fence_fd, &incr_cmd,
|
||||
&post_fence, need_wfi, need_sync_fence);
|
||||
else
|
||||
err = c->sync->incr(c->sync, &incr_cmd,
|
||||
&post_fence, need_sync_fence);
|
||||
if (err) {
|
||||
goto clean_up;
|
||||
}
|
||||
|
||||
if (wait_cmd)
|
||||
gk20a_submit_append_priv_cmdbuf(c, wait_cmd);
|
||||
@@ -2258,6 +2290,10 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c,
|
||||
if (err)
|
||||
goto clean_up;
|
||||
|
||||
/*
|
||||
* And here's where we add the incr_cmd we generated earlier. It should
|
||||
* always run!
|
||||
*/
|
||||
if (incr_cmd)
|
||||
gk20a_submit_append_priv_cmdbuf(c, incr_cmd);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user