msm: camera: isp : Fix race condition in close sequence
Serializing reset_hw and reset_irq, to avoid race condition Change-Id: I8f21cb816748129bde7f0f1455b203b42603d244 Signed-off-by: Srikanth Uyyala <suyyala@codeaurora.org>
This commit is contained in:
parent
093e11e9d2
commit
c9eb396da5
4 changed files with 32 additions and 8 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -712,7 +712,8 @@ int vfe_hw_probe(struct platform_device *pdev)
|
||||||
spin_lock_init(&vfe_dev->shared_data_lock);
|
spin_lock_init(&vfe_dev->shared_data_lock);
|
||||||
spin_lock_init(&vfe_dev->reg_update_lock);
|
spin_lock_init(&vfe_dev->reg_update_lock);
|
||||||
spin_lock_init(&req_history_lock);
|
spin_lock_init(&req_history_lock);
|
||||||
spin_lock_init(&vfe_dev->completion_lock);
|
spin_lock_init(&vfe_dev->reset_completion_lock);
|
||||||
|
spin_lock_init(&vfe_dev->halt_completion_lock);
|
||||||
media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
|
media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
|
||||||
vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
|
vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
|
||||||
vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
|
vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
|
||||||
|
|
|
@ -804,7 +804,8 @@ struct vfe_device {
|
||||||
struct mutex core_mutex;
|
struct mutex core_mutex;
|
||||||
spinlock_t shared_data_lock;
|
spinlock_t shared_data_lock;
|
||||||
spinlock_t reg_update_lock;
|
spinlock_t reg_update_lock;
|
||||||
spinlock_t completion_lock;
|
spinlock_t reset_completion_lock;
|
||||||
|
spinlock_t halt_completion_lock;
|
||||||
|
|
||||||
/* Tasklet info */
|
/* Tasklet info */
|
||||||
atomic_t irq_cnt;
|
atomic_t irq_cnt;
|
||||||
|
|
|
@ -370,15 +370,24 @@ static void msm_vfe40_clear_status_reg(struct vfe_device *vfe_dev)
|
||||||
static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev,
|
static void msm_vfe40_process_reset_irq(struct vfe_device *vfe_dev,
|
||||||
uint32_t irq_status0, uint32_t irq_status1)
|
uint32_t irq_status0, uint32_t irq_status1)
|
||||||
{
|
{
|
||||||
if (irq_status0 & (1 << 31))
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (irq_status0 & (1 << 31)) {
|
||||||
|
spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
|
||||||
complete(&vfe_dev->reset_complete);
|
complete(&vfe_dev->reset_complete);
|
||||||
|
spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev,
|
static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev,
|
||||||
uint32_t irq_status0, uint32_t irq_status1)
|
uint32_t irq_status0, uint32_t irq_status1)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (irq_status1 & (1 << 8)) {
|
if (irq_status1 & (1 << 8)) {
|
||||||
|
spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
|
||||||
complete(&vfe_dev->halt_complete);
|
complete(&vfe_dev->halt_complete);
|
||||||
|
spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
|
||||||
msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0);
|
msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -767,7 +776,11 @@ static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev,
|
||||||
uint32_t first_start, uint32_t blocking_call)
|
uint32_t first_start, uint32_t blocking_call)
|
||||||
{
|
{
|
||||||
long rc = 0;
|
long rc = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
|
||||||
init_completion(&vfe_dev->reset_complete);
|
init_completion(&vfe_dev->reset_complete);
|
||||||
|
spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
|
||||||
|
|
||||||
if (first_start) {
|
if (first_start) {
|
||||||
msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
|
msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
|
||||||
|
@ -1780,6 +1793,7 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
enum msm_vfe_input_src i;
|
enum msm_vfe_input_src i;
|
||||||
struct msm_isp_timestamp ts;
|
struct msm_isp_timestamp ts;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
/* Keep only halt and restart mask */
|
/* Keep only halt and restart mask */
|
||||||
msm_vfe40_config_irq(vfe_dev, (1 << 31), (1 << 8),
|
msm_vfe40_config_irq(vfe_dev, (1 << 31), (1 << 8),
|
||||||
|
@ -1796,7 +1810,9 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
|
||||||
msm_isp_stats_stream_update(vfe_dev);
|
msm_isp_stats_stream_update(vfe_dev);
|
||||||
|
|
||||||
if (blocking) {
|
if (blocking) {
|
||||||
|
spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
|
||||||
init_completion(&vfe_dev->halt_complete);
|
init_completion(&vfe_dev->halt_complete);
|
||||||
|
spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
|
||||||
/* Halt AXI Bus Bridge */
|
/* Halt AXI Bus Bridge */
|
||||||
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0);
|
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0);
|
||||||
rc = wait_for_completion_interruptible_timeout(
|
rc = wait_for_completion_interruptible_timeout(
|
||||||
|
|
|
@ -443,10 +443,10 @@ void msm_vfe47_process_reset_irq(struct vfe_device *vfe_dev,
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (irq_status0 & (1 << 31)) {
|
if (irq_status0 & (1 << 31)) {
|
||||||
spin_lock_irqsave(&vfe_dev->completion_lock, flags);
|
spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
|
||||||
complete(&vfe_dev->reset_complete);
|
complete(&vfe_dev->reset_complete);
|
||||||
vfe_dev->reset_pending = 0;
|
vfe_dev->reset_pending = 0;
|
||||||
spin_unlock_irqrestore(&vfe_dev->completion_lock, flags);
|
spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,9 +454,12 @@ void msm_vfe47_process_halt_irq(struct vfe_device *vfe_dev,
|
||||||
uint32_t irq_status0, uint32_t irq_status1)
|
uint32_t irq_status0, uint32_t irq_status1)
|
||||||
{
|
{
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (irq_status1 & (1 << 8)) {
|
if (irq_status1 & (1 << 8)) {
|
||||||
|
spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
|
||||||
complete(&vfe_dev->halt_complete);
|
complete(&vfe_dev->halt_complete);
|
||||||
|
spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
|
||||||
msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x400);
|
msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,9 +777,9 @@ long msm_vfe47_reset_hardware(struct vfe_device *vfe_dev,
|
||||||
uint32_t reset;
|
uint32_t reset;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&vfe_dev->completion_lock, flags);
|
spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
|
||||||
init_completion(&vfe_dev->reset_complete);
|
init_completion(&vfe_dev->reset_complete);
|
||||||
spin_unlock_irqrestore(&vfe_dev->completion_lock, flags);
|
spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
|
||||||
|
|
||||||
if (blocking_call)
|
if (blocking_call)
|
||||||
vfe_dev->reset_pending = 1;
|
vfe_dev->reset_pending = 1;
|
||||||
|
@ -1996,6 +1999,7 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev,
|
||||||
enum msm_vfe_input_src i;
|
enum msm_vfe_input_src i;
|
||||||
uint32_t val = 0;
|
uint32_t val = 0;
|
||||||
struct msm_isp_timestamp ts;
|
struct msm_isp_timestamp ts;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
val = msm_camera_io_r(vfe_dev->vfe_vbif_base + VFE47_VBIF_CLK_OFFSET);
|
val = msm_camera_io_r(vfe_dev->vfe_vbif_base + VFE47_VBIF_CLK_OFFSET);
|
||||||
val |= 0x1;
|
val |= 0x1;
|
||||||
|
@ -2012,7 +2016,9 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev,
|
||||||
__func__, vfe_dev->pdev->id, blocking);
|
__func__, vfe_dev->pdev->id, blocking);
|
||||||
|
|
||||||
if (blocking) {
|
if (blocking) {
|
||||||
|
spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
|
||||||
init_completion(&vfe_dev->halt_complete);
|
init_completion(&vfe_dev->halt_complete);
|
||||||
|
spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
|
||||||
/* Halt AXI Bus Bridge */
|
/* Halt AXI Bus Bridge */
|
||||||
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x400);
|
msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x400);
|
||||||
rc = wait_for_completion_interruptible_timeout(
|
rc = wait_for_completion_interruptible_timeout(
|
||||||
|
|
Loading…
Add table
Reference in a new issue