diff options
author | Allen Yu <alleny@nvidia.com> | 2014-07-02 15:14:24 +0800 |
---|---|---|
committer | Mandar Padmawar <mpadmawar@nvidia.com> | 2014-07-04 06:13:59 -0700 |
commit | 1be10e6325b730e8d4d6854965f66a147f0c2863 (patch) | |
tree | fe7a7ef6dbca48312856a0710e17ad42d74bb356 /drivers/media/platform/tegra | |
parent | 8e332826d660e52478ce7c3a407d8e004448cc28 (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.c | 7 |
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--; |