diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h index 4746fa9074..0777288cc6 100644 --- a/qdf/inc/qdf_mem.h +++ b/qdf/inc/qdf_mem.h @@ -28,6 +28,7 @@ #include #include #include +#include #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 */ diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h index de97deb6a7..069bffe789 100644 --- a/qdf/inc/qdf_nbuf.h +++ b/qdf/inc/qdf_nbuf.h @@ -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) diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h index 7b013115bc..ecc543357a 100644 --- a/qdf/linux/src/i_qdf_nbuf.h +++ b/qdf/linux/src/i_qdf_nbuf.h @@ -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; diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c index 74e8c5beba..2d3c640656 100644 --- a/qdf/linux/src/qdf_mem.c +++ b/qdf/linux/src/qdf_mem.c @@ -28,7 +28,6 @@ #include "qdf_mc_timer.h" #include "qdf_module.h" #include -#include "qdf_atomic.h" #include "qdf_str.h" #include "qdf_talloc.h" #include @@ -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); + diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 4ad0e2e023..350aae1f04 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -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);