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:
Praneeth Paladugu 2016-08-22 23:40:57 -07:00
parent ab26d09879
commit 30dc40c787
5 changed files with 145 additions and 57 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;