summaryrefslogtreecommitdiff
path: root/drivers/media/platform/tegra
diff options
context:
space:
mode:
authorAllen Yu <alleny@nvidia.com>2014-07-02 15:14:24 +0800
committerMandar Padmawar <mpadmawar@nvidia.com>2014-07-04 06:13:59 -0700
commit1be10e6325b730e8d4d6854965f66a147f0c2863 (patch)
treefe7a7ef6dbca48312856a0710e17ad42d74bb356 /drivers/media/platform/tegra
parent8e332826d660e52478ce7c3a407d8e004448cc28 (diff)
media: tegra: nvavp: fix deadlock issue
In nvavp_pushbuffer_update(), we acquire channel_info->pushbuffer_lock first then nvavp->open_lock. While in clock_disable_handler(), open_lock is acquired before pushbuffer_lock, causing the deadlock if clock_disable_work happens to be executing while running nvavp_pushbuffer_update(). This change reorder the locks in clock_disable_handler to avoid deadlock issue. And also in tegra_nvavp_release(), need to release nvavp->open_lock first before calling nvavp_uninit(), since nvavp_uninit() need to cancel clock_disable_work in a synchronous manner. Bug 200013513 Change-Id: I42082a97cc4e311a4141559f8a56c7c1eeb97eb2 Signed-off-by: Allen Yu <alleny@nvidia.com> Reviewed-on: http://git-master/r/433523 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Soumenkumar Dey <sdey@nvidia.com> Reviewed-by: Mandar Potdar <mpotdar@nvidia.com> Tested-by: Yogesh Solanke <ysolanke@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: Somu Sundaram <somasundarams@nvidia.com>
Diffstat (limited to 'drivers/media/platform/tegra')
-rw-r--r--drivers/media/platform/tegra/nvavp/nvavp_dev.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/media/platform/tegra/nvavp/nvavp_dev.c b/drivers/media/platform/tegra/nvavp/nvavp_dev.c
index be6c0e269a99..b14fd134d560 100644
--- a/drivers/media/platform/tegra/nvavp/nvavp_dev.c
+++ b/drivers/media/platform/tegra/nvavp/nvavp_dev.c
@@ -614,8 +614,8 @@ static void clock_disable_handler(struct work_struct *work)
clock_disable_work);
channel_info = nvavp_get_channel_info(nvavp, NVAVP_VIDEO_CHANNEL);
- mutex_lock(&nvavp->open_lock);
mutex_lock(&channel_info->pushbuffer_lock);
+ mutex_lock(&nvavp->open_lock);
if (nvavp_check_idle(nvavp, NVAVP_VIDEO_CHANNEL) && nvavp->pending) {
nvavp->pending = false;
nvavp_clks_disable(nvavp);
@@ -1950,8 +1950,11 @@ static int tegra_nvavp_release(struct nvavp_clientctx *clientctx,
if (nvavp->refcount > 0)
nvavp->refcount--;
- if (!nvavp->refcount)
+ if (!nvavp->refcount) {
+ mutex_unlock(&nvavp->open_lock);
nvavp_uninit(nvavp);
+ mutex_lock(&nvavp->open_lock);
+ }
if (IS_VIDEO_CHANNEL_ID(channel_id))
nvavp->video_refcnt--;