qcacmn: Use function name instead of file name in debug logs

Replace all instance of file name to function name in debug logs.

Change-Id: Iff731675772859f02c975005b2656eaa41c6f360
CRs-Fixed: 2377894
This commit is contained in:
Arif Hussain 2018-08-09 16:11:14 -07:00 committed by nshrivas
parent 6f8b924d64
commit 61847a9ba6
8 changed files with 158 additions and 159 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2019 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
@ -86,13 +86,13 @@ void qdf_mem_init(void);
*/
void qdf_mem_exit(void);
#define QDF_MEM_FILE_NAME_SIZE 48
#define QDF_MEM_FUNC_NAME_SIZE 48
#ifdef MEMORY_DEBUG
/**
* qdf_mem_malloc_debug() - debug version of QDF memory allocation API
* @size: Number of bytes of memory to allocate.
* @file: File name of the call site
* @func: Function name of the call site
* @line: Line number of the call site
* @caller: Address of the caller function
* @flag: GFP flag
@ -103,17 +103,17 @@ void qdf_mem_exit(void);
*
* Return: A valid memory location on success, or NULL on failure
*/
void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line,
void *qdf_mem_malloc_debug(size_t size, const char *func, uint32_t line,
void *caller, uint32_t flag);
#define qdf_mem_malloc(size) \
qdf_mem_malloc_debug(size, __FILE__, __LINE__, QDF_RET_IP, 0)
qdf_mem_malloc_debug(size, __func__, __LINE__, QDF_RET_IP, 0)
#define qdf_mem_malloc_fl(size, func, line) \
qdf_mem_malloc_debug(size, func, line, QDF_RET_IP, 0)
#define qdf_mem_malloc_atomic(size) \
qdf_mem_malloc_debug(size, __FILE__, __LINE__, QDF_RET_IP, GFP_ATOMIC)
qdf_mem_malloc_debug(size, __func__, __LINE__, QDF_RET_IP, GFP_ATOMIC)
/**
* qdf_mem_free_debug() - debug version of qdf_mem_free
* @ptr: Pointer to the starting address of the memory to be freed.
@ -126,7 +126,7 @@ void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line,
void qdf_mem_free_debug(void *ptr, const char *file, uint32_t line);
#define qdf_mem_free(ptr) \
qdf_mem_free_debug(ptr, __FILE__, __LINE__)
qdf_mem_free_debug(ptr, __func__, __LINE__)
/**
* qdf_mem_check_for_leaks() - Assert that the current memory domain is empty
@ -166,7 +166,7 @@ void qdf_mem_check_for_leaks(void);
* @dev: Pointer to device handle
* @size: Size to be allocated
* @paddr: Physical address
* @file: file name of the call site
* @func: Function name of the call site
* @line: line numbe rof the call site
* @caller: Address of the caller function
*
@ -174,12 +174,12 @@ void qdf_mem_check_for_leaks(void);
*/
void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev,
qdf_size_t size, qdf_dma_addr_t *paddr,
const char *file, uint32_t line,
const char *func, uint32_t line,
void *caller);
#define qdf_mem_alloc_consistent(osdev, dev, size, paddr) \
qdf_mem_alloc_consistent_debug(osdev, dev, size, paddr, \
__FILE__, __LINE__, QDF_RET_IP)
__func__, __LINE__, QDF_RET_IP)
/**
* qdf_mem_free_consistent_debug() - free consistent qdf memory
@ -188,7 +188,7 @@ void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev,
* @vaddr: virtual address
* @paddr: Physical address
* @memctx: Pointer to DMA context
* @file: file name of the call site
* @func: Function name of the call site
* @line: line numbe rof the call site
*
* Return: none
@ -197,11 +197,11 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev,
qdf_size_t size, void *vaddr,
qdf_dma_addr_t paddr,
qdf_dma_context_t memctx,
const char *file, uint32_t line);
const char *func, uint32_t line);
#define qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx) \
qdf_mem_free_consistent_debug(osdev, dev, size, vaddr, paddr, memctx, \
__FILE__, __LINE__)
__func__, __LINE__)
#else
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2019 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
@ -688,80 +688,80 @@ void qdf_nbuf_map_check_for_leaks(void);
QDF_STATUS qdf_nbuf_map_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_map(osdev, buf, dir) \
qdf_nbuf_map_debug(osdev, buf, dir, __FILE__, __LINE__)
qdf_nbuf_map_debug(osdev, buf, dir, __func__, __LINE__)
void qdf_nbuf_unmap_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_unmap(osdev, buf, dir) \
qdf_nbuf_unmap_debug(osdev, buf, dir, __FILE__, __LINE__)
qdf_nbuf_unmap_debug(osdev, buf, dir, __func__, __LINE__)
QDF_STATUS qdf_nbuf_map_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_map_single(osdev, buf, dir) \
qdf_nbuf_map_single_debug(osdev, buf, dir, __FILE__, __LINE__)
qdf_nbuf_map_single_debug(osdev, buf, dir, __func__, __LINE__)
void qdf_nbuf_unmap_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_unmap_single(osdev, buf, dir) \
qdf_nbuf_unmap_single_debug(osdev, buf, dir, __FILE__, __LINE__)
qdf_nbuf_unmap_single_debug(osdev, buf, dir, __func__, __LINE__)
QDF_STATUS qdf_nbuf_map_nbytes_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_map_nbytes(osdev, buf, dir, nbytes) \
qdf_nbuf_map_nbytes_debug(osdev, buf, dir, nbytes, __FILE__, __LINE__)
qdf_nbuf_map_nbytes_debug(osdev, buf, dir, nbytes, __func__, __LINE__)
void qdf_nbuf_unmap_nbytes_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_unmap_nbytes(osdev, buf, dir, nbytes) \
qdf_nbuf_unmap_nbytes_debug(osdev, buf, dir, nbytes, __FILE__, __LINE__)
qdf_nbuf_unmap_nbytes_debug(osdev, buf, dir, nbytes, __func__, __LINE__)
QDF_STATUS qdf_nbuf_map_nbytes_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_map_nbytes_single(osdev, buf, dir, nbytes) \
qdf_nbuf_map_nbytes_single_debug(osdev, buf, dir, nbytes, \
__FILE__, __LINE__)
__func__, __LINE__)
void qdf_nbuf_unmap_nbytes_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line);
#define qdf_nbuf_unmap_nbytes_single(osdev, buf, dir, nbytes) \
qdf_nbuf_unmap_nbytes_single_debug(osdev, buf, dir, nbytes, \
__FILE__, __LINE__)
__func__, __LINE__)
#else /* NBUF_MAP_UNMAP_DEBUG */
@ -1355,20 +1355,20 @@ void qdf_net_buf_debug_init(void);
void qdf_net_buf_debug_exit(void);
void qdf_net_buf_debug_clean(void);
void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size,
uint8_t *file_name, uint32_t line_num);
const char *func_name, uint32_t line_num);
/**
* qdf_net_buf_debug_update_node() - update nbuf in debug hash table
*
* Return: none
*/
void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, uint8_t *file_name,
void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, const char *func_name,
uint32_t line_num);
void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf);
/**
* qdf_net_buf_debug_acquire_skb() - acquire skb to avoid memory leak
* @net_buf: Network buf holding head segment (single)
* @file_name: pointer to file name
* @func_name: pointer to function name
* @line_num: line number
*
* WLAN driver module's SKB which are allocated by network stack are
@ -1378,30 +1378,31 @@ void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf);
* Return: none
*/
void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
uint8_t *file_name, uint32_t line_num);
const char *func_name,
uint32_t line_num);
void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf);
/* nbuf allocation rouines */
#define qdf_nbuf_alloc(d, s, r, a, p) \
qdf_nbuf_alloc_debug(d, s, r, a, p, __FILE__, __LINE__)
qdf_nbuf_alloc_debug(d, s, r, a, p, __func__, __LINE__)
qdf_nbuf_t qdf_nbuf_alloc_debug(qdf_device_t osdev, qdf_size_t size,
int reserve, int align, int prio,
uint8_t *file, uint32_t line);
const char *func, uint32_t line);
#define qdf_nbuf_free(d) \
qdf_nbuf_free_debug(d, __FILE__, __LINE__)
qdf_nbuf_free_debug(d, __func__, __LINE__)
void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, uint8_t *file, uint32_t line);
void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, const char *func, uint32_t line);
#define qdf_nbuf_clone(buf) \
qdf_nbuf_clone_debug(buf, __FILE__, __LINE__)
qdf_nbuf_clone_debug(buf, __func__, __LINE__)
/**
* qdf_nbuf_clone_debug() - clone the nbuf (copy is readonly)
* @buf: nbuf to clone from
* @file_name: pointer to file name
* @func_name: pointer to function name
* @line_num: line number
*
* This function clones the nbuf and creates a memory tracking
@ -1410,8 +1411,7 @@ void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, uint8_t *file, uint32_t line);
* Return: cloned buffer
*/
static inline qdf_nbuf_t
qdf_nbuf_clone_debug(qdf_nbuf_t buf, uint8_t *file_name,
uint32_t line_num)
qdf_nbuf_clone_debug(qdf_nbuf_t buf, const char *func_name, uint32_t line_num)
{
qdf_nbuf_t cloned_buf;
@ -1419,18 +1419,18 @@ qdf_nbuf_clone_debug(qdf_nbuf_t buf, uint8_t *file_name,
/* Store SKB in internal QDF tracking table */
if (qdf_likely(cloned_buf))
qdf_net_buf_debug_add_node(cloned_buf, 0, file_name, line_num);
qdf_net_buf_debug_add_node(cloned_buf, 0, func_name, line_num);
return cloned_buf;
}
#define qdf_nbuf_copy(buf) \
qdf_nbuf_copy_debug(buf, __FILE__, __LINE__)
qdf_nbuf_copy_debug(buf, __func__, __LINE__)
/**
* qdf_nbuf_copy_debug() - returns a private copy of the buf
* @buf: nbuf to copy from
* @file_name: pointer to file name
* @func_name: pointer to function name
* @line_num: line number
*
* This API returns a private copy of the buf, the buf returned is completely
@ -1440,8 +1440,7 @@ qdf_nbuf_clone_debug(qdf_nbuf_t buf, uint8_t *file_name,
* Return: copied buffer
*/
static inline qdf_nbuf_t
qdf_nbuf_copy_debug(qdf_nbuf_t buf, uint8_t *file_name,
uint32_t line_num)
qdf_nbuf_copy_debug(qdf_nbuf_t buf, const char *func_name, uint32_t line_num)
{
qdf_nbuf_t copied_buf;
@ -1449,7 +1448,7 @@ qdf_nbuf_copy_debug(qdf_nbuf_t buf, uint8_t *file_name,
/* Store SKB in internal QDF tracking table */
if (qdf_likely(copied_buf))
qdf_net_buf_debug_add_node(copied_buf, 0, file_name, line_num);
qdf_net_buf_debug_add_node(copied_buf, 0, func_name, line_num);
return copied_buf;
}
@ -1460,7 +1459,8 @@ static inline void qdf_net_buf_debug_init(void) {}
static inline void qdf_net_buf_debug_exit(void) {}
static inline void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
uint8_t *file_name, uint32_t line_num)
const char *func_name,
uint32_t line_num)
{
}
@ -1469,7 +1469,7 @@ static inline void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf)
}
static inline void
qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, uint8_t *file_name,
qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, const char *func_name,
uint32_t line_num)
{
}
@ -3097,10 +3097,10 @@ qdf_nbuf_linearize(qdf_nbuf_t buf)
#ifdef NBUF_MEMORY_DEBUG
#define qdf_nbuf_unshare(d) \
qdf_nbuf_unshare_debug(d, __FILE__, __LINE__)
qdf_nbuf_unshare_debug(d, __func__, __LINE__)
static inline qdf_nbuf_t
qdf_nbuf_unshare_debug(qdf_nbuf_t buf, uint8_t *file_name, uint32_t line_num)
qdf_nbuf_unshare_debug(qdf_nbuf_t buf, const char *func_name, uint32_t line_num)
{
qdf_nbuf_t unshared_buf;
@ -3110,7 +3110,7 @@ qdf_nbuf_unshare_debug(qdf_nbuf_t buf, uint8_t *file_name, uint32_t line_num)
qdf_net_buf_debug_delete_node(buf);
qdf_net_buf_debug_add_node(unshared_buf, 0,
file_name, line_num);
func_name, line_num);
}
return unshared_buf;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2019 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
@ -80,7 +80,7 @@ static inline qdf_list_t *qdf_mem_dma_list(enum qdf_debug_domain domain)
* @domain: the active memory domain at time of allocation
* @freed: flag set during free, used to detect double frees
* Use uint8_t so we can detect corruption
* @file: name of the file the allocation was made from
* @func: name of the function the allocation was made from
* @line: line number of the file the allocation was made from
* @size: size of the allocation in bytes
* @caller: Caller of the function for which memory is allocated
@ -91,7 +91,7 @@ struct qdf_mem_header {
qdf_list_node_t node;
enum qdf_debug_domain domain;
uint8_t freed;
char file[QDF_MEM_FILE_NAME_SIZE];
char func[QDF_MEM_FUNC_NAME_SIZE];
uint32_t line;
uint32_t size;
void *caller;
@ -140,7 +140,7 @@ static void qdf_mem_trailer_init(struct qdf_mem_header *header)
}
static void qdf_mem_header_init(struct qdf_mem_header *header, qdf_size_t size,
const char *file, uint32_t line, void *caller)
const char *func, uint32_t line, void *caller)
{
QDF_BUG(header);
if (!header)
@ -149,8 +149,7 @@ static void qdf_mem_header_init(struct qdf_mem_header *header, qdf_size_t size,
header->domain = qdf_debug_domain_get();
header->freed = false;
/* copy the file name, rather than pointing to it */
qdf_str_lcopy(header->file, kbasename(file), QDF_MEM_FILE_NAME_SIZE);
qdf_str_lcopy(header->func, func, QDF_MEM_FUNC_NAME_SIZE);
header->line = line;
header->size = size;
@ -213,7 +212,7 @@ static void
qdf_mem_header_assert_valid(struct qdf_mem_header *header,
enum qdf_debug_domain current_domain,
enum qdf_mem_validation_bitmap error_bitmap,
const char *file,
const char *func,
uint32_t line)
{
if (!error_bitmap)
@ -248,7 +247,7 @@ qdf_mem_header_assert_valid(struct qdf_mem_header *header,
qdf_debug_domain_name(header->domain), header->domain,
qdf_debug_domain_name(current_domain), current_domain);
QDF_DEBUG_PANIC("Fatal memory error detected @ %s:%d", file, line);
QDF_DEBUG_PANIC("Fatal memory error detected @ %s:%d", func, line);
}
#endif /* MEMORY_DEBUG */
@ -330,7 +329,7 @@ static int seq_printf_printer(void *priv, const char *fmt, ...)
/**
* struct __qdf_mem_info - memory statistics
* @file: the file which allocated memory
* @func: the function which allocated memory
* @line: the line at which allocation happened
* @size: the size of allocation
* @caller: Address of the caller function
@ -338,7 +337,7 @@ static int seq_printf_printer(void *priv, const char *fmt, ...)
* @time: timestamp at which allocation happened
*/
struct __qdf_mem_info {
char file[QDF_MEM_FILE_NAME_SIZE];
char func[QDF_MEM_FUNC_NAME_SIZE];
uint32_t line;
uint32_t size;
void *caller;
@ -399,13 +398,13 @@ static void qdf_mem_meta_table_print(struct __qdf_mem_info *table,
table[i].count,
table[i].size,
table[i].count * table[i].size,
table[i].file,
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].file,
table[i].func,
table[i].line,
table[i].caller);
}
@ -426,8 +425,8 @@ static bool qdf_mem_meta_table_insert(struct __qdf_mem_info *table,
for (i = 0; i < QDF_MEM_STAT_TABLE_SIZE; i++) {
if (!table[i].count) {
qdf_str_lcopy(table[i].file, meta->file,
QDF_MEM_FILE_NAME_SIZE);
qdf_str_lcopy(table[i].func, meta->func,
QDF_MEM_FUNC_NAME_SIZE);
table[i].line = meta->line;
table[i].size = meta->size;
table[i].count = 1;
@ -436,7 +435,7 @@ static bool qdf_mem_meta_table_insert(struct __qdf_mem_info *table,
break;
}
if (qdf_str_eq(table[i].file, meta->file) &&
if (qdf_str_eq(table[i].func, meta->func) &&
table[i].line == meta->line &&
table[i].size == meta->size &&
table[i].caller == meta->caller) {
@ -1024,7 +1023,7 @@ static void qdf_mem_debug_exit(void)
qdf_spinlock_destroy(&qdf_mem_dma_list_lock);
}
void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line,
void *qdf_mem_malloc_debug(size_t size, const char *func, uint32_t line,
void *caller, uint32_t flag)
{
QDF_STATUS status;
@ -1035,7 +1034,7 @@ void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line,
unsigned long start, duration;
if (!size || size > QDF_MEM_MAX_MALLOC) {
qdf_err("Cannot malloc %zu bytes @ %s:%d", size, file, line);
qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line);
return NULL;
}
@ -1052,14 +1051,14 @@ void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line,
if (duration > QDF_MEM_WARN_THRESHOLD)
qdf_warn("Malloc slept; %lums, %zuB @ %s:%d",
duration, size, file, line);
duration, size, func, line);
if (!header) {
qdf_warn("Failed to malloc %zuB @ %s:%d", size, file, line);
qdf_warn("Failed to malloc %zuB @ %s:%d", size, func, line);
return NULL;
}
qdf_mem_header_init(header, size, file, line, caller);
qdf_mem_header_init(header, size, func, line, caller);
qdf_mem_trailer_init(header);
ptr = qdf_mem_get_ptr(header);
@ -1075,7 +1074,7 @@ void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line,
}
qdf_export_symbol(qdf_mem_malloc_debug);
void qdf_mem_free_debug(void *ptr, const char *file, uint32_t line)
void qdf_mem_free_debug(void *ptr, const char *func, uint32_t line)
{
enum qdf_debug_domain current_domain = qdf_debug_domain_get();
struct qdf_mem_header *header;
@ -1091,7 +1090,7 @@ void qdf_mem_free_debug(void *ptr, const char *file, uint32_t line)
if (qdf_unlikely((qdf_size_t)ptr <= sizeof(*header)))
panic("Failed to free invalid memory location %pK", ptr);
qdf_talloc_assert_no_children_fl(ptr, file, line);
qdf_talloc_assert_no_children_fl(ptr, func, line);
qdf_spin_lock_irqsave(&qdf_mem_list_lock);
header = qdf_mem_get_header(ptr);
@ -1106,7 +1105,7 @@ void qdf_mem_free_debug(void *ptr, const char *file, uint32_t line)
qdf_spin_unlock_irqrestore(&qdf_mem_list_lock);
qdf_mem_header_assert_valid(header, current_domain, error_bitmap,
file, line);
func, line);
qdf_mem_kmalloc_dec(header->size);
kfree(header);
@ -1720,7 +1719,7 @@ qdf_mem_dma_free(void *dev, qdf_size_t size, void *vaddr, qdf_dma_addr_t paddr)
#ifdef MEMORY_DEBUG
void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev,
qdf_size_t size, qdf_dma_addr_t *paddr,
const char *file, uint32_t line,
const char *func, uint32_t line,
void *caller)
{
QDF_STATUS status;
@ -1730,7 +1729,7 @@ void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev,
void *vaddr;
if (!size || size > QDF_MEM_MAX_MALLOC) {
qdf_err("Cannot malloc %zu bytes @ %s:%d", size, file, line);
qdf_err("Cannot malloc %zu bytes @ %s:%d", size, func, line);
return NULL;
}
@ -1738,7 +1737,7 @@ void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev,
paddr);
if (!vaddr) {
qdf_warn("Failed to malloc %zuB @ %s:%d", size, file, line);
qdf_warn("Failed to malloc %zuB @ %s:%d", size, func, line);
return NULL;
}
@ -1748,7 +1747,7 @@ void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev,
* Prefix the header into DMA buffer causes SMMU faults, so
* do not prefix header into the DMA buffers
*/
qdf_mem_header_init(header, size, file, line, caller);
qdf_mem_header_init(header, size, func, line, caller);
qdf_spin_lock_irqsave(&qdf_mem_dma_list_lock);
status = qdf_list_insert_front(mem_list, &header->node);
@ -1766,7 +1765,7 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev,
qdf_size_t size, void *vaddr,
qdf_dma_addr_t paddr,
qdf_dma_context_t memctx,
const char *file, uint32_t line)
const char *func, uint32_t line)
{
enum qdf_debug_domain domain = qdf_debug_domain_get();
struct qdf_mem_header *header;
@ -1776,7 +1775,7 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev,
if (qdf_unlikely(!vaddr))
return;
qdf_talloc_assert_no_children_fl(vaddr, file, line);
qdf_talloc_assert_no_children_fl(vaddr, func, line);
qdf_spin_lock_irqsave(&qdf_mem_dma_list_lock);
/* For DMA buffers we only add trailers, this function will retrieve
@ -1793,7 +1792,7 @@ void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev,
}
qdf_spin_unlock_irqrestore(&qdf_mem_dma_list_lock);
qdf_mem_header_assert_valid(header, domain, error_bitmap, file, line);
qdf_mem_header_assert_valid(header, domain, error_bitmap, func, line);
qdf_mem_dma_dec(header->size);
qdf_mem_dma_free(dev, size + QDF_DMA_MEM_DEBUG_SIZE, vaddr, paddr);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2014-2019 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
@ -544,7 +544,7 @@ enum qdf_nbuf_event_type {
struct qdf_nbuf_event {
qdf_nbuf_t nbuf;
char file[QDF_MEM_FILE_NAME_SIZE];
char func[QDF_MEM_FUNC_NAME_SIZE];
uint32_t line;
enum qdf_nbuf_event_type type;
uint64_t timestamp;
@ -565,7 +565,7 @@ static int32_t qdf_nbuf_circular_index_next(qdf_atomic_t *index, int size)
}
static void
qdf_nbuf_history_add(qdf_nbuf_t nbuf, const char *file, uint32_t line,
qdf_nbuf_history_add(qdf_nbuf_t nbuf, const char *func, uint32_t line,
enum qdf_nbuf_event_type type)
{
int32_t idx = qdf_nbuf_circular_index_next(&qdf_nbuf_history_index,
@ -573,7 +573,7 @@ qdf_nbuf_history_add(qdf_nbuf_t nbuf, const char *file, uint32_t line,
struct qdf_nbuf_event *event = &qdf_nbuf_history[idx];
event->nbuf = nbuf;
qdf_str_lcopy(event->file, kbasename(file), QDF_MEM_FILE_NAME_SIZE);
qdf_str_lcopy(event->func, func, QDF_MEM_FUNC_NAME_SIZE);
event->line = line;
event->type = type;
event->timestamp = qdf_get_log_timestamp();
@ -584,7 +584,7 @@ qdf_nbuf_history_add(qdf_nbuf_t nbuf, const char *file, uint32_t line,
struct qdf_nbuf_map_metadata {
struct hlist_node node;
qdf_nbuf_t nbuf;
char file[QDF_MEM_FILE_NAME_SIZE];
char func[QDF_MEM_FUNC_NAME_SIZE];
uint32_t line;
};
@ -615,7 +615,7 @@ static void qdf_nbuf_map_leaks_print(void)
hash_for_each(qdf_nbuf_map_ht, bucket, meta, node) {
count++;
qdf_nofl_alert("0x%zx @ %s:%u",
(uintptr_t)meta->nbuf, meta->file, meta->line);
(uintptr_t)meta->nbuf, meta->func, meta->line);
}
QDF_DEBUG_PANIC("%u fatal nbuf map-no-unmap events detected!", count);
@ -651,7 +651,7 @@ static struct qdf_nbuf_map_metadata *qdf_nbuf_meta_get(qdf_nbuf_t nbuf)
}
static QDF_STATUS
qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *file, uint32_t line)
qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line)
{
struct qdf_nbuf_map_metadata *meta;
@ -667,7 +667,7 @@ qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *file, uint32_t line)
if (meta)
QDF_DEBUG_PANIC(
"Double nbuf map detected @ %s:%u; last map from %s:%u",
kbasename(file), line, meta->file, meta->line);
func, line, meta->func, meta->line);
meta = qdf_flex_mem_alloc(&qdf_nbuf_map_pool);
if (!meta) {
@ -676,20 +676,20 @@ qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *file, uint32_t line)
}
meta->nbuf = nbuf;
qdf_str_lcopy(meta->file, kbasename(file), QDF_MEM_FILE_NAME_SIZE);
qdf_str_lcopy(meta->func, func, QDF_MEM_FUNC_NAME_SIZE);
meta->line = line;
qdf_spin_lock_irqsave(&qdf_nbuf_map_lock);
hash_add(qdf_nbuf_map_ht, &meta->node, (size_t)nbuf);
qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock);
qdf_nbuf_history_add(nbuf, file, line, QDF_NBUF_MAP);
qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_MAP);
return QDF_STATUS_SUCCESS;
}
static void
qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *file, uint32_t line)
qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *func, uint32_t line)
{
struct qdf_nbuf_map_metadata *meta;
@ -705,31 +705,31 @@ qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *file, uint32_t line)
if (!meta)
QDF_DEBUG_PANIC(
"Double nbuf unmap or unmap without map detected @ %s:%u",
kbasename(file), line);
func, line);
hash_del(&meta->node);
qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock);
qdf_flex_mem_free(&qdf_nbuf_map_pool, meta);
qdf_nbuf_history_add(nbuf, file, line, QDF_NBUF_UNMAP);
qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_UNMAP);
}
QDF_STATUS qdf_nbuf_map_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line)
{
QDF_STATUS status;
status = qdf_nbuf_track_map(buf, file, line);
status = qdf_nbuf_track_map(buf, func, line);
if (QDF_IS_STATUS_ERROR(status))
return status;
status = __qdf_nbuf_map(osdev, buf, dir);
if (QDF_IS_STATUS_ERROR(status))
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
return status;
}
@ -739,10 +739,10 @@ qdf_export_symbol(qdf_nbuf_map_debug);
void qdf_nbuf_unmap_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line)
{
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
__qdf_nbuf_unmap_single(osdev, buf, dir);
}
@ -751,18 +751,18 @@ qdf_export_symbol(qdf_nbuf_unmap_debug);
QDF_STATUS qdf_nbuf_map_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line)
{
QDF_STATUS status;
status = qdf_nbuf_track_map(buf, file, line);
status = qdf_nbuf_track_map(buf, func, line);
if (QDF_IS_STATUS_ERROR(status))
return status;
status = __qdf_nbuf_map_single(osdev, buf, dir);
if (QDF_IS_STATUS_ERROR(status))
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
return status;
}
@ -772,10 +772,10 @@ qdf_export_symbol(qdf_nbuf_map_single_debug);
void qdf_nbuf_unmap_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
const char *file,
const char *func,
uint32_t line)
{
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
__qdf_nbuf_unmap_single(osdev, buf, dir);
}
@ -785,18 +785,18 @@ QDF_STATUS qdf_nbuf_map_nbytes_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line)
{
QDF_STATUS status;
status = qdf_nbuf_track_map(buf, file, line);
status = qdf_nbuf_track_map(buf, func, line);
if (QDF_IS_STATUS_ERROR(status))
return status;
status = __qdf_nbuf_map_nbytes(osdev, buf, dir, nbytes);
if (QDF_IS_STATUS_ERROR(status))
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
return status;
}
@ -807,10 +807,10 @@ void qdf_nbuf_unmap_nbytes_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line)
{
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
__qdf_nbuf_unmap_nbytes(osdev, buf, dir, nbytes);
}
@ -820,18 +820,18 @@ QDF_STATUS qdf_nbuf_map_nbytes_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line)
{
QDF_STATUS status;
status = qdf_nbuf_track_map(buf, file, line);
status = qdf_nbuf_track_map(buf, func, line);
if (QDF_IS_STATUS_ERROR(status))
return status;
status = __qdf_nbuf_map_nbytes_single(osdev, buf, dir, nbytes);
if (QDF_IS_STATUS_ERROR(status))
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
return status;
}
@ -842,16 +842,16 @@ void qdf_nbuf_unmap_nbytes_single_debug(qdf_device_t osdev,
qdf_nbuf_t buf,
qdf_dma_dir_t dir,
int nbytes,
const char *file,
const char *func,
uint32_t line)
{
qdf_nbuf_untrack_map(buf, file, line);
qdf_nbuf_untrack_map(buf, func, line);
__qdf_nbuf_unmap_nbytes_single(osdev, buf, dir, nbytes);
}
qdf_export_symbol(qdf_nbuf_unmap_nbytes_single_debug);
static void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf, uint8_t *file,
static void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf, const char *func,
uint32_t line)
{
struct qdf_nbuf_map_metadata *meta;
@ -861,7 +861,7 @@ static void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf, uint8_t *file,
if (meta)
QDF_DEBUG_PANIC(
"Nbuf freed @ %s:%u while mapped from %s:%u",
kbasename(file), line, meta->file, meta->line);
kbasename(func), line, meta->func, meta->line);
qdf_spin_unlock_irqrestore(&qdf_nbuf_map_lock);
}
#else
@ -874,7 +874,7 @@ static inline void qdf_nbuf_map_tracking_deinit(void)
}
static inline void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf,
uint8_t *file,
const char *func,
uint32_t line)
{
}
@ -2098,14 +2098,14 @@ qdf_export_symbol(__qdf_nbuf_is_bcast_pkt);
*
* @p_next: Pointer to next
* @net_buf: Pointer to network buffer
* @file_name: File name
* @func_name: Function name
* @line_num: Line number
* @size: Size
*/
struct qdf_nbuf_track_t {
struct qdf_nbuf_track_t *p_next;
qdf_nbuf_t net_buf;
char file_name[QDF_MEM_FILE_NAME_SIZE];
char func_name[QDF_MEM_FUNC_NAME_SIZE];
uint32_t line_num;
size_t size;
};
@ -2409,8 +2409,8 @@ void qdf_net_buf_debug_exit(void)
p_prev = p_node;
p_node = p_node->p_next;
count++;
qdf_info("SKB buf memory Leak@ File %s, @Line %d, size %zu, nbuf %pK",
p_prev->file_name, p_prev->line_num,
qdf_info("SKB buf memory Leak@ Func %s, @Line %d, size %zu, nbuf %pK",
p_prev->func_name, p_prev->line_num,
p_prev->size, p_prev->net_buf);
qdf_nbuf_track_free(p_prev);
}
@ -2474,7 +2474,7 @@ static QDF_NBUF_TRACK *qdf_net_buf_debug_look_up(qdf_nbuf_t net_buf)
* Return: none
*/
void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size,
uint8_t *file_name, uint32_t line_num)
const char *func_name, uint32_t line_num)
{
uint32_t i;
unsigned long irq_flag;
@ -2490,15 +2490,15 @@ void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size,
if (p_node) {
qdf_print("Double allocation of skb ! Already allocated from %pK %s %d current alloc from %pK %s %d",
p_node->net_buf, p_node->file_name, p_node->line_num,
net_buf, kbasename(file_name), line_num);
p_node->net_buf, p_node->func_name, p_node->line_num,
net_buf, func_name, line_num);
qdf_nbuf_track_free(new_node);
} else {
p_node = new_node;
if (p_node) {
p_node->net_buf = net_buf;
qdf_str_lcopy(p_node->file_name, kbasename(file_name),
QDF_MEM_FILE_NAME_SIZE);
qdf_str_lcopy(p_node->func_name, func_name,
QDF_MEM_FUNC_NAME_SIZE);
p_node->line_num = line_num;
p_node->size = size;
qdf_mem_skb_inc(size);
@ -2507,14 +2507,14 @@ void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size,
} else
qdf_print(
"Mem alloc failed ! Could not track skb from %s %d of size %zu",
kbasename(file_name), line_num, size);
func_name, line_num, size);
}
spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
}
qdf_export_symbol(qdf_net_buf_debug_add_node);
void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, uint8_t *file_name,
void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, const char *func_name,
uint32_t line_num)
{
uint32_t i;
@ -2527,8 +2527,8 @@ void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, uint8_t *file_name,
p_node = qdf_net_buf_debug_look_up(net_buf);
if (p_node) {
qdf_str_lcopy(p_node->file_name, kbasename(file_name),
QDF_MEM_FILE_NAME_SIZE);
qdf_str_lcopy(p_node->func_name, kbasename(func_name),
QDF_MEM_FUNC_NAME_SIZE);
p_node->line_num = line_num;
}
@ -2591,7 +2591,7 @@ done:
qdf_export_symbol(qdf_net_buf_debug_delete_node);
void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
uint8_t *file_name, uint32_t line_num)
const char *func_name, uint32_t line_num)
{
qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf);
@ -2603,10 +2603,10 @@ void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
qdf_nbuf_t next;
next = qdf_nbuf_queue_next(ext_list);
qdf_net_buf_debug_add_node(ext_list, 0, file_name, line_num);
qdf_net_buf_debug_add_node(ext_list, 0, func_name, line_num);
ext_list = next;
}
qdf_net_buf_debug_add_node(net_buf, 0, file_name, line_num);
qdf_net_buf_debug_add_node(net_buf, 0, func_name, line_num);
}
qdf_export_symbol(qdf_net_buf_debug_acquire_skb);
@ -2652,25 +2652,25 @@ qdf_export_symbol(qdf_net_buf_debug_release_skb);
qdf_nbuf_t qdf_nbuf_alloc_debug(qdf_device_t osdev, qdf_size_t size,
int reserve, int align, int prio,
uint8_t *file, uint32_t line)
const char *func, uint32_t line)
{
qdf_nbuf_t nbuf;
nbuf = __qdf_nbuf_alloc(osdev, size, reserve, align, prio, file, line);
nbuf = __qdf_nbuf_alloc(osdev, size, reserve, align, prio, func, line);
/* Store SKB in internal QDF tracking table */
if (qdf_likely(nbuf)) {
qdf_net_buf_debug_add_node(nbuf, size, file, line);
qdf_nbuf_history_add(nbuf, file, line, QDF_NBUF_ALLOC);
qdf_net_buf_debug_add_node(nbuf, size, func, line);
qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC);
} else {
qdf_nbuf_history_add(nbuf, file, line, QDF_NBUF_ALLOC_FAILURE);
qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC_FAILURE);
}
return nbuf;
}
qdf_export_symbol(qdf_nbuf_alloc_debug);
void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, uint8_t *file, uint32_t line)
void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, const char *func, uint32_t line)
{
if (qdf_unlikely(!nbuf))
return;
@ -2679,9 +2679,9 @@ void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, uint8_t *file, uint32_t line)
goto free_buf;
/* Remove SKB from internal QDF tracking table */
qdf_nbuf_panic_on_free_if_mapped(nbuf, file, line);
qdf_nbuf_panic_on_free_if_mapped(nbuf, func, line);
qdf_net_buf_debug_delete_node(nbuf);
qdf_nbuf_history_add(nbuf, file, line, QDF_NBUF_FREE);
qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_FREE);
free_buf:
__qdf_nbuf_free(nbuf);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2019 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
@ -95,14 +95,14 @@ QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl);
* wbuff_buff_get() - return buffer to the requester
* @handle: wbuff_handle corresponding to the module
* @len: length of buffer requested
* file_name: file from which buffer is requested
* line_num: line number in the file
* @func_name: function from which buffer is requested
* @line_num: line number in the file
*
* Return: Network buffer if success
* NULL if failure
*/
qdf_nbuf_t wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len,
uint8_t *file_name, uint32_t line_num);
const char *func_name, uint32_t line_num);
/**
* wbuff_buff_put() - put the buffer back to wbuff pool
@ -139,7 +139,7 @@ static inline QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl)
}
static inline qdf_nbuf_t
wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len, int8_t *file_name,
wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len, const char *func_name,
uint32_t line_num)
{
return NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2019 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
@ -297,7 +297,7 @@ QDF_STATUS wbuff_module_deregister(struct wbuff_mod_handle *hdl)
}
qdf_nbuf_t wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len,
uint8_t *file_name, uint32_t line_num)
const char *func_name, uint32_t line_num)
{
struct wbuff_handle *handle;
struct wbuff_module *mod = NULL;
@ -324,7 +324,7 @@ qdf_nbuf_t wbuff_buff_get(struct wbuff_mod_handle *hdl, uint32_t len,
qdf_spin_unlock_bh(&mod->lock);
if (buf) {
qdf_nbuf_set_next(buf, NULL);
qdf_net_buf_debug_update_node(buf, file_name, line_num);
qdf_net_buf_debug_update_node(buf, func_name, line_num);
}
return buf;

View File

@ -231,10 +231,10 @@ wmi_unified_remove_work(struct wmi_unified *wmi_handle);
* @return wmi_buf_t.
*/
#ifdef NBUF_MEMORY_DEBUG
#define wmi_buf_alloc(h, l) wmi_buf_alloc_debug(h, l, __FILE__, __LINE__)
#define wmi_buf_alloc(h, l) wmi_buf_alloc_debug(h, l, __func__, __LINE__)
wmi_buf_t
wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len,
uint8_t *file_name, uint32_t line_num);
const char *func_name, uint32_t line_num);
#else
/**
* wmi_buf_alloc() - generic function to allocate WMI buffer

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2015-2019 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
@ -1515,7 +1515,8 @@ int wmi_get_host_credits(wmi_unified_t wmi_handle);
#ifdef NBUF_MEMORY_DEBUG
wmi_buf_t
wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len, uint8_t *file_name,
wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len,
const char *func_name,
uint32_t line_num)
{
wmi_buf_t wmi_buf;
@ -1525,15 +1526,14 @@ wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len, uint8_t *file_name,
return NULL;
}
wmi_buf = wbuff_buff_get(wmi_handle->wbuff_handle, len, file_name,
wmi_buf = wbuff_buff_get(wmi_handle->wbuff_handle, len, func_name,
line_num);
if (!wmi_buf)
wmi_buf = qdf_nbuf_alloc_debug(NULL,
roundup(len + WMI_MIN_HEAD_ROOM,
4),
WMI_MIN_HEAD_ROOM, 4, false,
file_name, line_num);
func_name, line_num);
if (!wmi_buf)
return NULL;
@ -1568,7 +1568,7 @@ wmi_buf_t wmi_buf_alloc_fl(wmi_unified_t wmi_handle, uint32_t len,
return NULL;
}
wmi_buf = wbuff_buff_get(wmi_handle->wbuff_handle, len, __FILE__,
wmi_buf = wbuff_buff_get(wmi_handle->wbuff_handle, len, __func__,
__LINE__);
if (!wmi_buf)
wmi_buf = qdf_nbuf_alloc_fl(NULL, roundup(len +