summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c58
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
155static void gk20a_channel_syncpt_update(void *priv, int nr_completed) 155static 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
161static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, 176static 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,