qcacmn: Add mem stats for perf builds

Add memory allocation statistics for perf builds where MEMORY_DEBUG is
not enabled. Part of this effort, re-structure some of the QDF memory
APIs. Memory stats shows real size allocated.

Change-Id: I1e8fe0f4080ea186b8bfa0ce0438b4a06dde5a66
CRs-Fixed: 2045476
This commit is contained in:
Mahesh Kumar Kalikot Veetil
2017-05-05 09:43:38 -07:00
committed by snandini
parent 1ff1f2ef82
commit e4f8f0e015
2 changed files with 144 additions and 91 deletions

View File

@@ -76,33 +76,23 @@ struct qdf_mem_multi_page_t {
/* Preprocessor definitions and constants */
typedef __qdf_mempool_t qdf_mempool_t;
#ifdef MEMORY_DEBUG
void qdf_mem_clean(void);
/**
* qdf_mem_init() - Initialize QDF memory module
*
* Return: None
*
*/
void qdf_mem_init(void);
/**
* qdf_mem_exit() - Exit QDF memory module
*
* Return: None
*
*/
void qdf_mem_exit(void);
#else
/**
* qdf_mem_init() - initialize qdf memory debug functionality
*
* Return: none
*/
static inline void qdf_mem_init(void)
{
}
/**
* qdf_mem_exit() - exit qdf memory debug functionality
*
* Return: none
*/
static inline void qdf_mem_exit(void)
{
}
#endif
#ifdef MEMORY_DEBUG
#define qdf_mem_malloc(size) \
qdf_mem_malloc_debug(size, __FILE__, __LINE__)

View File

@@ -93,7 +93,14 @@ u_int8_t prealloc_disabled = 1;
qdf_declare_param(prealloc_disabled, byte);
EXPORT_SYMBOL(prealloc_disabled);
#if defined WLAN_DEBUGFS && defined MEMORY_DEBUG
#if defined WLAN_DEBUGFS
/* Debugfs root directory for qdf_mem */
static struct dentry *qdf_mem_debugfs_root;
/**
* struct __qdf_mem_stat - qdf memory statistics
@@ -105,33 +112,6 @@ static struct __qdf_mem_stat {
qdf_atomic_t dma;
} qdf_mem_stat;
/**
* struct __qdf_mem_info - memory statistics
* @file_name: the file which allocated memory
* @line_num: the line at which allocation happened
* @size: the size of allocation
* @count: how many allocations of same type
*
*/
struct __qdf_mem_info {
char *file_name;
unsigned int line_num;
unsigned int size;
unsigned int count;
};
/* Debugfs root directory for qdf_mem */
static struct dentry *qdf_mem_debugfs_root;
/*
* A table to identify duplicates in close proximity. The table depth defines
* the proximity scope. A deeper table takes more time. Chose any optimum value.
*
*/
#define QDF_MEM_STAT_TABLE_SIZE 4
static struct __qdf_mem_info qdf_mem_info_table[QDF_MEM_STAT_TABLE_SIZE];
static inline void qdf_mem_kmalloc_inc(qdf_size_t size)
{
qdf_atomic_add(size, &qdf_mem_stat.kmalloc);
@@ -152,6 +132,32 @@ static inline void qdf_mem_dma_dec(qdf_size_t size)
qdf_atomic_sub(size, &qdf_mem_stat.dma);
}
#ifdef MEMORY_DEBUG
/**
* struct __qdf_mem_info - memory statistics
* @file_name: the file which allocated memory
* @line_num: the line at which allocation happened
* @size: the size of allocation
* @count: how many allocations of same type
*
*/
struct __qdf_mem_info {
char *file_name;
unsigned int line_num;
unsigned int size;
unsigned int count;
};
/*
* A table to identify duplicates in close proximity. The table depth defines
* the proximity scope. A deeper table takes more time. Chose any optimum value.
*
*/
#define QDF_MEM_STAT_TABLE_SIZE 4
static struct __qdf_mem_info qdf_mem_info_table[QDF_MEM_STAT_TABLE_SIZE];
/**
* qdf_mem_info_table_init() - initialize the stat table
@@ -423,11 +429,46 @@ static const struct file_operations fops_qdf_mem_debugfs = {
.release = seq_release,
};
/**
* qdf_mem_debugfs_init() - initialize routine
*
* Return: QDF_STATUS
*/
static QDF_STATUS qdf_mem_debug_debugfs_init(void)
{
if (!qdf_mem_debugfs_root)
return QDF_STATUS_E_FAILURE;
debugfs_create_file("list",
S_IRUSR | S_IWUSR,
qdf_mem_debugfs_root,
NULL,
&fops_qdf_mem_debugfs);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS qdf_mem_debug_debugfs_exit(void)
{
return QDF_STATUS_SUCCESS;
}
#else /* MEMORY_DEBUG */
static QDF_STATUS qdf_mem_debug_debugfs_init(void)
{
return QDF_STATUS_E_NOSUPPORT;
}
static QDF_STATUS qdf_mem_debug_debugfs_exit(void)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif /* MEMORY_DEBUG */
static void qdf_mem_debugfs_exit(void)
{
debugfs_remove_recursive(qdf_mem_debugfs_root);
qdf_mem_debugfs_root = NULL;
}
static QDF_STATUS qdf_mem_debugfs_init(void)
{
struct dentry *qdf_debugfs_root = qdf_debugfs_get_root();
@@ -440,11 +481,6 @@ static QDF_STATUS qdf_mem_debugfs_init(void)
if (!qdf_mem_debugfs_root)
return QDF_STATUS_E_FAILURE;
debugfs_create_file("list",
S_IRUSR | S_IWUSR,
qdf_mem_debugfs_root,
NULL,
&fops_qdf_mem_debugfs);
debugfs_create_atomic_t("kmalloc",
S_IRUSR | S_IWUSR,
@@ -459,26 +495,13 @@ static QDF_STATUS qdf_mem_debugfs_init(void)
return QDF_STATUS_SUCCESS;
}
/**
* qdf_mem_debugfs_exit() - cleanup routine
*
* Return: None
*/
static void qdf_mem_debugfs_exit(void)
{
debugfs_remove_recursive(qdf_mem_debugfs_root);
qdf_mem_debugfs_root = NULL;
}
#else /* WLAN_DEBUGFS && MEMORY_DEBUG */
#else /* WLAN_DEBUGFS */
static inline void qdf_mem_kmalloc_inc(qdf_size_t size) {}
static inline void qdf_mem_dma_inc(qdf_size_t size) {}
static inline void qdf_mem_kmalloc_dec(qdf_size_t size) {}
static inline void qdf_mem_dma_dec(qdf_size_t size) {}
#ifdef MEMORY_DEBUG
static QDF_STATUS qdf_mem_debugfs_init(void)
{
@@ -486,9 +509,23 @@ static QDF_STATUS qdf_mem_debugfs_init(void)
}
static void qdf_mem_debugfs_exit(void) {}
#endif
#endif /* WLAN_DEBUGFS && MEMORY_DEBUG */
static QDF_STATUS qdf_mem_debug_debugfs_init(void)
{
return QDF_STATUS_E_NOSUPPORT;
}
static QDF_STATUS qdf_mem_debug_debugfs_init(void)
{
return QDF_STATUS_E_NOSUPPORT;
}
static QDF_STATUS qdf_mem_debug_debugfs_exit(void)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif /* WLAN_DEBUGFS */
/**
* __qdf_mempool_init() - Create and initialize memory pool
@@ -764,27 +801,26 @@ static inline bool qdf_mem_prealloc_put(void *ptr)
#ifdef MEMORY_DEBUG
/**
* qdf_mem_init() - initialize qdf memory debug functionality
* qdf_mem_debug_init() - initialize qdf memory debug functionality
*
* Return: none
*/
void qdf_mem_init(void)
static void qdf_mem_debug_init(void)
{
/* Initalizing the list with maximum size of 60000 */
qdf_list_create(&qdf_mem_list, 60000);
qdf_spinlock_create(&qdf_mem_list_lock);
qdf_net_buf_debug_init();
qdf_mem_debugfs_init();
return;
}
EXPORT_SYMBOL(qdf_mem_init);
/**
* qdf_mem_clean() - display memory leak debug info and free leaked pointers
* qdf_mem_debug_clean() - display memory leak debug info and free leaked
* pointers
*
* Return: none
*/
void qdf_mem_clean(void)
static void qdf_mem_debug_clean(void)
{
uint32_t list_size;
list_size = qdf_list_size(&qdf_mem_list);
@@ -848,21 +884,18 @@ void qdf_mem_clean(void)
#endif
}
}
EXPORT_SYMBOL(qdf_mem_clean);
/**
* qdf_mem_exit() - exit qdf memory debug functionality
* qdf_mem_debug_exit() - exit qdf memory debug functionality
*
* Return: none
*/
void qdf_mem_exit(void)
static void qdf_mem_debug_exit(void)
{
qdf_mem_debugfs_exit();
qdf_net_buf_debug_exit();
qdf_mem_clean();
qdf_mem_debug_clean();
qdf_list_destroy(&qdf_mem_list);
}
EXPORT_SYMBOL(qdf_mem_exit);
/**
* qdf_mem_malloc_debug() - debug version of QDF memory allocation API
@@ -925,7 +958,7 @@ void *qdf_mem_malloc_debug(size_t size,
mem_struct->line_num = line_num;
mem_struct->size = size;
qdf_atomic_inc(&mem_struct->in_use);
qdf_mem_kmalloc_inc(size);
qdf_mem_kmalloc_inc(ksize(mem_struct));
qdf_mem_copy(&mem_struct->header[0],
&WLAN_MEM_HEADER[0], sizeof(WLAN_MEM_HEADER));
@@ -1052,7 +1085,7 @@ void qdf_mem_free(void *ptr)
list_del_init(&mem_struct->node);
qdf_mem_list.count--;
qdf_spin_unlock_irqrestore(&qdf_mem_list_lock);
qdf_mem_kmalloc_dec(mem_struct->size);
qdf_mem_kmalloc_dec(ksize(mem_struct));
kfree(mem_struct);
return;
@@ -1096,6 +1129,9 @@ error:
}
EXPORT_SYMBOL(qdf_mem_free);
#else
static void qdf_mem_debug_init(void) {}
static void qdf_mem_debug_exit(void) {}
/**
* qdf_mem_malloc() - allocation QDF memory
@@ -1121,7 +1157,13 @@ void *qdf_mem_malloc(size_t size)
if (in_interrupt() || irqs_disabled() || in_atomic())
flags = GFP_ATOMIC;
return kzalloc(size, flags);
mem = kzalloc(size, flags);
if (mem)
qdf_mem_kmalloc_inc(ksize(mem));
return mem;
}
EXPORT_SYMBOL(qdf_mem_malloc);
@@ -1141,6 +1183,8 @@ void qdf_mem_free(void *ptr)
if (qdf_mem_prealloc_put(ptr))
return;
qdf_mem_kmalloc_dec(ksize(ptr));
kfree(ptr);
}
EXPORT_SYMBOL(qdf_mem_free);
@@ -1483,6 +1527,8 @@ void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, qdf_size_t size,
* of different size" warning on some platforms
*/
BUILD_BUG_ON(sizeof(*phy_addr) < sizeof(vaddr));
if (vaddr)
qdf_mem_dma_inc(ksize(vaddr));
return vaddr;
}
@@ -1555,6 +1601,7 @@ inline void qdf_mem_free_consistent(qdf_device_t osdev, void *dev,
qdf_dma_addr_t phy_addr,
qdf_dma_context_t memctx)
{
qdf_mem_dma_dec(ksize(vaddr));
qdf_mem_free(vaddr);
return;
}
@@ -1612,3 +1659,19 @@ void qdf_mem_dma_sync_single_for_cpu(qdf_device_t osdev,
dma_sync_single_for_cpu(osdev->dev, bus_addr, size, direction);
}
EXPORT_SYMBOL(qdf_mem_dma_sync_single_for_cpu);
void qdf_mem_init(void)
{
qdf_mem_debug_init();
qdf_mem_debugfs_init();
qdf_mem_debug_debugfs_init();
}
EXPORT_SYMBOL(qdf_mem_init);
void qdf_mem_exit(void)
{
qdf_mem_debug_debugfs_exit();
qdf_mem_debugfs_exit();
qdf_mem_debug_exit();
}
EXPORT_SYMBOL(qdf_mem_exit);