qcacmn: Add debugfs support for DBR ring debug

For each DBR ring, add debugfs entry to dump at real-time the ring
parameters like head, tail index, the timestamps at which a buffer is
received and replenished. Issues that are specific to tail index
movement from the target can be identified with this debugfs entry.

CRs-Fixed: 2466514
Change-Id: Iafbc61726264464212cb783a1cce46e16b8a48ff
This commit is contained in:
Shwetha G K
2019-10-25 14:18:27 +05:30
committed by nshrivas
parent 215bac70f5
commit 29121213c8
6 changed files with 627 additions and 49 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-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
@@ -240,6 +240,43 @@ void qdf_debugfs_remove_dir(qdf_dentry_t d);
*/
void qdf_debugfs_remove_file(qdf_dentry_t d);
/**
* qdf_debugfs_create_file_simplified() - Create a simple debugfs file
* where a single function call produces all the desired output
* @name: name of the file
* @mode: qdf file mode
* @parent: parent node. If NULL, defaults to base 'qdf_debugfs_root'
* @fops: file operations { .show, .write , .priv... }
*
* Users just have to define the show() function and pass it via @fops.show()
* argument. When the output time comes, the show() will be called once.
* The show() function must do everything that is needed to write the data,
* all in one function call.
* This is useful either for writing small amounts of data to debugfs or
* for cases in which the output is not iterative.
* The private data can be passed via @fops.priv, which will be available
* inside the show() function as the 'private' filed of the qdf_debugfs_file_t.
*
* Return: dentry structure pointer in case of success, otherwise NULL.
*
*/
qdf_dentry_t qdf_debugfs_create_file_simplified(const char *name, uint16_t mode,
qdf_dentry_t parent,
struct qdf_debugfs_fops *fops);
/**
* qdf_debugfs_printer() - Print formated string into debugfs file
* @priv: The private data
* @fmt: Format string
* @...: arguments for the format string
*
* This function prints a new line character after printing the formatted
* string into the debugfs file.
* This function can be passed when the argument is of type qdf_abstract_print
*/
int qdf_debugfs_printer(void *priv, const char *fmt, ...);
#else /* WLAN_DEBUGFS */
static inline QDF_STATUS qdf_debugfs_init(void)
@@ -333,5 +370,18 @@ static inline void qdf_debugfs_remove_dir_recursive(qdf_dentry_t d) {}
static inline void qdf_debugfs_remove_dir(qdf_dentry_t d) {}
static inline void qdf_debugfs_remove_file(qdf_dentry_t d) {}
static inline
qdf_dentry_t qdf_debugfs_create_file_simplified(const char *name, uint16_t mode,
qdf_dentry_t parent,
struct qdf_debugfs_fops *fops)
{
return NULL;
}
static inline
int qdf_debugfs_printer(void *priv, const char *fmt, ...)
{
return 0;
}
#endif /* WLAN_DEBUGFS */
#endif /* _QDF_DEBUGFS_H */

View File

@@ -468,3 +468,70 @@ void qdf_debugfs_remove_file(qdf_dentry_t d)
debugfs_remove(d);
}
qdf_export_symbol(qdf_debugfs_remove_file);
static int qdf_debugfs_single_show(struct seq_file *seq, void *v)
{
struct qdf_debugfs_fops *fops = seq->private;
if (fops && fops->show)
fops->show(seq, fops->priv);
return 0;
}
/* .open() */
static int qdf_debugfs_single_open(struct inode *inode, struct file *file)
{
return single_open(file, qdf_debugfs_single_show,
inode->i_private);
}
/* File operations for the simplified version */
static const struct file_operations qdf_debugfs_fops_simple = {
.owner = THIS_MODULE,
.open = qdf_debugfs_single_open,
.release = single_release,
.read = seq_read,
.llseek = seq_lseek,
};
qdf_dentry_t qdf_debugfs_create_file_simplified(
const char *name, uint16_t mode,
qdf_dentry_t parent, struct qdf_debugfs_fops *fops)
{
qdf_dentry_t file;
umode_t filemode;
if (!name || !fops)
return NULL;
if (!parent)
parent = qdf_debugfs_get_root();
filemode = qdf_debugfs_get_filemode(mode);
file = debugfs_create_file(name, filemode, parent, fops,
&qdf_debugfs_fops_simple);
if (IS_ERR_OR_NULL(file)) {
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
"%s creation failed 0x%pK", name, file);
file = NULL;
}
return file;
}
qdf_export_symbol(qdf_debugfs_create_file_simplified);
int qdf_debugfs_printer(void *priv, const char *fmt, ...)
{
struct seq_file *file = priv;
va_list args;
va_start(args, fmt);
seq_vprintf(file, fmt, args);
seq_puts(file, "\n");
va_end(args);
return 0;
}
qdf_export_symbol(qdf_debugfs_printer);

View File

@@ -23,6 +23,13 @@
#include "qdf_atomic.h"
#include "wmi_unified_api.h"
#ifdef WLAN_DEBUGFS
#ifdef DIRECT_BUF_RX_DEBUG
/* Base debugfs entry for DBR module */
extern qdf_dentry_t dbr_debugfs_entry;
#endif /* DIRECT_BUF_RX_DEBUG */
#endif /* WLAN_DEBUGFS */
#define direct_buf_rx_alert(params...) \
QDF_TRACE_FATAL(QDF_MODULE_ID_DIRECT_BUF_RX, params)
#define direct_buf_rx_err(params...) \

View File

@@ -25,6 +25,39 @@
#include "target_if_direct_buf_rx_main.h"
#include <qdf_module.h>
#if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG)
/* Base debugfs entry for DBR module */
qdf_dentry_t dbr_debugfs_entry;
static inline void
target_if_direct_buf_rx_debugfs_init(void)
{
dbr_debugfs_entry = qdf_debugfs_create_dir("dbr_ring_debug", NULL);
if (!dbr_debugfs_entry)
direct_buf_rx_err("error while creating direct_buf rx debugfs dir");
}
static inline void
target_if_direct_buf_rx_debugfs_deinit(void)
{
if (dbr_debugfs_entry) {
qdf_debugfs_remove_dir_recursive(dbr_debugfs_entry);
dbr_debugfs_entry = NULL;
}
}
#else
static inline void
target_if_direct_buf_rx_debugfs_init(void)
{
}
static inline void
target_if_direct_buf_rx_debugfs_deinit(void)
{
}
#endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */
QDF_STATUS direct_buf_rx_init(void)
{
QDF_STATUS status;
@@ -69,6 +102,8 @@ QDF_STATUS direct_buf_rx_init(void)
goto dbr_unreg_pdev_create;
}
target_if_direct_buf_rx_debugfs_init();
direct_buf_rx_info("Direct Buffer RX pdev,psoc create and destroy handlers registered");
return QDF_STATUS_SUCCESS;
@@ -99,6 +134,8 @@ QDF_STATUS direct_buf_rx_deinit(void)
{
QDF_STATUS status;
target_if_direct_buf_rx_debugfs_deinit();
status = wlan_objmgr_unregister_pdev_destroy_handler(
WLAN_TARGET_IF_COMP_DIRECT_BUF_RX,
target_if_direct_buf_rx_pdev_destroy_handler,

View File

@@ -120,14 +120,13 @@ static QDF_STATUS populate_dbr_cap_mod_param(struct wlan_objmgr_pdev *pdev,
return QDF_STATUS_SUCCESS;
}
#ifdef DIRECT_BUF_RX_DEBUG
static inline struct direct_buf_rx_module_debug *target_if_get_dbr_mod_debug(
struct wlan_objmgr_pdev *pdev,
static inline struct direct_buf_rx_module_debug *
target_if_get_dbr_mod_debug_from_dbr_pdev_obj(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
uint8_t mod_id)
{
struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
if (!pdev) {
direct_buf_rx_err("pdev is null");
if (!dbr_pdev_obj) {
direct_buf_rx_err("dir buf rx object is null");
return NULL;
}
@@ -136,14 +135,6 @@ static inline struct direct_buf_rx_module_debug *target_if_get_dbr_mod_debug(
return NULL;
}
dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
if (!dbr_pdev_obj) {
direct_buf_rx_err("dir buf rx object is null");
return NULL;
}
if (!dbr_pdev_obj->dbr_mod_debug) {
direct_buf_rx_err("dbr_pdev_obj->dbr_mod_debug is NULL");
return NULL;
@@ -155,9 +146,121 @@ static inline struct direct_buf_rx_module_debug *target_if_get_dbr_mod_debug(
}
return &dbr_pdev_obj->dbr_mod_debug[mod_id];
}
static inline struct direct_buf_rx_module_debug *
target_if_get_dbr_mod_debug_from_pdev(
struct wlan_objmgr_pdev *pdev,
uint8_t mod_id)
{
struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
if (!pdev) {
direct_buf_rx_err("pdev is null");
return NULL;
}
dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
return target_if_get_dbr_mod_debug_from_dbr_pdev_obj(
dbr_pdev_obj, mod_id);
}
#endif
#ifdef DIRECT_BUF_RX_DEBUG
#define RING_DEBUG_EVENT_NAME_SIZE 12
static const unsigned char
g_dbr_ring_debug_event[DBR_RING_DEBUG_EVENT_MAX][RING_DEBUG_EVENT_NAME_SIZE] = {
[DBR_RING_DEBUG_EVENT_RX] = "Rx",
[DBR_RING_DEBUG_EVENT_REPLENISH_RING] = "Replenish",
};
/**
* target_if_dbr_print_ring_debug_entries() - Print ring debug entries
* @print: The print adapter function
* @print_priv: The private data to be consumed by @print
* @dbr_pdev_obj: Pdev object of the DBR module
* @mod_id: Module ID
*
* Print ring debug entries of the ring identified by @dbr_pdev_obj and @mod_id
* using the given print adapter function
*
* Return: QDF_STATUS of operation
*/
static QDF_STATUS target_if_dbr_print_ring_debug_entries(
qdf_abstract_print print, void *print_priv,
struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
uint8_t mod_id, uint8_t srng_id)
{
struct direct_buf_rx_module_debug *mod_debug;
struct direct_buf_rx_ring_debug *ring_debug;
int idx;
mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj,
mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
mod_debug = &dbr_pdev_obj->dbr_mod_debug[mod_id];
ring_debug = &mod_debug->dbr_ring_debug[srng_id];
if (ring_debug->entries) {
print(print_priv, "Current debug entry is %d",
ring_debug->ring_debug_idx);
print(print_priv, "---------------------------------------------------------");
print(print_priv, "| Number | Head Idx | Tail Idx | Timestamp | event |");
print(print_priv, "---------------------------------------------------------");
for (idx = 0; idx < ring_debug->num_ring_debug_entries; ++idx) {
print(print_priv, "|%8u|%10u|%10u|%11llu|%12s|", idx,
ring_debug->entries[idx].head_idx,
ring_debug->entries[idx].tail_idx,
ring_debug->entries[idx].timestamp,
g_dbr_ring_debug_event[
ring_debug->entries[idx].event]);
}
print(print_priv, "---------------------------------------------------------");
}
return QDF_STATUS_SUCCESS;
}
/**
* target_if_dbr_qdf_err_printer() - QDF error level printer for DBR module
* @print_priv: The private data
* @fmt: Format string
*
* This function should be passed in place of the 'print' argument to
* target_if_dbr_print_ring_debug_entries function for the logs that should be
* printed via QDF trace
*
* Return: QDF_STATUS of operation
*/
static int target_if_dbr_qdf_err_printer(void *priv, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
QDF_VTRACE(QDF_MODULE_ID_DIRECT_BUF_RX, QDF_TRACE_LEVEL_ERROR,
(char *)fmt, args);
va_end(args);
return 0;
}
static inline void target_if_direct_buf_rx_free_mod_debug(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
{
if (!dbr_pdev_obj) {
direct_buf_rx_err("dir buf rx object is null");
return;
}
/* Free the debug data structures of all modules */
if (dbr_pdev_obj->dbr_mod_debug) {
qdf_mem_free(dbr_pdev_obj->dbr_mod_debug);
dbr_pdev_obj->dbr_mod_debug = NULL;
}
}
static inline QDF_STATUS target_if_direct_buf_rx_alloc_mod_debug(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
{
@@ -181,7 +284,71 @@ static inline QDF_STATUS target_if_direct_buf_rx_alloc_mod_debug(
{
return QDF_STATUS_SUCCESS;
}
#endif /* DIRECT_BUF_RX_DEBUG */
static inline void target_if_direct_buf_rx_free_mod_debug(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
{
}
#endif
#if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG)
static inline void target_if_direct_buf_pdev_debugfs_init(
struct wlan_objmgr_pdev *pdev)
{
char dir_name[32];
struct wlan_objmgr_psoc *psoc;
struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
if (!pdev) {
direct_buf_rx_err("pdev is null");
return;
}
psoc = wlan_pdev_get_psoc(pdev);
dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
if (!dbr_pdev_obj) {
direct_buf_rx_err("dir buf rx object is null");
return;
}
qdf_snprintf(dir_name, sizeof(dir_name), "SOC%u_PDEV%u",
wlan_psoc_get_id(psoc),
wlan_objmgr_pdev_get_pdev_id(pdev));
/* Create debugfs entry for this radio */
dbr_pdev_obj->debugfs_entry = qdf_debugfs_create_dir(
dir_name, dbr_debugfs_entry);
if (!dbr_pdev_obj->debugfs_entry)
direct_buf_rx_err("error while creating direct_buf debugfs dir");
}
static inline void target_if_direct_buf_pdev_debugfs_deinit(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
{
if (!dbr_pdev_obj) {
direct_buf_rx_err("dir buf rx object is null");
return;
}
/* Remove the debugfs entry of the radio */
if (dbr_pdev_obj->debugfs_entry) {
qdf_debugfs_remove_dir_recursive(dbr_pdev_obj->debugfs_entry);
dbr_pdev_obj->debugfs_entry = NULL;
}
}
#else
static inline void target_if_direct_buf_pdev_debugfs_init(
struct wlan_objmgr_pdev *pdev)
{
}
static inline void target_if_direct_buf_pdev_debugfs_deinit(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
{
}
#endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */
QDF_STATUS target_if_direct_buf_rx_pdev_create_handler(
struct wlan_objmgr_pdev *pdev, void *data)
@@ -247,6 +414,8 @@ QDF_STATUS target_if_direct_buf_rx_pdev_create_handler(
QDF_STATUS_SUCCESS)
goto dbr_mod_debug_fail;
target_if_direct_buf_pdev_debugfs_init(pdev);
return QDF_STATUS_SUCCESS;
dbr_mod_debug_fail:
@@ -261,27 +430,6 @@ dbr_mod_param_fail:
return QDF_STATUS_E_NOMEM;
}
#ifdef DIRECT_BUF_RX_DEBUG
static inline void target_if_direct_buf_rx_free_mod_debug(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
{
if (!dbr_pdev_obj) {
direct_buf_rx_err("dir buf rx object is null");
return;
}
/* Free the debug data structures of all modules */
if (dbr_pdev_obj->dbr_mod_debug) {
qdf_mem_free(dbr_pdev_obj->dbr_mod_debug);
dbr_pdev_obj->dbr_mod_debug = NULL;
}
}
#else
static inline void target_if_direct_buf_rx_free_mod_debug(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj)
{
}
#endif /* DIRECT_BUF_RX_DEBUG */
QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler(
struct wlan_objmgr_pdev *pdev, void *data)
{
@@ -315,6 +463,7 @@ QDF_STATUS target_if_direct_buf_rx_pdev_destroy_handler(
mod_idx, srng_id);
}
target_if_direct_buf_pdev_debugfs_deinit(dbr_pdev_obj);
target_if_direct_buf_rx_free_mod_debug(dbr_pdev_obj);
qdf_mem_free(dbr_pdev_obj->dbr_mod_param);
dbr_pdev_obj->dbr_mod_param = NULL;
@@ -401,6 +550,203 @@ QDF_STATUS target_if_direct_buf_rx_psoc_destroy_handler(
return status;
}
#if defined(WLAN_DEBUGFS) && defined(DIRECT_BUF_RX_DEBUG)
/**
* target_if_dbr_debugfs_show_ring_debug() - Function to display ring debug
* entries in debugfs
* @file: qdf debugfs file handler
* @arg: pointer to DBR debugfs private object
*
* Return: QDF_STATUS of operation
*/
static QDF_STATUS target_if_dbr_debugfs_show_ring_debug(
qdf_debugfs_file_t file, void *arg)
{
struct dbr_debugfs_priv *priv = arg;
return target_if_dbr_print_ring_debug_entries(qdf_debugfs_printer,
file, priv->dbr_pdev_obj,
priv->mod_id,
priv->srng_id);
}
/**
* target_if_dbr_mod_debugfs_init() - Init debugfs for a given module
* @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module
* @mod_id: Module ID corresponding to this ring
*
* Return: QDF_STATUS of operation
*/
static QDF_STATUS target_if_dbr_mod_debugfs_init(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
enum DBR_MODULE mod_id)
{
struct direct_buf_rx_module_debug *mod_debug;
mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj,
mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
if (mod_debug->debugfs_entry) {
direct_buf_rx_err("debugfs mod entry was already created for %s module",
g_dbr_module_name[mod_id].module_name_str);
return QDF_STATUS_SUCCESS;
}
mod_debug->debugfs_entry =
qdf_debugfs_create_dir(g_dbr_module_name[mod_id].module_name_str,
dbr_pdev_obj->debugfs_entry);
if (!mod_debug->debugfs_entry) {
direct_buf_rx_err("error while creating direct_buf debugfs entry for %s module",
g_dbr_module_name[mod_id].module_name_str);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* target_if_dbr_ring_debugfs_init() - Init debugfs for a given ring
* @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module
* @mod_id: Module ID corresponding to this ring
* @srng_id: srng ID corresponding to this ring
*
* Return: QDF_STATUS of operation
*/
static QDF_STATUS target_if_dbr_ring_debugfs_init(
struct direct_buf_rx_pdev_obj *dbr_pdev_obj,
enum DBR_MODULE mod_id, uint8_t srng_id)
{
struct direct_buf_rx_module_debug *mod_debug;
struct direct_buf_rx_ring_debug *ring_debug;
struct dbr_debugfs_priv *priv;
char debug_file_name[32];
mod_debug = target_if_get_dbr_mod_debug_from_dbr_pdev_obj(dbr_pdev_obj,
mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
ring_debug = &mod_debug->dbr_ring_debug[srng_id];
if (!mod_debug->debugfs_entry) {
direct_buf_rx_err("error mod_debug->debugfs_entry not created");
return QDF_STATUS_E_FAILURE;
}
if (ring_debug->debugfs_entry) {
direct_buf_rx_err("debugfs file for %d ring under %s module already created",
srng_id,
g_dbr_module_name[mod_id].module_name_str);
return QDF_STATUS_SUCCESS;
}
qdf_snprintf(debug_file_name, sizeof(debug_file_name),
"ring_%d", srng_id);
// Allocate debugfs ops
ring_debug->debugfs_fops =
qdf_mem_malloc(sizeof(*ring_debug->debugfs_fops));
if (!ring_debug->debugfs_fops) {
direct_buf_rx_err("error in allocating debugfs ops");
return QDF_STATUS_E_NOMEM;
}
// Allocate private data
priv = qdf_mem_malloc(sizeof(*priv));
if (!priv) {
direct_buf_rx_err("error in creating debugfs private data");
goto priv_alloc_fail;
}
priv->dbr_pdev_obj = dbr_pdev_obj;
priv->mod_id = mod_id;
priv->srng_id = srng_id;
/* Fill in the debugfs ops for this ring.
* When the output time comes, the 'show' function will be
* called with 'priv' as an argument.
*/
ring_debug->debugfs_fops->show = target_if_dbr_debugfs_show_ring_debug;
ring_debug->debugfs_fops->priv = priv;
ring_debug->debugfs_entry =
qdf_debugfs_create_file_simplified(
debug_file_name,
(QDF_FILE_USR_READ | QDF_FILE_GRP_READ |
QDF_FILE_OTH_READ),
mod_debug->debugfs_entry,
ring_debug->debugfs_fops);
if (!ring_debug->debugfs_entry) {
direct_buf_rx_err("error while creating direct_buf debugfs file for %d ring under %s module",
srng_id,
g_dbr_module_name[mod_id].module_name_str);
goto file_creation_fail;
}
return QDF_STATUS_SUCCESS;
file_creation_fail:
qdf_mem_free(ring_debug->debugfs_fops->priv);
priv_alloc_fail:
qdf_mem_free(ring_debug->debugfs_fops);
ring_debug->debugfs_fops = NULL;
return QDF_STATUS_E_NOMEM;
}
/**
* target_if_dbr_mod_debugfs_deinit() - De-init debugfs for a given module
* @mod_debug: Pointer to direct_buf_rx_module_debug structure
*
* Return: void
*/
static void target_if_dbr_mod_debugfs_deinit(
struct direct_buf_rx_module_debug *mod_debug)
{
if (!mod_debug) {
direct_buf_rx_err("mod_debug is null");
return;
}
if (mod_debug->debugfs_entry) {
qdf_debugfs_remove_file(mod_debug->debugfs_entry);
mod_debug->debugfs_entry = NULL;
}
}
/**
* target_if_dbr_ring_debugfs_deinit() - De-init debugfs for a given ring
* @ring_debug: Pointer to direct_buf_rx_ring_debug structure
*
* Return: void
*/
static void target_if_dbr_ring_debugfs_deinit(
struct direct_buf_rx_ring_debug *ring_debug)
{
if (!ring_debug) {
direct_buf_rx_err("ring_debug is null");
return;
}
if (ring_debug->debugfs_entry) {
qdf_debugfs_remove_file(ring_debug->debugfs_entry);
ring_debug->debugfs_entry = NULL;
}
// Free the private data and debugfs ops of this ring
if (ring_debug->debugfs_fops) {
qdf_mem_free(ring_debug->debugfs_fops->priv);
qdf_mem_free(ring_debug->debugfs_fops);
ring_debug->debugfs_fops = NULL;
}
}
#endif /* WLAN_DEBUGFS && DIRECT_BUF_RX_DEBUG */
#ifdef DIRECT_BUF_RX_DEBUG
QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev,
uint8_t mod_id)
@@ -409,13 +755,19 @@ QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev,
struct direct_buf_rx_ring_debug *ring_debug;
uint8_t srng_id;
mod_debug = target_if_get_dbr_mod_debug(pdev, mod_id);
mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) {
ring_debug = &mod_debug->dbr_ring_debug[srng_id];
if (!ring_debug->entries) {
direct_buf_rx_err("DBR ring debug for module %d srng %d was already disabled",
mod_id, srng_id);
continue;
}
/* De-init debugsfs for this ring */
target_if_dbr_ring_debugfs_deinit(ring_debug);
qdf_mem_free(ring_debug->entries);
ring_debug->entries = NULL;
ring_debug->ring_debug_idx = 0;
@@ -423,6 +775,7 @@ QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev,
direct_buf_rx_info("DBR ring debug for module %d srng %d is now stopped",
mod_id, srng_id);
}
target_if_dbr_mod_debugfs_deinit(mod_debug);
return QDF_STATUS_SUCCESS;
}
@@ -431,11 +784,12 @@ QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev,
uint8_t mod_id,
uint32_t num_ring_debug_entries)
{
struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
struct direct_buf_rx_module_debug *mod_debug;
struct direct_buf_rx_ring_debug *ring_debug;
uint8_t srng_id;
mod_debug = target_if_get_dbr_mod_debug(pdev, mod_id);
mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
@@ -448,13 +802,18 @@ QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev,
return QDF_STATUS_E_FAILURE;
}
dbr_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
target_if_dbr_mod_debugfs_init(dbr_pdev_obj, mod_id);
for (srng_id = 0; srng_id < DBR_SRNG_NUM; srng_id++) {
ring_debug = &mod_debug->dbr_ring_debug[srng_id];
if (ring_debug->entries) {
direct_buf_rx_err("DBR ring debug for module %d srng %d was already enabled",
mod_id, mod_debug);
return QDF_STATUS_E_FAILURE;
mod_id, srng_id);
continue;
}
ring_debug->entries = qdf_mem_malloc(
@@ -466,7 +825,10 @@ QDF_STATUS target_if_dbr_start_ring_debug(struct wlan_objmgr_pdev *pdev,
ring_debug->ring_debug_idx = 0;
ring_debug->num_ring_debug_entries = num_ring_debug_entries;
/* Init debugsfs for this ring */
target_if_dbr_ring_debugfs_init(
dbr_pdev_obj,
mod_id, srng_id);
direct_buf_rx_info("DBR ring debug for module %d srng %d is now started",
mod_id, srng_id);
}
@@ -478,7 +840,7 @@ QDF_STATUS target_if_dbr_start_buffer_poisoning(struct wlan_objmgr_pdev *pdev,
{
struct direct_buf_rx_module_debug *mod_debug;
mod_debug = target_if_get_dbr_mod_debug(pdev, mod_id);
mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
@@ -497,7 +859,7 @@ QDF_STATUS target_if_dbr_stop_buffer_poisoning(
{
struct direct_buf_rx_module_debug *mod_debug;
mod_debug = target_if_get_dbr_mod_debug(pdev, mod_id);
mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
@@ -557,7 +919,7 @@ static QDF_STATUS target_if_dbr_debug_poison_buffer(
{
struct direct_buf_rx_module_debug *mod_debug;
mod_debug = target_if_get_dbr_mod_debug(pdev, mod_id);
mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
if (!mod_debug)
return QDF_STATUS_E_INVAL;
@@ -570,6 +932,19 @@ static QDF_STATUS target_if_dbr_debug_poison_buffer(
return QDF_STATUS_SUCCESS;
}
static inline void target_if_dbr_qdf_show_ring_debug(
struct wlan_objmgr_pdev *pdev,
uint8_t mod_id, uint8_t srng_id)
{
struct direct_buf_rx_pdev_obj *dbr_pdev_obj =
wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_TARGET_IF_COMP_DIRECT_BUF_RX);
target_if_dbr_print_ring_debug_entries(
target_if_dbr_qdf_err_printer,
NULL, dbr_pdev_obj,
mod_id, srng_id);
}
#else
QDF_STATUS target_if_dbr_stop_ring_debug(struct wlan_objmgr_pdev *pdev,
uint8_t mod_id)
@@ -603,6 +978,12 @@ static QDF_STATUS target_if_dbr_debug_poison_buffer(
{
return QDF_STATUS_SUCCESS;
}
static inline void target_if_dbr_qdf_show_ring_debug(
struct wlan_objmgr_pdev *pdev,
uint8_t mod_id, uint8_t srng_id)
{
}
#endif /* DIRECT_BUF_RX_DEBUG */
static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev,
@@ -664,7 +1045,13 @@ static QDF_STATUS target_if_dbr_replenish_ring(struct wlan_objmgr_pdev *pdev,
hal_srng_access_start(hal_soc, srng);
ring_entry = hal_srng_src_get_next(hal_soc, srng);
QDF_ASSERT(ring_entry);
if (!ring_entry) {
target_if_dbr_qdf_show_ring_debug(pdev, mod_param->mod_id,
mod_param->srng_id);
QDF_BUG(0);
}
dw_lo = (uint64_t)paddr & 0xFFFFFFFF;
WMI_HOST_DBR_RING_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32);
WMI_HOST_DBR_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie);
@@ -961,6 +1348,7 @@ static QDF_STATUS target_if_init_dbr_ring(struct wlan_objmgr_pdev *pdev,
mod_param->mod_id = mod_id;
mod_param->pdev_id = dbr_get_pdev_id(
srng_id, wlan_objmgr_pdev_get_pdev_id(pdev));
mod_param->srng_id = srng_id;
/* Initialize DMA ring now */
status = target_if_dbr_init_srng(pdev, mod_param);
@@ -1303,7 +1691,7 @@ static void target_if_dbr_add_ring_debug_entry(
struct direct_buf_rx_ring_debug *ring_debug;
struct direct_buf_rx_ring_debug_entry *entry;
mod_debug = target_if_get_dbr_mod_debug(pdev, mod_id);
mod_debug = target_if_get_dbr_mod_debug_from_pdev(pdev, mod_id);
if (!mod_debug)
return;

View File

@@ -118,16 +118,36 @@ struct direct_buf_rx_ring_debug_entry {
enum DBR_RING_DEBUG_EVENT event;
};
#ifdef WLAN_DEBUGFS
/**
* struct dbr_debugfs_priv - Private data for DBR ring debugfs
* @dbr_pdev_obj: Pointer to the pdev obj of Direct buffer rx module
* @mod_id: Pointer to the registered module ID
* @srng_id: srng ID
*/
struct dbr_debugfs_priv {
struct direct_buf_rx_pdev_obj *dbr_pdev_obj;
enum DBR_MODULE mod_id;
uint8_t srng_id;
};
#endif
/**
* struct direct_buf_rx_ring_debug - DMA ring debug of a module
* @entries: Pointer to the array of ring debug entries
* @ring_debug_idx: Current index in the array of ring debug entries
* @num_ring_debug_entries: Total ring debug entries
* @debugfs_entry: Debugfs entry for this ring
* @debugfs_priv: Debugfs ops for this ring
*/
struct direct_buf_rx_ring_debug {
struct direct_buf_rx_ring_debug_entry *entries;
uint32_t ring_debug_idx;
uint32_t num_ring_debug_entries;
#ifdef WLAN_DEBUGFS
qdf_dentry_t debugfs_entry;
struct qdf_debugfs_fops *debugfs_fops;
#endif
};
/**
@@ -135,11 +155,15 @@ struct direct_buf_rx_ring_debug {
* @dbr_ring_debug: Array of ring debug structers corresponding to each srng
* @poisoning_enabled: Whether buffer poisoning is enabled for this module
* @poison_value: Value with which buffers should be poisoned
* @debugfs_entry: Debugfs entry for this module
*/
struct direct_buf_rx_module_debug {
struct direct_buf_rx_ring_debug dbr_ring_debug[DBR_SRNG_NUM];
bool poisoning_enabled;
uint32_t poison_value;
#ifdef WLAN_DEBUGFS
qdf_dentry_t debugfs_entry;
#endif
};
/**
@@ -155,6 +179,7 @@ struct direct_buf_rx_module_debug {
struct direct_buf_rx_module_param {
enum DBR_MODULE mod_id;
uint8_t pdev_id;
uint8_t srng_id;
struct dbr_module_config dbr_config;
struct direct_buf_rx_ring_cap *dbr_ring_cap;
struct direct_buf_rx_ring_cfg *dbr_ring_cfg;
@@ -168,12 +193,16 @@ struct direct_buf_rx_module_param {
* @num_modules: Number of modules registered to DBR for the pdev
* @dbr_mod_param: Pointer to direct buf rx module param struct
* @dbr_mod_debug: Pointer to the array of DBR module debug structures
* @debugfs_entry: DBR debugfs entry of this radio
*/
struct direct_buf_rx_pdev_obj {
uint32_t num_modules;
struct direct_buf_rx_module_param (*dbr_mod_param)[DBR_SRNG_NUM];
#ifdef DIRECT_BUF_RX_DEBUG
struct direct_buf_rx_module_debug *dbr_mod_debug;
#ifdef WLAN_DEBUGFS
qdf_dentry_t debugfs_entry;
#endif
#endif
};