mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-19 18:31:33 +00:00
383 lines
11 KiB
Diff
383 lines
11 KiB
Diff
From e16e606c956892bda991ffc50dedc85042ddd3ca Mon Sep 17 00:00:00 2001
|
|
From: Maharaja Kennadyrajan <mkenna@codeaurora.org>
|
|
Date: Mon, 4 Jan 2021 23:47:57 +0530
|
|
Subject: [PATCH 2/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 <mkenna@codeaurora.org>
|
|
---
|
|
net/mac80211/chan.c | 12 ++++++++++++
|
|
net/mac80211/debugfs.c | 4 ++++
|
|
net/mac80211/ieee80211_i.h | 6 ++++++
|
|
net/mac80211/iface.c | 5 +++++
|
|
net/mac80211/mesh.c | 4 ++++
|
|
net/mac80211/mesh_hwmp.c | 5 +++++
|
|
net/mac80211/mesh_pathtbl.c | 12 ++++++++++++
|
|
net/mac80211/offchannel.c | 7 +++++++
|
|
net/mac80211/scan.c | 18 ++++++++++++++++++
|
|
net/mac80211/sta_info.c | 16 ++++++++++++++++
|
|
10 files changed, 89 insertions(+)
|
|
|
|
--- a/net/mac80211/chan.c
|
|
+++ b/net/mac80211/chan.c
|
|
@@ -517,6 +517,9 @@ ieee80211_alloc_chanctx(struct ieee80211
|
|
if (!ctx)
|
|
return NULL;
|
|
|
|
+ atomic_add(sizeof(*ctx) + local->hw.chanctx_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
+
|
|
INIT_LIST_HEAD(&ctx->assigned_vifs);
|
|
INIT_LIST_HEAD(&ctx->reserved_vifs);
|
|
ctx->conf.def = *chandef;
|
|
@@ -577,6 +580,8 @@ ieee80211_new_chanctx(struct ieee80211_l
|
|
|
|
err = ieee80211_add_chanctx(local, ctx);
|
|
if (err) {
|
|
+ atomic_sub(sizeof(*ctx) + local->hw.chanctx_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree(ctx);
|
|
return ERR_PTR(err);
|
|
}
|
|
@@ -629,6 +634,8 @@ static void ieee80211_free_chanctx(struc
|
|
|
|
list_del_rcu(&ctx->list);
|
|
ieee80211_del_chanctx(local, ctx);
|
|
+ atomic_sub(sizeof(*ctx) + local->hw.chanctx_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree_rcu(ctx, rcu_head);
|
|
}
|
|
|
|
@@ -1265,6 +1272,9 @@ static int ieee80211_chsw_switch_vifs(st
|
|
if (!vif_chsw)
|
|
return -ENOMEM;
|
|
|
|
+ atomic_add(sizeof(vif_chsw[0]) * n_vifs,
|
|
+ &local->memory_stats.malloc_size);
|
|
+
|
|
i = 0;
|
|
list_for_each_entry(ctx, &local->chanctx_list, list) {
|
|
if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
|
|
@@ -1294,6 +1304,8 @@ static int ieee80211_chsw_switch_vifs(st
|
|
CHANCTX_SWMODE_SWAP_CONTEXTS);
|
|
|
|
out:
|
|
+ atomic_sub(sizeof(vif_chsw[0]) * n_vifs,
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree(vif_chsw);
|
|
return err;
|
|
}
|
|
--- a/net/mac80211/debugfs.c
|
|
+++ b/net/mac80211/debugfs.c
|
|
@@ -71,6 +71,8 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
|
|
local->wep_iv & 0xffffff);
|
|
DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
|
|
local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
|
|
+DEBUGFS_READONLY_FILE(memory_stats, "memory stats: malloc_size: %u",
|
|
+ atomic_read(&local->memory_stats.malloc_size));
|
|
|
|
static ssize_t aqm_read(struct file *file,
|
|
char __user *user_buf,
|
|
@@ -587,6 +589,8 @@ void debugfs_hw_add(struct ieee80211_loc
|
|
if (!statsd)
|
|
return;
|
|
|
|
+ DEBUGFS_ADD(memory_stats);
|
|
+
|
|
#ifdef CPTCFG_MAC80211_DEBUG_COUNTERS
|
|
DEBUGFS_STATS_ADD(dot11TransmittedFragmentCount);
|
|
DEBUGFS_STATS_ADD(dot11MulticastTransmittedFrameCount);
|
|
--- a/net/mac80211/ieee80211_i.h
|
|
+++ b/net/mac80211/ieee80211_i.h
|
|
@@ -1164,6 +1164,10 @@ enum mac80211_scan_state {
|
|
SCAN_ABORT,
|
|
};
|
|
|
|
+struct mac80211_memory_stats {
|
|
+ atomic_t malloc_size;
|
|
+};
|
|
+
|
|
struct ieee80211_local {
|
|
/* embed the driver visible part.
|
|
* don't cast (use the static inlines below), but we keep
|
|
@@ -1451,6 +1455,8 @@ struct ieee80211_local {
|
|
/* TDLS channel switch */
|
|
struct work_struct tdls_chsw_work;
|
|
struct sk_buff_head skb_queue_tdls_chsw;
|
|
+
|
|
+ struct mac80211_memory_stats memory_stats;
|
|
};
|
|
|
|
static inline struct ieee80211_sub_if_data *
|
|
--- a/net/mac80211/iface.c
|
|
+++ b/net/mac80211/iface.c
|
|
@@ -1065,6 +1065,9 @@ int ieee80211_add_virtual_monitor(struct
|
|
return ret;
|
|
}
|
|
|
|
+ atomic_add(sizeof(*sdata) + local->hw.vif_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
+
|
|
skb_queue_head_init(&sdata->skb_queue);
|
|
INIT_WORK(&sdata->work, ieee80211_iface_work);
|
|
|
|
@@ -1100,6 +1103,8 @@ void ieee80211_del_virtual_monitor(struc
|
|
|
|
drv_remove_interface(local, sdata);
|
|
|
|
+ atomic_sub(sizeof(*sdata) + local->hw.vif_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree(sdata);
|
|
}
|
|
|
|
--- a/net/mac80211/mesh.c
|
|
+++ b/net/mac80211/mesh.c
|
|
@@ -173,6 +173,8 @@ int mesh_rmc_init(struct ieee80211_sub_i
|
|
sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
|
|
if (!sdata->u.mesh.rmc)
|
|
return -ENOMEM;
|
|
+ atomic_add(sizeof(struct mesh_rmc),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
|
|
for (i = 0; i < RMC_BUCKETS; i++)
|
|
INIT_HLIST_HEAD(&sdata->u.mesh.rmc->bucket[i]);
|
|
@@ -196,6 +198,8 @@ void mesh_rmc_free(struct ieee80211_sub_
|
|
}
|
|
}
|
|
|
|
+ atomic_sub(sizeof(struct mesh_rmc),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
kfree(rmc);
|
|
sdata->u.mesh.rmc = NULL;
|
|
}
|
|
--- a/net/mac80211/mesh_hwmp.c
|
|
+++ b/net/mac80211/mesh_hwmp.c
|
|
@@ -997,6 +997,9 @@ static void mesh_queue_preq(struct mesh_
|
|
return;
|
|
}
|
|
|
|
+ atomic_add(sizeof(struct mesh_preq_queue),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
+
|
|
memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
|
|
preq_node->flags = flags;
|
|
|
|
@@ -1111,6 +1114,8 @@ void mesh_path_start_discovery(struct ie
|
|
|
|
enddiscovery:
|
|
rcu_read_unlock();
|
|
+ atomic_sub(sizeof(struct mesh_preq_queue),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
kfree(preq_node);
|
|
}
|
|
|
|
--- a/net/mac80211/mesh_pathtbl.c
|
|
+++ b/net/mac80211/mesh_pathtbl.c
|
|
@@ -764,6 +764,9 @@ int mesh_pathtbl_init(struct ieee80211_s
|
|
struct mesh_table *tbl_path, *tbl_mpp;
|
|
int ret;
|
|
|
|
+ atomic_add(sizeof(struct mesh_table),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
+
|
|
tbl_path = mesh_table_alloc();
|
|
if (!tbl_path)
|
|
return -ENOMEM;
|
|
@@ -774,12 +777,17 @@ int mesh_pathtbl_init(struct ieee80211_s
|
|
goto free_path;
|
|
}
|
|
|
|
+ atomic_add(sizeof(struct mesh_table),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
+
|
|
sdata->u.mesh.mesh_paths = tbl_path;
|
|
sdata->u.mesh.mpp_paths = tbl_mpp;
|
|
|
|
return 0;
|
|
|
|
free_path:
|
|
+ atomic_sub(sizeof(struct mesh_table),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
mesh_table_free(tbl_path);
|
|
return ret;
|
|
}
|
|
@@ -809,6 +817,10 @@ void mesh_path_expire(struct ieee80211_s
|
|
|
|
void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata)
|
|
{
|
|
+ atomic_sub(sizeof(struct mesh_table),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
+ atomic_sub(sizeof(struct mesh_table),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
mesh_table_free(sdata->u.mesh.mesh_paths);
|
|
mesh_table_free(sdata->u.mesh.mpp_paths);
|
|
}
|
|
--- a/net/mac80211/offchannel.c
|
|
+++ b/net/mac80211/offchannel.c
|
|
@@ -168,6 +168,7 @@ void ieee80211_offchannel_return(struct
|
|
|
|
static void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
|
|
{
|
|
+ struct ieee80211_sub_if_data *sdata = roc->sdata;
|
|
/* was never transmitted */
|
|
if (roc->frame) {
|
|
cfg80211_mgmt_tx_status(&roc->sdata->wdev, roc->mgmt_tx_cookie,
|
|
@@ -186,6 +187,8 @@ static void ieee80211_roc_notify_destroy
|
|
roc->chan, GFP_KERNEL);
|
|
|
|
list_del(&roc->list);
|
|
+ atomic_sub(sizeof(*roc),
|
|
+ &sdata->local->memory_stats.malloc_size);
|
|
kfree(roc);
|
|
}
|
|
|
|
@@ -548,6 +551,8 @@ static int ieee80211_start_roc_work(stru
|
|
if (!roc)
|
|
return -ENOMEM;
|
|
|
|
+ atomic_add(sizeof(*roc), &local->memory_stats.malloc_size);
|
|
+
|
|
/*
|
|
* If the duration is zero, then the driver
|
|
* wouldn't actually do anything. Set it to
|
|
@@ -593,6 +598,8 @@ static int ieee80211_start_roc_work(stru
|
|
ret = drv_remain_on_channel(local, sdata, channel,
|
|
duration, type);
|
|
if (ret) {
|
|
+ atomic_sub(sizeof(*roc),
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree(roc);
|
|
return ret;
|
|
}
|
|
--- a/net/mac80211/scan.c
|
|
+++ b/net/mac80211/scan.c
|
|
@@ -441,6 +441,12 @@ static void __ieee80211_scan_completed(s
|
|
scan_req = rcu_dereference_protected(local->scan_req,
|
|
lockdep_is_held(&local->mtx));
|
|
|
|
+ atomic_sub(sizeof(*local->hw_scan_req) +
|
|
+ scan_req->n_channels *
|
|
+ sizeof(scan_req->channels[0]) +
|
|
+ local->hw_scan_ies_bufsize,
|
|
+ &local->memory_stats.malloc_size);
|
|
+
|
|
if (scan_req != local->int_scan_req) {
|
|
local->scan_info.aborted = aborted;
|
|
cfg80211_scan_done(scan_req, &local->scan_info);
|
|
@@ -710,6 +716,12 @@ static int __ieee80211_start_scan(struct
|
|
if (!local->hw_scan_req)
|
|
return -ENOMEM;
|
|
|
|
+ atomic_add(sizeof(*local->hw_scan_req) +
|
|
+ req->n_channels *
|
|
+ sizeof(req->channels[0]) +
|
|
+ local->hw_scan_ies_bufsize,
|
|
+ &local->memory_stats.malloc_size);
|
|
+
|
|
local->hw_scan_req->req.chandef = req->chandef;
|
|
local->hw_scan_req->req.ssids = req->ssids;
|
|
local->hw_scan_req->req.n_ssids = req->n_ssids;
|
|
@@ -799,6 +811,12 @@ static int __ieee80211_start_scan(struct
|
|
}
|
|
|
|
if (rc) {
|
|
+ atomic_sub(sizeof(*local->hw_scan_req) +
|
|
+ req->n_channels *
|
|
+ sizeof(req->channels[0]) +
|
|
+ local->hw_scan_ies_bufsize,
|
|
+ &local->memory_stats.malloc_size);
|
|
+
|
|
kfree(local->hw_scan_req);
|
|
local->hw_scan_req = NULL;
|
|
local->scanning = 0;
|
|
--- a/net/mac80211/sta_info.c
|
|
+++ b/net/mac80211/sta_info.c
|
|
@@ -258,6 +258,7 @@ struct sta_info *sta_info_get_by_idx(str
|
|
*/
|
|
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
|
|
{
|
|
+ struct ieee80211_hw *hw = &local->hw;
|
|
/*
|
|
* If we had used sta_info_pre_move_state() then we might not
|
|
* have gone through the state transitions down again, so do
|
|
@@ -285,8 +286,13 @@ void sta_info_free(struct ieee80211_loca
|
|
kfree(to_txq_info(sta->sta.txq[0]));
|
|
kfree(rcu_dereference_raw(sta->sta.rates));
|
|
#ifdef CPTCFG_MAC80211_MESH
|
|
+ if (sta->mesh)
|
|
+ atomic_sub(sizeof(*sta->mesh),
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree(sta->mesh);
|
|
#endif
|
|
+ atomic_sub(sizeof(*sta) + hw->sta_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
free_percpu(sta->pcpu_rx_stats);
|
|
kfree(sta);
|
|
}
|
|
@@ -345,6 +351,9 @@ struct sta_info *sta_info_alloc(struct i
|
|
if (!sta)
|
|
return NULL;
|
|
|
|
+ atomic_add(sizeof(*sta) + hw->sta_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
+
|
|
if (ieee80211_hw_check(hw, USES_RSS)) {
|
|
sta->pcpu_rx_stats =
|
|
alloc_percpu_gfp(struct ieee80211_sta_rx_stats, gfp);
|
|
@@ -362,6 +371,8 @@ struct sta_info *sta_info_alloc(struct i
|
|
sta->mesh = kzalloc(sizeof(*sta->mesh), gfp);
|
|
if (!sta->mesh)
|
|
goto free;
|
|
+ atomic_add(sizeof(*sta->mesh),
|
|
+ &local->memory_stats.malloc_size);
|
|
sta->mesh->plink_sta = sta;
|
|
spin_lock_init(&sta->mesh->plink_lock);
|
|
if (ieee80211_vif_is_mesh(&sdata->vif) &&
|
|
@@ -526,8 +537,12 @@ free_txq:
|
|
free:
|
|
free_percpu(sta->pcpu_rx_stats);
|
|
#ifdef CPTCFG_MAC80211_MESH
|
|
+ atomic_sub(sizeof(*sta->mesh),
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree(sta->mesh);
|
|
#endif
|
|
+ atomic_sub(sizeof(*sta) + hw->sta_data_size,
|
|
+ &local->memory_stats.malloc_size);
|
|
kfree(sta);
|
|
return NULL;
|
|
}
|