summaryrefslogtreecommitdiff
path: root/drivers/mxc/ipu3/ipu_common.c
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2011-01-26 11:17:19 +0800
committerAlan Tull <alan.tull@freescale.com>2011-02-03 16:45:30 -0600
commitc9437846e5a472bf25841ec09fe9c744e9a1abb3 (patch)
tree1e3bbdb8ff11514f772ff62149ce1838ed288cd4 /drivers/mxc/ipu3/ipu_common.c
parent61f9b04c0d52b1615cb982031571fe5fdb51d873 (diff)
ENGR00138520 IPUv3:Correct IPU spinlock logic
1) Fix the double locking IPU spinlock issue. 2) Protect g_channel_enable_mask with IPU spinlock. Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
Diffstat (limited to 'drivers/mxc/ipu3/ipu_common.c')
-rw-r--r--drivers/mxc/ipu3/ipu_common.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index 1bacec010f77..898d408fcd6c 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -1696,17 +1696,19 @@ int32_t ipu_enable_channel(ipu_channel_t channel)
uint32_t sec_dma;
uint32_t thrd_dma;
+ spin_lock_irqsave(&ipu_lock, lock_flags);
+
if (g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
dev_err(g_ipu_dev, "Warning: channel already enabled %d\n",
IPU_CHAN_ID(channel));
+ spin_unlock_irqrestore(&ipu_lock, lock_flags);
+ return -EACCES;
}
/* Get input and output dma channels */
out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
- spin_lock_irqsave(&ipu_lock, lock_flags);
-
ipu_conf = __raw_readl(IPU_CONF);
if (ipu_di_use_count[0] > 0) {
ipu_conf |= IPU_CONF_DI0_EN;
@@ -1886,12 +1888,17 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
uint32_t sec_dma = NO_DMA;
uint32_t thrd_dma = NO_DMA;
+ spin_lock_irqsave(&ipu_lock, lock_flags);
+
if ((g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
dev_err(g_ipu_dev, "Channel already disabled %d\n",
IPU_CHAN_ID(channel));
- return 0;
+ spin_unlock_irqrestore(&ipu_lock, lock_flags);
+ return -EACCES;
}
+ spin_unlock_irqrestore(&ipu_lock, lock_flags);
+
/* Get input and output dma channels */
out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
@@ -2020,6 +2027,8 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
g_channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
+ spin_unlock_irqrestore(&ipu_lock, lock_flags);
+
/* Set channel buffers NOT to be ready */
if (idma_is_valid(in_dma)) {
ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 0);
@@ -2038,8 +2047,6 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop)
ipu_clear_buffer_ready(channel, IPU_ALPHA_IN_BUFFER, 1);
}
- spin_unlock_irqrestore(&ipu_lock, lock_flags);
-
return 0;
}
EXPORT_SYMBOL(ipu_disable_channel);