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

Commit e543c532 authored by Shubhraprakash Das's avatar Shubhraprakash Das
Browse files

msm: camera: isp: Vote for bandwidth to avoid race condition



Vote for bandwidth before enabling write masters.
This ensures no race condition between enabling write
masters and bandwidth voting.

Change-Id: I235f215908ebf5eb7289c5a7ff2d86d45902fe76
CRs-Fixed: 1112869
Signed-off-by: default avatarRajeev Kulkarni <krajeev@codeaurora.org>
Signed-off-by: default avatarShubhraprakash Das <sadas@codeaurora.org>
parent 4e6f40f2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -469,6 +469,7 @@ struct msm_vfe_axi_stream {
	 */
	uint32_t vfe_mask;
	uint32_t composite_irq[MSM_ISP_COMP_IRQ_MAX];
	int lpm_mode;
};

struct msm_vfe_axi_composite_info {
+56 −68
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ static void __msm_isp_axi_stream_update(
			struct msm_vfe_axi_stream *stream_info,
			struct msm_isp_timestamp *ts);

static int msm_isp_update_stream_bandwidth(
		struct msm_vfe_axi_stream *stream_info, int enable);

#define DUAL_VFE_AND_VFE1(s, v) ((s->stream_src < RDI_INTF_0) && \
			v->is_split && vfe_dev->pdev->id == ISP_VFE1)

@@ -2381,46 +2384,42 @@ static void msm_isp_update_intf_stream_cnt(
/*Factor in Q2 format*/
#define ISP_DEFAULT_FORMAT_FACTOR 6
#define ISP_BUS_UTILIZATION_FACTOR 6
static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
static int msm_isp_update_stream_bandwidth(
	struct msm_vfe_axi_stream *stream_info, int enable)
{
	int i, rc = 0;
	struct msm_vfe_axi_stream *stream_info;
	uint64_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
	uint32_t num_pix_streams = 0;
	uint64_t total_bandwidth = 0;
	int vfe_idx;
	struct vfe_device *vfe_dev;

	for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
		stream_info = msm_isp_get_stream_common_data(vfe_dev, i);
		if (stream_info->state == ACTIVE ||
			stream_info->state == START_PENDING) {
	for (i = 0; i < stream_info->num_isp; i++) {
		vfe_dev = stream_info->vfe_dev[i];
		vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev,
					stream_info);
			if (stream_info->stream_src < RDI_INTF_0) {
				total_pix_bandwidth +=
		if (enable) {
			total_bandwidth =
				vfe_dev->total_bandwidth +
				stream_info->bandwidth[vfe_idx];
				num_pix_streams++;
		} else {
				total_rdi_bandwidth +=
			total_bandwidth = vfe_dev->total_bandwidth -
				stream_info->bandwidth[vfe_idx];
		}
		}
	}
	vfe_dev->total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
		vfe_dev->total_bandwidth = total_bandwidth;
		rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
		(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
		(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
			(total_bandwidth + vfe_dev->hw_info->min_ab),
			(total_bandwidth + vfe_dev->hw_info->min_ib));

		if (rc < 0)
		pr_err("%s: update failed\n", __func__);

			pr_err("%s: update failed rc %d stream src %d vfe dev %d\n",
				__func__, rc, stream_info->stream_src,
				vfe_dev->pdev->id);
	}
	return rc;
}

int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
{
	int i, rc = 0;
	uint64_t total_bandwidth = 0;
	int vfe_idx;
	uint32_t intf;
	unsigned long flags;
	struct msm_vfe_axi_stream *stream_info;
@@ -2444,21 +2443,15 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
			intf = SRC_TO_INTF(stream_info->stream_src);
			vfe_dev->axi_data.src_info[intf].lpm =
				ab_ib_vote->lpm_mode;
			if (stream_info->state == ACTIVE) {
				vfe_idx =
					msm_isp_get_vfe_idx_for_stream(vfe_dev,
						stream_info);
					total_bandwidth +=
						stream_info->bandwidth[
							vfe_idx];
				stream_info->state = PAUSED;
			if (stream_info->lpm_mode) {
				spin_unlock_irqrestore(&stream_info->lock,
							flags);
				continue;
			}
			stream_info->lpm_mode = ab_ib_vote->lpm_mode;
			spin_unlock_irqrestore(&stream_info->lock, flags);
			msm_isp_update_stream_bandwidth(stream_info, 0);
		}
		vfe_dev->total_bandwidth -= total_bandwidth;
		rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
		(vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ab),
		(vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ib));
	} else {
		for (i = 0; i < ab_ib_vote->num_src; i++) {
			stream_info =
@@ -2470,24 +2463,19 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
			intf = SRC_TO_INTF(stream_info->stream_src);
			vfe_dev->axi_data.src_info[intf].lpm =
				ab_ib_vote->lpm_mode;
			if (stream_info->state == PAUSED) {
				vfe_idx =
					msm_isp_get_vfe_idx_for_stream(vfe_dev,
						stream_info);
					total_bandwidth +=
						stream_info->bandwidth[
							vfe_idx];
				stream_info->state = ACTIVE;
			if (stream_info->lpm_mode == 0) {
				spin_unlock_irqrestore(&stream_info->lock,
							flags);
				continue;
			}
			stream_info->lpm_mode = 0;
			spin_unlock_irqrestore(&stream_info->lock, flags);
			msm_isp_update_stream_bandwidth(stream_info, 1);
		}
		vfe_dev->total_bandwidth += total_bandwidth;
		rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
		(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
		(vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
	}
	return rc;
}

static int msm_isp_init_stream_ping_pong_reg(
	struct msm_vfe_axi_stream *stream_info)
{
@@ -2896,7 +2884,7 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
		 * be INACTIVE
		 */
		intf = SRC_TO_INTF(stream_info->stream_src);
		if ((!vfe_dev->axi_data.src_info[intf].lpm) ||
		if (stream_info->lpm_mode == 0 &&
			stream_info->state != PAUSED) {
			while (stream_info->state != ACTIVE)
				__msm_isp_axi_stream_update(stream_info,
@@ -2914,16 +2902,14 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
				vfe_dev->hw_info->vfe_ops.axi_ops.
				clear_wm_irq_mask(vfe_dev, stream_info);
		}
		if (stream_info->state == ACTIVE &&
			!vfe_dev->axi_data.src_info[intf].lpm) {
		init_completion(&stream_info->inactive_comp);
		stream_info->state = STOP_PENDING;
		} else if (vfe_dev->axi_data.src_info[intf].lpm ||
		if (stream_info->lpm_mode ||
			stream_info->state == PAUSED) {
			/* don't wait for reg update */
			stream_info->state = STOP_PENDING;
			msm_isp_axi_stream_enable_cfg(stream_info);
			stream_info->state = INACTIVE;
			while (stream_info->state != INACTIVE)
				__msm_isp_axi_stream_update(stream_info,
							&timestamp);
		}
		spin_unlock_irqrestore(&stream_info->lock, flags);
	}
@@ -2984,6 +2970,8 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
	/* clear buffers that are dequeued */
	for (i = 0; i < num_streams; i++) {
		stream_info = streams[i];
		if (stream_info->lpm_mode == 0)
			msm_isp_update_stream_bandwidth(stream_info, 0);
		for (bufq_id = 0; bufq_id < VFE_BUF_QUEUE_MAX; bufq_id++) {
			bufq_handle = stream_info->bufq_handle[bufq_id];
			if (!bufq_handle)
@@ -2999,12 +2987,6 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
		}
	}

	for (k = 0; k < MAX_VFE; k++) {
		if (!update_vfes[k])
			continue;
		msm_isp_update_stream_bandwidth(update_vfes[k]);
	}

	for (i = 0; i < num_streams; i++) {
		stream_info = streams[i];
		intf = SRC_TO_INTF(stream_info->stream_src);
@@ -3099,6 +3081,13 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
			}
		}
		intf = SRC_TO_INTF(stream_info->stream_src);
		stream_info->lpm_mode = vfe_dev_ioctl->
					axi_data.src_info[intf].lpm;
		if (stream_info->lpm_mode == 0) {
			spin_unlock_irqrestore(&stream_info->lock, flags);
			msm_isp_update_stream_bandwidth(stream_info, 1);
			spin_lock_irqsave(&stream_info->lock, flags);
		}
		init_completion(&stream_info->active_comp);
		stream_info->state = START_PENDING;
		msm_isp_update_intf_stream_cnt(stream_info, 1);
@@ -3108,7 +3097,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
			vfe_dev_ioctl->pdev->id);
		if (src_state) {
			src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
			if (vfe_dev_ioctl->axi_data.src_info[intf].lpm) {
			if (stream_info->lpm_mode) {
				while (stream_info->state != ACTIVE)
					__msm_isp_axi_stream_update(
						stream_info, &timestamp);
@@ -3142,7 +3131,6 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
		vfe_dev = update_vfes[i];
		if (!vfe_dev)
			continue;
		msm_isp_update_stream_bandwidth(vfe_dev);
		vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
			vfe_dev->vfe_base, wm_reload_mask[i]);

+3 −0
Original line number Diff line number Diff line
@@ -2339,6 +2339,7 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
	long rc = 0;
	int wm;
	int i;
	struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
	ISP_DBG("%s E open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt);
	mutex_lock(&vfe_dev->realtime_mutex);
@@ -2388,6 +2389,8 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
		msm_isp_end_avtimer();
		vfe_dev->vt_enable = 0;
	}
	for (i = 0; i < VFE_SRC_MAX; i++)
		vfe_dev->axi_data.src_info[i].lpm = 0;
	MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
	vfe_dev->is_split = 0;