aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Khoronzhuk <ivan.khoronzhuk@ti.com>2012-07-11 13:15:15 +0300
committerDmytro Kedrovskyi <x0169235@ti.com>2012-07-25 12:19:05 +0300
commit5061ecd622c62912e622192e77f53456c75317c1 (patch)
tree50aa4fcc73bf44c97b5ec7b94d2b2abbd6698320
parenta4207a0fb7eb7baa5c2f1f4ad4de874d40049e72 (diff)
downloadkernel_samsung_espresso10-5061ecd622c62912e622192e77f53456c75317c1.zip
kernel_samsung_espresso10-5061ecd622c62912e622192e77f53456c75317c1.tar.gz
kernel_samsung_espresso10-5061ecd622c62912e622192e77f53456c75317c1.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>
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c19
-rw-r--r--drivers/tty/serial/omap-serial.c11
2 files changed, 19 insertions, 11 deletions
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 4a601e4..c258403 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 <linux/cpufreq.h>
#include "dvfs.h"
@@ -1490,6 +1491,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))
@@ -1522,6 +1531,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);
@@ -1539,6 +1549,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 */
@@ -1574,6 +1592,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);
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index c994ace..bfaf5d1 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1488,14 +1488,6 @@ int omap_uart_recalibrate_baud_cb(struct notifier_block *nb,
case CLK_PRE_RATE_CHANGE:
for (portid = 0 ; portid < OMAP_MAX_HSUART_PORTS ; portid++) {
up = ui[portid];
- /* If Console, Stop from here, till the Frequencies
- * Change.
- */
- if (omap_is_console_port(&up->port)) {
- while (is_console_locked())
- usleep_range(100, 300);
- console_stop(up->port.cons);
- }
/* If the device uses the RTS based controlling,
* Pull Up the signal to stop transaction. As the
* Clocks are not disabled. It even if the data
@@ -1571,9 +1563,6 @@ int omap_uart_recalibrate_baud_cb(struct notifier_block *nb,
serial_omap_port_disable(up);
}
- if (omap_is_console_port(&up->port))
- console_start(up->port.cons);
-
if (up->rts_mux_driver_control)
omap_rts_mux_write(0, up->port.line);
}