summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
diff options
context:
space:
mode:
authorLauri Peltonen <lpeltonen@nvidia.com>2014-04-07 12:21:44 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:09:01 -0400
commit9c5d336fb77a9a6afd7126cfae5cbdc9af2b64d4 (patch)
tree97e99944612124a96ae2b194b20c9631100c4699 /drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
parent9727cf87bc0eeb62c00602ebb479c5f38d1bb30e (diff)
gpu: nvgpu: Don't request host1x irq on channel wfi
Fix regression caused by commit 67fa249b419d32bfd0873fe5d924f4f01d9048de "video: tegra: host: Abstract gk20a channel synchronization". The above change unintentionally modified the channel synchronization logic so that an nvhost interrupt handler was scheduled also when idling the channel in gk20a_channel_submit_wfi. That appears to cause intermittent hangs when running CUDA tests. Bug 1484824 Change-Id: I4a1f85dd9e6215350f93710a2be9b0bbaef24b8f Signed-off-by: Lauri Peltonen <lpeltonen@nvidia.com> Reviewed-on: http://git-master/r/394127 Reviewed-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
index 851ae18b..b94c0c93 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c
@@ -172,6 +172,7 @@ static void gk20a_channel_syncpt_update(void *priv, int nr_completed)
172 172
173static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, 173static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s,
174 bool gfx_class, bool wfi_cmd, 174 bool gfx_class, bool wfi_cmd,
175 bool register_irq,
175 struct priv_cmd_entry **entry, 176 struct priv_cmd_entry **entry,
176 struct gk20a_channel_fence *fence) 177 struct gk20a_channel_fence *fence)
177{ 178{
@@ -184,18 +185,12 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s,
184 container_of(s, struct gk20a_channel_syncpt, ops); 185 container_of(s, struct gk20a_channel_syncpt, ops);
185 struct channel_gk20a *c = sp->c; 186 struct channel_gk20a *c = sp->c;
186 187
187 /* nvhost action_gpfifo_submit_complete releases this ref. */
188 err = gk20a_channel_busy(c->g->dev);
189 if (err)
190 return err;
191
192 incr_cmd_size = 4; 188 incr_cmd_size = 4;
193 if (wfi_cmd) 189 if (wfi_cmd)
194 incr_cmd_size += 2; 190 incr_cmd_size += 2;
195 191
196 gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, &incr_cmd); 192 gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, &incr_cmd);
197 if (incr_cmd == NULL) { 193 if (incr_cmd == NULL) {
198 gk20a_channel_idle(c->g->dev);
199 gk20a_err(dev_from_gk20a(c->g), 194 gk20a_err(dev_from_gk20a(c->g),
200 "not enough priv cmd buffer space"); 195 "not enough priv cmd buffer space");
201 return -EAGAIN; 196 return -EAGAIN;
@@ -230,15 +225,22 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s,
230 225
231 thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 1); 226 thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 1);
232 227
233 err = nvhost_intr_register_notifier(sp->host1x_pdev, sp->id, thresh, 228 if (register_irq) {
234 gk20a_channel_syncpt_update, c); 229 /* nvhost action_gpfifo_submit_complete releases this ref. */
230 err = gk20a_channel_busy(c->g->dev);
231
232 if (!err) {
233 err = nvhost_intr_register_notifier(sp->host1x_pdev,
234 sp->id, thresh,
235 gk20a_channel_syncpt_update, c);
236 if (err)
237 gk20a_channel_idle(c->g->dev);
238 }
235 239
236 /* Adding interrupt action should never fail. A proper error handling 240 /* Adding interrupt action should never fail. A proper error
237 * here would require us to decrement the syncpt max back to its 241 * handling here would require us to decrement the syncpt max
238 * original value. */ 242 * back to its original value. */
239 if (WARN(err, "failed to set submit complete interrupt")) { 243 WARN(err, "failed to set submit complete interrupt");
240 gk20a_channel_idle(c->g->dev);
241 err = 0; /* Ignore this error. */
242 } 244 }
243 245
244 fence->thresh = thresh; 246 fence->thresh = thresh;
@@ -255,6 +257,7 @@ int gk20a_channel_syncpt_incr_wfi(struct gk20a_channel_sync *s,
255 return __gk20a_channel_syncpt_incr(s, 257 return __gk20a_channel_syncpt_incr(s,
256 false /* use host class */, 258 false /* use host class */,
257 true /* wfi */, 259 true /* wfi */,
260 false /* no irq handler */,
258 entry, fence); 261 entry, fence);
259} 262}
260 263
@@ -269,6 +272,7 @@ int gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s,
269 return __gk20a_channel_syncpt_incr(s, 272 return __gk20a_channel_syncpt_incr(s,
270 sp->c->obj_class == KEPLER_C /* may use gfx class */, 273 sp->c->obj_class == KEPLER_C /* may use gfx class */,
271 false /* no wfi */, 274 false /* no wfi */,
275 true /* register irq */,
272 entry, fence); 276 entry, fence);
273} 277}
274 278
@@ -284,6 +288,7 @@ int gk20a_channel_syncpt_incr_user_syncpt(struct gk20a_channel_sync *s,
284 int err = __gk20a_channel_syncpt_incr(s, 288 int err = __gk20a_channel_syncpt_incr(s,
285 sp->c->obj_class == KEPLER_C /* use gfx class? */, 289 sp->c->obj_class == KEPLER_C /* use gfx class? */,
286 sp->c->obj_class != KEPLER_C /* wfi if host class */, 290 sp->c->obj_class != KEPLER_C /* wfi if host class */,
291 true /* register irq */,
287 entry, fence); 292 entry, fence);
288 if (err) 293 if (err)
289 return err; 294 return err;