video: tegra: dsi: Fix OS idle suspend/resume
Animesh Kishore [Thu, 22 Aug 2013 07:27:32 +0000 (12:27 +0530)]
- Acquire all required locks atomically.
- Fix lock sequence

Bug 1334200

Change-Id: I00839d61d72373d748217313d26eab19768e5865
Signed-off-by: Animesh Kishore <ankishore@nvidia.com>
Signed-off-by: Vineel Kumar Reddy Kovvuri <vineelkumarr@nvidia.com>
Reviewed-on: http://git-master/r/261058
(cherry picked from commit b6e3b7a07cfbd741469d592b35a178bfc9dfde67)
Reviewed-on: http://git-master/r/265487
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
GVS: Gerrit_Virtual_Submit

drivers/video/tegra/dc/dsi.c

index 1a36880..18c211e 100644 (file)
@@ -4140,6 +4140,39 @@ fail:
        return err;
 }
 
+static int tegra_dsi_host_suspend_trylock(struct tegra_dc *dc,
+                                       struct tegra_dc_dsi_data *dsi)
+{
+       if (!mutex_trylock(&dc->one_shot_lp_lock))
+               goto fail;
+       if (!mutex_trylock(&dc->lock))
+               goto unlock_one_shot_lp;
+       if (!mutex_trylock(&dsi->host_lock))
+               goto unlock_dc_lock;
+       if (!mutex_trylock(&dc->one_shot_lock))
+               goto unlock_host_lock;
+
+       return 1;
+
+unlock_host_lock:
+       mutex_unlock(&dsi->host_lock);
+unlock_dc_lock:
+       mutex_unlock(&dc->lock);
+unlock_one_shot_lp:
+       mutex_unlock(&dc->one_shot_lp_lock);
+fail:
+       return 0;
+}
+
+static void tegra_dsi_host_suspend_unlock(struct tegra_dc *dc,
+                                       struct tegra_dc_dsi_data *dsi)
+{
+       mutex_unlock(&dc->one_shot_lock);
+       mutex_unlock(&dsi->host_lock);
+       mutex_unlock(&dc->lock);
+       mutex_unlock(&dc->one_shot_lp_lock);
+}
+
 static int tegra_dsi_host_suspend(struct tegra_dc *dc)
 {
        int err = 0;
@@ -4151,10 +4184,9 @@ static int tegra_dsi_host_suspend(struct tegra_dc *dc)
        if (dsi->host_suspended)
                return 0;
 
-       mutex_lock(&dsi->host_lock);
-       mutex_lock(&dc->one_shot_lock);
-       mutex_lock(&dc->lock);
-       mutex_lock(&dc->one_shot_lp_lock);
+       while (!tegra_dsi_host_suspend_trylock(dc, dsi))
+               cond_resched();
+
        tegra_dc_io_start(dc);
        dsi->host_suspended = true;
 
@@ -4169,10 +4201,7 @@ static int tegra_dsi_host_suspend(struct tegra_dc *dc)
        while (tegra_is_clk_enabled(dc->clk))
                clk_disable_unprepare(dc->clk);
        tegra_dc_io_end(dc);
-       mutex_unlock(&dc->one_shot_lp_lock);
-       mutex_unlock(&dc->lock);
-       mutex_unlock(&dc->one_shot_lock);
-       mutex_unlock(&dsi->host_lock);
+       tegra_dsi_host_suspend_unlock(dc, dsi);
        return err;
 }
 
@@ -4267,8 +4296,8 @@ static int tegra_dsi_host_resume(struct tegra_dc *dc)
        if (!dsi->enabled)
                return -EINVAL;
 
+       cancel_delayed_work(&dsi->idle_work);
        mutex_lock(&dsi->host_lock);
-       cancel_delayed_work_sync(&dsi->idle_work);
        if (!dsi->host_suspended) {
                mutex_unlock(&dsi->host_lock);
                return 0;