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: Praneeth Paladugu <ppaladug@codeaurora.org>
This commit is contained in:
parent
ab26d09879
commit
30dc40c787
5 changed files with 145 additions and 57 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue