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

Commit 72d2a8af authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: fix deadlock between queue and flush buffer handling"

parents 472cf8f2 d3ff13cc
Loading
Loading
Loading
Loading
+10 −12
Original line number Diff line number Diff line
@@ -521,6 +521,15 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
		return -EINVAL;
	}

	q = msm_comm_get_vb2q(inst, b->type);
	if (!q) {
		dprintk(VIDC_ERR,
		"Failed to find buffer queue for type = %d\n", b->type);
			return -EINVAL;
	}
	mutex_lock(&q->lock);


	for (i = 0; i < b->length; i++) {
		b->m.planes[i].m.fd = b->m.planes[i].reserved[0];
		b->m.planes[i].data_offset = b->m.planes[i].reserved[1];
@@ -545,19 +554,11 @@ int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
	tag_data.output_tag = b->m.planes[0].reserved[6];
	msm_comm_store_tags(inst, &tag_data);

	q = msm_comm_get_vb2q(inst, b->type);
	if (!q) {
		dprintk(VIDC_ERR,
			"Failed to find buffer queue for type = %d\n", b->type);
		return -EINVAL;
	}

	mutex_lock(&q->lock);
	rc = vb2_qbuf(&q->vb2_bufq, b);
	mutex_unlock(&q->lock);
	if (rc)
		dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);

	mutex_unlock(&q->lock);
	return rc;
}
EXPORT_SYMBOL(msm_vidc_qbuf);
@@ -1879,7 +1880,6 @@ void *msm_vidc_open(int core_id, int session_type)
	mutex_init(&inst->bufq[CAPTURE_PORT].lock);
	mutex_init(&inst->bufq[OUTPUT_PORT].lock);
	mutex_init(&inst->lock);
	mutex_init(&inst->flush_lock);

	INIT_MSM_VIDC_LIST(&inst->scratchbufs);
	INIT_MSM_VIDC_LIST(&inst->freqs);
@@ -2003,7 +2003,6 @@ void *msm_vidc_open(int core_id, int session_type)
	mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
	mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
	mutex_destroy(&inst->lock);
	mutex_destroy(&inst->flush_lock);

	DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
	DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
@@ -2157,7 +2156,6 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst)
	mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
	mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
	mutex_destroy(&inst->lock);
	mutex_destroy(&inst->flush_lock);

	msm_vidc_debugfs_deinit_inst(inst);

+35 −16
Original line number Diff line number Diff line
@@ -2079,7 +2079,11 @@ static void handle_session_flush(enum hal_command_response cmd, void *data)
		return;
	}

	mutex_lock(&inst->flush_lock);
	if (response->data.flush_type & HAL_FLUSH_INPUT)
		mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
	if (response->data.flush_type & HAL_FLUSH_OUTPUT)
		mutex_lock(&inst->bufq[CAPTURE_PORT].lock);

	if (msm_comm_get_stream_output_mode(inst) ==
			HAL_VIDEO_DECODER_SECONDARY) {

@@ -2122,7 +2126,11 @@ static void handle_session_flush(enum hal_command_response cmd, void *data)
	v4l2_event_queue_fh(&inst->event_handler, &flush_event);

exit:
	mutex_unlock(&inst->flush_lock);
	if (response->data.flush_type & HAL_FLUSH_OUTPUT)
		mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
	if (response->data.flush_type & HAL_FLUSH_INPUT)
		mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);

	put_inst(inst);
}

@@ -2331,7 +2339,7 @@ struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer(
		return NULL;
	}

	mutex_lock(&inst->bufq[port].lock);
	WARN_ON(!mutex_is_locked(&inst->bufq[port].lock));
	found = false;
	q = &inst->bufq[port].vb2_bufq;
	if (!q->streaming) {
@@ -2347,7 +2355,6 @@ struct vb2_buffer *msm_comm_get_vb_using_vidc_buffer(
		}
	}
unlock:
	mutex_unlock(&inst->bufq[port].lock);
	if (!found) {
		print_vidc_buffer(VIDC_ERR, "vb2 not found for", inst, mbuf);
		return NULL;
@@ -2362,6 +2369,7 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
	struct vb2_buffer *vb2;
	struct vb2_v4l2_buffer *vbuf;
	u32 i, port;
	int rc = 0;

	if (!inst || !mbuf) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
@@ -2378,16 +2386,20 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
	else
		return -EINVAL;

	vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
	if (!vb2)
		return -EINVAL;

	/*
	 * access vb2 buffer under q->lock and if streaming only to
	 * ensure the buffer was not free'd by vb2 framework while
	 * we are accessing it here.
	 */
	mutex_lock(&inst->bufq[port].lock);
	vb2 = msm_comm_get_vb_using_vidc_buffer(inst, mbuf);
	if (!vb2) {
		rc = -EINVAL;
		dprintk(VIDC_ERR, "%s:port %d buffer not found\n",
			__func__, port);
		goto unlock;
	}

	if (inst->bufq[port].vb2_bufq.streaming) {
		vbuf = to_vb2_v4l2_buffer(vb2);
		vbuf->flags = mbuf->vvb.flags;
@@ -2403,9 +2415,9 @@ int msm_comm_vb2_buffer_done(struct msm_vidc_inst *inst,
		dprintk(VIDC_ERR, "%s: port %d is not streaming\n",
			__func__, port);
	}
unlock:
	mutex_unlock(&inst->bufq[port].lock);

	return 0;
	return rc;
}

bool heic_encode_session_supported(struct msm_vidc_inst *inst)
@@ -5316,7 +5328,11 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
		return 0;
	}

	mutex_lock(&inst->flush_lock);
	if (ip_flush)
		mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
	if (op_flush)
		mutex_lock(&inst->bufq[CAPTURE_PORT].lock);

	/* enable in flush */
	inst->in_flush = true;

@@ -5370,7 +5386,12 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
		rc = call_hfi_op(hdev, session_flush, inst->session,
			HAL_FLUSH_OUTPUT);
	}
	mutex_unlock(&inst->flush_lock);

	if (op_flush)
		mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
	if (ip_flush)
		mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);

	if (rc) {
		dprintk(VIDC_ERR,
			"Sending flush to firmware failed, flush out all buffers\n");
@@ -6453,7 +6474,6 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
	else
		return -EINVAL;

	mutex_lock(&inst->bufq[port].lock);
	if (inst->bufq[port].vb2_bufq.streaming) {
		vb->planes[0].bytesused = 0;
		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
@@ -6461,7 +6481,6 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
		dprintk(VIDC_ERR, "%s: port %d is not streaming\n",
			__func__, port);
	}
	mutex_unlock(&inst->bufq[port].lock);

	return 0;
}
@@ -6815,7 +6834,7 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst,
	int i = 0;
	u32 planes[VIDEO_MAX_PLANES] = {0};

	mutex_lock(&inst->flush_lock);
	mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
	mutex_lock(&inst->registeredbufs.lock);
	found = false;
	/* check if mbuf was not removed by any chance */
@@ -6904,7 +6923,7 @@ void handle_release_buffer_reference(struct msm_vidc_inst *inst,
			print_vidc_buffer(VIDC_ERR,
				"rbr qbuf failed", inst, mbuf);
	}
	mutex_unlock(&inst->flush_lock);
	mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
}

int msm_comm_unmap_vidc_buffer(struct msm_vidc_inst *inst,
+2 −2
Original line number Diff line number Diff line
/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 *
 * 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
@@ -442,7 +442,7 @@ struct msm_vidc_core {

struct msm_vidc_inst {
	struct list_head list;
	struct mutex sync_lock, lock, flush_lock;
	struct mutex sync_lock, lock;
	struct msm_vidc_core *core;
	enum session_type session_type;
	void *session;
+3 −4
Original line number Diff line number Diff line
@@ -995,10 +995,9 @@ struct hal_fw_info {
};

enum hal_flush {
	HAL_FLUSH_INPUT,
	HAL_FLUSH_OUTPUT,
	HAL_FLUSH_ALL,
	HAL_UNUSED_FLUSH = 0x10000000,
	HAL_FLUSH_INPUT = BIT(0),
	HAL_FLUSH_OUTPUT = BIT(1),
	HAL_FLUSH_ALL = HAL_FLUSH_INPUT | HAL_FLUSH_OUTPUT,
};

enum hal_event_type {