qcacmn: WMI command/event Extended dump using qdf_debugfs APIs

Currently only 16 bytes of wmi command/event messages are logged
excluding wmi header information.

By enabling WMI_EXT_DBG whole command/event messages can be dumped
using qdf debugfs apis. This will help if it is needed to
collect whole command/event messages information.

Change-Id: I72dff1279b1145b8d2ee415db97656f457c0136f
CRs-Fixed: 2309286
Bu işleme şunda yer alıyor:
Venkat Karthik Kantamneni
2018-05-21 19:13:02 +05:30
işlemeyi yapan: nshrivas
ebeveyn e881c7c092
işleme bc8d329295

Dosyayı Görüntüle

@@ -24,6 +24,9 @@
#include "wmi_unified_priv.h"
#include "wmi_unified_api.h"
#include "qdf_module.h"
#ifdef WMI_EXT_DBG
#include "qdf_list.h"
#endif
#ifndef WMI_NON_TLV_SUPPORT
#include "wmi_tlv_helper.h"
@@ -31,6 +34,271 @@
#include <linux/debugfs.h>
#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_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) {
qdf_print("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);
qdf_print("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 */
/* This check for CONFIG_WIN temporary added due to redeclaration compilation
error in MCL. Error is caused due to inclusion of wmi.h in wmi_unified_api.h
which gets included here through ol_if_athvar.h. Eventually it is expected that
@@ -1381,7 +1649,8 @@ QDF_STATUS wmi_unified_cmd_send_fl(wmi_unified_t wmi_handle, wmi_buf_t buf,
#ifdef CONFIG_MCL
wmi_log_cmd_id(cmd_id, htc_tag);
#endif
wmi_ext_dbg_msg_cmd_record(wmi_handle,
qdf_nbuf_data(buf), qdf_nbuf_len(buf));
#ifdef WMI_INTERFACE_EVENT_LOGGING
if (wmi_handle->log_info.wmi_logging_enable) {
qdf_spin_lock_bh(&wmi_handle->log_info.wmi_record_lock);
@@ -1796,6 +2065,9 @@ void __wmi_control_rx(struct wmi_unified *wmi_handle, wmi_buf_t evt_buf)
id = WMI_GET_FIELD(qdf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
wmi_ext_dbg_msg_event_record(wmi_handle, qdf_nbuf_data(evt_buf),
qdf_nbuf_len(evt_buf));
if (qdf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
goto end;
@@ -2175,6 +2447,8 @@ void *wmi_unified_attach(void *scn_handle,
soc->ops = wmi_handle->ops;
soc->wmi_pdev[0] = wmi_handle;
if (wmi_ext_dbgfs_init(wmi_handle) != QDF_STATUS_SUCCESS)
qdf_print("failed to initialize wmi extended debugfs");
return wmi_handle;
@@ -2198,6 +2472,7 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle)
struct wmi_soc *soc;
uint8_t i;
wmi_ext_dbgfs_deinit(wmi_handle);
soc = wmi_handle->soc;
for (i = 0; i < WMI_MAX_RADIOS; i++) {
if (soc->wmi_pdev[i]) {