From 49ea5f107b36abc24cf3859c34b2cf48899ac1b6 Mon Sep 17 00:00:00 2001 From: Andy Carman Date: Tue, 7 Sep 2010 22:17:01 -0700 Subject: tegra video: remove cancelled actions from the list at power down [bug] 729378 Change-Id: I34d276d2552491c933983309df0fe31f7bf3ba7e Reviewed-on: http://git-master/r/6443 Reviewed-by: Andy Carman Tested-by: Andy Carman Reviewed-by: Yu-Huan Hsu --- drivers/video/tegra/host/nvhost_channel.c | 4 +++- drivers/video/tegra/host/nvhost_intr.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c index 5adcf2175684..9cad47ff761d 100644 --- a/drivers/video/tegra/host/nvhost_channel.c +++ b/drivers/video/tegra/host/nvhost_channel.c @@ -247,6 +247,7 @@ static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action) struct nvhost_op_pair save; struct nvhost_cpuinterrupt ctxsw; u32 syncval; + void *ref; syncval = nvhost_syncpt_incr_max(&ch->dev->syncpt, NVSYNCPT_3D, ch->cur_ctx->save_incrs); @@ -259,8 +260,9 @@ static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action) ch->cur_ctx = NULL; nvhost_channel_submit(ch, &save, 1, &ctxsw, 1, NULL, 0, NVSYNCPT_3D, syncval, 0); nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D, syncval, - NVHOST_INTR_ACTION_WAKEUP, &wq, NULL); + NVHOST_INTR_ACTION_WAKEUP, &wq, &ref); wait_event(wq, nvhost_syncpt_min_cmp(&ch->dev->syncpt, NVSYNCPT_3D, syncval)); + nvhost_intr_put_ref(&ch->dev->intr, ref); nvhost_cdma_update(&ch->cdma); } mutex_unlock(&ch->submitlock); diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c index 5b32b19c7a69..4a546babd5ab 100644 --- a/drivers/video/tegra/host/nvhost_intr.c +++ b/drivers/video/tegra/host/nvhost_intr.c @@ -552,7 +552,20 @@ void nvhost_intr_stop(struct nvhost_intr *intr) for (id = 0, syncpt = intr->syncpt; id < NV_HOST1X_SYNCPT_NB_PTS; ++id, ++syncpt) { - BUG_ON(!list_empty(&syncpt->wait_head)); + struct nvhost_waitlist *waiter, *next; + list_for_each_entry_safe(waiter, next, &syncpt->wait_head, list) { + if (atomic_cmpxchg(&waiter->state, WLS_CANCELLED, WLS_HANDLED) + == WLS_CANCELLED) { + list_del(&waiter->list); + kref_put(&waiter->refcount, waiter_release); + } + } + + if(!list_empty(&syncpt->wait_head)) { // output diagnostics + printk("%s id=%d\n",__func__,id); + BUG_ON(1); + } + free_syncpt_irq(syncpt); } -- cgit v1.2.3