From 948f3d74256f128abbf656da830862c99a785ca2 Mon Sep 17 00:00:00 2001 From: Sarada Prasanna Garnayak Date: Mon, 6 Jun 2016 15:22:49 +0530 Subject: [PATCH 1/2] net: cnss_prealloc: add debugfs entry to check the memory status This feature adds support to check the pre allocated memory pool status at runtime. This debugfs entry provide the required information for wlan host driver memory profiling and adds support to debug the pre-alloc memory failure issue. feature: 1. Total amount of pre-alloc memory avail and used in the memory pool. 2. Pre-alloc memory status per slots(used/free). CRs-Fixed: 2027352 Change-Id: I61c51f93dd7462b1fa9c36f6eea3814a6acbdd34 Signed-off-by: Sarada Prasanna Garnayak Signed-off-by: Hardik Kantilal Patel --- .../wireless/cnss_prealloc/cnss_prealloc.c | 87 ++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c index 913f756f9520..7f04750d415a 100644 --- a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c +++ b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c @@ -11,10 +11,15 @@ */ #include #include +#include #include #include #include #include +#include +#ifdef CONFIG_WCNSS_SKB_PRE_ALLOC +#include +#endif static DEFINE_SPINLOCK(alloc_lock); @@ -22,6 +27,11 @@ static DEFINE_SPINLOCK(alloc_lock); #define WCNSS_MAX_STACK_TRACE 64 #endif +#define PRE_ALLOC_DEBUGFS_DIR "cnss-prealloc" +#define PRE_ALLOC_DEBUGFS_FILE_OBJ "status" + +static struct dentry *debug_base; + struct wcnss_prealloc { int occupied; unsigned int size; @@ -233,14 +243,89 @@ int wcnss_pre_alloc_reset(void) return n; } +int prealloc_memory_stats_show(struct seq_file *fp, void *data) +{ + int i = 0; + int used_slots = 0, free_slots = 0; + unsigned int tsize = 0, tused = 0, size = 0; + + seq_puts(fp, "\nSlot_Size(Kb)\t\t[Used : Free]\n"); + for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) { + tsize += wcnss_allocs[i].size; + if (size != wcnss_allocs[i].size) { + if (size) { + seq_printf( + fp, "[%d : %d]\n", + used_slots, free_slots); + } + + size = wcnss_allocs[i].size; + used_slots = 0; + free_slots = 0; + seq_printf(fp, "%d Kb\t\t\t", size / 1024); + } + + if (wcnss_allocs[i].occupied) { + tused += wcnss_allocs[i].size; + ++used_slots; + } else { + ++free_slots; + } + } + seq_printf(fp, "[%d : %d]\n", used_slots, free_slots); + + /* Convert byte to Kb */ + if (tsize) + tsize = tsize / 1024; + if (tused) + tused = tused / 1024; + seq_printf(fp, "\nMemory Status:\nTotal Memory: %dKb\n", tsize); + seq_printf(fp, "Used: %dKb\nFree: %dKb\n", tused, tsize - tused); + + return 0; +} + +int prealloc_memory_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, prealloc_memory_stats_show, NULL); +} + +static const struct file_operations prealloc_memory_stats_fops = { + .owner = THIS_MODULE, + .open = prealloc_memory_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int __init wcnss_pre_alloc_init(void) { - return wcnss_prealloc_init(); + int ret; + + ret = wcnss_prealloc_init(); + if (ret) { + pr_err("%s: Failed to init the prealloc pool\n", __func__); + return ret; + } + + debug_base = debugfs_create_dir(PRE_ALLOC_DEBUGFS_DIR, NULL); + if (IS_ERR_OR_NULL(debug_base)) { + pr_err("%s: Failed to create debugfs dir\n", __func__); + } else if (IS_ERR_OR_NULL(debugfs_create_file( + PRE_ALLOC_DEBUGFS_FILE_OBJ, + 0644, debug_base, NULL, + &prealloc_memory_stats_fops))) { + pr_err("%s: Failed to create debugfs file\n", __func__); + debugfs_remove_recursive(debug_base); + } + + return ret; } static void __exit wcnss_pre_alloc_exit(void) { wcnss_prealloc_deinit(); + debugfs_remove_recursive(debug_base); } module_init(wcnss_pre_alloc_init); From 0e7de47c30178a647042a7abc7b4f30cc602c274 Mon Sep 17 00:00:00 2001 From: Hardik Kantilal Patel Date: Fri, 31 Mar 2017 13:02:47 +0530 Subject: [PATCH 2/2] icnss: pre-alloc memory leak check on probe failure and remove After wlan host driver probe failure and driver unload check the memory leak and reset the memory pool. CRs-Fixed: 2027407 Change-Id: Id6e413416ec7ea1d1bf0e69aab7eccb06de753d7 Signed-off-by: Hardik Kantilal Patel --- drivers/net/wireless/cnss_prealloc/cnss_prealloc.c | 2 ++ drivers/soc/qcom/icnss.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c index 7f04750d415a..e93416ebd343 100644 --- a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c +++ b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c @@ -226,6 +226,8 @@ void wcnss_prealloc_check_memory_leak(void) } } +#else +void wcnss_prealloc_check_memory_leak(void) {} #endif int wcnss_pre_alloc_reset(void) diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 16ab2400cd69..1692edbc045a 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -48,6 +48,11 @@ #include #include +#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC +#include +#endif + + #include "wlan_firmware_service_v01.h" #ifdef CONFIG_ICNSS_DEBUG @@ -1947,6 +1952,8 @@ static int icnss_call_driver_probe(struct icnss_priv *priv) if (ret < 0) { icnss_pr_err("Driver probe failed: %d, state: 0x%lx\n", ret, priv->state); + wcnss_prealloc_check_memory_leak(); + wcnss_pre_alloc_reset(); goto out; } @@ -2076,6 +2083,8 @@ static int icnss_driver_event_register_driver(void *data) if (ret) { icnss_pr_err("Driver probe failed: %d, state: 0x%lx\n", ret, penv->state); + wcnss_prealloc_check_memory_leak(); + wcnss_pre_alloc_reset(); goto power_off; } @@ -2101,6 +2110,8 @@ static int icnss_driver_event_unregister_driver(void *data) penv->ops->remove(&penv->pdev->dev); clear_bit(ICNSS_DRIVER_PROBED, &penv->state); + wcnss_prealloc_check_memory_leak(); + wcnss_pre_alloc_reset(); penv->ops = NULL; @@ -2125,6 +2136,8 @@ static int icnss_call_driver_remove(struct icnss_priv *priv) penv->ops->remove(&priv->pdev->dev); clear_bit(ICNSS_DRIVER_PROBED, &priv->state); + wcnss_prealloc_check_memory_leak(); + wcnss_pre_alloc_reset(); icnss_hw_power_off(penv);