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

Commit 172b6dc5 authored by Linux Build Service Account's avatar Linux Build Service Account
Browse files

Merge 3f3685b0 on remote branch

Change-Id: I7613c07035c3bae32162ef98acf5d4ce1d8587e7
parents 3fd5b7ba 3f3685b0
Loading
Loading
Loading
Loading
+36 −12
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link)
	link->sof_timestamp = 0;
	link->prev_sof_timestamp = 0;
	link->skip_wd_validation = false;
	link->last_applied_jiffies = 0;
}

void cam_req_mgr_handle_core_shutdown(void)
@@ -1376,6 +1377,7 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
{
	int                                  rc = 0, idx;
	int                                  reset_step = 0;
	bool                                 check_retry_cnt = false;
	uint32_t                             trigger = trigger_data->trigger;
	struct cam_req_mgr_slot             *slot = NULL;
	struct cam_req_mgr_req_queue        *in_q;
@@ -1497,6 +1499,13 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
	if (rc < 0) {
		/* Apply req failed retry at next sof */
		slot->status = CRM_SLOT_STATUS_REQ_PENDING;

		if (jiffies_to_msecs(jiffies - link->last_applied_jiffies) >
			MINIMUM_WORKQUEUE_SCHED_TIME_IN_MS)
			check_retry_cnt = true;

		if ((in_q->last_applied_idx < in_q->rd_idx) &&
			check_retry_cnt) {
			link->retry_cnt++;
			max_retry = MAXIMUM_RETRY_ATTEMPTS;
			if (link->max_delay == 1)
@@ -1509,6 +1518,11 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
				__cam_req_mgr_notify_error_on_link(link, dev);
				link->retry_cnt = 0;
			}
		} else
			CAM_WARN(CAM_CRM,
				"workqueue congestion, last applied idx:%d rd idx:%d",
				in_q->last_applied_idx,
				in_q->rd_idx);
	} else {
		if (link->retry_cnt)
			link->retry_cnt = 0;
@@ -1557,6 +1571,16 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link,
		}
	}

	/*
	 * Only update the jiffies of last applied request
	 * for SOF trigger, since it is used to protect from
	 * applying fails in ISP which is triggered at SOF.
	 * And, also don't need to do update for error case
	 * since error case doesn't check the retry count.
	 */
	if (trigger == CAM_TRIGGER_POINT_SOF)
		link->last_applied_jiffies = jiffies;

	mutex_unlock(&session->lock);
	return rc;
error:
+4 −1
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@

#define MAXIMUM_RETRY_ATTEMPTS 2

#define MINIMUM_WORKQUEUE_SCHED_TIME_IN_MS 5

#define VERSION_1  1
#define VERSION_2  2
#define CAM_REQ_MGR_MAX_TRIGGERS   2
@@ -351,6 +353,7 @@ struct cam_req_mgr_connected_device {
 * @trigger_cnt          : trigger count value per device initiating the trigger
 * @skip_wd_validation   : skip initial frames crm_wd_timer validation in the
 *                         case of long exposure use case
 * @last_applied_jiffies : Record the jiffies of last applied req
 */
struct cam_req_mgr_core_link {
	int32_t                              link_hdl;
@@ -384,7 +387,7 @@ struct cam_req_mgr_core_link {
	bool                                 dual_trigger;
	uint32_t    trigger_cnt[CAM_REQ_MGR_MAX_TRIGGERS];
	bool                                 skip_wd_validation;

	uint64_t                             last_applied_jiffies;
};

/**
+53 −105
Original line number Diff line number Diff line
@@ -575,19 +575,42 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
	struct cam_cci_clk_params_t *clk_params = NULL;
	enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
	enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode;
	struct cam_hw_soc_info *soc_info =
		&cci_dev->soc_info;
	void __iomem *base = soc_info->reg_map[0].mem_base;
	void __iomem *base = cci_dev->soc_info.reg_map[0].mem_base;
	struct cam_cci_master_info *cci_master =
		&cci_dev->cci_master_info[master];

	if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) {
		CAM_ERR(CAM_CCI, "invalid i2c_freq_mode = %d", i2c_freq_mode);
		return -EINVAL;
	}
	/*
	 * If no change in i2c freq, then acquire semaphore only for the first
	 * i2c transaction to indicate I2C transaction is in progress, else
	 * always try to acquire semaphore, to make sure that no other I2C
	 * transaction is in progress.
	 */
	mutex_lock(&cci_master->mutex);
	if (i2c_freq_mode == cci_dev->i2c_freq_mode[master]) {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d", master,
			i2c_freq_mode);
		spin_lock(&cci_master->freq_cnt_lock);
		if (cci_master->freq_ref_cnt == 0)
			down(&cci_master->master_sem);
		cci_master->freq_ref_cnt++;
		spin_unlock(&cci_master->freq_cnt_lock);
		mutex_unlock(&cci_master->mutex);
		return 0;
	}
	CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
		master, cci_dev->i2c_freq_mode[master], i2c_freq_mode);
	down(&cci_master->master_sem);

	spin_lock(&cci_master->freq_cnt_lock);
	cci_master->freq_ref_cnt++;
	spin_unlock(&cci_master->freq_cnt_lock);

	clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];

	if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode)
		return 0;
	if (master == MASTER_0) {
		cam_io_w_mb(clk_params->hw_thigh << 16 |
			clk_params->hw_tlow,
@@ -621,6 +644,7 @@ static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
	}
	cci_dev->i2c_freq_mode[master] = i2c_freq_mode;

	mutex_unlock(&cci_master->mutex);
	return 0;
}

@@ -899,42 +923,19 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,
		return -EINVAL;
	}

	soc_info = &cci_dev->soc_info;
	base = soc_info->reg_map[0].mem_base;

	mutex_lock(&cci_dev->cci_master_info[master].mutex);
	if (cci_dev->cci_master_info[master].is_first_req) {
		cci_dev->cci_master_info[master].is_first_req = false;
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else if (c_ctrl->cci_info->i2c_freq_mode
		!= cci_dev->i2c_freq_mode[master]) {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
		cci_dev->cci_master_info[master].freq_ref_cnt++;
		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	}

	/* Set the I2C Frequency */
	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
		goto rel_master;
		return rc;
	}
	mutex_unlock(&cci_dev->cci_master_info[master].mutex);

	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
	reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);

	soc_info = &cci_dev->soc_info;
	base = soc_info->reg_map[0].mem_base;

	/*
	 * Call validate queue to make sure queue is empty before starting.
	 * If this call fails, don't proceed with i2c_read call. This is to
@@ -1146,13 +1147,11 @@ static int32_t cam_cci_burst_read(struct v4l2_subdev *sd,

rel_mutex_q:
	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
rel_master:
	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)

	spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
	if (--cci_dev->cci_master_info[master].freq_ref_cnt == 0)
		up(&cci_dev->cci_master_info[master].master_sem);
	else
		cci_dev->cci_master_info[master].freq_ref_cnt--;
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
	return rc;
}

@@ -1177,46 +1176,24 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,

	if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
		|| c_ctrl->cci_info->cci_i2c_master < 0) {
		CAM_ERR(CAM_CCI, "Invalid I2C master addr");
		CAM_ERR(CAM_CCI, "Invalid I2C master addr:%d",
			c_ctrl->cci_info->cci_i2c_master);
		return -EINVAL;
	}

	soc_info = &cci_dev->soc_info;
	base = soc_info->reg_map[0].mem_base;

	mutex_lock(&cci_dev->cci_master_info[master].mutex);
	if (cci_dev->cci_master_info[master].is_first_req) {
		cci_dev->cci_master_info[master].is_first_req = false;
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else if (c_ctrl->cci_info->i2c_freq_mode
		!= cci_dev->i2c_freq_mode[master]) {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
		cci_dev->cci_master_info[master].freq_ref_cnt++;
		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	}

	/* Set the I2C Frequency */
	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
		goto rel_master;
		return rc;
	}
	mutex_unlock(&cci_dev->cci_master_info[master].mutex);

	mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
	reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);

	soc_info = &cci_dev->soc_info;
	base = soc_info->reg_map[0].mem_base;

	/*
	 * Call validate queue to make sure queue is empty before starting.
	 * If this call fails, don't proceed with i2c_read call. This is to
@@ -1366,13 +1343,11 @@ static int32_t cam_cci_read(struct v4l2_subdev *sd,
	}
rel_mutex_q:
	mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
rel_master:
	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)

	spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
	if (--cci_dev->cci_master_info[master].freq_ref_cnt == 0)
		up(&cci_dev->cci_master_info[master].master_sem);
	else
		cci_dev->cci_master_info[master].freq_ref_cnt--;
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
	return rc;
}

@@ -1396,37 +1371,12 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
		c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
		c_ctrl->cci_info->id_map);

	mutex_lock(&cci_dev->cci_master_info[master].mutex);
	if (cci_dev->cci_master_info[master].is_first_req) {
		cci_dev->cci_master_info[master].is_first_req = false;
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else if (c_ctrl->cci_info->i2c_freq_mode
		!= cci_dev->i2c_freq_mode[master]) {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		down(&cci_dev->cci_master_info[master].master_sem);
	} else {
		CAM_DBG(CAM_CCI, "Master: %d, curr_freq: %d, req_freq: %d",
			master, cci_dev->i2c_freq_mode[master],
			c_ctrl->cci_info->i2c_freq_mode);
		spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
		cci_dev->cci_master_info[master].freq_ref_cnt++;
		spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	}

	/* Set the I2C Frequency */
	rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
	if (rc < 0) {
		CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
		mutex_unlock(&cci_dev->cci_master_info[master].mutex);
		goto ERROR;
		return rc;
	}
	mutex_unlock(&cci_dev->cci_master_info[master].mutex);

	reinit_completion(&cci_dev->cci_master_info[master].report_q[queue]);
	/*
	 * Call validate queue to make sure queue is empty before starting.
@@ -1452,12 +1402,10 @@ static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
	}

ERROR:
	spin_lock(&cci_dev->cci_master_info[master].freq_cnt);
	if (cci_dev->cci_master_info[master].freq_ref_cnt == 0)
	spin_lock(&cci_dev->cci_master_info[master].freq_cnt_lock);
	if (--cci_dev->cci_master_info[master].freq_ref_cnt == 0)
		up(&cci_dev->cci_master_info[master].master_sem);
	else
		cci_dev->cci_master_info[master].freq_ref_cnt--;
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt);
	spin_unlock(&cci_dev->cci_master_info[master].freq_cnt_lock);
	return rc;
}

+1 −2
Original line number Diff line number Diff line
@@ -133,9 +133,8 @@ struct cam_cci_master_info {
	struct completion report_q[NUM_QUEUES];
	atomic_t done_pending[NUM_QUEUES];
	spinlock_t lock_q[NUM_QUEUES];
	spinlock_t freq_cnt;
	struct semaphore master_sem;
	bool is_first_req;
	spinlock_t freq_cnt_lock;
	uint16_t freq_ref_cnt;
	bool is_initilized;
};
+2 −2
Original line number Diff line number Diff line
@@ -212,11 +212,11 @@ static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)

	for (i = 0; i < MASTER_MAX; i++) {
		new_cci_dev->cci_master_info[i].status = 0;
		new_cci_dev->cci_master_info[i].is_first_req = true;
		new_cci_dev->cci_master_info[i].is_initilized = false;
		new_cci_dev->cci_master_info[i].freq_ref_cnt = 0;
		mutex_init(&new_cci_dev->cci_master_info[i].mutex);
		sema_init(&new_cci_dev->cci_master_info[i].master_sem, 1);
		spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt);
		spin_lock_init(&new_cci_dev->cci_master_info[i].freq_cnt_lock);
		init_completion(
			&new_cci_dev->cci_master_info[i].reset_complete);
		init_completion(