qcacmn: Add memory stats pertaining to DP usage

Add sysfs node for DP level memory stats:
/sys/kernel/wifi/wlan/wlan_dp_mem_stats
These include Tx, Rx SKB memory allocated, Tx/Rx
buffer count, outstanding Tx desc count.
Add and subtract the skb memory for Rx/Tx when
the map/unmap functions are invoked.

Change-Id: If62cc47bb60f7eb63f60e861f755f3417248677f
CRs-Fixed: 2724482
This commit is contained in:
Nisha Menon
2020-06-30 23:44:01 -07:00
committed by snandini
parent 3824548f38
commit 3db73f1414
5 changed files with 502 additions and 21 deletions

View File

@@ -28,6 +28,7 @@
#include <qdf_types.h>
#include <i_qdf_mem.h>
#include <i_qdf_trace.h>
#include <qdf_atomic.h>
#define QDF_CACHE_LINE_SZ __qdf_cache_line_sz
@@ -604,7 +605,85 @@ void qdf_mem_skb_inc(qdf_size_t size);
*/
void qdf_mem_skb_dec(qdf_size_t size);
/**
* qdf_mem_skb_total_inc() - increment total skb allocation size
* in host driver in both debug and perf builds
* @size: size to be added
*
* Return: none
*/
void qdf_mem_skb_total_inc(qdf_size_t size);
/**
* qdf_mem_skb_total_dec() - decrement total skb allocation size
* in the host driver in debug and perf flavors
* @size: size to be decremented
*
* Return: none
*/
void qdf_mem_skb_total_dec(qdf_size_t size);
/**
* qdf_mem_dp_tx_skb_inc() - Increment Tx skb allocation size
* @size: size to be added
*
* Return: none
*/
void qdf_mem_dp_tx_skb_inc(qdf_size_t size);
/**
* qdf_mem_dp_tx_skb_dec() - Decrement Tx skb allocation size
* @size: size to be decreased
*
* Return: none
*/
void qdf_mem_dp_tx_skb_dec(qdf_size_t size);
/**
* qdf_mem_dp_rx_skb_inc() - Increment Rx skb allocation size
* @size: size to be added
*
* Return: none
*/
void qdf_mem_dp_rx_skb_inc(qdf_size_t size);
/**
* qdf_mem_dp_rx_skb_dec() - Decrement Rx skb allocation size
* @size: size to be decreased
*
* Return: none
*/
void qdf_mem_dp_rx_skb_dec(qdf_size_t size);
/**
* qdf_mem_dp_tx_skb_cnt_inc() - Increment Tx buffer count
*
* Return: none
*/
void qdf_mem_dp_tx_skb_cnt_inc(void);
/**
* qdf_mem_dp_tx_skb_cnt_dec() - Decrement Tx buffer count
*
* Return: none
*/
void qdf_mem_dp_tx_skb_cnt_dec(void);
/**
* qdf_mem_dp_rx_skb_cnt_inc() - Increment Rx buffer count
*
* Return: none
*/
void qdf_mem_dp_rx_skb_cnt_inc(void);
/**
* qdf_mem_dp_rx_skb_cnt_dec() - Decrement Rx buffer count
*
* Return: none
*/
void qdf_mem_dp_rx_skb_cnt_dec(void);
#else
static inline void qdf_mem_skb_inc(qdf_size_t size)
{
}
@@ -612,6 +691,46 @@ static inline void qdf_mem_skb_inc(qdf_size_t size)
static inline void qdf_mem_skb_dec(qdf_size_t size)
{
}
static inline void qdf_mem_skb_total_inc(qdf_size_t size)
{
}
static inline void qdf_mem_skb_total_dec(qdf_size_t size)
{
}
static inline void qdf_mem_dp_tx_skb_inc(qdf_size_t size)
{
}
static inline void qdf_mem_dp_tx_skb_dec(qdf_size_t size)
{
}
static inline void qdf_mem_dp_rx_skb_inc(qdf_size_t size)
{
}
static inline void qdf_mem_dp_rx_skb_dec(qdf_size_t size)
{
}
static inline void qdf_mem_dp_tx_skb_cnt_inc(void)
{
}
static inline void qdf_mem_dp_tx_skb_cnt_dec(void)
{
}
static inline void qdf_mem_dp_rx_skb_cnt_inc(void)
{
}
static inline void qdf_mem_dp_rx_skb_cnt_dec(void)
{
}
#endif /* CONFIG_WLAN_SYSFS_MEM_STATS */
/**
@@ -868,7 +987,7 @@ static inline void qdf_mem_shared_mem_free(qdf_device_t osdev,
* qdf_dma_mem_stats_read() - Return the DMA memory allocated in
* host driver
*
* Return: None
* Return: Total DMA memory allocated
*/
int32_t qdf_dma_mem_stats_read(void);
@@ -876,7 +995,7 @@ int32_t qdf_dma_mem_stats_read(void);
* qdf_heap_mem_stats_read() - Return the heap memory allocated
* in host driver
*
* Return: None
* Return: Total heap memory allocated
*/
int32_t qdf_heap_mem_stats_read(void);
@@ -884,8 +1003,127 @@ int32_t qdf_heap_mem_stats_read(void);
* qdf_skb_mem_stats_read() - Return the SKB memory allocated in
* host driver
*
* Return: None
* Return: Total SKB memory allocated
*/
int32_t qdf_skb_mem_stats_read(void);
/**
* qdf_skb_total_mem_stats_read() - Return the SKB memory allocated
* in the host driver tracked in both debug and perf builds
*
* Return: Total SKB memory allocated
*/
int32_t qdf_skb_total_mem_stats_read(void);
/**
* qdf_skb_max_mem_stats_read() - Return the max SKB memory
* allocated in host driver. This is the high watermark for the
* total SKB allocated in the host driver
*
* Return: None
*/
int32_t qdf_skb_max_mem_stats_read(void);
/**
* qdf_mem_tx_desc_cnt_read() - Return the outstanding Tx descs
* which are waiting on Tx completions
*
* Return: Outstanding Tx desc count
*/
int32_t qdf_mem_tx_desc_cnt_read(void);
/**
* qdf_mem_tx_desc_max_read() - Return the max outstanding Tx
* descs which are waiting on Tx completions. This is the high
* watermark for the pending desc count
*
* Return: Max outstanding Tx desc count
*/
int32_t qdf_mem_tx_desc_max_read(void);
/**
* qdf_mem_stats_init() - Initialize the qdf memstats fields on
* creating the sysfs node
*
* Return: None
*/
void qdf_mem_stats_init(void);
/**
* qdf_dp_tx_skb_mem_stats_read() - Return the SKB memory
* allocated for Tx data path
*
* Return: Tx SKB memory allocated
*/
int32_t qdf_dp_tx_skb_mem_stats_read(void);
/**
* qdf_dp_rx_skb_mem_stats_read() - Return the SKB memory
* allocated for Rx data path
*
* Return: Rx SKB memory allocated
*/
int32_t qdf_dp_rx_skb_mem_stats_read(void);
/**
* qdf_dp_tx_skb_max_mem_stats_read() - Return the high
* watermark for the SKB memory allocated for Tx data path
*
* Return: Max Tx SKB memory allocated
*/
int32_t qdf_dp_tx_skb_max_mem_stats_read(void);
/**
* qdf_dp_rx_skb_max_mem_stats_read() - Return the high
* watermark for the SKB memory allocated for Rx data path
*
* Return: Max Rx SKB memory allocated
*/
int32_t qdf_dp_rx_skb_max_mem_stats_read(void);
/**
* qdf_mem_dp_tx_skb_cnt_read() - Return number of buffers
* allocated in the Tx data path by the host driver or
* buffers coming from the n/w stack
*
* Return: Number of DP Tx buffers allocated
*/
int32_t qdf_mem_dp_tx_skb_cnt_read(void);
/**
* qdf_mem_dp_tx_skb_max_cnt_read() - Return max number of
* buffers allocated in the Tx data path
*
* Return: Max number of DP Tx buffers allocated
*/
int32_t qdf_mem_dp_tx_skb_max_cnt_read(void);
/**
* qdf_mem_dp_rx_skb_cnt_read() - Return number of buffers
* allocated in the Rx data path
*
* Return: Number of DP Rx buffers allocated
*/
int32_t qdf_mem_dp_rx_skb_cnt_read(void);
/**
* qdf_mem_dp_rx_skb_max_cnt_read() - Return max number of
* buffers allocated in the Rx data path
*
* Return: Max number of DP Rx buffers allocated
*/
int32_t qdf_mem_dp_rx_skb_max_cnt_read(void);
/**
* qdf_mem_tx_desc_cnt_update() - Update the pending tx desc
* count and the high watermark for pending tx desc count
*
* @pending_tx_descs: outstanding Tx desc count
* @tx_descs_max: high watermark for outstanding Tx desc count
*
* Return: None
*/
void qdf_mem_tx_desc_cnt_update(qdf_atomic_t pending_tx_descs,
int32_t tx_descs_max);
#endif /* __QDF_MEMORY_H */

View File

@@ -1702,12 +1702,7 @@ static inline qdf_nbuf_t
qdf_nbuf_alloc_fl(qdf_device_t osdev, qdf_size_t size, int reserve, int align,
int prio, const char *func, uint32_t line)
{
qdf_nbuf_t nbuf;
nbuf = __qdf_nbuf_alloc(osdev, size, reserve, align, prio, func, line);
if (qdf_likely(nbuf))
qdf_mem_skb_inc(nbuf->truesize);
return nbuf;
return __qdf_nbuf_alloc(osdev, size, reserve, align, prio, func, line);
}
/**
@@ -1727,14 +1722,7 @@ static inline qdf_nbuf_t
qdf_nbuf_alloc_no_recycler_fl(size_t size, int reserve, int align,
const char *func, uint32_t line)
{
qdf_nbuf_t nbuf;
nbuf = __qdf_nbuf_alloc_no_recycler(size, reserve, align, func, line);
if (qdf_likely(nbuf))
qdf_mem_skb_inc(nbuf->truesize);
return nbuf;
return __qdf_nbuf_alloc_no_recycler(size, reserve, align, func, line);
}
static inline void qdf_nbuf_free(qdf_nbuf_t buf)

View File

@@ -2230,6 +2230,47 @@ static inline void __qdf_nbuf_orphan(struct sk_buff *skb)
return skb_orphan(skb);
}
#ifdef CONFIG_WLAN_SYSFS_MEM_STATS
/**
* __qdf_record_nbuf_nbytes() - add or subtract the size of the nbuf
* from the total skb mem and DP tx/rx skb mem
* @nbytes: number of bytes
* @dir: direction
* @is_mapped: is mapped or unmapped memory
*
* Return: none
*/
static inline void __qdf_record_nbuf_nbytes(
int nbytes, qdf_dma_dir_t dir, bool is_mapped)
{
if (is_mapped) {
if (dir == QDF_DMA_TO_DEVICE) {
qdf_mem_dp_tx_skb_cnt_inc();
qdf_mem_dp_tx_skb_inc(nbytes);
} else if (dir == QDF_DMA_FROM_DEVICE) {
qdf_mem_dp_rx_skb_cnt_inc();
qdf_mem_dp_rx_skb_inc(nbytes);
}
qdf_mem_skb_total_inc(nbytes);
} else {
if (dir == QDF_DMA_TO_DEVICE) {
qdf_mem_dp_tx_skb_cnt_dec();
qdf_mem_dp_tx_skb_dec(nbytes);
} else if (dir == QDF_DMA_FROM_DEVICE) {
qdf_mem_dp_rx_skb_cnt_dec();
qdf_mem_dp_rx_skb_dec(nbytes);
}
qdf_mem_skb_total_dec(nbytes);
}
}
#else /* CONFIG_WLAN_SYSFS_MEM_STATS */
static inline void __qdf_record_nbuf_nbytes(
int nbytes, qdf_dma_dir_t dir, bool is_mapped)
{
}
#endif /* CONFIG_WLAN_SYSFS_MEM_STATS */
/**
* __qdf_nbuf_map_nbytes_single() - map nbytes
* @osdev: os device
@@ -2255,13 +2296,17 @@ static inline QDF_STATUS __qdf_nbuf_map_nbytes_single(
qdf_dma_dir_t dir, int nbytes)
{
qdf_dma_addr_t paddr;
QDF_STATUS ret;
/* assume that the OS only provides a single fragment */
QDF_NBUF_CB_PADDR(buf) = paddr =
dma_map_single(osdev->dev, buf->data,
nbytes, __qdf_dma_dir_to_os(dir));
return dma_mapping_error(osdev->dev, paddr) ?
ret = dma_mapping_error(osdev->dev, paddr) ?
QDF_STATUS_E_FAULT : QDF_STATUS_SUCCESS;
if (QDF_IS_STATUS_SUCCESS(ret))
__qdf_record_nbuf_nbytes(nbytes, dir, true);
return ret;
}
#endif
/**
@@ -2288,6 +2333,7 @@ __qdf_nbuf_unmap_nbytes_single(qdf_device_t osdev, struct sk_buff *buf,
qdf_dma_addr_t paddr = QDF_NBUF_CB_PADDR(buf);
if (qdf_likely(paddr)) {
__qdf_record_nbuf_nbytes(nbytes, dir, false);
dma_unmap_single(osdev->dev, paddr, nbytes,
__qdf_dma_dir_to_os(dir));
return;

View File

@@ -28,7 +28,6 @@
#include "qdf_mc_timer.h"
#include "qdf_module.h"
#include <qdf_trace.h>
#include "qdf_atomic.h"
#include "qdf_str.h"
#include "qdf_talloc.h"
#include <linux/debugfs.h>
@@ -60,11 +59,35 @@ static bool is_initial_mem_debug_disabled;
* @kmalloc: total kmalloc allocations
* @dma: total dma allocations
* @skb: total skb allocations
* @skb_total: total skb allocations in host driver
* @dp_tx_skb: total Tx skb allocations in datapath
* @dp_rx_skb: total Rx skb allocations in datapath
* @skb_mem_max: high watermark for skb allocations
* @dp_tx_skb_mem_max: high watermark for Tx DP skb allocations
* @dp_rx_skb_mem_max: high watermark for Rx DP skb allocations
* @dp_tx_skb_count: DP Tx buffer count
* @dp_tx_skb_count_max: High watermark for DP Tx buffer count
* @dp_rx_skb_count: DP Rx buffer count
* @dp_rx_skb_count_max: High watermark for DP Rx buffer count
* @tx_descs_outstanding: Current pending Tx descs count
* @tx_descs_max: High watermark for pending Tx descs count
*/
static struct __qdf_mem_stat {
qdf_atomic_t kmalloc;
qdf_atomic_t dma;
qdf_atomic_t skb;
qdf_atomic_t skb_total;
qdf_atomic_t dp_tx_skb;
qdf_atomic_t dp_rx_skb;
int32_t skb_mem_max;
int32_t dp_tx_skb_mem_max;
int32_t dp_rx_skb_mem_max;
qdf_atomic_t dp_tx_skb_count;
int32_t dp_tx_skb_count_max;
qdf_atomic_t dp_rx_skb_count;
int32_t dp_rx_skb_count_max;
qdf_atomic_t tx_descs_outstanding;
int32_t tx_descs_max;
} qdf_mem_stat;
#ifdef MEMORY_DEBUG
@@ -1044,6 +1067,83 @@ void qdf_mem_skb_dec(qdf_size_t size)
{
qdf_atomic_sub(size, &qdf_mem_stat.skb);
}
void qdf_mem_skb_total_inc(qdf_size_t size)
{
int32_t skb_mem_max = 0;
qdf_atomic_add(size, &qdf_mem_stat.skb_total);
skb_mem_max = qdf_atomic_read(&qdf_mem_stat.skb_total);
if (qdf_mem_stat.skb_mem_max < skb_mem_max)
qdf_mem_stat.skb_mem_max = skb_mem_max;
}
void qdf_mem_skb_total_dec(qdf_size_t size)
{
qdf_atomic_sub(size, &qdf_mem_stat.skb_total);
}
void qdf_mem_dp_tx_skb_inc(qdf_size_t size)
{
int32_t curr_dp_tx_skb_mem_max = 0;
qdf_atomic_add(size, &qdf_mem_stat.dp_tx_skb);
curr_dp_tx_skb_mem_max = qdf_atomic_read(&qdf_mem_stat.dp_tx_skb);
if (qdf_mem_stat.dp_tx_skb_mem_max < curr_dp_tx_skb_mem_max)
qdf_mem_stat.dp_tx_skb_mem_max = curr_dp_tx_skb_mem_max;
}
void qdf_mem_dp_tx_skb_dec(qdf_size_t size)
{
qdf_atomic_sub(size, &qdf_mem_stat.dp_tx_skb);
}
void qdf_mem_dp_rx_skb_inc(qdf_size_t size)
{
int32_t curr_dp_rx_skb_mem_max = 0;
qdf_atomic_add(size, &qdf_mem_stat.dp_rx_skb);
curr_dp_rx_skb_mem_max = qdf_atomic_read(&qdf_mem_stat.dp_rx_skb);
if (qdf_mem_stat.dp_rx_skb_mem_max < curr_dp_rx_skb_mem_max)
qdf_mem_stat.dp_rx_skb_mem_max = curr_dp_rx_skb_mem_max;
}
void qdf_mem_dp_rx_skb_dec(qdf_size_t size)
{
qdf_atomic_sub(size, &qdf_mem_stat.dp_rx_skb);
}
void qdf_mem_dp_tx_skb_cnt_inc(void)
{
int32_t curr_dp_tx_skb_count_max = 0;
qdf_atomic_add(1, &qdf_mem_stat.dp_tx_skb_count);
curr_dp_tx_skb_count_max =
qdf_atomic_read(&qdf_mem_stat.dp_tx_skb_count);
if (qdf_mem_stat.dp_tx_skb_count_max < curr_dp_tx_skb_count_max)
qdf_mem_stat.dp_tx_skb_count_max = curr_dp_tx_skb_count_max;
}
void qdf_mem_dp_tx_skb_cnt_dec(void)
{
qdf_atomic_sub(1, &qdf_mem_stat.dp_tx_skb_count);
}
void qdf_mem_dp_rx_skb_cnt_inc(void)
{
int32_t curr_dp_rx_skb_count_max = 0;
qdf_atomic_add(1, &qdf_mem_stat.dp_rx_skb_count);
curr_dp_rx_skb_count_max =
qdf_atomic_read(&qdf_mem_stat.dp_rx_skb_count);
if (qdf_mem_stat.dp_rx_skb_count_max < curr_dp_rx_skb_count_max)
qdf_mem_stat.dp_rx_skb_count_max = curr_dp_rx_skb_count_max;
}
void qdf_mem_dp_rx_skb_cnt_dec(void)
{
qdf_atomic_sub(1, &qdf_mem_stat.dp_rx_skb_count);
}
#endif
void qdf_mem_kmalloc_dec(qdf_size_t size)
@@ -2543,3 +2643,108 @@ int32_t qdf_skb_mem_stats_read(void)
qdf_export_symbol(qdf_skb_mem_stats_read);
int32_t qdf_skb_total_mem_stats_read(void)
{
return qdf_atomic_read(&qdf_mem_stat.skb_total);
}
qdf_export_symbol(qdf_skb_total_mem_stats_read);
int32_t qdf_skb_max_mem_stats_read(void)
{
return qdf_mem_stat.skb_mem_max;
}
qdf_export_symbol(qdf_skb_max_mem_stats_read);
int32_t qdf_dp_tx_skb_mem_stats_read(void)
{
return qdf_atomic_read(&qdf_mem_stat.dp_tx_skb);
}
qdf_export_symbol(qdf_dp_tx_skb_mem_stats_read);
int32_t qdf_dp_rx_skb_mem_stats_read(void)
{
return qdf_atomic_read(&qdf_mem_stat.dp_rx_skb);
}
qdf_export_symbol(qdf_dp_rx_skb_mem_stats_read);
int32_t qdf_mem_dp_tx_skb_cnt_read(void)
{
return qdf_atomic_read(&qdf_mem_stat.dp_tx_skb_count);
}
qdf_export_symbol(qdf_mem_dp_tx_skb_cnt_read);
int32_t qdf_mem_dp_tx_skb_max_cnt_read(void)
{
return qdf_mem_stat.dp_tx_skb_count_max;
}
qdf_export_symbol(qdf_mem_dp_tx_skb_max_cnt_read);
int32_t qdf_mem_dp_rx_skb_cnt_read(void)
{
return qdf_atomic_read(&qdf_mem_stat.dp_rx_skb_count);
}
qdf_export_symbol(qdf_mem_dp_rx_skb_cnt_read);
int32_t qdf_mem_dp_rx_skb_max_cnt_read(void)
{
return qdf_mem_stat.dp_rx_skb_count_max;
}
qdf_export_symbol(qdf_mem_dp_rx_skb_max_cnt_read);
int32_t qdf_dp_tx_skb_max_mem_stats_read(void)
{
return qdf_mem_stat.dp_tx_skb_mem_max;
}
qdf_export_symbol(qdf_dp_tx_skb_max_mem_stats_read);
int32_t qdf_dp_rx_skb_max_mem_stats_read(void)
{
return qdf_mem_stat.dp_rx_skb_mem_max;
}
qdf_export_symbol(qdf_dp_rx_skb_max_mem_stats_read);
int32_t qdf_mem_tx_desc_cnt_read(void)
{
return qdf_atomic_read(&qdf_mem_stat.tx_descs_outstanding);
}
qdf_export_symbol(qdf_mem_tx_desc_cnt_read);
int32_t qdf_mem_tx_desc_max_read(void)
{
return qdf_mem_stat.tx_descs_max;
}
qdf_export_symbol(qdf_mem_tx_desc_max_read);
void qdf_mem_tx_desc_cnt_update(qdf_atomic_t pending_tx_descs,
int32_t tx_descs_max)
{
qdf_mem_stat.tx_descs_outstanding = pending_tx_descs;
qdf_mem_stat.tx_descs_max = tx_descs_max;
}
qdf_export_symbol(qdf_mem_tx_desc_cnt_update);
void qdf_mem_stats_init(void)
{
qdf_mem_stat.skb_mem_max = 0;
qdf_mem_stat.dp_tx_skb_mem_max = 0;
qdf_mem_stat.dp_rx_skb_mem_max = 0;
qdf_mem_stat.dp_tx_skb_count_max = 0;
qdf_mem_stat.dp_rx_skb_count_max = 0;
qdf_mem_stat.tx_descs_max = 0;
}
qdf_export_symbol(qdf_mem_stats_init);

View File

@@ -697,7 +697,6 @@ void __qdf_nbuf_free(struct sk_buff *skb)
qdf_nbuf_frag_count_dec(skb);
qdf_nbuf_count_dec(skb);
qdf_mem_skb_dec(skb->truesize);
if (nbuf_free_cb)
nbuf_free_cb(skb);
else
@@ -1088,6 +1087,8 @@ __qdf_nbuf_map_single(qdf_device_t osdev, qdf_nbuf_t buf, qdf_dma_dir_t dir)
dma_map_single(osdev->dev, buf->data,
skb_end_pointer(buf) - buf->data,
__qdf_dma_dir_to_os(dir));
__qdf_record_nbuf_nbytes(
__qdf_nbuf_get_data_len(buf), dir, true);
return dma_mapping_error(osdev->dev, paddr)
? QDF_STATUS_E_FAILURE
: QDF_STATUS_SUCCESS;
@@ -1111,10 +1112,13 @@ void __qdf_nbuf_unmap_single(qdf_device_t osdev, qdf_nbuf_t buf,
void __qdf_nbuf_unmap_single(qdf_device_t osdev, qdf_nbuf_t buf,
qdf_dma_dir_t dir)
{
if (QDF_NBUF_CB_PADDR(buf))
if (QDF_NBUF_CB_PADDR(buf)) {
__qdf_record_nbuf_nbytes(
__qdf_nbuf_get_data_len(buf), dir, false);
dma_unmap_single(osdev->dev, QDF_NBUF_CB_PADDR(buf),
skb_end_pointer(buf) - buf->data,
__qdf_dma_dir_to_os(dir));
}
}
#endif
qdf_export_symbol(__qdf_nbuf_unmap_single);