diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h index 3f59b8f522..63eba7193f 100644 --- a/qdf/inc/qdf_mem.h +++ b/qdf/inc/qdf_mem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -90,6 +90,13 @@ void qdf_mem_exit(void); #define QDF_MEM_FUNC_NAME_SIZE 48 #ifdef MEMORY_DEBUG +/** + * qdf_mem_debug_config_get() - Get the user configuration of mem_debug_disabled + * + * Return: value of mem_debug_disabled qdf module argument + */ +bool qdf_mem_debug_config_get(void); + /** * qdf_mem_malloc_debug() - debug version of QDF memory allocation API * @size: Number of bytes of memory to allocate. @@ -226,6 +233,10 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, qdf_mem_free_consistent_debug(osdev, dev, size, vaddr, paddr, memctx, \ __func__, __LINE__) #else +static inline bool qdf_mem_debug_config_get(void) +{ + return false; +} /** * qdf_mem_malloc() - allocation QDF memory @@ -240,9 +251,10 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, * specified (for any reason) it returns NULL. */ #define qdf_mem_malloc(size) \ - qdf_mem_malloc_fl(size, __func__, __LINE__) + __qdf_mem_malloc(size, __func__, __LINE__) -void *qdf_mem_malloc_fl(qdf_size_t size, const char *func, uint32_t line); +#define qdf_mem_malloc_fl(size, func, line) \ + __qdf_mem_malloc(size, func, line) /** * qdf_mem_malloc_atomic() - allocation QDF memory atomically @@ -263,22 +275,16 @@ void *qdf_mem_malloc_atomic_fl(qdf_size_t size, const char *func, uint32_t line); -/** - * qdf_mem_free() - free QDF memory - * @ptr: Pointer to the starting address of the memory to be freed. - * - * Return: None - */ -void qdf_mem_free(void *ptr); +#define qdf_mem_free(ptr) \ + __qdf_mem_free(ptr) static inline void qdf_mem_check_for_leaks(void) { } -void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, qdf_dma_addr_t *paddr); +#define qdf_mem_alloc_consistent(osdev, dev, size, paddr) \ + __qdf_mem_alloc_consistent(osdev, dev, size, paddr, __func__, __LINE__) -void qdf_mem_free_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, void *vaddr, - qdf_dma_addr_t paddr, qdf_dma_context_t memctx); +#define qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx) \ + __qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx) void qdf_mem_multi_pages_alloc(qdf_device_t osdev, struct qdf_mem_multi_page_t *pages, diff --git a/qdf/linux/src/i_qdf_mem.h b/qdf/linux/src/i_qdf_mem.h index c7ffdca8fe..5513820d05 100644 --- a/qdf/linux/src/i_qdf_mem.h +++ b/qdf/linux/src/i_qdf_mem.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -440,4 +440,61 @@ __qdf_mem_set_dma_pa(qdf_device_t osdev, { mem_info->pa = dma_pa; } + +/** + * __qdf_mem_alloc_consistent() - allocates consistent qdf memory + * @osdev: OS device handle + * @dev: Pointer to device handle + * @size: Size to be allocated + * @paddr: Physical address + * @func: Function name of the call site + * @line: line numbe rof the call site + * + * Return: pointer of allocated memory or null if memory alloc fails + */ +void *__qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, qdf_dma_addr_t *paddr, + const char *func, uint32_t line); + +/** + * __qdf_mem_malloc() - allocates QDF memory + * @size: Number of bytes of memory to allocate. + * + * @func: Function name of the call site + * @line: line numbe rof the call site + * + * This function will dynamicallly allocate the specified number of bytes of + * memory. + * + * Return: + * Upon successful allocate, returns a non-NULL pointer to the allocated + * memory. If this function is unable to allocate the amount of memory + * specified (for any reason) it returns NULL. + */ +void *__qdf_mem_malloc(qdf_size_t size, const char *func, uint32_t line); + +/** + * __qdf_mem_free() - free QDF memory + * @ptr: Pointer to the starting address of the memory to be freed. + * + * This function will free the memory pointed to by 'ptr'. + * Return: None + */ +void __qdf_mem_free(void *ptr); + +/** + * __qdf_mem_free_consistent() - free consistent qdf memory + * @osdev: OS device handle + * @dev: Pointer to device handle + * @size: Size to be allocated + * @vaddr: virtual address + * @paddr: Physical address + * @memctx: Pointer to DMA context + * + * Return: none + */ +void __qdf_mem_free_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, void *vaddr, + qdf_dma_addr_t paddr, qdf_dma_context_t memctx); + #endif /* __I_QDF_MEM_H */ diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c index 33ec0fab57..3a5387071d 100644 --- a/qdf/linux/src/qdf_mem.c +++ b/qdf/linux/src/qdf_mem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -43,6 +43,13 @@ #include #endif +#if defined(MEMORY_DEBUG) || defined(NBUF_MEMORY_DEBUG) +static bool mem_debug_disabled; +qdf_declare_param(mem_debug_disabled, bool); +qdf_export_symbol(mem_debug_disabled); +static bool is_initial_mem_debug_disabled; +#endif + /* Preprocessor Definitions and Constants */ #define QDF_MEM_MAX_MALLOC (4096 * 1024) /* 4 Mega Bytes */ #define QDF_MEM_WARN_THRESHOLD 300 /* ms */ @@ -571,6 +578,9 @@ static const struct file_operations fops_qdf_mem_debugfs = { static QDF_STATUS qdf_mem_debug_debugfs_init(void) { + if (is_initial_mem_debug_disabled) + return QDF_STATUS_SUCCESS; + if (!qdf_mem_debugfs_root) return QDF_STATUS_E_FAILURE; @@ -893,6 +903,15 @@ static int qdf_mem_malloc_flags(void) /* External Function implementation */ #ifdef MEMORY_DEBUG +/** + * qdf_mem_debug_config_get() - Get the user configuration of mem_debug_disabled + * + * Return: value of mem_debug_disabled qdf module argument + */ +bool qdf_mem_debug_config_get(void) +{ + return mem_debug_disabled; +} /** * qdf_mem_debug_init() - initialize qdf memory debug functionality @@ -903,6 +922,11 @@ static void qdf_mem_debug_init(void) { int i; + is_initial_mem_debug_disabled = qdf_mem_debug_config_get(); + + if (is_initial_mem_debug_disabled) + return; + /* Initalizing the list with maximum size of 60000 */ for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i) qdf_list_create(&qdf_mem_domains[i], 60000); @@ -918,6 +942,9 @@ static uint32_t qdf_mem_domain_check_for_leaks(enum qdf_debug_domain domain, qdf_list_t *mem_list) { + if (is_initial_mem_debug_disabled) + return 0; + if (qdf_list_empty(mem_list)) return 0; @@ -933,6 +960,9 @@ static void qdf_mem_domain_set_check_for_leaks(qdf_list_t *domains) uint32_t leak_count = 0; int i; + if (is_initial_mem_debug_disabled) + return; + /* detect and print leaks */ for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i) leak_count += qdf_mem_domain_check_for_leaks(i, domains + i); @@ -951,6 +981,9 @@ static void qdf_mem_debug_exit(void) { int i; + if (is_initial_mem_debug_disabled) + return; + /* mem */ qdf_mem_domain_set_check_for_leaks(qdf_mem_domains); for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i) @@ -975,6 +1008,9 @@ void *qdf_mem_malloc_debug(size_t size, const char *func, uint32_t line, void *ptr; unsigned long start, duration; + if (is_initial_mem_debug_disabled) + return __qdf_mem_malloc(size, func, line); + if (!size || size > QDF_MEM_MAX_MALLOC) { qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line); return NULL; @@ -1022,6 +1058,11 @@ void qdf_mem_free_debug(void *ptr, const char *func, uint32_t line) struct qdf_mem_header *header; enum qdf_mem_validation_bitmap error_bitmap; + if (is_initial_mem_debug_disabled) { + __qdf_mem_free(ptr); + return; + } + /* freeing a null pointer is valid */ if (qdf_unlikely(!ptr)) return; @@ -1062,6 +1103,9 @@ void qdf_mem_check_for_leaks(void) qdf_list_t *dma_list = qdf_mem_dma_list(current_domain); uint32_t leaks_count = 0; + if (is_initial_mem_debug_disabled) + return; + leaks_count += qdf_mem_domain_check_for_leaks(current_domain, mem_list); leaks_count += qdf_mem_domain_check_for_leaks(current_domain, dma_list); @@ -1232,33 +1276,6 @@ static void qdf_mem_debug_init(void) {} static void qdf_mem_debug_exit(void) {} -void *qdf_mem_malloc_fl(size_t size, const char *func, uint32_t line) -{ - void *ptr; - - if (!size || size > QDF_MEM_MAX_MALLOC) { - qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", size, func, - line); - return NULL; - } - - ptr = qdf_mem_prealloc_get(size); - if (ptr) - return ptr; - - ptr = kzalloc(size, qdf_mem_malloc_flags()); - if (!ptr) { - qdf_nofl_err("Failed to malloc %zuB @ %s:%d", - size, func, line); - return NULL; - } - - qdf_mem_kmalloc_inc(ksize(ptr)); - - return ptr; -} -qdf_export_symbol(qdf_mem_malloc_fl); - void *qdf_mem_malloc_atomic_fl(size_t size, const char *func, uint32_t line) { void *ptr; @@ -1280,29 +1297,6 @@ void *qdf_mem_malloc_atomic_fl(size_t size, const char *func, uint32_t line) } qdf_export_symbol(qdf_mem_malloc_atomic_fl); -/** - * qdf_mem_free() - free QDF memory - * @ptr: Pointer to the starting address of the memory to be free'd. - * - * This function will free the memory pointed to by 'ptr'. - * - * Return: None - */ -void qdf_mem_free(void *ptr) -{ - if (!ptr) - return; - - if (qdf_mem_prealloc_put(ptr)) - return; - - qdf_mem_kmalloc_dec(ksize(ptr)); - - kfree(ptr); -} - -qdf_export_symbol(qdf_mem_free); - /** * qdf_mem_multi_pages_alloc() - allocate large size of kernel memory * @osdev: OS device handle pointer @@ -1444,6 +1438,46 @@ void qdf_mem_multi_pages_free(qdf_device_t osdev, qdf_export_symbol(qdf_mem_multi_pages_free); #endif +void __qdf_mem_free(void *ptr) +{ + if (!ptr) + return; + + if (qdf_mem_prealloc_put(ptr)) + return; + + qdf_mem_kmalloc_dec(ksize(ptr)); + + kfree(ptr); +} + +qdf_export_symbol(__qdf_mem_free); + +void *__qdf_mem_malloc(size_t size, const char *func, uint32_t line) +{ + void *ptr; + + if (!size || size > QDF_MEM_MAX_MALLOC) { + qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", size, func, + line); + return NULL; + } + + ptr = qdf_mem_prealloc_get(size); + if (ptr) + return ptr; + + ptr = kzalloc(size, qdf_mem_malloc_flags()); + if (!ptr) + return NULL; + + qdf_mem_kmalloc_inc(ksize(ptr)); + + return ptr; +} + +qdf_export_symbol(__qdf_mem_malloc); + void *qdf_aligned_malloc_fl(uint32_t *size, void **vaddr_unaligned, qdf_dma_addr_t *paddr_unaligned, @@ -1797,6 +1831,11 @@ void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev, struct qdf_mem_header *header; void *vaddr; + if (is_initial_mem_debug_disabled) + return __qdf_mem_alloc_consistent(osdev, dev, + size, paddr, + func, line); + if (!size || size > QDF_MEM_MAX_MALLOC) { qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line); return NULL; @@ -1840,6 +1879,14 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, struct qdf_mem_header *header; enum qdf_mem_validation_bitmap error_bitmap; + if (is_initial_mem_debug_disabled) { + __qdf_mem_free_consistent( + osdev, dev, + size, vaddr, + paddr, memctx); + return; + } + /* freeing a null pointer is valid */ if (qdf_unlikely(!vaddr)) return; @@ -1867,31 +1914,39 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, qdf_mem_dma_free(dev, size + QDF_DMA_MEM_DEBUG_SIZE, vaddr, paddr); } qdf_export_symbol(qdf_mem_free_consistent_debug); +#endif /* MEMORY_DEBUG */ -#else - -void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, qdf_dma_addr_t *paddr) +void __qdf_mem_free_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, void *vaddr, + qdf_dma_addr_t paddr, qdf_dma_context_t memctx) { - void *vaddr = qdf_mem_dma_alloc(osdev, dev, size, paddr); + qdf_mem_dma_dec(size); + qdf_mem_dma_free(dev, size, vaddr, paddr); +} + +qdf_export_symbol(__qdf_mem_free_consistent); + +void *__qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, + qdf_size_t size, qdf_dma_addr_t *paddr, + const char *func, uint32_t line) +{ + void *vaddr; + + if (!size || size > QDF_MEM_MAX_MALLOC) { + qdf_nofl_err("Cannot malloc %zu bytes @ %s:%d", + size, func, line); + return NULL; + } + + vaddr = qdf_mem_dma_alloc(osdev, dev, size, paddr); if (vaddr) qdf_mem_dma_inc(size); return vaddr; } -qdf_export_symbol(qdf_mem_alloc_consistent); -void qdf_mem_free_consistent(qdf_device_t osdev, void *dev, - qdf_size_t size, void *vaddr, - qdf_dma_addr_t paddr, qdf_dma_context_t memctx) -{ - qdf_mem_dma_dec(size); - qdf_mem_dma_free(dev, size, vaddr, paddr); -} -qdf_export_symbol(qdf_mem_free_consistent); - -#endif /* MEMORY_DEBUG */ +qdf_export_symbol(__qdf_mem_alloc_consistent); void *qdf_aligned_mem_alloc_consistent_fl( qdf_device_t osdev, uint32_t *size, diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c index 91f45866cc..58f41b90f3 100644 --- a/qdf/linux/src/qdf_nbuf.c +++ b/qdf/linux/src/qdf_nbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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,6 +113,10 @@ static uint32_t nbuf_tx_data[QDF_NBUF_TX_PKT_STATE_MAX]; static qdf_atomic_t nbuf_count; #endif +#if defined(NBUF_MEMORY_DEBUG) +static bool is_initial_mem_debug_disabled; +#endif + /** * qdf_nbuf_tx_desc_count_display() - Displays the packet counter * @@ -616,6 +620,9 @@ qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) { QDF_STATUS status; + if (is_initial_mem_debug_disabled) + return QDF_STATUS_SUCCESS; + status = qdf_tracker_track(&qdf_nbuf_map_tracker, nbuf, func, line); if (QDF_IS_STATUS_ERROR(status)) return status; @@ -628,6 +635,9 @@ qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) static void qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *func, uint32_t line) { + if (is_initial_mem_debug_disabled) + return; + qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_UNMAP); qdf_tracker_untrack(&qdf_nbuf_map_tracker, nbuf, func, line); } @@ -2325,6 +2335,11 @@ void qdf_net_buf_debug_init(void) { uint32_t i; + is_initial_mem_debug_disabled = qdf_mem_debug_config_get(); + + if (is_initial_mem_debug_disabled) + return; + qdf_atomic_set(&qdf_nbuf_history_index, -1); qdf_nbuf_map_tracking_init(); @@ -2354,6 +2369,9 @@ void qdf_net_buf_debug_exit(void) QDF_NBUF_TRACK *p_node; QDF_NBUF_TRACK *p_prev; + if (is_initial_mem_debug_disabled) + return; + for (i = 0; i < QDF_NET_BUF_TRACK_MAX_SIZE; i++) { spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); p_node = gp_qdf_net_buf_track_tbl[i]; @@ -2433,6 +2451,9 @@ void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size, QDF_NBUF_TRACK *p_node; QDF_NBUF_TRACK *new_node; + if (is_initial_mem_debug_disabled) + return; + new_node = qdf_nbuf_track_alloc(); i = qdf_net_buf_debug_hash(net_buf); @@ -2473,6 +2494,9 @@ void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, const char *func_name, unsigned long irq_flag; QDF_NBUF_TRACK *p_node; + if (is_initial_mem_debug_disabled) + return; + i = qdf_net_buf_debug_hash(net_buf); spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); @@ -2502,6 +2526,9 @@ void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf) unsigned long irq_flag; QDF_NBUF_TRACK *p_prev; + if (is_initial_mem_debug_disabled) + return; + i = qdf_net_buf_debug_hash(net_buf); spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag); @@ -2547,6 +2574,9 @@ void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf, { qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf); + if (is_initial_mem_debug_disabled) + return; + while (ext_list) { /* * Take care to add if it is Jumbo packet connected using @@ -2576,6 +2606,9 @@ void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf) { qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf); + if (is_initial_mem_debug_disabled) + return; + while (ext_list) { /* * Take care to free if it is Jumbo packet connected using @@ -2607,6 +2640,11 @@ qdf_nbuf_t qdf_nbuf_alloc_debug(qdf_device_t osdev, qdf_size_t size, { qdf_nbuf_t nbuf; + if (is_initial_mem_debug_disabled) + return __qdf_nbuf_alloc(osdev, size, + reserve, align, + prio, func, line); + nbuf = __qdf_nbuf_alloc(osdev, size, reserve, align, prio, func, line); /* Store SKB in internal QDF tracking table */ @@ -2628,6 +2666,9 @@ void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, const char *func, uint32_t line) if (qdf_unlikely(!nbuf)) return; + if (is_initial_mem_debug_disabled) + goto free_buf; + if (qdf_nbuf_get_users(nbuf) > 1) goto free_buf; @@ -2656,6 +2697,9 @@ qdf_nbuf_t qdf_nbuf_clone_debug(qdf_nbuf_t buf, const char *func, uint32_t line) { qdf_nbuf_t cloned_buf = __qdf_nbuf_clone(buf); + if (is_initial_mem_debug_disabled) + return cloned_buf; + if (qdf_unlikely(!cloned_buf)) return NULL; @@ -2671,6 +2715,9 @@ qdf_nbuf_t qdf_nbuf_copy_debug(qdf_nbuf_t buf, const char *func, uint32_t line) { qdf_nbuf_t copied_buf = __qdf_nbuf_copy(buf); + if (is_initial_mem_debug_disabled) + return copied_buf; + if (qdf_unlikely(!copied_buf)) return NULL; @@ -2691,6 +2738,9 @@ qdf_nbuf_copy_expand_debug(qdf_nbuf_t buf, int headroom, int tailroom, if (qdf_unlikely(!copied_buf)) return NULL; + if (is_initial_mem_debug_disabled) + return copied_buf; + /* Store SKB in internal QDF tracking table */ qdf_net_buf_debug_add_node(copied_buf, 0, func, line); qdf_nbuf_history_add(copied_buf, func, line,