summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDaniel Solomon <daniels@nvidia.com>2014-08-14 17:50:15 -0700
committerWinnie Hsu <whsu@nvidia.com>2014-09-18 11:13:51 -0700
commited69dc2adccd7cec79c724c2269a7c4cc6c0a74e (patch)
tree6fb48d2fa5f24403dddbfffdc552a36f749add56 /drivers
parent7ea8e5317c76e8618e011af1c951b00ab7ac5403 (diff)
video: tegra: dc: Avoid FRAME_END_INT conflict
Allowing for dc->lock to be acquired by the caller in function tegra_dc_config_frame_end_intr can result in FRAME_END_INT mask register being overwritten if the lock is actually acquired by another thread. Refactor the critical section into its own function and allow callers to call either function. Also Change the name of tegra_dc_wait_for_frame_end to indicate that it should be called with dc->lock locked. Bug 1534724 Change-Id: I87b1fc529f29f707a1bdadf18efa6bb19d6966b3 Signed-off-by: Daniel Solomon <daniels@nvidia.com> Reviewed-on: http://git-master/r/456988 (cherry picked from commit ec9b7f555b9648e3aee0cd9781a92b14178a3344) Reviewed-on: http://git-master/r/496581 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Jong Kim <jongk@nvidia.com> Reviewed-by: Matthew Pedro <mapedro@nvidia.com> Reviewed-by: Jon Mayo <jmayo@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> Tested-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/dc/dc.c42
-rw-r--r--drivers/video/tegra/dc/dc_priv.h2
-rw-r--r--drivers/video/tegra/dc/dsi.c2
3 files changed, 23 insertions, 23 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 541e6f00820f..476d0459f91f 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -1641,7 +1641,20 @@ int tegra_dc_wait_for_vsync(struct tegra_dc *dc)
return ret;
}
-int tegra_dc_wait_for_frame_end(struct tegra_dc *dc,
+static int _tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
+{
+ tegra_dc_io_start(dc);
+ if (enable) {
+ atomic_inc(&dc->frame_end_ref);
+ tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
+ } else if (!atomic_dec_return(&dc->frame_end_ref))
+ tegra_dc_mask_interrupt(dc, FRAME_END_INT);
+ tegra_dc_io_end(dc);
+
+ return 0;
+}
+
+int _tegra_dc_wait_for_frame_end(struct tegra_dc *dc,
u32 timeout_ms)
{
int ret;
@@ -1652,13 +1665,13 @@ int tegra_dc_wait_for_frame_end(struct tegra_dc *dc,
tegra_dc_flush_interrupt(dc, FRAME_END_INT);
/* unmask frame end interrupt */
- tegra_dc_config_frame_end_intr(dc, true);
+ _tegra_dc_config_frame_end_intr(dc, true);
ret = wait_for_completion_interruptible_timeout(
&dc->frame_end_complete,
msecs_to_jiffies(timeout_ms));
- tegra_dc_config_frame_end_intr(dc, false);
+ _tegra_dc_config_frame_end_intr(dc, false);
tegra_dc_put(dc);
@@ -1896,26 +1909,13 @@ static void tegra_dc_vpulse2(struct work_struct *work)
int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
{
- bool locked_by_caller;
-
- /* This function is called in situations where dc->lock
- * is either free or already acquired - avoid a deadlock. */
- locked_by_caller = mutex_is_locked(&dc->lock);
- if (!locked_by_caller)
- mutex_lock(&dc->lock);
-
- tegra_dc_io_start(dc);
- if (enable) {
- atomic_inc(&dc->frame_end_ref);
- tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
- } else if (!atomic_dec_return(&dc->frame_end_ref))
- tegra_dc_mask_interrupt(dc, FRAME_END_INT);
- tegra_dc_io_end(dc);
+ int ret;
- if (!locked_by_caller)
- mutex_unlock(&dc->lock);
+ mutex_lock(&dc->lock);
+ ret = _tegra_dc_config_frame_end_intr(dc, enable);
+ mutex_unlock(&dc->lock);
- return 0;
+ return ret;
}
static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status,
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index 1c5d53b92035..fe4124bbfad1 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -407,7 +407,7 @@ u32 timeout_ms);
int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable);
/* defined in dc.c, used in dsi.c */
-int tegra_dc_wait_for_frame_end(struct tegra_dc *dc,
+int _tegra_dc_wait_for_frame_end(struct tegra_dc *dc,
u32 timeout_ms);
/* defined in bandwidth.c, used in dc.c */
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index df76712a5975..b770d83fac05 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -1706,7 +1706,7 @@ static int tegra_dsi_wait_frame_end(struct tegra_dc *dc,
dev_WARN(&dc->ndev->dev,
"dsi: to stop at next frame give at least 2 frame delay\n");
- timeout = tegra_dc_wait_for_frame_end(dc, timeout_n_frames *
+ timeout = _tegra_dc_wait_for_frame_end(dc, timeout_n_frames *
frame_period);
/* wait for v_ref_to_sync no. of lines after frame end interrupt */