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

Commit 30dc40c7 authored by Praneeth Paladugu's avatar Praneeth Paladugu
Browse files

msm: vidc: Enhance debug capabilities of video driver



When Venus HW is not responding, before crashing the system,
print all the pending messages, current sessions and each
session info.

CRs-Fixed: 1059604
Change-Id: I8d39eaaa425e5e6fa97704c9bc15414f9a0f61ce
Signed-off-by: default avatarPraneeth Paladugu <ppaladug@codeaurora.org>
parent ab26d098
Loading
Loading
Loading
Loading
+120 −1
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ static void msm_comm_generate_session_error(struct msm_vidc_inst *inst);
static void msm_comm_generate_sys_error(struct msm_vidc_inst *inst);
static void handle_session_error(enum hal_command_response cmd, void *data);
static void msm_vidc_print_running_insts(struct msm_vidc_core *core);
static void msm_comm_print_debug_info(struct msm_vidc_inst *inst);

bool msm_comm_turbo_session(struct msm_vidc_inst *inst)
{
@@ -905,7 +906,7 @@ static int wait_for_sess_signal_receipt(struct msm_vidc_inst *inst,
		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
		dprintk(VIDC_ERR,
			"sess resp timeout can potentially crash the system\n");

		msm_comm_print_debug_info(inst);
		BUG_ON(inst->core->resources.debug_timeout);
		rc = -EIO;
	} else {
@@ -1601,6 +1602,7 @@ static void handle_sys_error(enum hal_command_response cmd, void *data)
	struct msm_vidc_cb_cmd_done *response = data;
	struct msm_vidc_core *core = NULL;
	struct hfi_device *hdev = NULL;
	struct msm_vidc_inst *inst = NULL;
	int rc = 0;

	subsystem_crashed("venus");
@@ -1640,6 +1642,19 @@ static void handle_sys_error(enum hal_command_response cmd, void *data)
	dprintk(VIDC_ERR,
		"SYS_ERROR can potentially crash the system\n");

	/*
	 * For SYS_ERROR, there will not be any inst pointer.
	 * Just grab one of the inst from instances list and
	 * use it.
	 */

	mutex_lock(&core->lock);
	inst = list_first_entry(&core->instances,
		struct msm_vidc_inst, list);
	mutex_unlock(&core->lock);

	msm_comm_print_debug_info(inst);

	BUG_ON(core->resources.debug_timeout);
}

@@ -2450,6 +2465,7 @@ static int msm_comm_session_abort(struct msm_vidc_inst *inst)
		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
		dprintk(VIDC_ERR,
			"ABORT timeout can potentially crash the system\n");
		msm_comm_print_debug_info(inst);

		BUG_ON(inst->core->resources.debug_timeout);
		rc = -EBUSY;
@@ -2522,6 +2538,7 @@ int msm_comm_check_core_init(struct msm_vidc_core *core)
{
	int rc = 0;
	struct hfi_device *hdev;
	struct msm_vidc_inst *inst = NULL;

	mutex_lock(&core->lock);
	if (core->state >= VIDC_CORE_INIT_DONE) {
@@ -2540,6 +2557,17 @@ int msm_comm_check_core_init(struct msm_vidc_core *core)
		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
		dprintk(VIDC_ERR,
			"SYS_INIT timeout can potentially crash the system\n");
		/*
		 * For SYS_INIT, there will not be any inst pointer.
		 * Just grab one of the inst from instances list and
		 * use it.
		 */
		inst = list_first_entry(&core->instances,
			struct msm_vidc_inst, list);

		mutex_unlock(&core->lock);
		msm_comm_print_debug_info(inst);
		mutex_lock(&core->lock);

		BUG_ON(core->resources.debug_timeout);
		rc = -EIO;
@@ -4017,6 +4045,8 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype,
		call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
		dprintk(VIDC_ERR,
			"SESS_PROP timeout can potentially crash the system\n");
		if (inst->core->resources.debug_timeout)
			msm_comm_print_debug_info(inst);

		BUG_ON(inst->core->resources.debug_timeout);
		rc = -ETIMEDOUT;
@@ -5232,3 +5262,92 @@ int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
exit:
	return rc;
}

void msm_comm_print_inst_info(struct msm_vidc_inst *inst)
{
	struct buffer_info *temp;
	struct internal_buf *buf;
	int i = 0;
	bool is_decode = false;
	enum vidc_ports port;

	if (!inst) {
		dprintk(VIDC_ERR, "%s - invalid param %p\n",
			__func__, inst);
		return;
	}

	is_decode = inst->session_type == MSM_VIDC_DECODER;
	port = is_decode ? OUTPUT_PORT : CAPTURE_PORT;
	dprintk(VIDC_ERR,
			"%s session, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n",
			is_decode ? "Decode" : "Encode", inst->fmts[port]->name,
			inst->prop.height[port], inst->prop.width[port],
			inst->prop.fps, inst->prop.bitrate,
			!inst->bit_depth ? "8" : "10");

	dprintk(VIDC_ERR,
			"---Buffer details for inst: %p of type: %d---\n",
			inst, inst->session_type);
	mutex_lock(&inst->registeredbufs.lock);
	dprintk(VIDC_ERR, "registered buffer list:\n");
	list_for_each_entry(temp, &inst->registeredbufs.list, list)
		for (i = 0; i < temp->num_planes; i++)
			dprintk(VIDC_ERR,
					"type: %d plane: %d addr: %pa size: %d\n",
					temp->type, i, &temp->device_addr[i],
					temp->size[i]);

	mutex_unlock(&inst->registeredbufs.lock);

	mutex_lock(&inst->scratchbufs.lock);
	dprintk(VIDC_ERR, "scratch buffer list:\n");
	list_for_each_entry(buf, &inst->scratchbufs.list, list)
		dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
				buf->buffer_type, &buf->handle->device_addr,
				buf->handle->size);
	mutex_unlock(&inst->scratchbufs.lock);

	mutex_lock(&inst->persistbufs.lock);
	dprintk(VIDC_ERR, "persist buffer list:\n");
	list_for_each_entry(buf, &inst->persistbufs.list, list)
		dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
				buf->buffer_type, &buf->handle->device_addr,
				buf->handle->size);
	mutex_unlock(&inst->persistbufs.lock);

	mutex_lock(&inst->outputbufs.lock);
	dprintk(VIDC_ERR, "dpb buffer list:\n");
	list_for_each_entry(buf, &inst->outputbufs.list, list)
		dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
				buf->buffer_type, &buf->handle->device_addr,
				buf->handle->size);
	mutex_unlock(&inst->outputbufs.lock);
}

static void msm_comm_print_debug_info(struct msm_vidc_inst *inst)
{
	struct msm_vidc_core *core = NULL;
	struct msm_vidc_inst *temp = NULL;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s - invalid param %p %p\n",
				__func__, inst, core);
		return;
	}
	core = inst->core;

	dprintk(VIDC_ERR, "Venus core frequency = %lu",
		msm_comm_get_clock_rate(core));
	dprintk(VIDC_ERR, "Printing instance info that caused Error\n");
	msm_comm_print_inst_info(inst);
	dprintk(VIDC_ERR, "Printing remaining instances info\n");
	mutex_lock(&core->lock);
	list_for_each_entry(temp, &core->instances, list) {
		/* inst already printed above. Hence don't repeat.*/
		if (temp == inst)
			continue;
		msm_comm_print_inst_info(temp);
	}
	mutex_unlock(&core->lock);
}
+1 −0
Original line number Diff line number Diff line
@@ -98,4 +98,5 @@ int msm_comm_ctrl_deinit(struct msm_vidc_inst *inst);
void msm_comm_cleanup_internal_buffers(struct msm_vidc_inst *inst);
int msm_vidc_comm_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a);
bool msm_comm_turbo_session(struct msm_vidc_inst *inst);
void msm_comm_print_inst_info(struct msm_vidc_inst *inst);
#endif
+1 −51
Original line number Diff line number Diff line
@@ -1238,11 +1238,6 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,
{
	struct msm_vidc_core *core = token;
	struct msm_vidc_inst *inst;
	struct buffer_info *temp;
	struct internal_buf *buf;
	int i = 0;
	bool is_decode = false;
	enum vidc_ports port;

	if (!domain || !core) {
		dprintk(VIDC_ERR, "%s - invalid param %pK %pK\n",
@@ -1257,52 +1252,7 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,

	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {
		is_decode = inst->session_type == MSM_VIDC_DECODER;
		port = is_decode ? OUTPUT_PORT : CAPTURE_PORT;
		dprintk(VIDC_ERR,
			"%s session, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n",
			is_decode ? "Decode" : "Encode", inst->fmts[port]->name,
			inst->prop.height[port], inst->prop.width[port],
			inst->prop.fps, inst->prop.bitrate,
			!inst->bit_depth ? "8" : "10");

		dprintk(VIDC_ERR,
			"---Buffer details for inst: %pK of type: %d---\n",
			inst, inst->session_type);
		mutex_lock(&inst->registeredbufs.lock);
		dprintk(VIDC_ERR, "registered buffer list:\n");
		list_for_each_entry(temp, &inst->registeredbufs.list, list)
			for (i = 0; i < temp->num_planes; i++)
				dprintk(VIDC_ERR,
					"type: %d plane: %d addr: %pa size: %d\n",
					temp->type, i, &temp->device_addr[i],
					temp->size[i]);

		mutex_unlock(&inst->registeredbufs.lock);

		mutex_lock(&inst->scratchbufs.lock);
		dprintk(VIDC_ERR, "scratch buffer list:\n");
		list_for_each_entry(buf, &inst->scratchbufs.list, list)
			dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
				buf->buffer_type, &buf->handle->device_addr,
				buf->handle->size);
		mutex_unlock(&inst->scratchbufs.lock);

		mutex_lock(&inst->persistbufs.lock);
		dprintk(VIDC_ERR, "persist buffer list:\n");
		list_for_each_entry(buf, &inst->persistbufs.list, list)
			dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
				buf->buffer_type, &buf->handle->device_addr,
				buf->handle->size);
		mutex_unlock(&inst->persistbufs.lock);

		mutex_lock(&inst->outputbufs.lock);
		dprintk(VIDC_ERR, "dpb buffer list:\n");
		list_for_each_entry(buf, &inst->outputbufs.list, list)
			dprintk(VIDC_ERR, "type: %d addr: %pa size: %zu\n",
				buf->buffer_type, &buf->handle->device_addr,
				buf->handle->size);
		mutex_unlock(&inst->outputbufs.lock);
		msm_comm_print_inst_info(inst);
	}
	core->smmu_fault_handled = true;
	mutex_unlock(&core->lock);
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#define DT_PARSE
#include <linux/of.h>
#include "msm_vidc_resources.h"
#include "msm_vidc_common.h"
void msm_vidc_free_platform_resources(
		struct msm_vidc_platform_resources *res);

+22 −5
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ static inline bool __core_in_valid_state(struct venus_hfi_device *device)
	return device->state != VENUS_STATE_DEINIT;
}

static void __dump_packet(u8 *packet)
static void __dump_packet(u8 *packet, enum vidc_msg_prio log_level)
{
	u32 c = 0, packet_size = *(u32 *)packet;
	const int row_size = 32;
@@ -132,7 +132,7 @@ static void __dump_packet(u8 *packet)
			packet_size % row_size : row_size;
		hex_dump_to_buffer(packet + c * row_size, bytes_to_read,
				row_size, 4, row, sizeof(row), false);
		dprintk(VIDC_PKT, "%s\n", row);
		dprintk(log_level, "%s\n", row);
	}
}

@@ -342,7 +342,7 @@ static int __write_queue(struct vidc_iface_q_info *qinfo, u8 *packet,

	if (msm_vidc_debug & VIDC_PKT) {
		dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo);
		__dump_packet(packet);
		__dump_packet(packet, VIDC_PKT);
	}

	packet_size_in_words = (*(u32 *)packet) >> 2;
@@ -548,7 +548,7 @@ static int __read_queue(struct vidc_iface_q_info *qinfo, u8 *packet,

	if (msm_vidc_debug & VIDC_PKT) {
		dprintk(VIDC_PKT, "%s: %pK\n", __func__, qinfo);
		__dump_packet(packet);
		__dump_packet(packet, VIDC_PKT);
	}

	return rc;
@@ -2517,7 +2517,6 @@ static int venus_hfi_session_clean(void *session)
	mutex_lock(&device->lock);

	__session_clean(sess_close);
	__flush_debug_queue(device, NULL);

	mutex_unlock(&device->lock);
	return 0;
@@ -3337,6 +3336,7 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
{
	bool local_packet = false;
	enum vidc_msg_prio log_level = VIDC_FW;
	unsigned int pending_packet_count = 0;

	if (!device) {
		dprintk(VIDC_ERR, "%s: Invalid params\n", __func__);
@@ -3361,6 +3361,23 @@ static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet)
		log_level = VIDC_ERR;
	}

	/*
	 * In FATAL situation, print all the pending messages in msg
	 * queue. This is useful for debugging. At this time, message
	 * queues may be corrupted. Hence don't trust them and just print
	 * first max_packets packets.
	 */

	if (local_packet) {
		dprintk(VIDC_ERR,
			"Printing all pending messages in message Queue\n");
		while (!__iface_msgq_read(device, packet) &&
				pending_packet_count < max_packets) {
			__dump_packet(packet, log_level);
			pending_packet_count++;
		}
	}

	while (!__iface_dbgq_read(device, packet)) {
		struct hfi_msg_sys_coverage_packet *pkt =
			(struct hfi_msg_sys_coverage_packet *) packet;