diff options
author | Liu Ying <Ying.Liu@freescale.com> | 2011-01-26 11:17:19 +0800 |
---|---|---|
committer | Alan Tull <alan.tull@freescale.com> | 2011-02-03 16:45:30 -0600 |
commit | c9437846e5a472bf25841ec09fe9c744e9a1abb3 (patch) | |
tree | 1e3bbdb8ff11514f772ff62149ce1838ed288cd4 /drivers/mxc/ipu3/ipu_common.c | |
parent | 61f9b04c0d52b1615cb982031571fe5fdb51d873 (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.c | 17 |
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); |