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

Commit 396475a0 authored by George Shen's avatar George Shen Committed by Gerrit - the friendly Code Review server
Browse files

msm: cvp: Support CVP session abort



Abort cvp session provides a faster session recovery
mechanism compared with SSR. It doesn't affect
functionality of other ongoing sessions.

Change-Id: I58b0e629b6e0c5139d63c5d54063daf483196e41
Signed-off-by: default avatarGeorge Shen <sqiao@codeaurora.org>
parent 4a1ec086
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -2674,7 +2674,6 @@ static int venus_hfi_session_abort(void *sess)

	mutex_lock(&device->lock);

	__flush_debug_queue(device, NULL);
	rc = __send_session_cmd(session, HFI_CMD_SYS_SESSION_ABORT);

	mutex_unlock(&device->lock);
+1 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ enum hal_ssr_trigger_type {
	SSR_ERR_FATAL = 1,
	SSR_SW_DIV_BY_ZERO,
	SSR_HW_WDOG_IRQ,
	SSR_SESSION_ABORT,
};

struct cvp_hal_profile_level {
+1 −1
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ static int hfi_process_session_error(u32 device_id,
		dprintk(CVP_ERR,
			"%s: session %x data1 %#x, data2 %#x\n", __func__,
			pkt->session_id, pkt->event_data1, pkt->event_data2);
		info->response_type = HAL_SESSION_ERROR;
		info->response_type = HAL_RESPONSE_UNUSED;
		break;
	}

+47 −20
Original line number Diff line number Diff line
@@ -84,9 +84,11 @@ static int msm_cvp_get_session_info(struct msm_cvp_inst *inst,
	if (!s)
		return -ECONNRESET;

	s->cur_cmd_type = CVP_KMD_GET_SESSION_INFO;
	session->session_id = hash32_ptr(inst->session);
	dprintk(CVP_DBG, "%s: id 0x%x\n", __func__, session->session_id);

	s->cur_cmd_type = 0;
	cvp_put_inst(s);
	return rc;
}
@@ -539,8 +541,7 @@ static bool _cvp_msg_pending(struct msm_cvp_inst *inst,
	bool result = false;

	spin_lock(&sq->lock);
	if (!kref_read(&inst->kref) ||
		sq->state != QUEUE_ACTIVE) {
	if (sq->state != QUEUE_ACTIVE) {
		/* The session is being deleted */
		spin_unlock(&sq->lock);
		*msg = NULL;
@@ -579,6 +580,7 @@ static int msm_cvp_session_receive_hfi(struct msm_cvp_inst *inst,
	if (!s)
		return -ECONNRESET;

	s->cur_cmd_type = CVP_KMD_RECEIVE_MSG_PKT;
	sq = &inst->session_queue;
	sc = (struct cvp_kmd_session_control *)out_pkt;

@@ -586,7 +588,8 @@ static int msm_cvp_session_receive_hfi(struct msm_cvp_inst *inst,

	if (wait_event_timeout(sq->wq,
		_cvp_msg_pending(inst, sq, &msg), wait_time) == 0) {
		dprintk(CVP_DBG, "session queue wait timeout\n");
		dprintk(CVP_WARN, "session queue wait timeout\n");
		msm_cvp_comm_kill_session(inst);
		rc = -ETIMEDOUT;
		goto exit;
	}
@@ -595,19 +598,17 @@ static int msm_cvp_session_receive_hfi(struct msm_cvp_inst *inst,
				>> HFI_VERSION_MINOR_SHIFT;

	if (msg == NULL) {
		dprintk(CVP_DBG,
		dprintk(CVP_WARN,
			"%s: session deleted, queue state %d, msg cnt %d\n",
			__func__, inst->session_queue.state,
			inst->session_queue.msg_count);

		spin_lock(&sq->lock);
		if (sq->msg_count) {
			sc->ctrl_data[0] = sq->msg_count;
			rc = -EUCLEAN;
		} else {
			rc = -ENOLINK;
		if (inst->state >= MSM_CVP_CLOSE_DONE) {
			rc = -ECONNRESET;
			goto exit;
		}
		spin_unlock(&sq->lock);

		msm_cvp_comm_kill_session(inst);
	} else {
		if (version >= 1) {
			u64 ktid;
@@ -625,6 +626,7 @@ static int msm_cvp_session_receive_hfi(struct msm_cvp_inst *inst,
	}

exit:
	s->cur_cmd_type = 0;
	cvp_put_inst(inst);
	return rc;
}
@@ -770,6 +772,7 @@ static int msm_cvp_session_process_hfi(
	if (!s)
		return -ECONNRESET;

	inst->cur_cmd_type = CVP_KMD_SEND_CMD_PKT;
	sq = &inst->session_queue;
	spin_lock(&sq->lock);
	if (sq->state != QUEUE_ACTIVE) {
@@ -826,10 +829,12 @@ static int msm_cvp_session_process_hfi(

	}
exit:
	inst->cur_cmd_type = 0;
	cvp_put_inst(inst);
	return rc;
}

#define CVP_FENCE_RUN	0x100
static int msm_cvp_thread_fence_run(void *data)
{
	int i, rc = 0;
@@ -851,13 +856,13 @@ static int msm_cvp_thread_fence_run(void *data)
	}

	fence_thread_data = data;
	inst = cvp_get_inst(get_cvp_core(fence_thread_data->device_id),
				(void *)fence_thread_data->inst);
	inst = fence_thread_data->inst;
	if (!inst) {
		dprintk(CVP_ERR, "%s Wrong inst %pK\n", __func__, inst);
		rc = -EINVAL;
		return rc;
	}
	inst->cur_cmd_type = CVP_FENCE_RUN;
	in_fence_pkt = (struct cvp_kmd_hfi_fence_packet *)
					&fence_thread_data->in_fence_pkt;
	in_pkt = (struct cvp_kmd_hfi_packet *)(in_fence_pkt);
@@ -1066,6 +1071,7 @@ static int msm_cvp_thread_fence_run(void *data)

exit:
	kmem_cache_free(inst->fence_data_cache, fence_thread_data);
	inst->cur_cmd_type = 0;
	cvp_put_inst(inst);
	do_exit(rc);
}
@@ -1095,12 +1101,14 @@ static int msm_cvp_session_process_hfi_fence(
	if (!s)
		return -ECONNRESET;

	fence_thread_data = kmem_cache_zalloc(inst->fence_data_cache,
	inst->cur_cmd_type = CVP_KMD_SEND_FENCE_CMD_PKT;
	fence_thread_data = kmem_cache_alloc(inst->fence_data_cache,
			GFP_KERNEL);
	if (!fence_thread_data) {
		dprintk(CVP_ERR, "%s: fence_thread_data alloc failed\n",
				__func__);
		return -ENOMEM;
		rc = -ENOMEM;
		goto exit;
	}

	in_offset = arg->buf_offset;
@@ -1139,10 +1147,17 @@ static int msm_cvp_session_process_hfi_fence(
				"thread_fence_%d", thread_num);
	thread = kthread_run(msm_cvp_thread_fence_run,
			fence_thread_data, thread_fence_name);
	if (!thread)
	if (!thread) {
		kmem_cache_free(inst->fence_data_cache, fence_thread_data);
		dprintk(CVP_ERR, "%s fail to create kthread\n", __func__);
		rc = -ECHILD;
		goto exit;
	}

	return 0;

exit:
	inst->cur_cmd_type = 0;
	cvp_put_inst(s);
	return rc;
}
@@ -1312,6 +1327,7 @@ static int msm_cvp_request_power(struct msm_cvp_inst *inst,
	if (!s)
		return -ECONNRESET;

	inst->cur_cmd_type = CVP_KMD_REQUEST_POWER;
	core = inst->core;

	mutex_lock(&core->lock);
@@ -1332,6 +1348,7 @@ static int msm_cvp_request_power(struct msm_cvp_inst *inst,
		dprintk(CVP_ERR, "Instance %pK power request out of range\n");

	mutex_unlock(&core->lock);
	inst->cur_cmd_type = 0;
	cvp_put_inst(s);

	return rc;
@@ -1357,6 +1374,7 @@ static int msm_cvp_register_buffer(struct msm_cvp_inst *inst,
	if (!s)
		return -ECONNRESET;

	inst->cur_cmd_type = CVP_KMD_REGISTER_BUFFER;
	session = (struct cvp_hal_session *)inst->session;
	if (!session) {
		dprintk(CVP_ERR, "%s: invalid session\n", __func__);
@@ -1368,6 +1386,7 @@ static int msm_cvp_register_buffer(struct msm_cvp_inst *inst,

	rc = msm_cvp_map_buf_dsp(inst, buf);
exit:
	inst->cur_cmd_type = 0;
	cvp_put_inst(s);
	return rc;
}
@@ -1391,9 +1410,11 @@ static int msm_cvp_unregister_buffer(struct msm_cvp_inst *inst,
	if (!s)
		return -ECONNRESET;

	inst->cur_cmd_type = CVP_KMD_UNREGISTER_BUFFER;
	print_client_buffer(CVP_DBG, "unregister", inst, buf);

	rc = msm_cvp_unmap_buf_dsp(inst, buf);
	inst->cur_cmd_type = 0;
	cvp_put_inst(s);
	return rc;
}
@@ -1405,9 +1426,14 @@ static int msm_cvp_session_create(struct msm_cvp_inst *inst)
	if (!inst || !inst->core)
		return -EINVAL;

	if (inst->state >= MSM_CVP_CLOSE_DONE)
		return -ECONNRESET;

	if (inst->state != MSM_CVP_CORE_INIT_DONE ||
		inst->state > MSM_CVP_OPEN_DONE) {
		dprintk(CVP_ERR, "not ready create instance %d\n", inst->state);
		dprintk(CVP_ERR,
			"%s Incorrect CVP state %d to create session\n",
			__func__, inst->state);
		return -EINVAL;
	}

@@ -1607,8 +1633,9 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg)

		rc = session_state_check_init(inst);
		if (rc) {
			dprintk(CVP_ERR, "session not ready for commands %d",
					arg->type);
			dprintk(CVP_ERR,
				"Incorrect session state %d for command %d",
				inst->state, arg->type);
			return rc;
		}
	}
+71 −23
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include "msm_cvp_debug.h"
#include "msm_cvp_clocks.h"
#include "msm_cvp.h"
#include "cvp_core_hfi.h"

#define IS_ALREADY_IN_STATE(__p, __d) (\
	(__p >= __d)\
@@ -22,6 +23,27 @@

static void handle_session_error(enum hal_command_response cmd, void *data);

static void dump_hfi_queue_info(struct iris_hfi_device *device)
{
	struct cvp_hfi_queue_header *queue;
	struct cvp_iface_q_info *qinfo;
	int i;

	dprintk(CVP_ERR, "HFI queues in order of cmd(rd, wr), msg and dbg:\n");

	/*
	 * mb() to ensure driver reads the updated header values from
	 * main memory.
	 */
	mb();
	for (i = 0; i <= CVP_IFACEQ_DBGQ_IDX; i++) {
		qinfo = &device->iface_queues[i];
		queue = (struct cvp_hfi_queue_header *)qinfo->q_hdr;
		dprintk(CVP_ERR, "queue details: %d %d\n",
				queue->qhdr_read_idx, queue->qhdr_write_idx);
	}
}

int msm_cvp_comm_get_inst_load(struct msm_cvp_inst *inst,
		enum load_calc_quirks quirks)
{
@@ -296,9 +318,6 @@ static void handle_session_release_buf_done(enum hal_command_response cmd,
	}
	mutex_unlock(&inst->persistbufs.lock);

	if (!buf_found)
		dprintk(CVP_WARN, "invalid buffer %#x from firmware\n",
				address);
	if (IS_HAL_SESSION_CMD(cmd))
		complete(&inst->completions[SESSION_MSG_INDEX(cmd)]);
	else
@@ -621,7 +640,9 @@ static void handle_sys_error(enum hal_command_response cmd, void *data)
	call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
	list_for_each_entry(inst, &core->instances, list) {
		dprintk(CVP_WARN,
			"%s: Send sys error for inst %#x\n", __func__, inst);
			"%s: sys error for inst %#x kref %x, cmd %x\n",
				__func__, inst, kref_read(&inst->kref),
				inst->cur_cmd_type);
		change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);

		spin_lock_irqsave(&inst->event_handler.lock, flags);
@@ -868,6 +889,8 @@ static int msm_comm_session_abort(struct msm_cvp_inst *inst)
	if (!rc) {
		dprintk(CVP_ERR, "%s: inst %pK session %x abort timed out\n",
				__func__, inst, hash32_ptr(inst->session));
		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
		dump_hfi_queue_info(hdev->hfi_device_data);
		msm_cvp_comm_generate_sys_error(inst);
		rc = -EBUSY;
	} else {
@@ -1036,7 +1059,7 @@ static int msm_comm_init_core(struct msm_cvp_inst *inst)
	return rc;
}

static int msm_cvp_deinit_core(struct msm_cvp_inst *inst)
int msm_cvp_deinit_core(struct msm_cvp_inst *inst)
{
	struct msm_cvp_core *core;
	struct cvp_hfi_device *hdev;
@@ -1085,12 +1108,6 @@ static int msm_cvp_deinit_core(struct msm_cvp_inst *inst)
	return 0;
}

int msm_cvp_comm_force_cleanup(struct msm_cvp_inst *inst)
{
	msm_cvp_comm_kill_session(inst);
	return msm_cvp_deinit_core(inst);
}

static int msm_comm_session_init_done(int flipped_state,
	struct msm_cvp_inst *inst)
{
@@ -1267,8 +1284,8 @@ int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state)

	flipped_state = get_flipped_state(inst->state, state);
	dprintk(CVP_DBG,
		"inst: %pK (%#x) flipped_state = %#x\n",
		inst, hash32_ptr(inst->session), flipped_state);
		"inst: %pK (%#x) flipped_state = %#x %x\n",
		inst, hash32_ptr(inst->session), flipped_state, state);
	switch (flipped_state) {
	case MSM_CVP_CORE_UNINIT_DONE:
	case MSM_CVP_CORE_INIT:
@@ -1302,12 +1319,13 @@ int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state)
	case MSM_CVP_RELEASE_RESOURCES:
		dprintk(CVP_WARN, "Deprecated state RELEASE_SOURCES\n");
	case MSM_CVP_RELEASE_RESOURCES_DONE:
		dprintk(CVP_WARN, "Deprecated state RELEASE_RESOURCES_DONE\n");
	case MSM_CVP_CLOSE:
		dprintk(CVP_INFO, "to CVP_CLOSE state\n");
		rc = msm_comm_session_close(flipped_state, inst);
		if (rc || state <= get_flipped_state(inst->state, state))
			break;
	case MSM_CVP_CLOSE_DONE:
		dprintk(CVP_INFO, "to CVP_CLOSE_DONE state\n");
		rc = wait_for_state(inst, flipped_state, MSM_CVP_CLOSE_DONE,
				HAL_SESSION_END_DONE);
		if (rc || state <= get_flipped_state(inst->state, state))
@@ -1315,7 +1333,7 @@ int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state)
		msm_cvp_comm_session_clean(inst);
	case MSM_CVP_CORE_UNINIT:
	case MSM_CVP_CORE_INVALID:
		dprintk(CVP_DBG, "Sending core uninit\n");
		dprintk(CVP_INFO, "Sending core uninit\n");
		rc = msm_cvp_deinit_core(inst);
		if (rc || state == get_flipped_state(inst->state, state))
			break;
@@ -1387,6 +1405,32 @@ void msm_cvp_ssr_handler(struct work_struct *work)
	}
	hdev = core->device;

	if (core->ssr_type == SSR_SESSION_ABORT) {
		struct msm_cvp_inst *inst = NULL, *s;

		dprintk(CVP_ERR, "Session abort triggered\n");
		list_for_each_entry(inst, &core->instances, list) {
			dprintk(CVP_WARN,
				"Session to abort: inst %#x cmd %x ref %x\n",
				inst, inst->cur_cmd_type,
				kref_read(&inst->kref));
			break;
		}

		if (inst != NULL) {
			s = cvp_get_inst_validate(inst->core, inst);
			if (!s)
				return;

			msm_cvp_comm_kill_session(inst);
			cvp_put_inst(s);
		} else {
			dprintk(CVP_WARN, "No active CVP session to abort\n");
		}

		return;
	}

	mutex_lock(&core->lock);
	if (core->state == CVP_CORE_INIT_DONE) {
		dprintk(CVP_WARN, "%s: ssr type %d\n", __func__,
@@ -1447,6 +1491,7 @@ void msm_cvp_comm_generate_sys_error(struct msm_cvp_inst *inst)
int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst)
{
	int rc = 0;
	unsigned long flags = 0;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(CVP_ERR, "%s: invalid input parameters\n", __func__);
@@ -1456,7 +1501,6 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst)
			__func__, inst);
		return 0;
	}

	dprintk(CVP_WARN, "%s: inst %pK, session %x state %d\n", __func__,
		inst, hash32_ptr(inst->session), inst->state);
	/*
@@ -1464,23 +1508,26 @@ int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst)
	 * the session send session_abort to firmware to clean up and release
	 * the session, else just kill the session inside the driver.
	 */
	if ((inst->state >= MSM_CVP_OPEN_DONE &&
			inst->state < MSM_CVP_CLOSE_DONE) ||
			inst->state == MSM_CVP_CORE_INVALID) {
	if (inst->state >= MSM_CVP_OPEN_DONE &&
			inst->state < MSM_CVP_CLOSE_DONE) {
		rc = msm_comm_session_abort(inst);
		if (rc) {
			dprintk(CVP_ERR,
				"%s: inst %pK session %x abort failed\n",
				__func__, inst, hash32_ptr(inst->session));
			change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);
		} else {
			change_cvp_inst_state(inst, MSM_CVP_CORE_UNINIT);
		}
	}

	change_cvp_inst_state(inst, MSM_CVP_CLOSE_DONE);
	msm_cvp_comm_session_clean(inst);
	if (inst->state == MSM_CVP_CORE_UNINIT) {
		spin_lock_irqsave(&inst->event_handler.lock, flags);
		inst->event_handler.event = CVP_SSR_EVENT;
		spin_unlock_irqrestore(&inst->event_handler.lock, flags);
		wake_up_all(&inst->event_handler.wq);
	}

	dprintk(CVP_WARN, "%s: inst %pK session %x handled\n", __func__,
		inst, hash32_ptr(inst->session));
	return rc;
}

@@ -1566,6 +1613,7 @@ void msm_cvp_comm_print_inst_info(struct msm_cvp_inst *inst)
		return;
	}

	dprintk(CVP_ERR, "active session cmd %d\n", inst->cur_cmd_type);
	is_secure = inst->flags & CVP_SECURE;
	dprintk(CVP_ERR,
			"---Buffer details for inst: %pK of type: %d---\n",
Loading