diff options
author | Bibek Basu <bbasu@nvidia.com> | 2014-08-04 12:57:21 +0530 |
---|---|---|
committer | Winnie Hsu <whsu@nvidia.com> | 2014-09-03 18:00:03 -0700 |
commit | ac954dd4168e97d41d68d79d530144333a8ef132 (patch) | |
tree | cbe8a49e3775e0927be98812396efeba980b62e4 | |
parent | 2eed826401188b5d241d3bb9302915b50c6ef91e (diff) |
tegra: dc: dont synchronize irq from irq thread
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>
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 7602b4e87c9e..2809eef48ea3 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -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)) |