From 9c99e124a279391dbe2cef66226fd4e86bde8f4d Mon Sep 17 00:00:00 2001 From: Maharaja Kennadyrajan Date: Mon, 4 Jan 2021 23:46:53 +0530 Subject: [PATCH 1/2] ath11k/mac80211: Add support to account memory stats Memory allocations in the driver & mac80211 are logged and populate those values to the user space via debugfs. This stats will give the snapshot of the memory being used by the driver at the time of dumping these memory stats. Command: cat /sys/kernel/debug/ath11k/ipq8074\ hw2.0/memory_stats Sample output of the stats MEMORY STATS IN BYTES: malloc size : 6287583 ce_ring_alloc size: 109308 dma_alloc size:: 10831860 htc_skb_alloc size: 3840 wmi alloc size: 0 per peer object: 4644 rx_post_buf size: 5091840 Total size: 22329075 User can disable/enable the memory stats accounting with the below command. echo N > /sys/kernel/debug/ath11k/ipq8074\ hw2.0/enable_memory_stats where N = 0 to disable logging, 1 to enable the logging. Note: This should be enabled/disabled only after wifi is down. User shouldn't enable/disable when the wifi is up to avoid accounting the negative values which cause incorrect values in the memory stats. Command: cat /sys/kernel/debug/ieee80211/phyX/memory_stats memory stats: malloc_size: 108 Signed-off-by: Maharaja Kennadyrajan --- drivers/net/wireless/ath/ath11k/ce.c | 24 ++++ drivers/net/wireless/ath/ath11k/core.c | 2 +- drivers/net/wireless/ath/ath11k/core.h | 19 +++ drivers/net/wireless/ath/ath11k/coredump.c | 15 ++- drivers/net/wireless/ath/ath11k/dbring.c | 3 + drivers/net/wireless/ath/ath11k/debugfs.c | 115 ++++++++++++++++++ drivers/net/wireless/ath/ath11k/debugfs.h | 29 +++++ drivers/net/wireless/ath/ath11k/debugfs_sta.c | 4 + drivers/net/wireless/ath/ath11k/dp.c | 13 ++ drivers/net/wireless/ath/ath11k/hal.c | 6 + drivers/net/wireless/ath/ath11k/htc.c | 5 + drivers/net/wireless/ath/ath11k/mac.c | 15 ++- drivers/net/wireless/ath/ath11k/nss.c | 46 +++++++ drivers/net/wireless/ath/ath11k/peer.c | 5 + drivers/net/wireless/ath/ath11k/wmi.c | 4 + 15 files changed, 302 insertions(+), 3 deletions(-) --- a/drivers/net/wireless/ath/ath11k/ce.c +++ b/drivers/net/wireless/ath/ath11k/ce.c @@ -357,6 +357,9 @@ static int ath11k_ce_rx_post_pipe(struct dev_kfree_skb_any(skb); goto exit; } + + ATH11K_MEMORY_STATS_INC(ab, ce_rx_pipe, skb->truesize); + } exit: @@ -425,6 +428,9 @@ static void ath11k_ce_recv_process_cb(st __skb_queue_head_init(&list); while (ath11k_ce_completed_recv_next(pipe, &skb, &nbytes) == 0) { max_nbytes = skb->len + skb_tailroom(skb); + + ATH11K_MEMORY_STATS_DEC(ab, ce_rx_pipe, skb->truesize); + dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr, max_nbytes, DMA_FROM_DEVICE); @@ -618,6 +624,9 @@ ath11k_ce_alloc_ring(struct ath11k_base if (ce_ring == NULL) return ERR_PTR(-ENOMEM); + ATH11K_MEMORY_STATS_INC(ab, ce_ring_alloc, + struct_size(ce_ring, skb, nentries)); + ce_ring->nentries = nentries; ce_ring->nentries_mask = nentries - 1; @@ -633,6 +642,9 @@ ath11k_ce_alloc_ring(struct ath11k_base return ERR_PTR(-ENOMEM); } + ATH11K_MEMORY_STATS_INC(ab, ce_ring_alloc, + nentries * desc_sz + CE_DESC_RING_ALIGN); + ce_ring->base_addr_ce_space_unaligned = base_addr; ce_ring->base_addr_owner_space = PTR_ALIGN( @@ -812,6 +824,9 @@ static void ath11k_ce_rx_pipe_cleanup(st continue; ring->skb[i] = NULL; + + ATH11K_MEMORY_STATS_DEC(ab, ce_rx_pipe, skb->truesize); + dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); dev_kfree_skb_any(skb); @@ -991,6 +1006,9 @@ void ath11k_ce_free_pipes(struct ath11k_ CE_DESC_RING_ALIGN, pipe->src_ring->base_addr_owner_space, pipe->src_ring->base_addr_ce_space); + ATH11K_MEMORY_STATS_DEC(ab, ce_ring_alloc, + pipe->src_ring->nentries * desc_sz + + CE_DESC_RING_ALIGN); kfree(pipe->src_ring); pipe->src_ring = NULL; } @@ -1002,6 +1020,9 @@ void ath11k_ce_free_pipes(struct ath11k_ CE_DESC_RING_ALIGN, pipe->dest_ring->base_addr_owner_space, pipe->dest_ring->base_addr_ce_space); + ATH11K_MEMORY_STATS_DEC(ab, ce_ring_alloc, + pipe->dest_ring->nentries * desc_sz + + CE_DESC_RING_ALIGN); kfree(pipe->dest_ring); pipe->dest_ring = NULL; } @@ -1014,6 +1035,9 @@ void ath11k_ce_free_pipes(struct ath11k_ CE_DESC_RING_ALIGN, pipe->status_ring->base_addr_owner_space, pipe->status_ring->base_addr_ce_space); + ATH11K_MEMORY_STATS_DEC(ab, ce_ring_alloc, + pipe->status_ring->nentries * desc_sz + + CE_DESC_RING_ALIGN); kfree(pipe->status_ring); pipe->status_ring = NULL; } --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1353,6 +1353,8 @@ int ath11k_core_pre_init(struct ath11k_b if (nss_offload) ab->nss.stats_enabled = 1; + ab->enable_memory_stats = ATH11K_DEBUG_ENABLE_MEMORY_STATS; + return 0; } EXPORT_SYMBOL(ath11k_core_pre_init); --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -801,6 +801,23 @@ struct ath11k_internal_pci { wait_queue_head_t qgic_msi_waitq; }; +struct ath11k_memory_stats { + /* Account kzalloc and valloc */ + atomic_t malloc_size; + /* Account dma_alloc in dp.c & hal.c */ + atomic_t dma_alloc; + /* Account memory used in ce rings */ + atomic_t ce_ring_alloc; + /* Account memory used in htc_send */ + atomic_t htc_skb_alloc; + /* Account memory used in wmi tx skb alloc */ + atomic_t wmi_tx_skb_alloc; + /* Account memory consumed for peer object */ + atomic_t per_peer_object; + /* Account memory used in ce rx pipe */ + atomic_t ce_rx_pipe; +}; + /* Master structure to hold the hw data which may be used in core module */ struct ath11k_base { enum ath11k_hw_rev hw_rev; @@ -878,6 +895,7 @@ struct ath11k_base { enum ath11k_dfs_region dfs_region; #ifdef CPTCFG_ATH11K_DEBUGFS struct dentry *debugfs_soc; + struct ath11k_memory_stats memory_stats; #endif struct ath11k_soc_dp_stats soc_stats; @@ -916,6 +934,7 @@ struct ath11k_base { struct ath11k_num_vdevs_peers *num_vdevs_peers; int userpd_id; struct ath11k_internal_pci ipci; + bool enable_memory_stats; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); --- a/drivers/net/wireless/ath/ath11k/coredump.c +++ b/drivers/net/wireless/ath/ath11k/coredump.c @@ -109,6 +109,8 @@ void ath11k_coredump_build_inline(struct if (!buf) return; + ATH11K_MEMORY_STATS_INC(ab, malloc_size, header_size); + file_data = (struct ath11k_dump_file_data *)buf; strlcpy(file_data->df_magic, "ATH11K-FW-DUMP", sizeof(file_data->df_magic)); @@ -132,8 +134,10 @@ void ath11k_coredump_build_inline(struct memcpy(file_data->seg, segments, num_seg * sizeof(*segments)); dump_state = vzalloc(sizeof(*dump_state)); - if(!dump_state) + if(!dump_state) { + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, header_size); return; + } dump_state->header = file_data; dump_state->num_seg = num_seg; @@ -145,6 +149,8 @@ void ath11k_coredump_build_inline(struct /* Wait until the dump is read and free is called */ wait_for_completion(&dump_state->dump_done); + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(*dump_state)); + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, header_size); vfree(dump_state); vfree(file_data); } @@ -274,14 +280,19 @@ void ath11k_coredump_qdss_dump(struct at return; } + ATH11K_MEMORY_STATS_INC(ab, malloc_size, len); + if (event_data->total_size && event_data->total_size <= ab->qmi.qdss_mem[0].size) dump = vzalloc(event_data->total_size); if (!dump) { + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, len); vfree(segment); return; } + ATH11K_MEMORY_STATS_INC(ab, malloc_size, event_data->total_size); + if (num_seg == 1) { segment->len = event_data->mem_seg[0].size; segment->vaddr = ab->qmi.qdss_mem[0].vaddr; @@ -339,6 +350,8 @@ void ath11k_coredump_qdss_dump(struct at } ath11k_coredump_build_inline(ar_pci, segment, 1); out: + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, event_data->total_size); + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, len); vfree(segment); vfree(dump); } --- a/drivers/net/wireless/ath/ath11k/dbring.c +++ b/drivers/net/wireless/ath/ath11k/dbring.c @@ -104,6 +104,7 @@ static int ath11k_dbring_fill_bufs(struc break; } num_remain--; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, size); } spin_unlock_bh(&srng->lock); @@ -348,6 +349,8 @@ void ath11k_dbring_buf_cleanup(struct at idr_remove(&ring->bufs_idr, buf_id); dma_unmap_single(ar->ab->dev, buff->paddr, ring->buf_sz, DMA_FROM_DEVICE); + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, sizeof(*buff) + + ring->buf_sz + ring->buf_align - 1); kfree(buff); } --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -1358,6 +1358,8 @@ static ssize_t ath11k_debugfs_dump_soc_d if (!buf) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, malloc_size, size); + len += scnprintf(buf + len, size - len, "SOC RX STATS:\n\n"); len += scnprintf(buf + len, size - len, "err ring pkts: %u\n", soc_stats->err_ring_pkts); @@ -1399,6 +1401,8 @@ static ssize_t ath11k_debugfs_dump_soc_d retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, size); + return retval; } @@ -1476,6 +1480,106 @@ static const struct file_operations fops .open = simple_open, }; +static ssize_t +ath11k_debug_read_enable_memory_stats(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath11k_base *ab = file->private_data; + char buf[10]; + size_t len; + + len = scnprintf(buf, sizeof(buf), "%d\n", ab->enable_memory_stats); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t +ath11k_debug_write_enable_memory_stats(struct file *file, + char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct ath11k_base *ab = file->private_data; + bool enable; + int ret; + + if (kstrtobool_from_user(ubuf, count, &enable)) + return -EINVAL; + + if (enable == ab->enable_memory_stats) { + ret = count; + goto exit; + } + + ab->enable_memory_stats = enable; + ret = count; +exit: + return ret; +} + +static const struct file_operations fops_enable_memory_stats = { + .read = ath11k_debug_read_enable_memory_stats, + .write = ath11k_debug_write_enable_memory_stats, + .owner = THIS_MODULE, + .llseek = default_llseek, + .open = simple_open, +}; + +static ssize_t ath11k_debug_dump_memory_stats(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath11k_base *ab = file->private_data; + struct ath11k_memory_stats *memory_stats = &ab->memory_stats; + int len = 0, retval; + const int size = 4096; + + char *buf; + + buf = kzalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + len += scnprintf(buf + len, size - len, "MEMORY STATS IN BYTES:\n"); + len += scnprintf(buf + len, size - len, "malloc size : %u\n", + atomic_read(&memory_stats->malloc_size)); + len += scnprintf(buf + len, size - len, "ce_ring_alloc size: %u\n", + atomic_read(&memory_stats->ce_ring_alloc)); + len += scnprintf(buf + len, size - len, "dma_alloc size:: %u\n", + atomic_read(&memory_stats->dma_alloc)); + len += scnprintf(buf + len, size - len, "htc_skb_alloc size: %u\n", + atomic_read(&memory_stats->htc_skb_alloc)); + len += scnprintf(buf + len, size - len, "wmi tx skb alloc size: %u\n", + atomic_read(&memory_stats->wmi_tx_skb_alloc)); + len += scnprintf(buf + len, size - len, "per peer object: %u\n", + atomic_read(&memory_stats->per_peer_object)); + len += scnprintf(buf + len, size - len, "rx_post_buf size: %u\n", + atomic_read(&memory_stats->ce_rx_pipe)); + len += scnprintf(buf + len, size - len, "Total size: %u\n\n", + (atomic_read(&memory_stats->malloc_size) + + atomic_read(&memory_stats->ce_ring_alloc) + + atomic_read(&memory_stats->dma_alloc) + + atomic_read(&memory_stats->htc_skb_alloc) + + atomic_read(&memory_stats->wmi_tx_skb_alloc) + + atomic_read(&memory_stats->per_peer_object) + + atomic_read(&memory_stats->ce_rx_pipe))); + + if (len > size) + len = size; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; +} + +static const struct file_operations fops_memory_stats = { + .read = ath11k_debug_dump_memory_stats, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath11k_debugfs_pdev_create(struct ath11k_base *ab) { if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) @@ -1639,6 +1743,12 @@ static ssize_t ath11k_write_pktlog_filte } } + debugfs_create_file("enable_memory_stats", 0600, ab->debugfs_soc, + ab, &fops_enable_memory_stats); + + debugfs_create_file("memory_stats", 0600, ab->debugfs_soc, ab, + &fops_memory_stats); + #define HTT_RX_FILTER_TLV_LITE_MODE \ (HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \ @@ -2225,6 +2335,8 @@ static ssize_t ath11k_dump_mgmt_stats(st if (!buf) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, size); + mutex_lock(&ar->conf_mutex); spin_lock_bh(&ar->data_lock); @@ -2275,6 +2387,9 @@ static ssize_t ath11k_dump_mgmt_stats(st ret = simple_read_from_buffer(ubuf, count, ppos, buf, len); mutex_unlock(&ar->conf_mutex); kfree(buf); + + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, size); + return ret; } --- a/drivers/net/wireless/ath/ath11k/debugfs.h +++ b/drivers/net/wireless/ath/ath11k/debugfs.h @@ -10,6 +10,7 @@ #define ATH11K_TX_POWER_MAX_VAL 70 #define ATH11K_TX_POWER_MIN_VAL 0 +#define ATH11K_DEBUG_ENABLE_MEMORY_STATS 1 /* htt_dbg_ext_stats_type */ enum ath11k_dbg_htt_ext_stats_type { @@ -163,6 +164,24 @@ void ath11k_debugfs_wmi_ctrl_stats(struc void ath11k_wmi_crl_path_stats_list_free(struct list_head *head); #ifdef CPTCFG_ATH11K_DEBUGFS +#define ATH11K_MEMORY_STATS_INC(_struct, _field, _size) \ +do { \ + if (ath11k_debug_is_memory_stats_enabled(_struct)) \ + atomic_add(_size, &_struct->memory_stats._field); \ +} while(0) + +#define ATH11K_MEMORY_STATS_DEC(_struct, _field, _size) \ +do { \ + if (ath11k_debug_is_memory_stats_enabled(_struct)) \ + atomic_sub(_size, &_struct->memory_stats._field); \ +} while(0) + +#else +#define ATH11K_MEMORY_STATS_INC(_struct, _field, _size) +#define ATH11K_MEMORY_STATS_DEC(_struct, _field, _size) +#endif + +#ifdef CPTCFG_ATH11K_DEBUGFS int ath11k_debugfs_create(void); void ath11k_debugfs_destroy(void); int ath11k_debugfs_soc_create(struct ath11k_base *ab); @@ -208,6 +227,11 @@ static inline int ath11k_debugfs_rx_filt return ar->debug.rx_filter; } +static inline int ath11k_debug_is_memory_stats_enabled(struct ath11k_base *ab) +{ + return ab->enable_memory_stats; +} + #else static inline int ath11k_debugfs_create(void) { @@ -285,6 +309,11 @@ static inline bool ath11k_debugfs_is_pkt return false; } +static inline int ath11k_debug_is_memory_stats_enabled(struct ath11k_base *ab) +{ + return 0; +} + static inline int ath11k_debugfs_rx_filter(struct ath11k *ar) { return 0; --- a/drivers/net/wireless/ath/ath11k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath11k/debugfs_sta.c @@ -492,6 +492,8 @@ static ssize_t ath11k_dbg_sta_dump_rx_st if (!buf) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, size); + he_rates_avail = (rx_stats->pream_cnt[HAL_RX_PREAMBLE_11AX] > 1) ? 1 : 0; rate_table_len = he_rates_avail ? ATH11K_RX_RATE_TABLE_11AX_NUM : ATH11K_RX_RATE_TABLE_NUM; @@ -636,6 +638,8 @@ static ssize_t ath11k_dbg_sta_dump_rx_st retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); kfree(buf); + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, size); + mutex_unlock(&ar->conf_mutex); return retval; } --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -109,6 +109,8 @@ void ath11k_dp_srng_cleanup(struct ath11 dma_free_coherent(ab->dev, ring->size, ring->vaddr_unaligned, ring->paddr_unaligned); + ATH11K_MEMORY_STATS_DEC(ab, dma_alloc, ring->size); + ring->vaddr_unaligned = NULL; } @@ -253,6 +255,8 @@ int ath11k_dp_srng_setup(struct ath11k_b if (!ring->vaddr_unaligned) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, dma_alloc, ring->size); + ring->vaddr = PTR_ALIGN(ring->vaddr_unaligned, HAL_RING_BASE_ALIGN); ring->paddr = ring->paddr_unaligned + ((unsigned long)ring->vaddr - (unsigned long)ring->vaddr_unaligned); @@ -485,6 +489,7 @@ static void ath11k_dp_scatter_idle_link_ dma_free_coherent(ab->dev, HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX, slist[i].vaddr, slist[i].paddr); slist[i].vaddr = NULL; + ATH11K_MEMORY_STATS_DEC(ab, dma_alloc, HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX); } } @@ -522,6 +527,7 @@ static int ath11k_dp_scatter_idle_link_d ret = -ENOMEM; goto err; } + ATH11K_MEMORY_STATS_INC(ab, dma_alloc, HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX); } scatter_idx = 0; @@ -576,6 +582,7 @@ ath11k_dp_link_desc_bank_free(struct ath link_desc_banks[i].vaddr_unaligned, link_desc_banks[i].paddr_unaligned); link_desc_banks[i].vaddr_unaligned = NULL; + ATH11K_MEMORY_STATS_DEC(ab, dma_alloc, link_desc_banks[i].size); } } } @@ -609,6 +616,7 @@ static int ath11k_dp_link_desc_bank_allo ((unsigned long)desc_bank[i].vaddr - (unsigned long)desc_bank[i].vaddr_unaligned); desc_bank[i].size = desc_sz; + ATH11K_MEMORY_STATS_INC(ab, dma_alloc, desc_bank[i].size); } return 0; @@ -1023,8 +1031,11 @@ static int ath11k_dp_tx_pending_cleanup( void ath11k_dp_free(struct ath11k_base *ab) { struct ath11k_dp *dp = &ab->dp; + size_t size = 0; int i; + size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE; + ath11k_dp_link_desc_cleanup(ab, dp->link_desc_banks, HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring); @@ -1038,6 +1049,7 @@ void ath11k_dp_free(struct ath11k_base * ath11k_dp_tx_pending_cleanup, ab); idr_destroy(&dp->tx_ring[i].txbuf_idr); spin_unlock_bh(&dp->tx_ring[i].tx_idr_lock); + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, size); kfree(dp->tx_ring[i].tx_status); } @@ -1095,6 +1107,7 @@ int ath11k_dp_alloc(struct ath11k_base * ret = -ENOMEM; goto fail_cmn_srng_cleanup; } + ATH11K_MEMORY_STATS_INC(ab, malloc_size, size); } for (i = 0; i < HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX; i++) --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c @@ -200,6 +200,8 @@ static int ath11k_hal_alloc_cont_rdp(str if (!hal->rdp.vaddr) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, dma_alloc, size); + return 0; } @@ -214,6 +216,7 @@ static void ath11k_hal_free_cont_rdp(str size = sizeof(u32) * HAL_SRNG_RING_ID_MAX; dma_free_coherent(ab->dev, size, hal->rdp.vaddr, hal->rdp.paddr); + ATH11K_MEMORY_STATS_DEC(ab, dma_alloc, size); hal->rdp.vaddr = NULL; } @@ -228,6 +231,8 @@ static int ath11k_hal_alloc_cont_wrp(str if (!hal->wrp.vaddr) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, dma_alloc, size); + return 0; } @@ -242,6 +247,7 @@ static void ath11k_hal_free_cont_wrp(str size = sizeof(u32) * HAL_SRNG_NUM_LMAC_RINGS; dma_free_coherent(ab->dev, size, hal->wrp.vaddr, hal->wrp.paddr); + ATH11K_MEMORY_STATS_DEC(ab, dma_alloc, size); hal->wrp.vaddr = NULL; } --- a/drivers/net/wireless/ath/ath11k/htc.c +++ b/drivers/net/wireless/ath/ath11k/htc.c @@ -28,6 +28,7 @@ struct sk_buff *ath11k_htc_alloc_skb(str static void ath11k_htc_control_tx_complete(struct ath11k_base *ab, struct sk_buff *skb) { + ATH11K_MEMORY_STATS_DEC(ab, htc_skb_alloc, skb->truesize); kfree_skb(skb); } @@ -650,6 +651,8 @@ int ath11k_htc_connect_service(struct at return status; } + ATH11K_MEMORY_STATS_INC(ab, htc_skb_alloc, skb->truesize); + /* wait for response */ time_left = wait_for_completion_timeout(&htc->ctl_resp, ATH11K_HTC_CONN_SVC_TIMEOUT_HZ); @@ -773,6 +776,8 @@ int ath11k_htc_start(struct ath11k_htc * return status; } + ATH11K_MEMORY_STATS_INC(ab, htc_skb_alloc, skb->truesize); + return 0; } --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -3535,6 +3535,8 @@ static int ath11k_mac_op_hw_scan(struct goto exit; } + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, sizeof(*arg)); + ath11k_wmi_start_scan_init(ar, arg); arg->vdev_id = arvif->vdev_id; arg->scan_id = ATH11K_SCAN_ID; @@ -3546,6 +3548,8 @@ static int ath11k_mac_op_hw_scan(struct memcpy(arg->extraie.ptr, req->ie, req->ie_len); } + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, req->ie_len); + if (req->n_ssids) { arg->num_ssids = req->n_ssids; for (i = 0; i < arg->num_ssids; i++) { @@ -3597,8 +3601,13 @@ static int ath11k_mac_op_hw_scan(struct exit: if (arg) { - if (arg->extraie.ptr) + if (arg->extraie.ptr) { + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, req->ie_len); kfree(arg->extraie.ptr); + } + + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, sizeof(*arg)); + kfree(arg); } @@ -6770,6 +6779,8 @@ ath11k_mac_update_active_vif_chan(struct if (!arg.vifs) return; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, sizeof(arg.vifs[0])); + ieee80211_iterate_active_interfaces_atomic(ar->hw, IEEE80211_IFACE_ITER_NORMAL, ath11k_mac_change_chanctx_fill_iter, @@ -6777,6 +6788,8 @@ ath11k_mac_update_active_vif_chan(struct ath11k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs); + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, sizeof(arg.vifs[0])); + kfree(arg.vifs); } --- a/drivers/net/wireless/ath/ath11k/nss.c +++ b/drivers/net/wireless/ath/ath11k/nss.c @@ -876,6 +876,8 @@ int ath11k_nss_vdev_set_cmd(struct ath11 if (!vdev_msg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, sizeof(*vdev_msg)); + /* TODO: Convert to function for conversion in case of many * such commands */ @@ -906,6 +908,7 @@ int ath11k_nss_vdev_set_cmd(struct ath11 ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev set cmd success cmd:%d val:%d\n", cmd, val); free: + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, sizeof(*vdev_msg)); kfree(vdev_msg); return status; } @@ -922,6 +925,9 @@ static int ath11k_nss_vdev_configure(str if (!vdev_msg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, + sizeof(struct nss_wifi_vdev_msg)); + vdev_cfg = &vdev_msg->msg.vdev_config; vdev_cfg->radio_ifnum = ar->nss.if_num; @@ -957,6 +963,8 @@ static int ath11k_nss_vdev_configure(str ret = 0; free: + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, + sizeof(struct nss_wifi_vdev_msg)); kfree(vdev_msg); return ret; @@ -1180,6 +1188,9 @@ int ath11k_nss_vdev_up(struct ath11k_vif if (!vdev_msg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, + sizeof(struct nss_wifi_vdev_msg)); + vdev_en = &vdev_msg->msg.vdev_enable; ether_addr_copy(vdev_en->mac_addr, arvif->vif->addr); @@ -1198,6 +1209,8 @@ int ath11k_nss_vdev_up(struct ath11k_vif ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev up tx msg success\n"); free: + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, + sizeof(struct nss_wifi_vdev_msg)); kfree(vdev_msg); return ret; } @@ -1220,6 +1233,8 @@ int ath11k_nss_vdev_down(struct ath11k_v if (!vdev_msg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, + sizeof(struct nss_wifi_vdev_msg)); nss_wifi_vdev_msg_init(vdev_msg, arvif->nss.if_num, NSS_WIFI_VDEV_INTERFACE_DOWN_MSG, sizeof(struct nss_wifi_vdev_disable_msg), @@ -1234,6 +1249,8 @@ int ath11k_nss_vdev_down(struct ath11k_v ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss vdev down tx msg success\n"); free: + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, + sizeof(struct nss_wifi_vdev_msg)); kfree(vdev_msg); return ret; } @@ -1257,6 +1274,9 @@ int ath11k_nss_set_peer_sec_type(struct if (!wlmsg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ar->ab, malloc_size, + sizeof(struct nss_wifili_msg)); + sec_msg = &wlmsg->msg.securitymsg; sec_msg->peer_id = peer->peer_id; @@ -1288,6 +1308,8 @@ int ath11k_nss_set_peer_sec_type(struct ath11k_dbg(ar->ab, ATH11K_DBG_NSS, "nss peer id %d security cfg complete\n", peer->peer_id); free: + ATH11K_MEMORY_STATS_DEC(ar->ab, malloc_size, + sizeof(struct nss_wifili_msg)); kfree(wlmsg); return status; } @@ -1886,6 +1908,7 @@ static void ath11k_nss_tx_desc_mem_free( ab->nss.tx_desc_vaddr[i], ab->nss.tx_desc_paddr[i]); ab->nss.tx_desc_vaddr[i] = NULL; + ATH11K_MEMORY_STATS_DEC(ab, dma_alloc, ab->nss.tx_desc_size[i]); } ath11k_dbg(ab, ATH11K_DBG_NSS, "allocated tx desc mem freed\n"); @@ -1917,6 +1940,8 @@ static int ath11k_nss_tx_desc_mem_alloc( ab->nss.tx_desc_size[curr_page_idx] = alloc_size; curr_page_idx++; + ATH11K_MEMORY_STATS_INC(ab, dma_alloc, alloc_size); + ath11k_dbg(ab, ATH11K_DBG_NSS, "curr page %d, allocated %d, total allocated %d\n", curr_page_idx, alloc_size, i + alloc_size); @@ -2093,6 +2118,8 @@ static int ath11k_nss_init(struct ath11k if (!wlmsg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + wim = &wlmsg->msg.init; wim->target_type = target_type; @@ -2211,6 +2238,7 @@ unregister: nss_unregister_wifili_if(ab->nss.if_num); free: ath11k_nss_tx_desc_mem_free(ab); + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(struct nss_wifili_msg)); kfree(wlmsg); return -EINVAL; } @@ -2316,6 +2344,8 @@ int ath11k_nss_pdev_init(struct ath11k_b goto unregister; } + ATH11K_MEMORY_STATS_INC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + pdevmsg = &wlmsg->msg.pdevmsg; pdevmsg->radio_id = radio_id; @@ -2361,6 +2391,8 @@ int ath11k_nss_pdev_init(struct ath11k_b goto free; } + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + kfree(wlmsg); /* Disable nss sojourn stats by default */ @@ -2379,6 +2411,7 @@ int ath11k_nss_pdev_init(struct ath11k_b return 0; free: + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(struct nss_wifili_msg)); kfree(wlmsg); unregister: nss_unregister_wifili_radio_if(ar->nss.if_num); @@ -2401,6 +2434,8 @@ int ath11k_nss_start(struct ath11k_base if (!wlmsg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; /* Empty message for NSS Start message */ @@ -2441,6 +2476,7 @@ int ath11k_nss_start(struct ath11k_base ath11k_dbg(ab, ATH11K_DBG_NSS, "nss start success\n"); free: + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(struct nss_wifili_msg)); kfree(wlmsg); return ret; } @@ -2459,6 +2495,8 @@ static void ath11k_nss_reset(struct ath1 return; } + ATH11K_MEMORY_STATS_INC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; /* Empty message for NSS Reset message */ @@ -2497,6 +2535,7 @@ static void ath11k_nss_reset(struct ath1 nss_unregister_wifili_if(ab->nss.if_num); free: + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(struct nss_wifili_msg)); kfree(wlmsg); } @@ -2512,6 +2551,8 @@ static int ath11k_nss_stop(struct ath11k if (!wlmsg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + msg_cb = (nss_wifili_msg_callback_t)ath11k_nss_wifili_event_receive; /* Empty message for Stop command */ @@ -2551,6 +2592,8 @@ static int ath11k_nss_stop(struct ath11k /* NSS Stop success */ ret = 0; free: + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + kfree(wlmsg); return ret; } @@ -2576,6 +2619,8 @@ int ath11k_nss_pdev_deinit(struct ath11k if (!wlmsg) return -ENOMEM; + ATH11K_MEMORY_STATS_INC(ab, malloc_size, sizeof(struct nss_wifili_msg)); + deinit = &wlmsg->msg.pdevdeinit; deinit->ifnum = radio_id; @@ -2618,6 +2663,7 @@ int ath11k_nss_pdev_deinit(struct ath11k nss_dynamic_interface_dealloc_node(ar->nss.if_num, dyn_if_type); nss_unregister_wifili_radio_if(ar->nss.if_num); free: + ATH11K_MEMORY_STATS_DEC(ab, malloc_size, sizeof(struct nss_wifili_msg)); kfree(wlmsg); return ret; } --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c @@ -633,6 +633,9 @@ int ath11k_peer_delete(struct ath11k *ar if (ret) return ret; + ATH11K_MEMORY_STATS_DEC(ar->ab, per_peer_object, + sizeof(struct ath11k_peer)); + ar->num_peers--; return 0; @@ -729,6 +732,8 @@ int ath11k_peer_create(struct ath11k *ar ath11k_dp_sta_tx_attach(arsta, peer->peer_id); } + ATH11K_MEMORY_STATS_INC(ar->ab, per_peer_object, sizeof(*peer)); + ar->num_peers++; spin_unlock_bh(&ar->ab->base_lock); --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -599,6 +599,8 @@ struct sk_buff *ath11k_wmi_alloc_skb(str if (!skb) return NULL; + ATH11K_MEMORY_STATS_INC(ab, wmi_tx_skb_alloc, skb->truesize); + skb_reserve(skb, WMI_SKB_HEADROOM); if (!IS_ALIGNED((unsigned long)skb->data, 4)) ath11k_warn(ab, "unaligned WMI skb data\n"); @@ -6666,6 +6668,7 @@ static void ath11k_wmi_htc_tx_complete(s if (wmi_ep_count > ab->hw_params.max_radios) goto out; + ATH11K_MEMORY_STATS_DEC(ab, wmi_tx_skb_alloc, skb->truesize); dev_kfree_skb(skb); for (i = 0; i < ab->htc.wmi_ep_count; i++) { @@ -6679,6 +6682,7 @@ static void ath11k_wmi_htc_tx_complete(s return; out: + ATH11K_MEMORY_STATS_DEC(ab, wmi_tx_skb_alloc, skb->truesize); dev_kfree_skb(skb); }