From 9c5d336fb77a9a6afd7126cfae5cbdc9af2b64d4 Mon Sep 17 00:00:00 2001 From: Lauri Peltonen Date: Mon, 7 Apr 2014 19:21:44 +0300 Subject: 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 Reviewed-on: http://git-master/r/394127 Reviewed-by: Deepak Nibade Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a/channel_sync_gk20a.c') 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) static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, bool gfx_class, bool wfi_cmd, + bool register_irq, struct priv_cmd_entry **entry, struct gk20a_channel_fence *fence) { @@ -184,18 +185,12 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, container_of(s, struct gk20a_channel_syncpt, ops); struct channel_gk20a *c = sp->c; - /* nvhost action_gpfifo_submit_complete releases this ref. */ - err = gk20a_channel_busy(c->g->dev); - if (err) - return err; - incr_cmd_size = 4; if (wfi_cmd) incr_cmd_size += 2; gk20a_channel_alloc_priv_cmdbuf(c, incr_cmd_size, &incr_cmd); if (incr_cmd == NULL) { - gk20a_channel_idle(c->g->dev); gk20a_err(dev_from_gk20a(c->g), "not enough priv cmd buffer space"); return -EAGAIN; @@ -230,15 +225,22 @@ static int __gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, thresh = nvhost_syncpt_incr_max_ext(sp->host1x_pdev, sp->id, 1); - err = nvhost_intr_register_notifier(sp->host1x_pdev, sp->id, thresh, - gk20a_channel_syncpt_update, c); + if (register_irq) { + /* nvhost action_gpfifo_submit_complete releases this ref. */ + err = gk20a_channel_busy(c->g->dev); + + if (!err) { + err = nvhost_intr_register_notifier(sp->host1x_pdev, + sp->id, thresh, + gk20a_channel_syncpt_update, c); + if (err) + gk20a_channel_idle(c->g->dev); + } - /* Adding interrupt action should never fail. A proper error handling - * here would require us to decrement the syncpt max back to its - * original value. */ - if (WARN(err, "failed to set submit complete interrupt")) { - gk20a_channel_idle(c->g->dev); - err = 0; /* Ignore this error. */ + /* Adding interrupt action should never fail. A proper error + * handling here would require us to decrement the syncpt max + * back to its original value. */ + WARN(err, "failed to set submit complete interrupt"); } fence->thresh = thresh; @@ -255,6 +257,7 @@ int gk20a_channel_syncpt_incr_wfi(struct gk20a_channel_sync *s, return __gk20a_channel_syncpt_incr(s, false /* use host class */, true /* wfi */, + false /* no irq handler */, entry, fence); } @@ -269,6 +272,7 @@ int gk20a_channel_syncpt_incr(struct gk20a_channel_sync *s, return __gk20a_channel_syncpt_incr(s, sp->c->obj_class == KEPLER_C /* may use gfx class */, false /* no wfi */, + true /* register irq */, entry, fence); } @@ -284,6 +288,7 @@ int gk20a_channel_syncpt_incr_user_syncpt(struct gk20a_channel_sync *s, int err = __gk20a_channel_syncpt_incr(s, sp->c->obj_class == KEPLER_C /* use gfx class? */, sp->c->obj_class != KEPLER_C /* wfi if host class */, + true /* register irq */, entry, fence); if (err) return err; -- cgit v1.2.2