diff options
author | Alex Waterman <alexw@nvidia.com> | 2016-11-08 14:03:50 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-12-19 18:40:14 -0500 |
commit | c1be5105dadc864159c40bdf1548336ac6fab3f9 (patch) | |
tree | da6bfe71a2634712baa34a01d3b37fbce48766d4 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |
parent | 508ec183db0ca94d6d909475d44d02d580c49d9f (diff) |
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>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 30 |
1 files changed, 20 insertions, 10 deletions
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( | |||
910 | } | 910 | } |
911 | } | 911 | } |
912 | 912 | ||
913 | |||
914 | |||
915 | /* call ONLY when no references to the channel exist: after the last put */ | 913 | /* call ONLY when no references to the channel exist: after the last put */ |
916 | static void gk20a_free_channel(struct channel_gk20a *ch) | 914 | static void gk20a_free_channel(struct channel_gk20a *ch, bool force) |
917 | { | 915 | { |
918 | struct gk20a *g = ch->g; | 916 | struct gk20a *g = ch->g; |
919 | struct fifo_gk20a *f = &g->fifo; | 917 | struct fifo_gk20a *f = &g->fifo; |
@@ -935,9 +933,10 @@ static void gk20a_free_channel(struct channel_gk20a *ch) | |||
935 | gk20a_disable_channel(ch); | 933 | gk20a_disable_channel(ch); |
936 | 934 | ||
937 | /* wait until there's only our ref to the channel */ | 935 | /* wait until there's only our ref to the channel */ |
938 | gk20a_wait_until_counter_is_N( | 936 | if (!force) |
939 | ch, &ch->ref_count, 1, &ch->ref_count_dec_wq, | 937 | gk20a_wait_until_counter_is_N( |
940 | __func__, "references"); | 938 | ch, &ch->ref_count, 1, &ch->ref_count_dec_wq, |
939 | __func__, "references"); | ||
941 | 940 | ||
942 | /* wait until all pending interrupts for recently completed | 941 | /* wait until all pending interrupts for recently completed |
943 | * jobs are handled */ | 942 | * jobs are handled */ |
@@ -959,9 +958,10 @@ static void gk20a_free_channel(struct channel_gk20a *ch) | |||
959 | atomic_dec(&ch->ref_count); | 958 | atomic_dec(&ch->ref_count); |
960 | 959 | ||
961 | /* wait until no more refs to the channel */ | 960 | /* wait until no more refs to the channel */ |
962 | gk20a_wait_until_counter_is_N( | 961 | if (!force) |
963 | ch, &ch->ref_count, 0, &ch->ref_count_dec_wq, | 962 | gk20a_wait_until_counter_is_N( |
964 | __func__, "references"); | 963 | ch, &ch->ref_count, 0, &ch->ref_count_dec_wq, |
964 | __func__, "references"); | ||
965 | 965 | ||
966 | /* if engine reset was deferred, perform it now */ | 966 | /* if engine reset was deferred, perform it now */ |
967 | mutex_lock(&f->deferred_reset_mutex); | 967 | mutex_lock(&f->deferred_reset_mutex); |
@@ -1132,7 +1132,17 @@ void _gk20a_channel_put(struct channel_gk20a *ch, const char *caller) | |||
1132 | 1132 | ||
1133 | void gk20a_channel_close(struct channel_gk20a *ch) | 1133 | void gk20a_channel_close(struct channel_gk20a *ch) |
1134 | { | 1134 | { |
1135 | gk20a_free_channel(ch); | 1135 | gk20a_free_channel(ch, false); |
1136 | } | ||
1137 | |||
1138 | /* | ||
1139 | * Be careful with this - it is meant for terminating channels when we know the | ||
1140 | * driver is otherwise dying. Ref counts and the like are ignored by this | ||
1141 | * version of the cleanup. | ||
1142 | */ | ||
1143 | void __gk20a_channel_kill(struct channel_gk20a *ch) | ||
1144 | { | ||
1145 | gk20a_free_channel(ch, true); | ||
1136 | } | 1146 | } |
1137 | 1147 | ||
1138 | struct channel_gk20a *gk20a_get_channel_from_file(int fd) | 1148 | struct channel_gk20a *gk20a_get_channel_from_file(int fd) |