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

Commit d5d13998 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: isp: avoid race on free buffer queue"

parents 87f11d81 70c2351e
Loading
Loading
Loading
Loading
+66 −59
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ static uint32_t msm_isp_get_buf_handle(
	return 0;
}

static int msm_isp_free_buf_handle(struct msm_isp_buf_mgr *buf_mgr,
static int msm_isp_free_bufq_handle(struct msm_isp_buf_mgr *buf_mgr,
	uint32_t bufq_handle)
{
	struct msm_isp_bufq *bufq =
@@ -427,19 +427,28 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	struct buffer_cmd *buf_pending = NULL;
	struct msm_isp_buffer_mapped_info *mped_info_tmp1;
	struct msm_isp_buffer_mapped_info *mped_info_tmp2;

	if (buf_mgr->open_count == 0) {
		pr_err_ratelimited("%s: bug mgr open cnt = 0\n",
			__func__);
		return 0;
	}

	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
	if (!bufq) {
		pr_err_ratelimited("%s: Invalid bufq\n", __func__);
		return rc;
	}

	spin_lock_irqsave(&bufq->bufq_lock, flags);
	if (!bufq->bufq_handle) {
		pr_err_ratelimited("%s: Invalid bufq handle\n", __func__);
		spin_unlock_irqrestore(&bufq->bufq_lock, flags);
		return rc;
	}

	*buf_info = NULL;
	*buf_cnt = 0;
	spin_lock_irqsave(&bufq->bufq_lock, flags);
	if (bufq->buf_type == ISP_SHARE_BUF) {
		list_count = 0;
		list_for_each_entry(temp_buf_info,
@@ -529,8 +538,8 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
							mped_info_tmp2->len)
						&& (mped_info_tmp1->paddr ==
						mped_info_tmp2->paddr)) {
						*buf_info =
					&bufq->bufs[vb2_buf->v4l2_buf.index];
						*buf_info = &bufq->bufs[vb2_buf
							->v4l2_buf.index];
						(*buf_info)->vb2_buf = vb2_buf;
						break;
					}
@@ -1035,11 +1044,10 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
		buf_request->num_buf, GFP_KERNEL);
	if (!bufq->bufs) {
		pr_err("No free memory for buf info\n");
		msm_isp_free_buf_handle(buf_mgr, buf_request->handle);
		msm_isp_free_bufq_handle(buf_mgr, buf_request->handle);
		return rc;
	}

	spin_lock_init(&bufq->bufq_lock);
	bufq->bufq_handle = buf_request->handle;
	bufq->session_id = buf_request->session_id;
	bufq->stream_id = buf_request->stream_id;
@@ -1072,10 +1080,9 @@ static int msm_isp_release_bufq(struct msm_isp_buf_mgr *buf_mgr,

	msm_isp_buf_unprepare_all(buf_mgr, bufq_handle);

	kfree(bufq->bufs);

	spin_lock_irqsave(&bufq->bufq_lock, flags);
	msm_isp_free_buf_handle(buf_mgr, bufq_handle);
	kfree(bufq->bufs);
	msm_isp_free_bufq_handle(buf_mgr, bufq_handle);
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);

	return 0;
@@ -1094,10 +1101,9 @@ static void msm_isp_release_all_bufq(

		msm_isp_buf_unprepare_all(buf_mgr, bufq->bufq_handle);

		kfree(bufq->bufs);

		spin_lock_irqsave(&bufq->bufq_lock, flags);
		msm_isp_free_buf_handle(buf_mgr, bufq->bufq_handle);
		kfree(bufq->bufs);
		msm_isp_free_bufq_handle(buf_mgr, bufq->bufq_handle);
		spin_unlock_irqrestore(&bufq->bufq_lock, flags);
	}
}
@@ -1255,33 +1261,22 @@ err1:
}


static int msm_isp_init_isp_buf_mgr(
	struct msm_isp_buf_mgr *buf_mgr,
	const char *ctx_name, uint16_t num_buf_q)
static int msm_isp_init_isp_buf_mgr(struct msm_isp_buf_mgr *buf_mgr,
	const char *ctx_name)
{
	int rc = -1;
	int i = 0;
	mutex_lock(&buf_mgr->lock);
	if (buf_mgr->open_count++) {
		mutex_unlock(&buf_mgr->lock);
		return 0;
	}

	if (!num_buf_q) {
		pr_err("Invalid buffer queue number\n");
		mutex_unlock(&buf_mgr->lock);
		return rc;
	}
	CDBG("%s: E\n", __func__);

	INIT_LIST_HEAD(&buf_mgr->buffer_q);
	buf_mgr->num_buf_q = num_buf_q;
	buf_mgr->bufq =
		kzalloc(sizeof(struct msm_isp_bufq) * num_buf_q,
		GFP_KERNEL);
	if (!buf_mgr->bufq) {
		pr_err("Bufq malloc error\n");
		goto bufq_error;
	}
	buf_mgr->num_buf_q = BUF_MGR_NUM_BUF_Q;
	memset(buf_mgr->bufq, 0, sizeof(buf_mgr->bufq));

	rc = cam_smmu_get_handle("vfe_image", &buf_mgr->img_iommu_hdl);
	if (rc < 0) {
@@ -1293,6 +1288,10 @@ static int msm_isp_init_isp_buf_mgr(
		pr_err("vfe get stats handle failed\n");
		goto get_handle_error2;
	}

	for (i = 0; i < BUF_MGR_NUM_BUF_Q; i++)
		spin_lock_init(&buf_mgr->bufq[i].bufq_lock);

	buf_mgr->buf_handle_cnt = 0;
	buf_mgr->pagefault_debug_disable = 0;
	buf_mgr->frameId_mismatch_recovery = 0;
@@ -1302,8 +1301,6 @@ static int msm_isp_init_isp_buf_mgr(
get_handle_error2:
	cam_smmu_destroy_handle(buf_mgr->img_iommu_hdl);
get_handle_error1:
	kfree(buf_mgr->bufq);
bufq_error:
	mutex_unlock(&buf_mgr->lock);
	return rc;
}
@@ -1320,7 +1317,6 @@ static int msm_isp_deinit_isp_buf_mgr(
		return 0;
	}
	msm_isp_release_all_bufq(buf_mgr);
	kfree(buf_mgr->bufq);
	buf_mgr->num_buf_q = 0;
	buf_mgr->pagefault_debug_disable = 0;

@@ -1378,6 +1374,8 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
	uint32_t debug_end_addr = 0;
	uint32_t debug_frame_id = 0;
	enum msm_isp_buffer_state debug_state;
	unsigned long flags;
	struct msm_isp_bufq *bufq = NULL;

	if (!buf_mgr) {
		pr_err_ratelimited("%s: %d] NULL buf_mgr\n",
@@ -1386,12 +1384,21 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
	}

	for (i = 0; i < BUF_MGR_NUM_BUF_Q; i++) {
		if (buf_mgr->bufq[i].bufq_handle != 0) {
			for (j = 0; j < buf_mgr->bufq[i].num_bufs; j++) {
				bufs = &buf_mgr->bufq[i].bufs[j];
				if (!bufs) {
		bufq = &buf_mgr->bufq[i];
		if (!bufq)
			continue;

		spin_lock_irqsave(&bufq->bufq_lock, flags);
		if (!bufq->bufq_handle) {
			spin_unlock_irqrestore(&bufq->bufq_lock, flags);
			continue;
		}

		for (j = 0; j < bufq->num_bufs; j++) {
			bufs = &bufq->bufs[j];
			if (!bufs)
				continue;

			for (k = 0; k < bufs->num_planes; k++) {
				start_addr = bufs->
						mapped_info[k].paddr;
@@ -1404,8 +1411,7 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
				if (buf_addr_delta == -1 ||
					temp_delta < buf_addr_delta) {
					buf_addr_delta = temp_delta;
						debug_stream_id = buf_mgr->
							bufq[i].stream_id;
					debug_stream_id = bufq->stream_id;
					debug_buf_idx = j;
					debug_buf_plane = k;
					debug_start_addr = start_addr;
@@ -1417,8 +1423,9 @@ static int msm_isp_buf_mgr_debug(struct msm_isp_buf_mgr *buf_mgr,
		}
		start_addr = 0;
		end_addr = 0;
		spin_unlock_irqrestore(&bufq->bufq_lock, flags);
	}
	}

	pr_err("%s: ==== SMMU page fault addr %lx ====\n", __func__,
		fault_addr);
	pr_err("%s: nearby stream id %x, frame_id %d\n", __func__,
+2 −2
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ struct msm_isp_buf_ops {
		struct device **iommu_ctx1, struct device **iommu_ctx2,
		int num_iommu_ctx1, int num_iommu_ctx2);
	int (*buf_mgr_init)(struct msm_isp_buf_mgr *buf_mgr,
		const char *ctx_name, uint16_t num_buf_q);
		const char *ctx_name);
	int (*buf_mgr_deinit)(struct msm_isp_buf_mgr *buf_mgr);
	int (*buf_mgr_debug)(struct msm_isp_buf_mgr *buf_mgr,
		unsigned long fault_addr);
@@ -167,7 +167,7 @@ struct msm_isp_buf_mgr {
	uint32_t pagefault_debug_disable;
	uint32_t frameId_mismatch_recovery;
	uint16_t num_buf_q;
	struct msm_isp_bufq *bufq;
	struct msm_isp_bufq bufq[BUF_MGR_NUM_BUF_Q];

	struct ion_client *client;
	struct msm_isp_buf_ops *ops;
+14 −2
Original line number Diff line number Diff line
@@ -963,12 +963,24 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
		/* fallthrough */
	case VIDIOC_MSM_ISP_ENQUEUE_BUF:
		/* fallthrough */
	case VIDIOC_MSM_ISP_DEQUEUE_BUF:
	case VIDIOC_MSM_ISP_DEQUEUE_BUF: {
		/* fallthrough */
		mutex_lock(&vfe_dev->buf_mgr_mutex);
		rc = msm_isp_proc_buf_cmd(vfe_dev->buf_mgr, cmd, arg);
		mutex_unlock(&vfe_dev->buf_mgr_mutex);
		break;
	}
	case VIDIOC_MSM_ISP_RELEASE_BUF: {
		if (vfe_dev->buf_mgr == NULL) {
			pr_err("%s: buf mgr NULL! rc = -1\n", __func__);
			rc = -EINVAL;
			return rc;
		}
		mutex_lock(&vfe_dev->buf_mgr->lock);
		mutex_lock(&vfe_dev->buf_mgr_mutex);
		rc = msm_isp_proc_buf_cmd(vfe_dev->buf_mgr, cmd, arg);
		mutex_unlock(&vfe_dev->buf_mgr_mutex);
		mutex_unlock(&vfe_dev->buf_mgr->lock);
		break;
	}
	case VIDIOC_MSM_ISP_REQUEST_STREAM:
@@ -2128,7 +2140,7 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
	vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);

	vfe_dev->buf_mgr->ops->buf_mgr_init(vfe_dev->buf_mgr,
		"msm_isp", BUF_MGR_NUM_BUF_Q);
		"msm_isp");

	memset(&vfe_dev->axi_data, 0, sizeof(struct msm_vfe_axi_shared_data));
	memset(&vfe_dev->stats_data, 0,