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

Commit 68ddf4f0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: Add spinlock protection for flags in CCI driver"

parents 661a45ee fd7aadcb
Loading
Loading
Loading
Loading
+58 −1
Original line number Original line Diff line number Diff line
@@ -201,6 +201,7 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
	enum cci_i2c_queue_t queue)
	enum cci_i2c_queue_t queue)
{
{
	int32_t rc = 0;
	int32_t rc = 0;
	unsigned long flags;
	uint32_t read_val = 0;
	uint32_t read_val = 0;
	uint32_t reg_offset = master * 0x200 + queue * 0x100;
	uint32_t reg_offset = master * 0x200 + queue * 0x100;
	read_val = msm_camera_io_r_mb(cci_dev->base +
	read_val = msm_camera_io_r_mb(cci_dev->base +
@@ -223,6 +224,8 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
			CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
			CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
		reg_val = 1 << ((master * 2) + queue);
		reg_val = 1 << ((master * 2) + queue);
		CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__);
		CDBG("%s:%d CCI_QUEUE_START_ADDR\n", __func__, __LINE__);
		spin_lock_irqsave(&cci_dev->cci_master_info[master].
						lock_q[queue], flags);
		atomic_set(&cci_dev->cci_master_info[master].
		atomic_set(&cci_dev->cci_master_info[master].
						done_pending[queue], 1);
						done_pending[queue], 1);
		msm_camera_io_w_mb(reg_val, cci_dev->base +
		msm_camera_io_w_mb(reg_val, cci_dev->base +
@@ -230,6 +233,8 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev,
		CDBG("%s line %d wait_for_completion_timeout\n",
		CDBG("%s line %d wait_for_completion_timeout\n",
			__func__, __LINE__);
			__func__, __LINE__);
		atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
		atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
		spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
						lock_q[queue], flags);
		rc = wait_for_completion_timeout(&cci_dev->
		rc = wait_for_completion_timeout(&cci_dev->
			cci_master_info[master].report_q[queue], CCI_TIMEOUT);
			cci_master_info[master].report_q[queue], CCI_TIMEOUT);
		if (rc <= 0) {
		if (rc <= 0) {
@@ -438,10 +443,17 @@ static int32_t msm_cci_wait_report_cmd(struct cci_device *cci_dev,
	enum cci_i2c_master_t master,
	enum cci_i2c_master_t master,
	enum cci_i2c_queue_t queue)
	enum cci_i2c_queue_t queue)
{
{
	unsigned long flags;
	uint32_t reg_val = 1 << ((master * 2) + queue);
	uint32_t reg_val = 1 << ((master * 2) + queue);
	msm_cci_load_report_cmd(cci_dev, master, queue);
	msm_cci_load_report_cmd(cci_dev, master, queue);

	spin_lock_irqsave(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);
	atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
	atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
	atomic_set(&cci_dev->cci_master_info[master].done_pending[queue], 1);
	atomic_set(&cci_dev->cci_master_info[master].done_pending[queue], 1);
	spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);

	msm_camera_io_w_mb(reg_val, cci_dev->base +
	msm_camera_io_w_mb(reg_val, cci_dev->base +
		CCI_QUEUE_START_ADDR);
		CCI_QUEUE_START_ADDR);
	return msm_cci_wait(cci_dev, master, queue);
	return msm_cci_wait(cci_dev, master, queue);
@@ -451,13 +463,19 @@ static void msm_cci_process_half_q(struct cci_device *cci_dev,
	enum cci_i2c_master_t master,
	enum cci_i2c_master_t master,
	enum cci_i2c_queue_t queue)
	enum cci_i2c_queue_t queue)
{
{
	unsigned long flags;
	uint32_t reg_val = 1 << ((master * 2) + queue);
	uint32_t reg_val = 1 << ((master * 2) + queue);

	spin_lock_irqsave(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);
	if (0 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
	if (0 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
		msm_cci_load_report_cmd(cci_dev, master, queue);
		msm_cci_load_report_cmd(cci_dev, master, queue);
		atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
		atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
		msm_camera_io_w_mb(reg_val, cci_dev->base +
		msm_camera_io_w_mb(reg_val, cci_dev->base +
			CCI_QUEUE_START_ADDR);
			CCI_QUEUE_START_ADDR);
	}
	}
	spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);
}
}


static int32_t msm_cci_process_full_q(struct cci_device *cci_dev,
static int32_t msm_cci_process_full_q(struct cci_device *cci_dev,
@@ -465,15 +483,23 @@ static int32_t msm_cci_process_full_q(struct cci_device *cci_dev,
	enum cci_i2c_queue_t queue)
	enum cci_i2c_queue_t queue)
{
{
	int32_t rc = 0;
	int32_t rc = 0;
	unsigned long flags;

	spin_lock_irqsave(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);
	if (1 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
	if (1 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
		atomic_set(&cci_dev->cci_master_info[master].
		atomic_set(&cci_dev->cci_master_info[master].
						done_pending[queue], 1);
						done_pending[queue], 1);
		spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);
		rc = msm_cci_wait(cci_dev, master, queue);
		rc = msm_cci_wait(cci_dev, master, queue);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
			return rc;
			return rc;
		}
		}
	} else {
	} else {
		spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
						lock_q[queue], flags);
		rc = msm_cci_wait_report_cmd(cci_dev, master, queue);
		rc = msm_cci_wait_report_cmd(cci_dev, master, queue);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
@@ -501,8 +527,13 @@ static int32_t msm_cci_transfer_end(struct cci_device *cci_dev,
	enum cci_i2c_queue_t queue)
	enum cci_i2c_queue_t queue)
{
{
	int32_t rc = 0;
	int32_t rc = 0;
	unsigned long flags;


	spin_lock_irqsave(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);
	if (0 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
	if (0 == atomic_read(&cci_dev->cci_master_info[master].q_free[queue])) {
		spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
						lock_q[queue], flags);
		rc = msm_cci_lock_queue(cci_dev, master, queue, 0);
		rc = msm_cci_lock_queue(cci_dev, master, queue, 0);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("%s failed line %d\n", __func__, __LINE__);
			pr_err("%s failed line %d\n", __func__, __LINE__);
@@ -516,6 +547,8 @@ static int32_t msm_cci_transfer_end(struct cci_device *cci_dev,
	} else {
	} else {
		atomic_set(&cci_dev->cci_master_info[master].
		atomic_set(&cci_dev->cci_master_info[master].
						done_pending[queue], 1);
						done_pending[queue], 1);
		spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
						lock_q[queue], flags);
		rc = msm_cci_wait(cci_dev, master, queue);
		rc = msm_cci_wait(cci_dev, master, queue);
		if (rc < 0) {
		if (rc < 0) {
			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
			pr_err("%s: %d failed rc %d\n", __func__, __LINE__, rc);
@@ -570,6 +603,7 @@ static int32_t msm_cci_data_queue(struct cci_device *cci_dev,
	uint32_t reg_offset;
	uint32_t reg_offset;
	uint32_t val = 0;
	uint32_t val = 0;
	uint32_t max_queue_size;
	uint32_t max_queue_size;
	unsigned long flags;


	if (i2c_cmd == NULL) {
	if (i2c_cmd == NULL) {
		pr_err("%s:%d Failed line\n", __func__,
		pr_err("%s:%d Failed line\n", __func__,
@@ -613,7 +647,11 @@ static int32_t msm_cci_data_queue(struct cci_device *cci_dev,
	msm_camera_io_w_mb(val, cci_dev->base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
	msm_camera_io_w_mb(val, cci_dev->base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
		reg_offset);
		reg_offset);


	spin_lock_irqsave(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);
	atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0);
	atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0);
	spin_unlock_irqrestore(&cci_dev->cci_master_info[master].
					lock_q[queue], flags);


	max_queue_size = cci_dev->cci_i2c_queue_info[master][queue].
	max_queue_size = cci_dev->cci_i2c_queue_info[master][queue].
			max_queue_size;
			max_queue_size;
@@ -1641,6 +1679,7 @@ static int32_t msm_cci_config(struct v4l2_subdev *sd,
static irqreturn_t msm_cci_irq(int irq_num, void *data)
static irqreturn_t msm_cci_irq(int irq_num, void *data)
{
{
	uint32_t irq;
	uint32_t irq;
	unsigned long flags;
	struct cci_device *cci_dev = data;
	struct cci_device *cci_dev = data;
	irq = msm_camera_io_r_mb(cci_dev->base + CCI_IRQ_STATUS_0_ADDR);
	irq = msm_camera_io_r_mb(cci_dev->base + CCI_IRQ_STATUS_0_ADDR);
	msm_camera_io_w_mb(irq, cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
	msm_camera_io_w_mb(irq, cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
@@ -1667,22 +1706,30 @@ static irqreturn_t msm_cci_irq(int irq_num, void *data)
	if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK) {
	if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT_BMSK) {
		struct msm_camera_cci_master_info *cci_master_info;
		struct msm_camera_cci_master_info *cci_master_info;
		cci_master_info = &cci_dev->cci_master_info[MASTER_0];
		cci_master_info = &cci_dev->cci_master_info[MASTER_0];
		spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_0].
						lock_q[QUEUE_0], flags);
		atomic_set(&cci_master_info->q_free[QUEUE_0], 0);
		atomic_set(&cci_master_info->q_free[QUEUE_0], 0);
		cci_master_info->status = 0;
		cci_master_info->status = 0;
		if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) {
		if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) {
			complete(&cci_master_info->report_q[QUEUE_0]);
			complete(&cci_master_info->report_q[QUEUE_0]);
			atomic_set(&cci_master_info->done_pending[QUEUE_0], 0);
			atomic_set(&cci_master_info->done_pending[QUEUE_0], 0);
		}
		}
		spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_0].
					lock_q[QUEUE_0], flags);
	}
	}
	if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK) {
	if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT_BMSK) {
		struct msm_camera_cci_master_info *cci_master_info;
		struct msm_camera_cci_master_info *cci_master_info;
		cci_master_info = &cci_dev->cci_master_info[MASTER_0];
		cci_master_info = &cci_dev->cci_master_info[MASTER_0];
		spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_0].
						lock_q[QUEUE_1], flags);
		atomic_set(&cci_master_info->q_free[QUEUE_1], 0);
		atomic_set(&cci_master_info->q_free[QUEUE_1], 0);
		cci_master_info->status = 0;
		cci_master_info->status = 0;
		if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) {
		if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) {
			complete(&cci_master_info->report_q[QUEUE_1]);
			complete(&cci_master_info->report_q[QUEUE_1]);
			atomic_set(&cci_master_info->done_pending[QUEUE_1], 0);
			atomic_set(&cci_master_info->done_pending[QUEUE_1], 0);
		}
		}
		spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_0].
						lock_q[QUEUE_1], flags);
	}
	}
	if (irq & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) {
	if (irq & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE_BMSK) {
		cci_dev->cci_master_info[MASTER_1].status = 0;
		cci_dev->cci_master_info[MASTER_1].status = 0;
@@ -1691,22 +1738,30 @@ static irqreturn_t msm_cci_irq(int irq_num, void *data)
	if (irq & CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK) {
	if (irq & CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT_BMSK) {
		struct msm_camera_cci_master_info *cci_master_info;
		struct msm_camera_cci_master_info *cci_master_info;
		cci_master_info = &cci_dev->cci_master_info[MASTER_1];
		cci_master_info = &cci_dev->cci_master_info[MASTER_1];
		spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_1].
						lock_q[QUEUE_0], flags);
		atomic_set(&cci_master_info->q_free[QUEUE_0], 0);
		atomic_set(&cci_master_info->q_free[QUEUE_0], 0);
		cci_master_info->status = 0;
		cci_master_info->status = 0;
		if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) {
		if (atomic_read(&cci_master_info->done_pending[QUEUE_0]) == 1) {
			complete(&cci_master_info->report_q[QUEUE_0]);
			complete(&cci_master_info->report_q[QUEUE_0]);
			atomic_set(&cci_master_info->done_pending[QUEUE_0], 0);
			atomic_set(&cci_master_info->done_pending[QUEUE_0], 0);
		}
		}
		spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_1].
						lock_q[QUEUE_0], flags);
	}
	}
	if (irq & CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK) {
	if (irq & CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT_BMSK) {
		struct msm_camera_cci_master_info *cci_master_info;
		struct msm_camera_cci_master_info *cci_master_info;
		cci_master_info = &cci_dev->cci_master_info[MASTER_1];
		cci_master_info = &cci_dev->cci_master_info[MASTER_1];
		spin_lock_irqsave(&cci_dev->cci_master_info[MASTER_1].
						lock_q[QUEUE_1], flags);
		atomic_set(&cci_master_info->q_free[QUEUE_1], 0);
		atomic_set(&cci_master_info->q_free[QUEUE_1], 0);
		cci_master_info->status = 0;
		cci_master_info->status = 0;
		if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) {
		if (atomic_read(&cci_master_info->done_pending[QUEUE_1]) == 1) {
			complete(&cci_master_info->report_q[QUEUE_1]);
			complete(&cci_master_info->report_q[QUEUE_1]);
			atomic_set(&cci_master_info->done_pending[QUEUE_1], 0);
			atomic_set(&cci_master_info->done_pending[QUEUE_1], 0);
		}
		}
		spin_unlock_irqrestore(&cci_dev->cci_master_info[MASTER_1].
						lock_q[QUEUE_1], flags);
	}
	}
	if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) {
	if (irq & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK_BMSK) {
		cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
		cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
@@ -1795,6 +1850,8 @@ static void msm_cci_init_cci_params(struct cci_device *new_cci_dev)
			mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]);
			mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]);
			init_completion(&new_cci_dev->
			init_completion(&new_cci_dev->
				cci_master_info[i].report_q[j]);
				cci_master_info[i].report_q[j]);
			spin_lock_init(&new_cci_dev->
				cci_master_info[i].lock_q[j]);
		}
		}
	}
	}
	return;
	return;
+2 −1
Original line number Original line Diff line number Diff line
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2017, 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
@@ -125,6 +125,7 @@ struct msm_camera_cci_master_info {
	struct mutex mutex_q[NUM_QUEUES];
	struct mutex mutex_q[NUM_QUEUES];
	struct completion report_q[NUM_QUEUES];
	struct completion report_q[NUM_QUEUES];
	atomic_t done_pending[NUM_QUEUES];
	atomic_t done_pending[NUM_QUEUES];
	spinlock_t lock_q[NUM_QUEUES];
};
};


struct msm_cci_clk_params_t {
struct msm_cci_clk_params_t {