]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
tegra: dc: dont synchronize irq from irq thread
authorBibek Basu <bbasu@nvidia.com>
Mon, 4 Aug 2014 07:27:21 +0000 (12:57 +0530)
committerWinnie Hsu <whsu@nvidia.com>
Thu, 4 Sep 2014 01:00:03 +0000 (18:00 -0700)
Synchronizing IRQ from irq thread context will never return
because the thread will sleep forever.And thats the reason
for DPM timeout and kernel crash when suspend hook also
tries to do so.
[  204.471652] tegradc tegradc.1: **** DPM device timeout ****
[  204.484865] [<c07a58a8>] (__schedule+0x3b4/0x6e0) from [<c00ccf94>] (synchronize_irq+0xac/0xe4)
[  204.501399] [<c00ccf94>] (synchronize_irq+0xac/0xe4) from [<c0341628>] (tegra_dc_suspend+0xcc/0x15c)
[  204.518507] [<c0341628>] (tegra_dc_suspend+0xcc/0x15c) from [<c03da574>] (platform_pm_suspend+0x58/0x64)
[  204.536166] [<c03da574>] (platform_pm_suspend+0x58/0x64) from [<c0032c00>] (tegra_pd_suspend_dev+0x34/0x9c)
[  204.554226] [<c0032c00>] (tegra_pd_suspend_dev+0x34/0x9c) from [<c03e5384>] (pm_genpd_default_suspend+0x24/0x30)
[  204.572942] [<c03e5384>] (pm_genpd_default_suspend+0x24/0x30) from [<c03e5864>] (pm_genpd_suspend+0x58/0xa4)
[  204.591515] [<c03e5864>] (pm_genpd_suspend+0x58/0xa4) from [<c03dfb30>] (dpm_run_callback+0x34/0x54)
[  204.609552] [<c03dfb30>] (dpm_run_callback+0x34/0x54) from [<c03dffe4>] (__device_suspend+0x16c/0x380)

Bug 1486344

Change-Id: Ie512262fdfef90dc199f1f39ebffb540b909f3e2
Signed-off-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-on: http://git-master/r/450815
GVS: Gerrit_Virtual_Submit
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
drivers/video/tegra/dc/dc.c

index 7602b4e87c9edc07ff12b37c3e1843fca1ab354c..2809eef48ea33a96e051f312ace2a79df9a2bcf9 100644 (file)
@@ -100,7 +100,7 @@ static struct fb_videomode tegra_dc_vga_mode = {
 static struct tegra_dc_mode override_disp_mode[3];
 
 static void _tegra_dc_controller_disable(struct tegra_dc *dc);
-
+static void tegra_dc_disable_nosync(struct tegra_dc *dc);
 struct tegra_dc *tegra_dcs[TEGRA_MAX_DC];
 
 DEFINE_MUTEX(tegra_dc_lock);
@@ -2035,7 +2035,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *ptr)
        mutex_unlock(&dc->lock);
 
        if (need_disable)
-               tegra_dc_disable(dc);
+               tegra_dc_disable_nosync(dc);
        return IRQ_HANDLED;
 }
 
@@ -2667,6 +2667,42 @@ static void _tegra_dc_disable(struct tegra_dc *dc)
        tegra_log_suspend_time();
 }
 
+static void tegra_dc_disable_nosync(struct tegra_dc *dc)
+{
+       if (WARN_ON(!dc || !dc->out || !dc->out_ops))
+               return;
+
+       tegra_dc_ext_disable(dc->ext);
+
+       /* it's important that new underflow work isn't scheduled before the
+        * lock is acquired. */
+       cancel_delayed_work_sync(&dc->underflow_work);
+
+       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+               mutex_lock(&dc->one_shot_lp_lock);
+       mutex_lock(&dc->lock);
+
+       if (dc->enabled) {
+               dc->enabled = false;
+               dc->blanked = false;
+
+               if (!dc->suspended)
+                       _tegra_dc_disable(dc);
+       }
+
+#ifdef CONFIG_SWITCH
+       switch_set_state(&dc->modeset_switch, 0);
+#endif
+       mutex_unlock(&dc->lock);
+       if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
+               mutex_unlock(&dc->one_shot_lp_lock);
+       trace_display_mode(dc, &dc->mode);
+
+       /* disable pending clks due to uncompleted frames */
+       while (tegra_is_clk_enabled(dc->clk))
+               tegra_dc_put(dc);
+}
+
 void tegra_dc_disable(struct tegra_dc *dc)
 {
        if (WARN_ON(!dc || !dc->out || !dc->out_ops))