Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9743084d authored by Sarada Prasanna Garnayak's avatar Sarada Prasanna Garnayak
Browse files

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: default avatarSarada Prasanna Garnayak <sgarna@codeaurora.org>
Signed-off-by: default avatarHardik Kantilal Patel <hkpatel@codeaurora.org>
parent 4d9a308b
Loading
Loading
Loading
Loading
+86 −1
Original line number Diff line number Diff line
@@ -11,9 +11,14 @@
 */
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/err.h>
#include <linux/stacktrace.h>
#include <linux/spinlock.h>
#include <linux/debugfs.h>
#ifdef	CONFIG_WCNSS_SKB_PRE_ALLOC
#include <linux/skbuff.h>
#endif

static DEFINE_SPINLOCK(alloc_lock);

@@ -21,6 +26,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;
@@ -228,14 +238,89 @@ int wcnss_pre_alloc_reset(void)
}
EXPORT_SYMBOL(wcnss_pre_alloc_reset);

static 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;
}

static 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);