]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
media: tegra: nvavp: fix deadlock issue
authorAllen Yu <alleny@nvidia.com>
Wed, 2 Jul 2014 07:14:24 +0000 (15:14 +0800)
committerMandar Padmawar <mpadmawar@nvidia.com>
Fri, 4 Jul 2014 13:13:59 +0000 (06:13 -0700)
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>
drivers/media/platform/tegra/nvavp/nvavp_dev.c

index be6c0e269a998221edd890d3fe279d4c33bc0f7f..b14fd134d560efb203506a60b981368573bd3653 100644 (file)
@@ -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--;