gpu: nvgpu: Allow channel free to be forced

Allow forced channel freeing. This is useful when the driver is
being cleaned up and the gk20a_wait_until_counter_is_N() could
potentially hang.

Bug 1816516
Bug 1807277

Change-Id: I711f5f3f6413d0bb30b4857e785ca3b504b494ee
Signed-off-by: Alex Waterman <alexw@nvidia.com>
Reviewed-on: http://git-master/r/1250022
(cherry picked from commit e132d0e5ae77d758680ac708622a4883bbd69ba3)
Reviewed-on: http://git-master/r/1261918
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
Alex Waterman
2016-11-08 11:03:50 -08:00
committed by mobile promotions
parent 508ec183db
commit c1be5105da
2 changed files with 21 additions and 10 deletions

View File

@@ -910,10 +910,8 @@ static void gk20a_wait_until_counter_is_N(
}
}
/* call ONLY when no references to the channel exist: after the last put */
static void gk20a_free_channel(struct channel_gk20a *ch)
static void gk20a_free_channel(struct channel_gk20a *ch, bool force)
{
struct gk20a *g = ch->g;
struct fifo_gk20a *f = &g->fifo;
@@ -935,9 +933,10 @@ static void gk20a_free_channel(struct channel_gk20a *ch)
gk20a_disable_channel(ch);
/* wait until there's only our ref to the channel */
gk20a_wait_until_counter_is_N(
ch, &ch->ref_count, 1, &ch->ref_count_dec_wq,
__func__, "references");
if (!force)
gk20a_wait_until_counter_is_N(
ch, &ch->ref_count, 1, &ch->ref_count_dec_wq,
__func__, "references");
/* wait until all pending interrupts for recently completed
* jobs are handled */
@@ -959,9 +958,10 @@ static void gk20a_free_channel(struct channel_gk20a *ch)
atomic_dec(&ch->ref_count);
/* wait until no more refs to the channel */
gk20a_wait_until_counter_is_N(
ch, &ch->ref_count, 0, &ch->ref_count_dec_wq,
__func__, "references");
if (!force)
gk20a_wait_until_counter_is_N(
ch, &ch->ref_count, 0, &ch->ref_count_dec_wq,
__func__, "references");
/* if engine reset was deferred, perform it now */
mutex_lock(&f->deferred_reset_mutex);
@@ -1132,7 +1132,17 @@ void _gk20a_channel_put(struct channel_gk20a *ch, const char *caller)
void gk20a_channel_close(struct channel_gk20a *ch)
{
gk20a_free_channel(ch);
gk20a_free_channel(ch, false);
}
/*
* Be careful with this - it is meant for terminating channels when we know the
* driver is otherwise dying. Ref counts and the like are ignored by this
* version of the cleanup.
*/
void __gk20a_channel_kill(struct channel_gk20a *ch)
{
gk20a_free_channel(ch, true);
}
struct channel_gk20a *gk20a_get_channel_from_file(int fd)

View File

@@ -226,6 +226,7 @@ int gk20a_init_channel_support(struct gk20a *, u32 chid);
/* must be inside gk20a_busy()..gk20a_idle() */
void gk20a_channel_close(struct channel_gk20a *ch);
void __gk20a_channel_kill(struct channel_gk20a *ch);
bool gk20a_channel_update_and_check_timeout(struct channel_gk20a *ch,
u32 timeout_delta_ms, bool *progress);