aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorIvan Khoronzhuk <ivan.khoronzhuk@ti.com>2012-07-11 13:15:15 +0300
committerZiyann <jaraidaniel@gmail.com>2014-10-01 12:59:49 +0200
commit993a2e8b29f00d7bc285fff80c4b87f52f80f8e3 (patch)
treead9ab4af149bc22ffcded91ba6ff26bbf0c1e7d6 /arch/arm
parentef15fb5fb08a7c58e4cfe72304e592268aa8ae52 (diff)
downloadkernel_samsung_tuna-993a2e8b29f00d7bc285fff80c4b87f52f80f8e3.zip
kernel_samsung_tuna-993a2e8b29f00d7bc285fff80c4b87f52f80f8e3.tar.gz
kernel_samsung_tuna-993a2e8b29f00d7bc285fff80c4b87f52f80f8e3.tar.bz2
OMAP4: DPLL cascading: Removed deadlock during DPLL cascading transition
We need take a console lock due to change uart frequency. We cannot do it under omap_dvfs_lock because it can lead to deadlock in situation when some thread has taken the console lock and trying to scale waiting for the omap_dvfs_lock that has been taken already by DPLL cascading transition. Example: +--------------------------------------------+--------------------------------+ | thread 1 | thread 2 | +--------------------------------------------+--------------------------------+ | ->omap4_dpll_cascading_blocker_release() { | | | ... | | | mutex_lock(dvfs_lock) | | | ... -> | | | | -> ... | | | console_lock() | | | omap_device_scale() { | | | ... | | | mutex_lock(dvfs_lock) -> | | -> ... | | | console_lock() // deadlock | | +--------------------------------------------+--------------------------------+ Change-Id: I90f7c66ef9d490a4552e94adddf2e2eb79c58b99 Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 75ad156..cda941f 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -17,6 +17,7 @@
#include <linux/spinlock.h>
#ifdef CONFIG_OMAP4_DPLL_CASCADING
+#include <linux/console.h>
#include <linux/slab.h>
#include "dvfs.h"
#include "smartreflex.h"
@@ -1484,6 +1485,14 @@ int omap4_dpll_cascading_blocker_hold(struct device *dev)
if (!dev)
return -EINVAL;
+ /*
+ * We need take a console lock due to change uart frequency.
+ * We cannot do it under omap_dvfs_lock because it can lead to
+ * deadlock in situation when some thread has taken the console
+ * lock and trying to scale waiting for the omap_dvfs_lock that has
+ * been taken already by dpll_cascading.
+ */
+ console_lock();
mutex_lock(&omap_dvfs_lock);
if (list_empty(&dpll_cascading_blocker_list))
@@ -1516,6 +1525,7 @@ int omap4_dpll_cascading_blocker_hold(struct device *dev)
out:
mutex_unlock(&omap_dvfs_lock);
+ console_unlock();
return ret;
}
EXPORT_SYMBOL(omap4_dpll_cascading_blocker_hold);
@@ -1529,6 +1539,14 @@ int omap4_dpll_cascading_blocker_release(struct device *dev)
if (!dev)
return -EINVAL;
+ /*
+ * We need take a console lock due to change uart frequency.
+ * We cannot do it under omap_dvfs_lock because it can lead to
+ * deadlock in situation when some thread has taken the console
+ * lock and trying to scale waiting for the omap_dvfs_lock that has
+ * been taken already by dpll_cascading.
+ */
+ console_lock();
mutex_lock(&omap_dvfs_lock);
/* bail early if list is empty */
@@ -1560,6 +1578,7 @@ int omap4_dpll_cascading_blocker_release(struct device *dev)
}
out:
mutex_unlock(&omap_dvfs_lock);
+ console_unlock();
return ret;
}
EXPORT_SYMBOL(omap4_dpll_cascading_blocker_release);