diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c index 8cc852c7..7a707fbd 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | |||
@@ -154,8 +154,23 @@ static int gk20a_channel_syncpt_wait_fd(struct gk20a_channel_sync *s, int fd, | |||
154 | 154 | ||
155 | static void gk20a_channel_syncpt_update(void *priv, int nr_completed) | 155 | static void gk20a_channel_syncpt_update(void *priv, int nr_completed) |
156 | { | 156 | { |
157 | struct channel_gk20a *ch20a = priv; | 157 | struct channel_gk20a *ch = priv; |
158 | gk20a_channel_update(ch20a, nr_completed); | 158 | struct gk20a *g = ch->g; |
159 | |||
160 | /* need busy for possible channel deletion */ | ||
161 | if (gk20a_busy(ch->g->dev)) { | ||
162 | gk20a_err(dev_from_gk20a(ch->g), | ||
163 | "failed to busy while syncpt update"); | ||
164 | /* Last gk20a_idle()s are in channel_update, so we shouldn't | ||
165 | * get here. If we do, the channel is badly broken now */ | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | /* note: channel_get() is in __gk20a_channel_syncpt_incr() */ | ||
170 | gk20a_channel_update(ch, nr_completed); | ||
171 | gk20a_channel_put(ch); | ||
172 | |||
173 | gk20a_idle(g->dev); | ||
159 | } | 174 | } |
160 | 175 | ||
161 | static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, | 176 | static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, |
@@ -209,14 +224,37 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, | |||
209 | thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 2); | 224 | thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 2); |
210 | 225 | ||
211 | if (register_irq) { | 226 | if (register_irq) { |
212 | err = nvhost_intr_register_notifier(sp->host1x_pdev, | 227 | err = gk20a_busy(c->g->dev); |
213 | sp->id, thresh, | 228 | if (err) |
214 | gk20a_channel_syncpt_update, c); | 229 | gk20a_err(dev_from_gk20a(c->g), |
215 | 230 | "failed to add syncpt interrupt notifier for channel %d", | |
216 | /* Adding interrupt action should never fail. A proper error | 231 | c->hw_chid); |
217 | * handling here would require us to decrement the syncpt max | 232 | else { |
218 | * back to its original value. */ | 233 | struct channel_gk20a *referenced = gk20a_channel_get(c); |
219 | WARN(err, "failed to set submit complete interrupt"); | 234 | |
235 | WARN_ON(!referenced); | ||
236 | gk20a_idle(c->g->dev); | ||
237 | |||
238 | if (referenced) { | ||
239 | /* note: channel_put() is in | ||
240 | * gk20a_channel_syncpt_update() */ | ||
241 | |||
242 | err = nvhost_intr_register_notifier( | ||
243 | sp->host1x_pdev, | ||
244 | sp->id, thresh, | ||
245 | gk20a_channel_syncpt_update, c); | ||
246 | if (err) | ||
247 | gk20a_channel_put(referenced); | ||
248 | |||
249 | /* Adding interrupt action should | ||
250 | * never fail. A proper error handling | ||
251 | * here would require us to decrement | ||
252 | * the syncpt max back to its original | ||
253 | * value. */ | ||
254 | WARN(err, | ||
255 | "failed to set submit complete interrupt"); | ||
256 | } | ||
257 | } | ||
220 | } | 258 | } |
221 | 259 | ||
222 | *fence = gk20a_fence_from_syncpt(sp->host1x_pdev, sp->id, thresh, | 260 | *fence = gk20a_fence_from_syncpt(sp->host1x_pdev, sp->id, thresh, |