Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca1b8b24 authored by Srikanth Uyyala's avatar Srikanth Uyyala Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarSrikanth Uyyala <suyyala@codeaurora.org>
parent d18e6bf7
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -691,7 +691,8 @@ int vfe_hw_probe(struct platform_device *pdev)
	spin_lock_init(&vfe_dev->shared_data_lock);
	spin_lock_init(&vfe_dev->reg_update_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_pads_init(&vfe_dev->subdev.sd.entity, 0, NULL);
	vfe_dev->subdev.sd.entity.function = MSM_CAMERA_SUBDEV_VFE;
	//vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
+2 −1
Original line number Diff line number Diff line
@@ -802,7 +802,8 @@ struct vfe_device {
	struct mutex core_mutex;
	spinlock_t shared_data_lock;
	spinlock_t reg_update_lock;
	spinlock_t completion_lock;
	spinlock_t reset_completion_lock;
	spinlock_t halt_completion_lock;

	/* Tasklet info */
	atomic_t irq_cnt;
+16 −1
Original line number Diff line number Diff line
@@ -363,15 +363,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,
	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);
		spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
	}
}

static void msm_vfe40_process_halt_irq(struct vfe_device *vfe_dev,
	uint32_t irq_status0, uint32_t irq_status1)
{
	unsigned long flags;

	if (irq_status1 & (1 << 8)) {
		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
		complete(&vfe_dev->halt_complete);
		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x2C0);
	}
}
@@ -761,8 +770,11 @@ static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev,
	uint32_t first_start, uint32_t blocking_call)
{
	long rc = 0;
	unsigned long flags;

	spin_lock_irqsave(&vfe_dev->reset_completion_lock, flags);
	init_completion(&vfe_dev->reset_complete);
	spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);

	if (first_start) {
		msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
@@ -1777,6 +1789,7 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
	int rc = 0;
	enum msm_vfe_input_src i;
	struct msm_isp_timestamp ts;
	unsigned long flags;

	/* Keep only halt and restart mask */
	msm_vfe40_config_irq(vfe_dev, (1 << 31), (1 << 8),
@@ -1793,7 +1806,9 @@ static int msm_vfe40_axi_halt(struct vfe_device *vfe_dev,
	msm_isp_stats_stream_update(vfe_dev);

	if (blocking) {
		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
		init_completion(&vfe_dev->halt_complete);
		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
		/* Halt AXI Bus Bridge */
		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x2C0);
		rc = wait_for_completion_interruptible_timeout(
+10 −4
Original line number Diff line number Diff line
@@ -440,10 +440,10 @@ void msm_vfe47_process_reset_irq(struct vfe_device *vfe_dev,
	unsigned long flags;

	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);
		vfe_dev->reset_pending = 0;
		spin_unlock_irqrestore(&vfe_dev->completion_lock, flags);
		spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);
	}
}

@@ -451,9 +451,12 @@ void msm_vfe47_process_halt_irq(struct vfe_device *vfe_dev,
	uint32_t irq_status0, uint32_t irq_status1)
{
	uint32_t val = 0;
	unsigned long flags;

	if (irq_status1 & (1 << 8)) {
		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
		complete(&vfe_dev->halt_complete);
		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x400);
	}

@@ -770,9 +773,9 @@ long msm_vfe47_reset_hardware(struct vfe_device *vfe_dev,
	uint32_t reset;
	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);
	spin_unlock_irqrestore(&vfe_dev->completion_lock, flags);
	spin_unlock_irqrestore(&vfe_dev->reset_completion_lock, flags);

	if (blocking_call)
		vfe_dev->reset_pending = 1;
@@ -2002,6 +2005,7 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev,
	enum msm_vfe_input_src i;
	uint32_t val = 0;
	struct msm_isp_timestamp ts;
	unsigned long flags;

	val = msm_camera_io_r(vfe_dev->vfe_vbif_base + VFE47_VBIF_CLK_OFFSET);
	val |= 0x1;
@@ -2018,7 +2022,9 @@ int msm_vfe47_axi_halt(struct vfe_device *vfe_dev,
			__func__, vfe_dev->pdev->id, blocking);

	if (blocking) {
		spin_lock_irqsave(&vfe_dev->halt_completion_lock, flags);
		init_completion(&vfe_dev->halt_complete);
		spin_unlock_irqrestore(&vfe_dev->halt_completion_lock, flags);
		/* Halt AXI Bus Bridge */
		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x400);
		rc = wait_for_completion_interruptible_timeout(