From c1be5105dadc864159c40bdf1548336ac6fab3f9 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Tue, 8 Nov 2016 11:03:50 -0800 Subject: 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 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 --- drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c') diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index c2a21b22..40766857 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c @@ -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) -- cgit v1.2.2