summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc/ext
diff options
context:
space:
mode:
authorNitin Kumbhar <nkumbhar@nvidia.com>2012-02-09 11:37:16 +0530
committerSimone Willett <swillett@nvidia.com>2012-02-14 09:29:23 -0800
commitc24bb73b2dcecc1e05c6dae40999201c71d4f0e7 (patch)
tree8788ac6adedd3a6e8d9b197b08d03402edd92a9c /drivers/video/tegra/dc/ext
parentdb513ad44b82c7ddd44323c14efe4c53ca41f5ba (diff)
video: tegra: dc: acquire window locks in an order to avoid a deadlock
All window locks are grabbed while performing dc window updates. Currently, no particular locking order is followed for these locks. If user provided windows are not in order, this leads to deadlock due to race between flip ioctl and dc underflow reset worker. Now on all window locks are acquired in an order as below 1. window A i.e. index 0 2. window B i.e. index 1 3. window C i.e. index 2 And unlocked in the reverse order 1. window C i.e. index 2 2. window B i.e. index 1 3. window A i.e. index 0 Bug 936545 Signed-off-by: Nitin Kumbhar <nkumbhar@nvidia.com> Reviewed-on: http://git-master/r/83107 (cherry picked from commit 68815fa87e879d0c783e8fd38f473f414806c0be) Change-Id: I3b3e00eaf91384c39ff74047f06af8199848ad92 Reviewed-on: http://git-master/r/83405 Tested-by: Nitin Kumbhar <nkumbhar@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Reviewed-by: Jon Mayo <jmayo@nvidia.com> Reviewed-by: Robert Morell <rmorell@nvidia.com>
Diffstat (limited to 'drivers/video/tegra/dc/ext')
-rw-r--r--drivers/video/tegra/dc/ext/dev.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c
index ca4ca5370633..a0d0949f27a7 100644
--- a/drivers/video/tegra/dc/ext/dev.c
+++ b/drivers/video/tegra/dc/ext/dev.c
@@ -301,16 +301,25 @@ static int lock_windows_for_flip(struct tegra_dc_ext_user *user,
struct tegra_dc_ext_flip *args)
{
struct tegra_dc_ext *ext = user->ext;
+ u8 idx_mask = 0;
int i;
for (i = 0; i < DC_N_WINDOWS; i++) {
int index = args->win[i].index;
- struct tegra_dc_ext_win *win;
if (index < 0)
continue;
- win = &ext->win[index];
+ idx_mask |= BIT(index);
+ }
+
+ for (i = 0; i < DC_N_WINDOWS; i++) {
+ struct tegra_dc_ext_win *win;
+
+ if (!(idx_mask & BIT(i)))
+ continue;
+
+ win = &ext->win[i];
mutex_lock(&win->lock);
@@ -322,12 +331,10 @@ static int lock_windows_for_flip(struct tegra_dc_ext_user *user,
fail_unlock:
do {
- int index = args->win[i].index;
-
- if (index < 0)
+ if (!(idx_mask & BIT(i)))
continue;
- mutex_unlock(&ext->win[index].lock);
+ mutex_unlock(&ext->win[i].lock);
} while (i--);
return -EACCES;
@@ -337,6 +344,7 @@ static void unlock_windows_for_flip(struct tegra_dc_ext_user *user,
struct tegra_dc_ext_flip *args)
{
struct tegra_dc_ext *ext = user->ext;
+ u8 idx_mask = 0;
int i;
for (i = 0; i < DC_N_WINDOWS; i++) {
@@ -345,7 +353,14 @@ static void unlock_windows_for_flip(struct tegra_dc_ext_user *user,
if (index < 0)
continue;
- mutex_unlock(&ext->win[index].lock);
+ idx_mask |= BIT(index);
+ }
+
+ for (i = DC_N_WINDOWS - 1; i >= 0; i--) {
+ if (!(idx_mask & BIT(i)))
+ continue;
+
+ mutex_unlock(&ext->win[i].lock);
}
}