diff options
author | David Nieto <dmartineznie@nvidia.com> | 2017-03-13 23:23:03 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-03-25 05:06:55 -0400 |
commit | e0f2afe5eb43fb32490ccabd504879c3e3e54623 (patch) | |
tree | d227311914fd44e88e1ab13b652870c0fa772cf1 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |
parent | b48186488d0108dee7b3fb755b2d99f4652780df (diff) |
gpu: nvgpu: refactor teardown to support unbind
This change refactors the teardown in remove to ensure that it is
possible to unload the driver while leaving fds open. This is achieved
by making sure that the SW state is kept alive till all fds are closed
and by checking that subsequent calls to ioctls after the teardown fail.
Normally, this would be achieved ny calls into gk20a_busy(), but in
kickoff we dont call into that to reduce latency, so we need to check
the driver status directly, and also in some of the functions
as we need to make sure the ioctl does not dereference the device or
platform struct
bug 200277762
JIRA: EVLR-1023
Change-Id: I163e47a08c29d4d5b3ab79f0eb531ef234f40bde
Signed-off-by: David Nieto <dmartineznie@nvidia.com>
Reviewed-on: http://git-master/r/1320219
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
Reviewed-by: Shreshtha Sahu <ssahu@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 0249a1c6..d0d38f83 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -122,7 +122,8 @@ static struct channel_gk20a *allocate_channel(struct fifo_gk20a *f) | |||
122 | static void free_channel(struct fifo_gk20a *f, | 122 | static void free_channel(struct fifo_gk20a *f, |
123 | struct channel_gk20a *ch) | 123 | struct channel_gk20a *ch) |
124 | { | 124 | { |
125 | struct gk20a_platform *platform = gk20a_get_platform(f->g->dev); | 125 | struct gk20a_platform *platform; |
126 | struct gk20a *g = f->g; | ||
126 | 127 | ||
127 | trace_gk20a_release_used_channel(ch->hw_chid); | 128 | trace_gk20a_release_used_channel(ch->hw_chid); |
128 | /* refcount is zero here and channel is in a freed/dead state */ | 129 | /* refcount is zero here and channel is in a freed/dead state */ |
@@ -132,10 +133,18 @@ static void free_channel(struct fifo_gk20a *f, | |||
132 | f->used_channels--; | 133 | f->used_channels--; |
133 | nvgpu_mutex_release(&f->free_chs_mutex); | 134 | nvgpu_mutex_release(&f->free_chs_mutex); |
134 | 135 | ||
135 | if (platform->aggressive_sync_destroy_thresh && | 136 | /* |
137 | * On teardown it is not possible to dereference platform, but ignoring | ||
138 | * this is fine then because no new channels would be created. | ||
139 | */ | ||
140 | if (!g->driver_is_dying) { | ||
141 | platform = gk20a_get_platform(g->dev); | ||
142 | |||
143 | if (platform->aggressive_sync_destroy_thresh && | ||
136 | (f->used_channels < | 144 | (f->used_channels < |
137 | platform->aggressive_sync_destroy_thresh)) | 145 | platform->aggressive_sync_destroy_thresh)) |
138 | platform->aggressive_sync_destroy = false; | 146 | platform->aggressive_sync_destroy = false; |
147 | } | ||
139 | } | 148 | } |
140 | 149 | ||
141 | int channel_gk20a_commit_va(struct channel_gk20a *c) | 150 | int channel_gk20a_commit_va(struct channel_gk20a *c) |
@@ -3016,7 +3025,12 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
3016 | bool need_deferred_cleanup = false; | 3025 | bool need_deferred_cleanup = false; |
3017 | struct nvgpu_gpfifo __user *user_gpfifo = args ? | 3026 | struct nvgpu_gpfifo __user *user_gpfifo = args ? |
3018 | (struct nvgpu_gpfifo __user *)(uintptr_t)args->gpfifo : NULL; | 3027 | (struct nvgpu_gpfifo __user *)(uintptr_t)args->gpfifo : NULL; |
3019 | struct gk20a_platform *platform = gk20a_get_platform(d); | 3028 | struct gk20a_platform *platform; |
3029 | |||
3030 | if (g->driver_is_dying) | ||
3031 | return -ENODEV; | ||
3032 | |||
3033 | platform = gk20a_get_platform(d); | ||
3020 | 3034 | ||
3021 | if (c->has_timedout) | 3035 | if (c->has_timedout) |
3022 | return -ETIMEDOUT; | 3036 | return -ETIMEDOUT; |