qcacmn: Hex dump generation for WMI events and commands

This records all the WMI events and commands, for all
PDEVs. Set WMI_EXT_DBG flag to enable this feature. Refer
Original Change-Id: I18e46f683e35912cad717ca3b9cc3d1885315362

Change-Id: I4c9bdfe6fdd195656ca0c01ca400eba595be24a3
CRs-Fixed: 2762266
This commit is contained in:
Jhalak Naik
2020-09-03 12:25:39 +05:30
committed by snandini
parent 1e325d2b3a
commit 41e8d82db9
3 changed files with 302 additions and 296 deletions

View File

@@ -340,271 +340,6 @@ uint32_t wmi_diag_log_max_entry = WMI_DIAG_RX_EVENT_DEBUG_MAX_ENTRY;
uint32_t wmi_record_max_length = WMI_DEBUG_ENTRY_MAX_LENGTH;
uint32_t wmi_display_size = 100;
#ifdef WMI_EXT_DBG
/**
* wmi_ext_dbg_msg_enqueue() - enqueue wmi message
*
* @wmi_handle: wmi handler
*
* Return: size of wmi message queue after enqueue
*/
static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
struct wmi_ext_dbg_msg *msg)
{
uint32_t list_size;
qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
&msg->node, &list_size);
qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
return list_size;
}
/**
* wmi_ext_dbg_msg_dequeue() - dequeue wmi message
*
* @wmi_handle: wmi handler
*
* Return: wmi msg on success else NULL
*/
static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
*wmi_handle)
{
qdf_list_node_t *list_node = NULL;
qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
if (!list_node)
return NULL;
return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
}
/**
* wmi_ext_dbg_msg_record() - record wmi messages
*
* @wmi_handle: wmi handler
* @buf: wmi message buffer
* @len: wmi message length
* @type: wmi message type
*
* Return: QDF_STATUS_SUCCESS on successful recording else failure.
*/
static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
uint8_t *buf, uint32_t len,
enum WMI_MSG_TYPE type)
{
struct wmi_ext_dbg_msg *msg;
uint32_t list_size;
msg = wmi_ext_dbg_msg_get(len);
if (!msg)
return QDF_STATUS_E_NOMEM;
msg->len = len;
msg->type = type;
qdf_mem_copy(msg->buf, buf, len);
msg->ts = qdf_get_log_timestamp();
list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
wmi_ext_dbg_msg_put(msg);
}
return QDF_STATUS_SUCCESS;
}
/**
* wmi_ext_dbg_msg_cmd_record() - record wmi command messages
*
* @wmi_handle: wmi handler
* @buf: wmi command buffer
* @len: wmi command message length
*
* Return: QDF_STATUS_SUCCESS on successful recording else failure.
*/
static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
uint8_t *buf, uint32_t len)
{
return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
WMI_MSG_TYPE_CMD);
}
/**
* wmi_ext_dbg_msg_event_record() - record wmi event messages
*
* @wmi_handle: wmi handler
* @buf: wmi event buffer
* @len: wmi event message length
*
* Return: QDF_STATUS_SUCCESS on successful recording else failure.
*/
static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
uint8_t *buf, uint32_t len)
{
uint32_t id;
id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
if (id != wmi_handle->wmi_events[wmi_diag_event_id])
return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
WMI_MSG_TYPE_EVENT);
return QDF_STATUS_SUCCESS;
}
/**
* wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
*
* @wmi_handle: wmi handler
*
* Return: none
*/
static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
{
qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
wmi_handle->wmi_ext_dbg_msg_queue_size);
qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
}
/**
* wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
*
* @wmi_handle: wmi handler
*
* Return: none
*/
static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
{
qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
}
/**
* wmi_ext_dbg_msg_show() - debugfs function to display whole content of
* wmi command/event messages including headers.
*
* @file: qdf debugfs file handler
* @arg: pointer to wmi handler
*
* Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
* else QDF_STATUS_E_AGAIN if more data to show.
*/
static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
{
struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
struct wmi_ext_dbg_msg *msg;
uint64_t secs, usecs;
msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
if (!msg)
return QDF_STATUS_SUCCESS;
qdf_debugfs_printf(file, "%s: 0x%x\n",
msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
"EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
COMMANDID));
qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
qdf_debugfs_printf(file, "Length:%d\n", msg->len);
qdf_debugfs_hexdump(file, msg->buf, msg->len,
WMI_EXT_DBG_DUMP_ROW_SIZE,
WMI_EXT_DBG_DUMP_GROUP_SIZE);
qdf_debugfs_printf(file, "\n");
if (qdf_debugfs_overflow(file)) {
qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
&msg->node);
qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
} else {
wmi_ext_dbg_msg_put(msg);
}
return QDF_STATUS_E_AGAIN;
}
/**
* wmi_ext_dbg_msg_write() - debugfs write not supported
*
* @priv: private data
* @buf: received data buffer
* @len: length of received buffer
*
* Return: QDF_STATUS_E_NOSUPPORT.
*/
static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
qdf_size_t len)
{
return QDF_STATUS_E_NOSUPPORT;
}
static struct qdf_debugfs_fops wmi_ext_dbgfs_ops = {
.show = wmi_ext_dbg_msg_show,
.write = wmi_ext_dbg_msg_write,
.priv = NULL,
};
/**
* wmi_ext_debugfs_init() - init debugfs items for extended wmi dump.
*
* @wmi_handle: wmi handler
*
* Return: QDF_STATUS_SUCCESS if debugfs is initialized else
* QDF_STATUS_E_FAILURE
*/
static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle)
{
qdf_dentry_t dentry;
dentry = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
if (!dentry) {
WMI_LOGE("error while creating extended wmi debugfs dir");
return QDF_STATUS_E_FAILURE;
}
wmi_ext_dbgfs_ops.priv = wmi_handle;
if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
dentry, &wmi_ext_dbgfs_ops)) {
qdf_debugfs_remove_dir(dentry);
WMI_LOGE("error while creating extended wmi debugfs file");
return QDF_STATUS_E_FAILURE;
}
wmi_handle->wmi_ext_dbg_dentry = dentry;
wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
wmi_ext_dbg_msg_queue_init(wmi_handle);
return QDF_STATUS_SUCCESS;
}
/**
* wmi_ext_debugfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
*
* @wmi_handle: wmi handler
*
* Return: QDF_STATUS_SUCCESS if cleanup is successful
*/
static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
{
struct wmi_ext_dbg_msg *msg;
while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
wmi_ext_dbg_msg_put(msg);
wmi_ext_dbg_msg_queue_deinit(wmi_handle);
qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
return QDF_STATUS_SUCCESS;
}
#endif /*WMI_EXT_DBG */
/**
* wmi_log_init() - Initialize WMI event logging
* @wmi_handle: WMI handle.
@@ -1407,7 +1142,6 @@ struct wmi_debugfs_info wmi_debugfs_infos[NUM_DEBUG_INFOS] = {
#endif
};
/**
* wmi_debugfs_create() - Create debug_fs entry for wmi logging.
*
@@ -1540,6 +1274,299 @@ static inline void wmi_log_buffer_free(struct wmi_unified *wmi_handle) { }
#endif /*WMI_INTERFACE_EVENT_LOGGING */
qdf_export_symbol(wmi_mgmt_cmd_record);
#ifdef WMI_EXT_DBG
/**
* wmi_ext_dbg_msg_enqueue() - enqueue wmi message
* @wmi_handle: wmi handler
*
* Return: size of wmi message queue after enqueue
*/
static uint32_t wmi_ext_dbg_msg_enqueue(struct wmi_unified *wmi_handle,
struct wmi_ext_dbg_msg *msg)
{
uint32_t list_size;
qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
qdf_list_insert_back_size(&wmi_handle->wmi_ext_dbg_msg_queue,
&msg->node, &list_size);
qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
return list_size;
}
/**
* wmi_ext_dbg_msg_dequeue() - dequeue wmi message
* @wmi_handle: wmi handler
*
* Return: wmi msg on success else NULL
*/
static struct wmi_ext_dbg_msg *wmi_ext_dbg_msg_dequeue(struct wmi_unified
*wmi_handle)
{
qdf_list_node_t *list_node = NULL;
qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
qdf_list_remove_front(&wmi_handle->wmi_ext_dbg_msg_queue, &list_node);
qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
if (!list_node)
return NULL;
return qdf_container_of(list_node, struct wmi_ext_dbg_msg, node);
}
/**
* wmi_ext_dbg_msg_record() - record wmi messages
* @wmi_handle: wmi handler
* @buf: wmi message buffer
* @len: wmi message length
* @type: wmi message type
*
* Return: QDF_STATUS_SUCCESS on successful recording else failure.
*/
static QDF_STATUS wmi_ext_dbg_msg_record(struct wmi_unified *wmi_handle,
uint8_t *buf, uint32_t len,
enum WMI_MSG_TYPE type)
{
struct wmi_ext_dbg_msg *msg;
uint32_t list_size;
msg = wmi_ext_dbg_msg_get(len);
if (!msg)
return QDF_STATUS_E_NOMEM;
msg->len = len;
msg->type = type;
qdf_mem_copy(msg->buf, buf, len);
msg->ts = qdf_get_log_timestamp();
list_size = wmi_ext_dbg_msg_enqueue(wmi_handle, msg);
if (list_size >= wmi_handle->wmi_ext_dbg_msg_queue_size) {
msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
wmi_ext_dbg_msg_put(msg);
}
return QDF_STATUS_SUCCESS;
}
/**
* wmi_ext_dbg_msg_cmd_record() - record wmi command messages
* @wmi_handle: wmi handler
* @buf: wmi command buffer
* @len: wmi command message length
*
* Return: QDF_STATUS_SUCCESS on successful recording else failure.
*/
static QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified *wmi_handle,
uint8_t *buf, uint32_t len)
{
return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
WMI_MSG_TYPE_CMD);
}
/**
* wmi_ext_dbg_msg_event_record() - record wmi event messages
* @wmi_handle: wmi handler
* @buf: wmi event buffer
* @len: wmi event message length
*
* Return: QDF_STATUS_SUCCESS on successful recording else failure.
*/
static QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified *wmi_handle,
uint8_t *buf, uint32_t len)
{
uint32_t id;
id = WMI_GET_FIELD(buf, WMI_CMD_HDR, COMMANDID);
if (id != wmi_handle->wmi_events[wmi_diag_event_id])
return wmi_ext_dbg_msg_record(wmi_handle, buf, len,
WMI_MSG_TYPE_EVENT);
return QDF_STATUS_SUCCESS;
}
/**
* wmi_ext_dbg_msg_queue_init() - create debugfs queue and associated lock
* @wmi_handle: wmi handler
*
* Return: none
*/
static void wmi_ext_dbg_msg_queue_init(struct wmi_unified *wmi_handle)
{
qdf_list_create(&wmi_handle->wmi_ext_dbg_msg_queue,
wmi_handle->wmi_ext_dbg_msg_queue_size);
qdf_spinlock_create(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
}
/**
* wmi_ext_dbg_msg_queue_deinit() - destroy debugfs queue and associated lock
* @wmi_handle: wmi handler
*
* Return: none
*/
static void wmi_ext_dbg_msg_queue_deinit(struct wmi_unified *wmi_handle)
{
qdf_list_destroy(&wmi_handle->wmi_ext_dbg_msg_queue);
qdf_spinlock_destroy(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
}
/**
* wmi_ext_dbg_msg_show() - debugfs function to display whole content of
* wmi command/event messages including headers.
* @file: qdf debugfs file handler
* @arg: pointer to wmi handler
*
* Return: QDF_STATUS_SUCCESS if all the messages are shown successfully,
* else QDF_STATUS_E_AGAIN if more data to show.
*/
static QDF_STATUS wmi_ext_dbg_msg_show(qdf_debugfs_file_t file, void *arg)
{
struct wmi_unified *wmi_handle = (struct wmi_unified *)arg;
struct wmi_ext_dbg_msg *msg;
uint64_t secs, usecs;
msg = wmi_ext_dbg_msg_dequeue(wmi_handle);
if (!msg)
return QDF_STATUS_SUCCESS;
qdf_debugfs_printf(file, "%s: 0x%x\n",
msg->type == WMI_MSG_TYPE_CMD ? "COMMAND" :
"EVENT", WMI_GET_FIELD(msg->buf, WMI_CMD_HDR,
COMMANDID));
qdf_log_timestamp_to_secs(msg->ts, &secs, &usecs);
qdf_debugfs_printf(file, "Time: %llu.%llu\n", secs, usecs);
qdf_debugfs_printf(file, "Length:%d\n", msg->len);
qdf_debugfs_hexdump(file, msg->buf, msg->len,
WMI_EXT_DBG_DUMP_ROW_SIZE,
WMI_EXT_DBG_DUMP_GROUP_SIZE);
qdf_debugfs_printf(file, "\n");
if (qdf_debugfs_overflow(file)) {
qdf_spinlock_acquire(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
qdf_list_insert_front(&wmi_handle->wmi_ext_dbg_msg_queue,
&msg->node);
qdf_spinlock_release(&wmi_handle->wmi_ext_dbg_msg_queue_lock);
} else {
wmi_ext_dbg_msg_put(msg);
}
return QDF_STATUS_E_AGAIN;
}
/**
* wmi_ext_dbg_msg_write() - debugfs write not supported
* @priv: private data
* @buf: received data buffer
* @len: length of received buffer
*
* Return: QDF_STATUS_E_NOSUPPORT.
*/
static QDF_STATUS wmi_ext_dbg_msg_write(void *priv, const char *buf,
qdf_size_t len)
{
return QDF_STATUS_E_NOSUPPORT;
}
static struct qdf_debugfs_fops wmi_ext_dbgfs_ops[WMI_MAX_RADIOS];
/**
* wmi_ext_debugfs_init() - init debugfs items for extended wmi dump.
* @wmi_handle: wmi handler
* @pdev_idx: pdev index
*
* Return: QDF_STATUS_SUCCESS if debugfs is initialized else
* QDF_STATUS_E_FAILURE
*/
static QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle,
uint32_t pdev_idx)
{
qdf_dentry_t dentry;
char buf[32];
/* To maintain backward compatibility, naming convention for PDEV 0
* dentry is kept same as before. For more than 1 PDEV, dentry
* names will be appended with PDEVx.
*/
if (wmi_handle->soc->soc_idx == 0 && pdev_idx == 0) {
dentry = qdf_debugfs_create_dir(WMI_EXT_DBG_DIR, NULL);
} else {
snprintf(buf, sizeof(buf), "WMI_EXT_DBG_SOC%u_PDEV%u",
wmi_handle->soc->soc_idx, pdev_idx);
dentry = qdf_debugfs_create_dir(buf, NULL);
}
if (!dentry) {
WMI_LOGE("error while creating extended wmi debugfs dir");
return QDF_STATUS_E_FAILURE;
}
wmi_ext_dbgfs_ops[pdev_idx].show = wmi_ext_dbg_msg_show;
wmi_ext_dbgfs_ops[pdev_idx].write = wmi_ext_dbg_msg_write;
wmi_ext_dbgfs_ops[pdev_idx].priv = wmi_handle;
if (!qdf_debugfs_create_file(WMI_EXT_DBG_FILE, WMI_EXT_DBG_FILE_PERM,
dentry, &wmi_ext_dbgfs_ops[pdev_idx])) {
qdf_debugfs_remove_dir(dentry);
WMI_LOGE("error while creating extended wmi debugfs file");
return QDF_STATUS_E_FAILURE;
}
wmi_handle->wmi_ext_dbg_dentry = dentry;
wmi_handle->wmi_ext_dbg_msg_queue_size = WMI_EXT_DBG_QUEUE_SIZE;
wmi_ext_dbg_msg_queue_init(wmi_handle);
return QDF_STATUS_SUCCESS;
}
/**
* wmi_ext_debugfs_deinit() - cleanup/deinit debugfs items of extended wmi dump.
* @wmi_handle: wmi handler
*
* Return: QDF_STATUS_SUCCESS if cleanup is successful
*/
static QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
{
struct wmi_ext_dbg_msg *msg;
while ((msg = wmi_ext_dbg_msg_dequeue(wmi_handle)))
wmi_ext_dbg_msg_put(msg);
wmi_ext_dbg_msg_queue_deinit(wmi_handle);
qdf_debugfs_remove_dir_recursive(wmi_handle->wmi_ext_dbg_dentry);
return QDF_STATUS_SUCCESS;
}
#else
static inline QDF_STATUS wmi_ext_dbg_msg_cmd_record(struct wmi_unified
*wmi_handle,
uint8_t *buf, uint32_t len)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS wmi_ext_dbg_msg_event_record(struct wmi_unified
*wmi_handle,
uint8_t *buf, uint32_t len)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS wmi_ext_dbgfs_init(struct wmi_unified *wmi_handle,
uint32_t pdev_idx)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS wmi_ext_dbgfs_deinit(struct wmi_unified *wmi_handle)
{
return QDF_STATUS_SUCCESS;
}
#endif /*WMI_EXT_DBG */
int wmi_get_host_credits(wmi_unified_t wmi_handle);
/* WMI buffer APIs */
@@ -2754,6 +2781,9 @@ void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx)
wmi_handle->wmi_max_cmds = soc->wmi_max_cmds;
wmi_interface_sequence_init(wmi_handle);
if (wmi_ext_dbgfs_init(wmi_handle, pdev_idx) !=
QDF_STATUS_SUCCESS)
WMI_LOGE("failed to initialize wmi extended debugfs");
soc->wmi_pdev[pdev_idx] = wmi_handle;
} else
@@ -2902,7 +2932,7 @@ void *wmi_unified_attach(void *scn_handle,
qdf_spinlock_create(&soc->ctx_lock);
soc->ops = wmi_handle->ops;
soc->wmi_pdev[0] = wmi_handle;
if (wmi_ext_dbgfs_init(wmi_handle) != QDF_STATUS_SUCCESS)
if (wmi_ext_dbgfs_init(wmi_handle, 0) != QDF_STATUS_SUCCESS)
WMI_LOGE("failed to initialize wmi extended debugfs");
wmi_wbuff_register(wmi_handle);
@@ -2935,8 +2965,6 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle)
wmi_wbuff_deregister(wmi_handle);
wmi_ext_dbgfs_deinit(wmi_handle);
soc = wmi_handle->soc;
for (i = 0; i < WMI_MAX_RADIOS; i++) {
if (soc->wmi_pdev[i]) {
@@ -2963,6 +2991,7 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle)
qdf_spinlock_destroy(&soc->wmi_pdev[i]->eventq_lock);
wmi_interface_sequence_deinit(soc->wmi_pdev[i]);
wmi_ext_dbgfs_deinit(soc->wmi_pdev[i]);
qdf_mem_free(soc->wmi_pdev[i]);
}