summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/ext
diff options
context:
space:
mode:
authorRobert Morell <rmorell@nvidia.com>2011-03-03 20:54:09 -0800
committerVarun Colbert <vcolbert@nvidia.com>2011-08-11 11:52:28 -0700
commitcd73bb54da8c388f7ec143c1fca204aa15705661 (patch)
tree799f3715752d49a84fad3c043ef218d697274a4b /drivers/video/tegra/dc/ext
parentb8ddd1da9311ba55893f97326937cc4c8ffff004 (diff)
video: tegra: Prevent hang when output disabled
This adds code to track when the dc is disabled and prevent flips or cursor moves. This prevents system hangs since the dc is powergated when it's disabled. bug 818525 Change-Id: I061da1f6a831fa14a216520e603e0fbc5dbb0437 Signed-off-by: Robert Morell <rmorell@nvidia.com> Reviewed-on: http://git-master/r/40519 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'drivers/video/tegra/dc/ext')
-rw-r--r--drivers/video/tegra/dc/ext/cursor.c35
-rw-r--r--drivers/video/tegra/dc/ext/dev.c39
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h2
3 files changed, 67 insertions, 9 deletions
diff --git a/drivers/video/tegra/dc/ext/cursor.c b/drivers/video/tegra/dc/ext/cursor.c
index e25ca0fd3fc2..d8fa5fd8e6d9 100644
--- a/drivers/video/tegra/dc/ext/cursor.c
+++ b/drivers/video/tegra/dc/ext/cursor.c
@@ -105,17 +105,20 @@ int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
mutex_lock(&ext->cursor.lock);
if (ext->cursor.user != user) {
- mutex_unlock(&ext->cursor.lock);
- return -EACCES;
+ ret = -EACCES;
+ goto unlock;
+ }
+
+ if (!ext->enabled) {
+ ret = -ENXIO;
+ goto unlock;
}
old_handle = ext->cursor.cur_handle;
ret = tegra_dc_ext_pin_window(user, args->buff_id, &handle, &phys_addr);
- if (ret) {
- mutex_unlock(&ext->cursor.lock);
- return -EACCES;
- }
+ if (ret)
+ goto unlock;
ext->cursor.cur_handle = handle;
@@ -138,6 +141,11 @@ int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user,
}
return 0;
+
+unlock:
+ mutex_unlock(&ext->cursor.lock);
+
+ return ret;
}
int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
@@ -147,12 +155,18 @@ int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
struct tegra_dc *dc = ext->dc;
u32 win_options;
bool enable;
+ int ret;
mutex_lock(&ext->cursor.lock);
if (ext->cursor.user != user) {
- mutex_unlock(&ext->cursor.lock);
- return -EACCES;
+ ret = -EACCES;
+ goto unlock;
+ }
+
+ if (!ext->enabled) {
+ ret = -ENXIO;
+ goto unlock;
}
enable = !!(args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_VISIBLE);
@@ -181,4 +195,9 @@ int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
mutex_unlock(&ext->cursor.lock);
return 0;
+
+unlock:
+ mutex_unlock(&ext->cursor.lock);
+
+ return ret;
}
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index b51b9378c551..7e077737f910 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -124,10 +124,39 @@ static int tegra_dc_ext_put_window(struct tegra_dc_ext_user *user,
return ret;
}
-void tegra_dc_ext_suspend(struct tegra_dc_ext *ext)
+static void set_enable(struct tegra_dc_ext *ext, bool en)
{
int i;
+ /*
+ * Take all locks to make sure any flip requests or cursor moves are
+ * out of their critical sections
+ */
+ for (i = 0; i < ext->dc->n_windows; i++)
+ mutex_lock(&ext->win[i].lock);
+ mutex_lock(&ext->cursor.lock);
+
+ ext->enabled = en;
+
+ mutex_unlock(&ext->cursor.lock);
+ for (i = ext->dc->n_windows - 1; i >= 0 ; i--)
+ mutex_unlock(&ext->win[i].lock);
+}
+
+void tegra_dc_ext_enable(struct tegra_dc_ext *ext)
+{
+ set_enable(ext, true);
+}
+
+void tegra_dc_ext_disable(struct tegra_dc_ext *ext)
+{
+ int i;
+ set_enable(ext, false);
+
+ /*
+ * Flush the flip queue -- note that this must be called with dc->lock
+ * unlocked or else it will hang.
+ */
for (i = 0; i < ext->dc->n_windows; i++) {
struct tegra_dc_ext_win *win = &ext->win[i];
@@ -357,6 +386,11 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
if (ret)
goto fail_pin;
+ if (!ext->enabled) {
+ ret = -ENXIO;
+ goto unlock;
+ }
+
for (i = 0; i < DC_N_WINDOWS; i++) {
u32 syncpt_max;
int index = args->win[i].index;
@@ -382,6 +416,9 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user,
return 0;
+unlock:
+ unlock_windows_for_flip(user, args);
+
fail_pin:
while (i--) {
if (!data->win[i].handle)
diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
index 3040cf7fc601..251c072683c7 100644
--- a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
+++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h
@@ -63,6 +63,8 @@ struct tegra_dc_ext {
struct nvmap_handle_ref *cur_handle;
struct mutex lock;
} cursor;
+
+ bool enabled;
};
extern int tegra_dc_ext_pin_window(struct tegra_dc_ext_user *user, u32 id,