diff options
author | Ivan Khoronzhuk <ivan.khoronzhuk@ti.com> | 2012-07-11 13:15:15 +0300 |
---|---|---|
committer | Dmytro Kedrovskyi <x0169235@ti.com> | 2012-07-25 12:19:05 +0300 |
commit | 5061ecd622c62912e622192e77f53456c75317c1 (patch) | |
tree | 50aa4fcc73bf44c97b5ec7b94d2b2abbd6698320 | |
parent | a4207a0fb7eb7baa5c2f1f4ad4de874d40049e72 (diff) | |
download | kernel_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.c | 19 | ||||
-rw-r--r-- | drivers/tty/serial/omap-serial.c | 11 |
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); } |