ファイル
android_kernel_samsung_sm86…/dp/wifi3.0/dp_htt_logger.c
Ankit Kumar e2b621246b qca-wifi: Change event dump log size
Changing event dump size to 25 to make it same for all
events as qdf has limitation on event size.
If size is more than 25 then event of type command doesn't
gets printed.

Change-Id: Iaf2d4c52242b99194f7405d7d69a4566db71ff01
CRs-Fixed: 2510317
2019-08-16 14:40:00 +05:30

1095 行
33 KiB
C

/*
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include "qdf_lock.h"
#include "qdf_debugfs.h"
#include "qdf_module.h"
#include "qdf_list.h"
#include "dp_htt_logger.h"
#define HTT_DBG_FILE_PERM (QDF_FILE_USR_READ | QDF_FILE_USR_WRITE | \
QDF_FILE_GRP_READ | \
QDF_FILE_OTH_READ)
/**
* HTT_DISPLAY_SIZE : Supported Number of command/event/wbm_event to be
* read at one shot through wdf debugfs framework
*/
#define HTT_DISPLAY_SIZE 25
/**
* Used for stop_seq
* Bit 0: htt_command_log
* Bit 1: htt_event_log
* Bit 2: htt_wbm_event_log
* Bit 3: htt_log_size
* Bit 4: htt_enable
* Bit 5: htt_cmd_disable_list
* Bit 6: htt_event_disable_list
* Bit 7: htt_wbm_event_disable_list
* Bit 8-15: Reserved
*/
#define HTT_COMMAND_LOG_BP 0
#define HTT_EVENT_LOG_BP 1
#define HTT_WBM_EVENT_LOG_BP 2
#define HTT_LOG_SIZE_BP 3
#define HTT_ENABLE_BP 4
#define HTT_CMD_DISABLE_LIST_BP 5
#define HTT_EVENT_DISABLE_LIST 6
#define HTT_WBM_EVENT_DISABLE_LIST 7
/**
* Host messages which needs to be enabled by default
*
* Note: Below macro definition is cloned from
* enum htt_t2h_msg_type fw_hdr/fw/htt.h and any
* change in enum htt_t2h_msg_type for below field
* will need a change here as well.
*/
#define HTT_T2H_MSG_TYPE_PEER_MAP_C 0x3
#define HTT_T2H_MSG_TYPE_PEER_UNMAP_C 0x4
#define HTT_T2H_MSG_TYPE_RX_ADDBA_C 0x5
#define HTT_T2H_MSG_TYPE_RX_DELBA_C 0x6
#define HTT_T2H_MSG_TYPE_PEER_MAP_V2_C 0x1e
#define HTT_T2H_MSG_TYPE_PEER_UNMAP_V2_C 0x1f
/**
* disable_all_command(): Disable all command
* disable_all_event(): Disable all event
* enable_event(): Enable specific event
*/
#define disable_all_command(htt_logger_handle) \
htt_logger_handle->log_info.htt_cmd_disable_list = 0xFFFFFFFFFFFFFFFF
#define disable_all_event(htt_logger_handle)\
htt_logger_handle->log_info.htt_event_disable_list = 0xFFFFFFFFFFFFFFFF
#define disable_wbm_success_status(htt_logger_handle) \
htt_logger_handle->log_info.htt_wbm_event_disable_list = 0x1
#define enable_htt_logging(htt_logger_handle) \
htt_logger_handle->log_info.htt_logging_enable = 1
#define enable_event(htt_logger_handle, eventid) \
do { \
htt_disable_mask = ~(0x1 << eventid); \
htt_logger_handle->log_info.htt_event_disable_list &= \
htt_disable_mask; \
} while (0)
/**
* log_buf_init() - Initialize htt buffer
*/
static inline void log_buf_init(struct htt_log_buf_t *buf)
{
buf->length = 0;
buf->buf_tail_idx = 0;
buf->size = HTT_EVENT_DEBUG_MAX_ENTRY;
}
/**
* htt_command_record() - Record Command
* @ h - htt logger handle
* @ msg_type - Command Id
* @ msg_data - Data to be logged
*/
int htt_command_record(struct htt_logger *h, uint8_t msg_type,
uint8_t *msg_data)
{
struct htt_command_debug *buf = NULL;
uint32_t *p_buf_tail_idx = NULL;
uint8_t tdata[HTT_COMMAND_DEBUG_ENTRY_MAX_LENGTH];
struct htt_log_buf_t *cmd_log_buf;
/* return 0 if:
* 1. Initialization failed.
* 2. htt_logging_enable is 0 -> can get disable from file ops
* 3. This specific msg_type is disabled
*/
if (!h)
return 0;
cmd_log_buf = &h->log_info.htt_command_log_buf_info;
if ((0 == h->log_info.htt_logging_enable) ||
((1 << msg_type) & h->log_info.htt_cmd_disable_list))
return 0;
qdf_spin_lock(&cmd_log_buf->record_lock);
if (!msg_data) {
/* if msg_data is NULL then fill 0xFF in data field */
qdf_mem_set(tdata, HTT_COMMAND_DEBUG_ENTRY_MAX_LENGTH, 0xFF);
msg_data = tdata;
}
p_buf_tail_idx = &h->log_info.htt_command_log_buf_info.buf_tail_idx;
/* rewind pointer index if buffer became full */
if (HTT_EVENT_DEBUG_MAX_ENTRY <= *p_buf_tail_idx)
*p_buf_tail_idx = 0;
buf = h->log_info.htt_command_log_buf_info.buf;
buf[*p_buf_tail_idx].command = msg_type;
qdf_mem_copy(buf[*p_buf_tail_idx].data, msg_data,
HTT_COMMAND_DEBUG_ENTRY_MAX_LENGTH);
buf[*p_buf_tail_idx].time = qdf_get_log_timestamp();
buf[*p_buf_tail_idx].cpu_id = smp_processor_id();
(*p_buf_tail_idx)++;
h->log_info.htt_command_log_buf_info.length++;
qdf_spin_unlock(&cmd_log_buf->record_lock);
return 0;
}
/**
* htt_event_record() - Record Event
* @ h - htt logger handle
* @ msg_type - Event Id
* @ msg_data - Data to be logged
*/
int htt_event_record(struct htt_logger *h, uint8_t msg_type, uint8_t *msg_data)
{
struct htt_event_debug *buf = NULL;
uint32_t *p_buf_tail_idx = NULL;
uint8_t tdata[HTT_EVENT_DEBUG_ENTRY_MAX_LENGTH];
struct htt_log_buf_t *event_log_buf;
/* return 0 if:
* 1. Initialization failed.
* 2. htt_logging_enable is 0 -> can get disable from file ops
* 3. This specific msg_type is disabled
*/
if (!h)
return 0;
event_log_buf = &h->log_info.htt_event_log_buf_info;
if ((0 == h->log_info.htt_logging_enable) ||
((1 << msg_type) & h->log_info.htt_event_disable_list))
return 0;
qdf_spin_lock(&event_log_buf->record_lock);
if (!msg_data) {
/* if msg_data is NULL then fill 0xFF in data field */
qdf_mem_set(tdata, HTT_EVENT_DEBUG_ENTRY_MAX_LENGTH, 0xFF);
msg_data = tdata;
}
p_buf_tail_idx = &h->log_info.htt_event_log_buf_info.buf_tail_idx;
/* rewind pointer index if buffer became full */
if (HTT_EVENT_DEBUG_MAX_ENTRY <= *p_buf_tail_idx)
*p_buf_tail_idx = 0;
buf = h->log_info.htt_event_log_buf_info.buf;
buf[*p_buf_tail_idx].event = msg_type;
qdf_mem_copy(buf[*p_buf_tail_idx].data, msg_data,
HTT_EVENT_DEBUG_ENTRY_MAX_LENGTH);
buf[*p_buf_tail_idx].time = qdf_get_log_timestamp();
buf[*p_buf_tail_idx].cpu_id = smp_processor_id();
(*p_buf_tail_idx)++;
h->log_info.htt_event_log_buf_info.length++;
qdf_spin_unlock(&event_log_buf->record_lock);
return 0;
}
/**
* htt_wbm_event_recored() - Record HTT wbm event
*
* @ h - Pointer for HTT tracer
* @ tx_status - Status flag
* @ msg_data - Event data
*/
int htt_wbm_event_record(struct htt_logger *h, uint8_t tx_status,
uint8_t *msg_data)
{
uint32_t *p_buf_tail_idx = NULL;
struct htt_wbm_event_debug *buf = NULL;
uint8_t tdata[HTT_WBM_EVENT_DEBUG_ENTRY_MAX_LENGTH];
struct htt_log_buf_t *wbm_event_log_buf;
/* return 0 if:
* 1. Initialization failed.
* 2. htt_logging_enable is 0 -> can get disable from file ops
* 3. This specific tx_status is disabled can be used to disable
* tx_Status when tx_status is successful.
*/
if (!h)
return 0;
wbm_event_log_buf = &h->log_info.htt_wbm_event_log_buf_info;
if ((0 == h->log_info.htt_logging_enable) ||
((1 << tx_status) & h->log_info.htt_wbm_event_disable_list))
return 0;
qdf_spin_lock(&wbm_event_log_buf->record_lock);
if (!msg_data) {
/* if msg_data is NULL then fill 0xFF in data field */
qdf_mem_set(tdata, HTT_WBM_EVENT_DEBUG_ENTRY_MAX_LENGTH, 0xFF);
msg_data = tdata;
}
p_buf_tail_idx = &h->log_info.htt_wbm_event_log_buf_info.buf_tail_idx;
if (HTT_EVENT_DEBUG_MAX_ENTRY <= *p_buf_tail_idx)
*p_buf_tail_idx = 0;
buf = h->log_info.htt_wbm_event_log_buf_info.buf;
buf[*p_buf_tail_idx].tx_status = tx_status;
qdf_mem_copy(buf[*p_buf_tail_idx].data, msg_data,
HTT_WBM_EVENT_DEBUG_ENTRY_MAX_LENGTH);
buf[*p_buf_tail_idx].time = qdf_get_log_timestamp();
buf[*p_buf_tail_idx].cpu_id = smp_processor_id();
(*p_buf_tail_idx)++;
h->log_info.htt_wbm_event_log_buf_info.length++;
qdf_spin_unlock(&wbm_event_log_buf->record_lock);
return 0;
}
/* debugfs routines */
/**
* debug_htt_command_log_show() - debugfs functions to display content of
* command and event buffers. Macro uses max buffer length to display
* buffer when it is wraparound.
*
* @m: qdf_debugfs handler to access htt_logger_handle
* @arg: Private data htt_logger_hand here
*
* Return: Status
*/
static QDF_STATUS debug_htt_command_log_show(qdf_debugfs_file_t file, void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
struct htt_log_buf_t *htt_log = NULL;
int pos, nread, i;
uint64_t secs, usecs;
htt_log = &htt_logger_handle->log_info.htt_command_log_buf_info;
/* If message already read, return and reset this bit*/
/* Bit set to 1 : indicates it is read
* Bit set to 0 : indicates 1st time read
*/
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_COMMAND_LOG_BP))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_COMMAND_LOG_BP));
return QDF_STATUS_SUCCESS;
}
qdf_spin_lock(&htt_logger_handle->log_info.htt_record_lock);
if (!htt_log->length) {
qdf_spin_unlock(&htt_logger_handle->log_info.htt_record_lock);
qdf_debugfs_printf(file,
"no elements to read from ring buffer!\n");
/* setting bit sothat in next come we will return in start */
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_COMMAND_LOG_BP);
return QDF_STATUS_SUCCESS;
}
if (htt_log->length <= HTT_DISPLAY_SIZE)
nread = htt_log->length;
else
nread = HTT_DISPLAY_SIZE;
if (htt_log->buf_tail_idx == 0)
pos = HTT_DISPLAY_SIZE - 1;
else
pos = htt_log->buf_tail_idx - 1;
qdf_debugfs_printf(file, "Length = %d\n", htt_log->length);
qdf_spin_unlock(&htt_logger_handle->log_info.htt_record_lock);
while (nread--) {
struct htt_command_debug *htt_record;
htt_record = (struct htt_command_debug *)
&(((struct htt_command_debug *)htt_log->buf)[pos]);
qdf_debugfs_printf(file, "CMD ID = %x\n",
htt_record->command);
qdf_debugfs_printf(file, "DATA[0-%d]:",
HTT_COMMAND_DEBUG_ENTRY_MAX_LENGTH - 1);
for (i = 0; i < HTT_COMMAND_DEBUG_ENTRY_MAX_LENGTH; i++)
qdf_debugfs_printf(file, "%x ", htt_record->data[i]);
qdf_log_timestamp_to_secs(htt_record->time, &secs, &usecs);
qdf_debugfs_printf(file, "\nCPU ID = %d", htt_record->cpu_id);
qdf_debugfs_printf(file, "\nCMD TIME = [%llu.%06llu]\n",
secs, usecs);
if (pos == 0)
pos = HTT_DISPLAY_SIZE - 1;
else
pos--;
}
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_COMMAND_LOG_BP);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS debug_htt_event_log_show(qdf_debugfs_file_t file, void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
struct htt_log_buf_t *htt_log = NULL;
int pos, nread, i;
uint64_t secs, usecs;
htt_log = &htt_logger_handle->log_info.htt_event_log_buf_info;
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_EVENT_LOG_BP))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_EVENT_LOG_BP));
return QDF_STATUS_SUCCESS;
}
qdf_spin_lock(&htt_logger_handle->log_info.htt_record_lock);
if (!htt_log->length) {
qdf_spin_unlock(&htt_logger_handle->log_info.htt_record_lock);
qdf_debugfs_printf(file,
"no elements to read from ring buffer!\n");
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_EVENT_LOG_BP);
return QDF_STATUS_SUCCESS;
}
if (htt_log->length <= HTT_DISPLAY_SIZE)
nread = htt_log->length;
else
nread = HTT_DISPLAY_SIZE;
if (htt_log->buf_tail_idx == 0)
pos = HTT_DISPLAY_SIZE - 1;
else
pos = htt_log->buf_tail_idx - 1;
qdf_debugfs_printf(file, "Length = %d\n", htt_log->length);
qdf_spin_unlock(&htt_logger_handle->log_info.htt_record_lock);
while (nread--) {
struct htt_event_debug *htt_record;
htt_record = (struct htt_event_debug *)
&(((struct htt_event_debug *)htt_log->buf)[pos]);
qdf_debugfs_printf(file, "EVENT ID = %x\n", htt_record->event);
qdf_debugfs_printf(file, "DATA[0 - %d]:",
HTT_EVENT_DEBUG_ENTRY_MAX_LENGTH - 1);
for (i = 0; i < HTT_EVENT_DEBUG_ENTRY_MAX_LENGTH; i++)
qdf_debugfs_printf(file, "%x ", htt_record->data[i]);
qdf_log_timestamp_to_secs(htt_record->time, &secs, &usecs);
qdf_debugfs_printf(file, "\nCPU ID = %d", (htt_record->cpu_id));
qdf_debugfs_printf(file, "\nEVENT TIME = [%llu.%06llu]\n",
secs, usecs);
if (pos == 0)
pos = HTT_DISPLAY_SIZE - 1;
else
pos--;
}
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_EVENT_LOG_BP);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS debug_htt_wbm_event_log_show(qdf_debugfs_file_t file,
void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
struct htt_log_buf_t *htt_log = NULL;
int pos, nread, i;
uint64_t secs, usecs;
htt_log = &htt_logger_handle->log_info.htt_wbm_event_log_buf_info;
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_WBM_EVENT_LOG_BP))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_WBM_EVENT_LOG_BP));
return QDF_STATUS_SUCCESS;
}
qdf_spin_lock(&htt_logger_handle->log_info.htt_record_lock);
if (!htt_log->length) {
qdf_spin_unlock(&htt_logger_handle->log_info.htt_record_lock);
qdf_debugfs_printf(file,
"no elements to read from ring buffer!\n");
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_WBM_EVENT_LOG_BP);
return QDF_STATUS_SUCCESS;
}
if (htt_log->length <= HTT_DISPLAY_SIZE)
nread = htt_log->length;
else
nread = HTT_DISPLAY_SIZE;
if (htt_log->buf_tail_idx == 0)
pos = HTT_DISPLAY_SIZE - 1;
else
pos = htt_log->buf_tail_idx - 1;
qdf_debugfs_printf(file, "Length = %d\n", htt_log->length);
qdf_spin_unlock(&htt_logger_handle->log_info.htt_record_lock);
while (nread--) {
struct htt_wbm_event_debug *htt_record;
htt_record = (struct htt_wbm_event_debug *)
&(((struct htt_wbm_event_debug *)htt_log->buf)[pos]);
qdf_debugfs_printf(file, "WBM Event Tx status = = %x\n",
htt_record->tx_status);
qdf_debugfs_printf(file, "DATA[0-%d]:",
HTT_WBM_EVENT_DEBUG_ENTRY_MAX_LENGTH - 1);
for (i = 0; i < HTT_WBM_EVENT_DEBUG_ENTRY_MAX_LENGTH; i++)
qdf_debugfs_printf(file, "%x ", htt_record->data[i]);
qdf_log_timestamp_to_secs(htt_record->time, &secs, &usecs);
qdf_debugfs_printf(file, "\nCPU ID = %d", (htt_record->cpu_id));
qdf_debugfs_printf(file, "\nWBM EVENT TIME = [%llu.%06llu]\n",
secs, usecs);
if (pos == 0)
pos = HTT_DISPLAY_SIZE - 1;
else
pos--;
}
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_WBM_EVENT_LOG_BP);
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_enable_show() - debugfs functions to display enable state of
* htt logging feature.
*
* @file: qdf debugfs handler
* @arg: priv data used to get htt_logger_handler
*
* Return: Status
*/
static QDF_STATUS debug_htt_enable_show(qdf_debugfs_file_t file, void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
struct htt_debug_log_info *log_info_p = &htt_logger_handle->log_info;
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_ENABLE_BP))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_ENABLE_BP));
return QDF_STATUS_SUCCESS;
}
qdf_debugfs_printf(file, "%d\n",
log_info_p->htt_logging_enable);
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_ENABLE_BP);
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_cmd_disable_list_show() - debugfs functions to display disabled
* command id for tracing.
*
* @file: qdf debugfs handler
* @arg: priv data used to get htt_logger_handler
*
* Return: Status
*/
static QDF_STATUS debug_htt_cmd_disable_list_show(qdf_debugfs_file_t file,
void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
struct htt_debug_log_info *log_info_p = &htt_logger_handle->log_info;
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_CMD_DISABLE_LIST_BP))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_CMD_DISABLE_LIST_BP));
return QDF_STATUS_SUCCESS;
}
qdf_debugfs_printf(file, "%llu\n",
log_info_p->htt_cmd_disable_list);
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_CMD_DISABLE_LIST_BP);
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_event_disable_list_show() - debugfs functions to display disabled
* event id for tracing.
*
* @file: qdf debugfs handler
* @arg: priv data used to get htt_logger_handler
*
* Return: Status
*/
static QDF_STATUS debug_htt_event_disable_list_show(qdf_debugfs_file_t file,
void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
struct htt_debug_log_info *log_info_p = &htt_logger_handle->log_info;
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_EVENT_DISABLE_LIST))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_EVENT_DISABLE_LIST));
return QDF_STATUS_SUCCESS;
}
qdf_debugfs_printf(file, "%llu\n",
log_info_p->htt_event_disable_list);
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_EVENT_DISABLE_LIST);
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_cmd_disable_list_show() - debugfs functions to display disabled
* wbm event id for tracing.
*
* @file: qdf debugfs handler
* @arg: priv data used to get htt_logger_handler
*
* Return: Status
*/
static QDF_STATUS debug_htt_wbm_event_disable_list_show(qdf_debugfs_file_t file
, void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
struct htt_debug_log_info *log_info_p = &htt_logger_handle->log_info;
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_WBM_EVENT_DISABLE_LIST))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_WBM_EVENT_DISABLE_LIST));
return QDF_STATUS_SUCCESS;
}
qdf_debugfs_printf(file, "%llu\n",
log_info_p->htt_wbm_event_disable_list);
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_WBM_EVENT_DISABLE_LIST);
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_log_size_show() - debugfs functions to display configured size of
* htt logging command/event buffer and management command/event buffer.
*
* @file: qdf debugfs handler
* @arg: priv data used to get htt_logger_handler
*
* Return: Status
*/
static QDF_STATUS debug_htt_log_size_show(qdf_debugfs_file_t file, void *arg)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)arg;
if ((htt_logger_handle->log_info.stop_seq &
(0x1 << HTT_LOG_SIZE_BP))) {
htt_logger_handle->log_info.stop_seq &=
(~(0x1 << HTT_LOG_SIZE_BP));
return QDF_STATUS_SUCCESS;
}
qdf_debugfs_printf(file, "HTT command/event log max size:%d\n",
HTT_EVENT_DEBUG_MAX_ENTRY);
htt_logger_handle->log_info.stop_seq |=
(0x1 << HTT_LOG_SIZE_BP);
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_##func_base##_write() - debugfs functions to clear
* htt logging command/event buffer and management command/event buffer.
*
* @priv: file handler to access htt_logger_handle
* @buf: received data buffer
* @len: length of received buffer
*
* Return: Status
*/
#define GENERATE_DEBUG_WRITE_FUNCS(func_base, htt_ring_size, htt_record_type) \
static QDF_STATUS debug_htt_##func_base##_write(void *priv, \
const char *buf, qdf_size_t len) \
{ \
int k, ret; \
struct htt_logger *htt_logger_handle = (struct htt_logger *)priv; \
struct htt_log_buf_t *htt_log = &htt_logger_handle->log_info. \
htt_##func_base##_buf_info; \
ret = kstrtoint(buf, 0, &k); \
if ((ret != 0) || (k != 0)) { \
return QDF_STATUS_E_PERM; \
} \
qdf_spin_lock(&htt_logger_handle->log_info.htt_record_lock); \
qdf_mem_zero(htt_log->buf, (htt_ring_size) * \
sizeof(struct htt_record_type)); \
htt_log->length = 0; \
htt_log->buf_tail_idx = 0; \
qdf_spin_unlock(&htt_logger_handle->log_info.htt_record_lock); \
return QDF_STATUS_SUCCESS ; \
}
GENERATE_DEBUG_WRITE_FUNCS(command_log, HTT_EVENT_DEBUG_MAX_ENTRY,
htt_command_debug);
GENERATE_DEBUG_WRITE_FUNCS(event_log, HTT_EVENT_DEBUG_MAX_ENTRY,
htt_event_debug);
GENERATE_DEBUG_WRITE_FUNCS(wbm_event_log, HTT_EVENT_DEBUG_MAX_ENTRY,
htt_wbm_event_debug);
/**
* debug_htt_enable_write() - debugfs functions to enable/disable
* htt logging feature.
*
* @priv: file handler to access htt_logger_handle
* @buf: received data buffer
* @len: length of received buffer
*
* Return: QDF_STATUS
*/
static QDF_STATUS debug_htt_enable_write(void *priv, const char *buf,
qdf_size_t len)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)priv;
int k, ret;
ret = kstrtoint(buf, 0, &k);
if ((ret != 1) || ((k != 0) && (k != 1)))
return QDF_STATUS_E_PERM;
htt_logger_handle->log_info.htt_logging_enable = k;
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_cmd_disable_list_write() - Debugfs write for command
* to be disabled for tracing
* @priv: file handler to access htt_logger_handle
* @buf: received data buffer
* @len: length of received buffer
*
* Return: QDF_STATUS
*/
static QDF_STATUS debug_htt_cmd_disable_list_write(void *priv,
const char *buf,
qdf_size_t len)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)priv;
int ret;
uint64_t k;
ret = kstrtou64(buf, 0, &k);
if ((ret != 0) || ((k < 0) || (k > 0xFFFFFFFF)))
return QDF_STATUS_E_PERM;
htt_logger_handle->log_info.htt_cmd_disable_list = k;
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_event_disable_list_write() - Debugfs write for event
* to be disabled for tracing
* @priv: file handler to access htt_logger_handle
* @buf: received data buffer
* @len: length of received buffer
*
* Return: QDF_STATUS
*/
static QDF_STATUS debug_htt_event_disable_list_write(void *priv,
const char *buf,
qdf_size_t len)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)priv;
int ret;
uint64_t k;
ret = kstrtou64(buf, 0, &k);
if ((ret != 0) || ((k < 0) || (k > 0xFFFFFFFF)))
return QDF_STATUS_E_PERM;
htt_logger_handle->log_info.htt_event_disable_list = k;
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_wbm_event_disable_list_write() - Debugfs write for wbm event
* to be disabled for tracing
* @priv: file handler to access htt_logger_handle
* @buf: received data buffer
* @len: length of received buffer
*
* Return: QDF_STATUS
*/
static QDF_STATUS debug_htt_wbm_event_disable_list_write(void *priv,
const char *buf,
qdf_size_t len)
{
struct htt_logger *htt_logger_handle = (struct htt_logger *)priv;
int ret;
uint64_t k;
ret = kstrtou64(buf, 0, &k);
if ((ret != 0) || ((k < 0) || (k > 0xFFFFFFFF)))
return QDF_STATUS_E_PERM;
htt_logger_handle->log_info.htt_wbm_event_disable_list = k;
return QDF_STATUS_SUCCESS;
}
/**
* debug_htt_log_size_write() - reserved.
*
* @priv: file handler to access htt_logger_handle
* @buf: received data buffer
* @len: length of received buffer
*
* Return: QDF_STATUS
*/
static QDF_STATUS debug_htt_log_size_write(void *priv,
const char *buf,
qdf_size_t len)
{
return -EINVAL;
}
/* Structure to maintain debug information */
struct htt_debugfs_info {
const char *name;
struct qdf_debugfs_fops *ops;
};
#define DEBUGFS_FOPS(func_base) { .name = #func_base, \
.ops = &debug_##func_base##_ops }
#define GENERATE_DEBUG_STRUCTS(func_base) \
\
static struct qdf_debugfs_fops debug_##func_base##_ops = { \
.show = debug_##func_base##_show, \
.write = debug_##func_base##_write, \
.priv = NULL, \
}
GENERATE_DEBUG_STRUCTS(htt_command_log);
GENERATE_DEBUG_STRUCTS(htt_event_log);
GENERATE_DEBUG_STRUCTS(htt_wbm_event_log);
GENERATE_DEBUG_STRUCTS(htt_enable);
GENERATE_DEBUG_STRUCTS(htt_log_size);
GENERATE_DEBUG_STRUCTS(htt_cmd_disable_list);
GENERATE_DEBUG_STRUCTS(htt_event_disable_list);
GENERATE_DEBUG_STRUCTS(htt_wbm_event_disable_list);
struct htt_debugfs_info htt_debugfs_infos[NUM_HTT_DEBUG_INFOS] = {
DEBUGFS_FOPS(htt_command_log),
DEBUGFS_FOPS(htt_event_log),
DEBUGFS_FOPS(htt_wbm_event_log),
DEBUGFS_FOPS(htt_enable),
DEBUGFS_FOPS(htt_log_size),
DEBUGFS_FOPS(htt_cmd_disable_list),
DEBUGFS_FOPS(htt_event_disable_list),
DEBUGFS_FOPS(htt_wbm_event_disable_list),
};
/**
* htt_log_buffer_free() - Free all dynamic allocated buffer memory for
* event logging
* @htt_logger_handle: HTT handle.
*
* Return: None
*/
static inline void htt_log_buffer_free(struct htt_logger *htt_logger_handle)
{
struct htt_debug_log_info *log_info_p = &htt_logger_handle->log_info;
/* first disable logging and then free buffer and release lock */
log_info_p->htt_logging_enable = 0;
/* Free allocated buffer */
if (log_info_p->htt_command_log_buf_info.buf) {
qdf_mem_free(log_info_p->htt_command_log_buf_info.buf);
log_info_p->htt_command_log_buf_info.buf = NULL;
}
if (log_info_p->htt_event_log_buf_info.buf) {
qdf_mem_free(log_info_p->htt_event_log_buf_info.buf);
log_info_p->htt_event_log_buf_info.buf = NULL;
}
if (log_info_p->htt_wbm_event_log_buf_info.buf) {
qdf_mem_free(log_info_p->htt_wbm_event_log_buf_info.buf);
log_info_p->htt_wbm_event_log_buf_info.buf = NULL;
}
}
/**
* htt_log_buffer_alloc() - Allocate all dynamic allocated buffer memory for
* event logging
* @htt_logger_handle: HTT handle.
*
* Return: None
*/
static QDF_STATUS htt_log_buffer_alloc(struct htt_logger *htt_logger_handle)
{
struct htt_log_buf_t *cmd_log_buf;
struct htt_log_buf_t *event_log_buf;
struct htt_log_buf_t *wbm_event_log_buf;
cmd_log_buf =
&htt_logger_handle->log_info.htt_command_log_buf_info;
event_log_buf =
&htt_logger_handle->log_info.htt_event_log_buf_info;
wbm_event_log_buf =
&htt_logger_handle->log_info.htt_wbm_event_log_buf_info;
/* first disable logging and then free buffer and release lock */
htt_logger_handle->log_info.htt_logging_enable = 0;
/* Allocate data buffer */
cmd_log_buf->buf = (struct htt_command_debug *)qdf_mem_malloc(
HTT_EVENT_DEBUG_MAX_ENTRY *
sizeof(struct htt_command_debug));
if (!cmd_log_buf->buf) {
HTT_LOGE("Memory allocation for HTT CMD log failed.");
goto error_mem_fail;
}
event_log_buf->buf = (struct htt_event_debug *)qdf_mem_malloc(
HTT_EVENT_DEBUG_MAX_ENTRY *
sizeof(struct htt_event_debug));
if (!event_log_buf->buf) {
HTT_LOGE("Memory allocation for HTT EVENT log failed.");
goto error_mem_fail;
}
wbm_event_log_buf->buf = (struct htt_wbm_event_debug *)qdf_mem_malloc(
HTT_EVENT_DEBUG_MAX_ENTRY *
sizeof(struct htt_wbm_event_debug));
if (!wbm_event_log_buf->buf) {
HTT_LOGE("Memory allocation for HTT WBM EVENT log failed.");
goto error_mem_fail;
}
return QDF_STATUS_SUCCESS;
error_mem_fail:
htt_log_buffer_free(htt_logger_handle);
return QDF_STATUS_E_NOMEM;
}
/**
* htt_log_lock_free - Destroy lock
*/
static inline void htt_log_lock_alloc(struct htt_logger *htt_logger_handle)
{
struct htt_debug_log_info *log_info_p = &htt_logger_handle->log_info;
struct htt_log_buf_t *cmd_log_buf =
&htt_logger_handle->log_info.htt_command_log_buf_info;
struct htt_log_buf_t *event_log_buf =
&htt_logger_handle->log_info.htt_event_log_buf_info;
struct htt_log_buf_t *wbm_event_log_buf =
&htt_logger_handle->log_info.htt_wbm_event_log_buf_info;
/* Create lock for cmd/event/wbm */
qdf_spinlock_create(&cmd_log_buf->record_lock);
qdf_spinlock_create(&event_log_buf->record_lock);
qdf_spinlock_create(&wbm_event_log_buf->record_lock);
/* Create recording lock in read through debugfs */
qdf_spinlock_create(&log_info_p->htt_record_lock);
}
/**
* htt_log_lock_free - Destroy lock
*/
static inline void htt_log_lock_free(struct htt_logger *htt_logger_handle)
{
struct htt_debug_log_info *log_info_p = &htt_logger_handle->log_info;
struct htt_log_buf_t *cmd_log_buf =
&htt_logger_handle->log_info.htt_command_log_buf_info;
struct htt_log_buf_t *event_log_buf =
&htt_logger_handle->log_info.htt_event_log_buf_info;
struct htt_log_buf_t *wbm_event_log_buf =
&htt_logger_handle->log_info.htt_wbm_event_log_buf_info;
/* Destroy lock for cmd/event/wbm */
qdf_spinlock_destroy(&cmd_log_buf->record_lock);
qdf_spinlock_destroy(&event_log_buf->record_lock);
qdf_spinlock_destroy(&wbm_event_log_buf->record_lock);
/* Destroy recording lock in read through debugfs */
qdf_spinlock_destroy(&log_info_p->htt_record_lock);
}
/**
* htt_debugfs_remove() - Remove debugfs entry for htt logging.
* @htt_logger_handle: htt handle
* @dentry: qdf_debugfs directory entry
* @id: Index to debug info data array
*
* Return: none
*/
static void htt_debugfs_remove(struct htt_logger *htt_logger_handle)
{
int i;
qdf_dentry_t dentry = htt_logger_handle->log_info.htt_log_debugfs_dir;
if (dentry) {
for (i = 0; i < NUM_HTT_DEBUG_INFOS; ++i) {
if (htt_logger_handle->debugfs_de[i])
htt_logger_handle->debugfs_de[i] = NULL;
}
}
if (dentry)
qdf_debugfs_remove_dir_recursive(dentry);
}
/**
* htt_debugfs_init() - debugfs functions to create debugfs directory and to
* create debugfs enteries.
*
* @ htt_logger_handle: htt logger handler
*
* Return: init status
*/
static QDF_STATUS htt_debugfs_init(struct htt_logger *htt_logger_handle)
{
char buf[32];
int i;
snprintf(buf, sizeof(buf), "HTT_SOC_LOGGER");
htt_logger_handle->log_info.htt_log_debugfs_dir =
qdf_debugfs_create_dir(buf, NULL);
if (!htt_logger_handle->log_info.htt_log_debugfs_dir) {
HTT_LOGE("error while creating debugfs dir for %s", buf);
return QDF_STATUS_E_FAILURE;
}
for (i = 0; i < NUM_HTT_DEBUG_INFOS; ++i) {
htt_debugfs_infos[i].ops->priv = htt_logger_handle;
htt_logger_handle->debugfs_de[i] = qdf_debugfs_create_file(
htt_debugfs_infos[i].name, HTT_DBG_FILE_PERM,
htt_logger_handle->log_info.htt_log_debugfs_dir,
htt_debugfs_infos[i].ops);
if (!htt_logger_handle->debugfs_de[i])
goto out;
}
return QDF_STATUS_SUCCESS;
out:
HTT_LOGE("debug Entry creation failed[%s]!", htt_debugfs_infos[i].name);
htt_debugfs_remove(htt_logger_handle);
return QDF_STATUS_E_FAILURE;
}
/**
* htt_interface_logging_init() - Initialize HTT tracer
* @ htt_logger_handle: htt logger handler
*/
void htt_interface_logging_init(struct htt_logger **phtt_logger_handle)
{
QDF_STATUS ret;
struct htt_logger *htt_logger_handle;
struct htt_log_buf_t *cmd_log_buf;
struct htt_log_buf_t *event_log_buf;
struct htt_log_buf_t *wbm_event_log_buf;
uint64_t htt_disable_mask;
*phtt_logger_handle = (struct htt_logger *)qdf_mem_malloc(
sizeof(struct htt_logger));
if (!*phtt_logger_handle) {
HTT_LOGE("Memory allocation for HTT logger buffer failed.");
return;
}
/* Allocate Buffer */
if (QDF_STATUS_SUCCESS != htt_log_buffer_alloc(*phtt_logger_handle)) {
qdf_mem_free(*phtt_logger_handle);
*phtt_logger_handle = NULL;
return;
}
htt_logger_handle = *phtt_logger_handle;
cmd_log_buf =
&htt_logger_handle->log_info.htt_command_log_buf_info;
event_log_buf =
&htt_logger_handle->log_info.htt_event_log_buf_info;
wbm_event_log_buf =
&htt_logger_handle->log_info.htt_wbm_event_log_buf_info;
/* Initialize HTT Cmd/Event/WBM Event */
log_buf_init(cmd_log_buf);
log_buf_init(event_log_buf);
log_buf_init(wbm_event_log_buf);
/* Disable all command */
disable_all_command(htt_logger_handle);
/* Disable all event except:
* HTT_T2H_MSG_TYPE_PEER_MAP, HTT_T2H_MSG_TYPE_PEER_UNMAP
* HTT_T2H_MSG_TYPE_RX_ADDBA HTT_T2H_MSG_TYPE_RX_DELBA
* HTT_T2H_MSG_TYPE_PEER_MAP_V2 HTT_T2H_MSG_TYPE_PEER_UNMAP_V2
*/
disable_all_event(htt_logger_handle);
enable_event(htt_logger_handle, HTT_T2H_MSG_TYPE_PEER_MAP_C);
enable_event(htt_logger_handle, HTT_T2H_MSG_TYPE_PEER_UNMAP_C);
enable_event(htt_logger_handle, HTT_T2H_MSG_TYPE_RX_ADDBA_C);
enable_event(htt_logger_handle, HTT_T2H_MSG_TYPE_RX_DELBA_C);
enable_event(htt_logger_handle, HTT_T2H_MSG_TYPE_PEER_MAP_V2_C);
enable_event(htt_logger_handle, HTT_T2H_MSG_TYPE_PEER_UNMAP_V2_C);
/* Disable success status*/
disable_wbm_success_status(htt_logger_handle);
/* Create lock for all event */
htt_log_lock_alloc(htt_logger_handle);
/* Enable HTT logging */
enable_htt_logging(htt_logger_handle);
ret = htt_debugfs_init(*phtt_logger_handle);
if (QDF_STATUS_SUCCESS != ret)
goto debugfs_init_failed;
return;
debugfs_init_failed:
htt_log_buffer_free(*phtt_logger_handle);
htt_log_lock_free(*phtt_logger_handle);
(*phtt_logger_handle)->log_info.htt_logging_enable = 0;
qdf_mem_free(*phtt_logger_handle);
*phtt_logger_handle = NULL;
}
/**
* htt_interface_logging_deinit() - Deinitialize HTT tracer
* @ htt_logger_handle: htt logger handler
*/
void htt_interface_logging_deinit(struct htt_logger *htt_logger_handle)
{
/**
* This case will hit in deinit path
* if htt_initialization failed
*/
if (!htt_logger_handle)
return;
htt_debugfs_remove(htt_logger_handle);
htt_log_buffer_free(htt_logger_handle);
htt_log_lock_free(htt_logger_handle);
qdf_mem_free(htt_logger_handle);
}