|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
|
|
|
+ * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
|
|
|
*
|
|
|
* Permission to use, copy, modify, and/or distribute this software for
|
|
|
* any purpose with or without fee is hereby granted, provided that the
|
|
@@ -113,27 +113,6 @@ struct major_alloc_priv {
|
|
|
uint32_t threshold;
|
|
|
};
|
|
|
|
|
|
-static struct major_alloc_priv mem_priv = {
|
|
|
- /* List type set to mem */
|
|
|
- LIST_TYPE_MEM,
|
|
|
- /* initial threshold to list APIs which allocates mem >= 50 times */
|
|
|
- 50
|
|
|
-};
|
|
|
-
|
|
|
-static struct major_alloc_priv dma_priv = {
|
|
|
- /* List type set to DMA */
|
|
|
- LIST_TYPE_DMA,
|
|
|
- /* initial threshold to list APIs which allocates dma >= 50 times */
|
|
|
- 50
|
|
|
-};
|
|
|
-
|
|
|
-static struct major_alloc_priv nbuf_priv = {
|
|
|
- /* List type set to NBUF */
|
|
|
- LIST_TYPE_NBUF,
|
|
|
- /* initial threshold to list APIs which allocates nbuf >= 50 times */
|
|
|
- 50
|
|
|
-};
|
|
|
-
|
|
|
static qdf_list_t qdf_mem_domains[QDF_DEBUG_DOMAIN_COUNT];
|
|
|
static qdf_spinlock_t qdf_mem_list_lock;
|
|
|
|
|
@@ -325,41 +304,6 @@ qdf_mem_header_assert_valid(struct qdf_mem_header *header,
|
|
|
|
|
|
QDF_MEMDEBUG_PANIC("Fatal memory error detected @ %s:%d", func, line);
|
|
|
}
|
|
|
-#endif /* MEMORY_DEBUG */
|
|
|
-
|
|
|
-u_int8_t prealloc_disabled = 1;
|
|
|
-qdf_declare_param(prealloc_disabled, byte);
|
|
|
-qdf_export_symbol(prealloc_disabled);
|
|
|
-
|
|
|
-#if defined WLAN_DEBUGFS
|
|
|
-
|
|
|
-/* Debugfs root directory for qdf_mem */
|
|
|
-static struct dentry *qdf_mem_debugfs_root;
|
|
|
-
|
|
|
-#ifdef MEMORY_DEBUG
|
|
|
-static int qdf_err_printer(void *priv, const char *fmt, ...)
|
|
|
-{
|
|
|
- va_list args;
|
|
|
-
|
|
|
- va_start(args, fmt);
|
|
|
- QDF_VTRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, (char *)fmt, args);
|
|
|
- va_end(args);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int seq_printf_printer(void *priv, const char *fmt, ...)
|
|
|
-{
|
|
|
- struct seq_file *file = priv;
|
|
|
- va_list args;
|
|
|
-
|
|
|
- va_start(args, fmt);
|
|
|
- seq_vprintf(file, fmt, args);
|
|
|
- seq_puts(file, "\n");
|
|
|
- va_end(args);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
|
|
|
/**
|
|
|
* struct __qdf_mem_info - memory statistics
|
|
@@ -408,81 +352,6 @@ static void qdf_mem_debug_print_header(qdf_abstract_print print,
|
|
|
"--------------------------------------------------------------");
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * qdf_mem_meta_table_print() - memory metadata table print logic
|
|
|
- * @table: the memory metadata table to print
|
|
|
- * @print: the print adapter function
|
|
|
- * @print_priv: the private data to be consumed by @print
|
|
|
- * @threshold: the threshold value set by user to list top allocations
|
|
|
- *
|
|
|
- * Return: None
|
|
|
- */
|
|
|
-static void qdf_mem_meta_table_print(struct __qdf_mem_info *table,
|
|
|
- qdf_abstract_print print,
|
|
|
- void *print_priv,
|
|
|
- uint32_t threshold)
|
|
|
-{
|
|
|
- int i;
|
|
|
- char debug_str[QDF_DEBUG_STRING_SIZE];
|
|
|
- size_t len = 0;
|
|
|
- char *debug_prefix = "WLAN_BUG_RCA: memory leak detected";
|
|
|
-
|
|
|
- len += qdf_scnprintf(debug_str, sizeof(debug_str) - len,
|
|
|
- "%s", debug_prefix);
|
|
|
-
|
|
|
- for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) {
|
|
|
- if (!table[i].count)
|
|
|
- break;
|
|
|
-
|
|
|
- print(print_priv,
|
|
|
- "%6u x %5u = %7uB @ %s:%u %pS %llu",
|
|
|
- table[i].count,
|
|
|
- table[i].size,
|
|
|
- table[i].count * table[i].size,
|
|
|
- table[i].func,
|
|
|
- table[i].line, table[i].caller,
|
|
|
- table[i].time);
|
|
|
- len += qdf_scnprintf(debug_str + len,
|
|
|
- sizeof(debug_str) - len,
|
|
|
- " @ %s:%u %pS",
|
|
|
- table[i].func,
|
|
|
- table[i].line,
|
|
|
- table[i].caller);
|
|
|
- }
|
|
|
- print(print_priv, "%s", debug_str);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * qdf_print_major_alloc() - memory metadata table print logic
|
|
|
- * @table: the memory metadata table to print
|
|
|
- * @print: the print adapter function
|
|
|
- * @print_priv: the private data to be consumed by @print
|
|
|
- * @threshold: the threshold value set by uset to list top allocations
|
|
|
- *
|
|
|
- * Return: None
|
|
|
- */
|
|
|
-static void qdf_print_major_alloc(struct __qdf_mem_info *table,
|
|
|
- qdf_abstract_print print,
|
|
|
- void *print_priv,
|
|
|
- uint32_t threshold)
|
|
|
-{
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) {
|
|
|
- if (!table[i].count)
|
|
|
- break;
|
|
|
- if (table[i].count >= threshold)
|
|
|
- print(print_priv,
|
|
|
- "%6u x %5u = %7uB @ %s:%u %pS %llu",
|
|
|
- table[i].count,
|
|
|
- table[i].size,
|
|
|
- table[i].count * table[i].size,
|
|
|
- table[i].func,
|
|
|
- table[i].line, table[i].caller,
|
|
|
- table[i].time);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* qdf_mem_meta_table_insert() - insert memory metadata into the given table
|
|
|
* @table: the memory metadata table to insert into
|
|
@@ -567,6 +436,117 @@ static void qdf_mem_domain_print(qdf_list_t *domain,
|
|
|
(*mem_print)(table, print, print_priv, threshold);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * qdf_mem_meta_table_print() - memory metadata table print logic
|
|
|
+ * @table: the memory metadata table to print
|
|
|
+ * @print: the print adapter function
|
|
|
+ * @print_priv: the private data to be consumed by @print
|
|
|
+ * @threshold: the threshold value set by user to list top allocations
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static void qdf_mem_meta_table_print(struct __qdf_mem_info *table,
|
|
|
+ qdf_abstract_print print,
|
|
|
+ void *print_priv,
|
|
|
+ uint32_t threshold)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ char debug_str[QDF_DEBUG_STRING_SIZE];
|
|
|
+ size_t len = 0;
|
|
|
+ char *debug_prefix = "WLAN_BUG_RCA: memory leak detected";
|
|
|
+
|
|
|
+ len += qdf_scnprintf(debug_str, sizeof(debug_str) - len,
|
|
|
+ "%s", debug_prefix);
|
|
|
+
|
|
|
+ for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) {
|
|
|
+ if (!table[i].count)
|
|
|
+ break;
|
|
|
+
|
|
|
+ print(print_priv,
|
|
|
+ "%6u x %5u = %7uB @ %s:%u %pS %llu",
|
|
|
+ table[i].count,
|
|
|
+ table[i].size,
|
|
|
+ table[i].count * table[i].size,
|
|
|
+ table[i].func,
|
|
|
+ table[i].line, table[i].caller,
|
|
|
+ table[i].time);
|
|
|
+ len += qdf_scnprintf(debug_str + len,
|
|
|
+ sizeof(debug_str) - len,
|
|
|
+ " @ %s:%u %pS",
|
|
|
+ table[i].func,
|
|
|
+ table[i].line,
|
|
|
+ table[i].caller);
|
|
|
+ }
|
|
|
+ print(print_priv, "%s", debug_str);
|
|
|
+}
|
|
|
+
|
|
|
+static int qdf_err_printer(void *priv, const char *fmt, ...)
|
|
|
+{
|
|
|
+ va_list args;
|
|
|
+
|
|
|
+ va_start(args, fmt);
|
|
|
+ QDF_VTRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, (char *)fmt, args);
|
|
|
+ va_end(args);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#endif /* MEMORY_DEBUG */
|
|
|
+
|
|
|
+u_int8_t prealloc_disabled = 1;
|
|
|
+qdf_declare_param(prealloc_disabled, byte);
|
|
|
+qdf_export_symbol(prealloc_disabled);
|
|
|
+
|
|
|
+#if defined WLAN_DEBUGFS
|
|
|
+
|
|
|
+/* Debugfs root directory for qdf_mem */
|
|
|
+static struct dentry *qdf_mem_debugfs_root;
|
|
|
+
|
|
|
+#ifdef MEMORY_DEBUG
|
|
|
+static int seq_printf_printer(void *priv, const char *fmt, ...)
|
|
|
+{
|
|
|
+ struct seq_file *file = priv;
|
|
|
+ va_list args;
|
|
|
+
|
|
|
+ va_start(args, fmt);
|
|
|
+ seq_vprintf(file, fmt, args);
|
|
|
+ seq_puts(file, "\n");
|
|
|
+ va_end(args);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * qdf_print_major_alloc() - memory metadata table print logic
|
|
|
+ * @table: the memory metadata table to print
|
|
|
+ * @print: the print adapter function
|
|
|
+ * @print_priv: the private data to be consumed by @print
|
|
|
+ * @threshold: the threshold value set by uset to list top allocations
|
|
|
+ *
|
|
|
+ * Return: None
|
|
|
+ */
|
|
|
+static void qdf_print_major_alloc(struct __qdf_mem_info *table,
|
|
|
+ qdf_abstract_print print,
|
|
|
+ void *print_priv,
|
|
|
+ uint32_t threshold)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) {
|
|
|
+ if (!table[i].count)
|
|
|
+ break;
|
|
|
+ if (table[i].count >= threshold)
|
|
|
+ print(print_priv,
|
|
|
+ "%6u x %5u = %7uB @ %s:%u %pS %llu",
|
|
|
+ table[i].count,
|
|
|
+ table[i].size,
|
|
|
+ table[i].count * table[i].size,
|
|
|
+ table[i].func,
|
|
|
+ table[i].line, table[i].caller,
|
|
|
+ table[i].time);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* qdf_mem_seq_start() - sequential callback to start
|
|
|
* @seq: seq_file handle
|
|
@@ -934,6 +914,27 @@ static const struct file_operations fops_qdf_nbuf_major_allocs = {
|
|
|
.write = qdf_major_nbuf_alloc_set_threshold,
|
|
|
};
|
|
|
|
|
|
+static struct major_alloc_priv mem_priv = {
|
|
|
+ /* List type set to mem */
|
|
|
+ LIST_TYPE_MEM,
|
|
|
+ /* initial threshold to list APIs which allocates mem >= 50 times */
|
|
|
+ 50
|
|
|
+};
|
|
|
+
|
|
|
+static struct major_alloc_priv dma_priv = {
|
|
|
+ /* List type set to DMA */
|
|
|
+ LIST_TYPE_DMA,
|
|
|
+ /* initial threshold to list APIs which allocates dma >= 50 times */
|
|
|
+ 50
|
|
|
+};
|
|
|
+
|
|
|
+static struct major_alloc_priv nbuf_priv = {
|
|
|
+ /* List type set to NBUF */
|
|
|
+ LIST_TYPE_NBUF,
|
|
|
+ /* initial threshold to list APIs which allocates nbuf >= 50 times */
|
|
|
+ 50
|
|
|
+};
|
|
|
+
|
|
|
static QDF_STATUS qdf_mem_debug_debugfs_init(void)
|
|
|
{
|
|
|
if (is_initial_mem_debug_disabled)
|