diff --git a/qdf/inc/qdf_file.h b/qdf/inc/qdf_file.h index a90b921400..9ab401d027 100644 --- a/qdf/inc/qdf_file.h +++ b/qdf/inc/qdf_file.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-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 @@ -50,5 +50,47 @@ QDF_STATUS qdf_file_read(const char *path, char **out_buf); */ void qdf_file_buf_free(char *file_buf); +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +/** + * qdf_module_param_file_read() - read the entire contents of a file + * @path: the full path of the file to read + * @out_buf: double pointer for referring to the file contents buffer + * + * This API allocates a new buffer before qdf_mem_init() is being called. + * Thus, this API helps to allocate memory which is being used before qdf + * memory tracking framework is available. Buffer is null-terminated, + * containing the contents of the file at @path. On success, @out_buf + * points to this new buffer, otherwise @out_buf is set to NULL. + * + * Consumers must free the allocated buffer by calling + * qdf_module_param_file_free(). + * + * Return: QDF_STATUS + */ + +QDF_STATUS qdf_module_param_file_read(const char *path, char **out_buf); + +/** + * qdf_module_param_file_free() - free a previously allocated file buffer + * @file_buf: pointer to the file buffer to free. The buffer allocated in + * qdf_module_param_file_read is not tracked by qdf framework. + * + * This API is used in conjunction with qdf_module_param_file_read(). + * + * Return: None + */ +void qdf_module_param_file_free(char *file_buf); +#else +static inline +QDF_STATUS qdf_module_param_file_read(const char *path, char **out_buf) +{ + return QDF_STATUS_E_INVAL; +} + +static inline +void qdf_module_param_file_free(char *file_buf) +{ +} +#endif #endif /* __QDF_FILE_H */ diff --git a/qdf/inc/qdf_mem.h b/qdf/inc/qdf_mem.h index 0777288cc6..c41eae9a23 100644 --- a/qdf/inc/qdf_mem.h +++ b/qdf/inc/qdf_mem.h @@ -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 @@ -94,6 +94,14 @@ void qdf_mem_init(void); */ void qdf_mem_exit(void); +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +#define qdf_untracked_mem_malloc(size) \ + __qdf_untracked_mem_malloc(size, __func__, __LINE__) + +#define qdf_untracked_mem_free(ptr) \ + __qdf_untracked_mem_free(ptr) +#endif + #define QDF_MEM_FUNC_NAME_SIZE 48 #ifdef MEMORY_DEBUG @@ -104,6 +112,18 @@ void qdf_mem_exit(void); */ bool qdf_mem_debug_config_get(void); +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +/** + * qdf_mem_debug_disabled_set() - Set mem_debug_disabled + * @str_value: value of the module param + * + * This function will set qdf module param mem_debug_disabled + * + * Return: QDF_STATUS_SUCCESS on Success + */ +QDF_STATUS qdf_mem_debug_disabled_config_set(const char *str_value); +#endif + /** * qdf_mem_malloc_debug() - debug version of QDF memory allocation API * @size: Number of bytes of memory to allocate. @@ -245,6 +265,12 @@ static inline bool qdf_mem_debug_config_get(void) return false; } +static inline +QDF_STATUS qdf_mem_debug_disabled_config_set(const char *str_value) +{ + return QDF_STATUS_SUCCESS; +} + /** * qdf_mem_malloc() - allocation QDF memory * @size: Number of bytes of memory to allocate. @@ -304,6 +330,26 @@ void qdf_mem_multi_pages_free(qdf_device_t osdev, #endif /* MEMORY_DEBUG */ +/** + * qdf_prealloc_disabled_config_get() - Get the user configuration of + * prealloc_disabled + * + * Return: value of prealloc_disabled qdf module argument + */ +bool qdf_prealloc_disabled_config_get(void); + +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +/** + * qdf_prealloc_disabled_config_set() - Set prealloc_disabled + * @str_value: value of the module param + * + * This function will set qdf module param prealloc_disabled + * + * Return: QDF_STATUS_SUCCESS on Success + */ +QDF_STATUS qdf_prealloc_disabled_config_set(const char *str_value); +#endif + /** * qdf_mem_multi_pages_zero() - zero out each page memory * @pages: Multi page information storage diff --git a/qdf/inc/qdf_trace.h b/qdf/inc/qdf_trace.h index 8283dbf18b..1de8849ada 100644 --- a/qdf/inc/qdf_trace.h +++ b/qdf/inc/qdf_trace.h @@ -538,6 +538,8 @@ enum qdf_dpt_debugfs_state { QDF_DPT_DEBUGFS_STATE_SHOW_COMPLETE, }; +#define QDF_WIFI_MODULE_PARAMS_FILE "wifi_module_param.ini" + typedef void (*tp_qdf_trace_cb)(void *p_mac, tp_qdf_trace_record, uint16_t); typedef void (*tp_qdf_state_info_cb) (char **buf, uint16_t *size); #ifdef WLAN_FEATURE_MEMDUMP_ENABLE @@ -1426,6 +1428,24 @@ int qdf_print_ctrl_register(const struct category_info *cinfo, void *custom_ctx, const char *pctrl_name); +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +/** + * qdf_update_module_param() - Update qdf module params + * + * + * Read the file which has wifi module params, parse and update + * qdf module params. + * + * Return: void + */ +void qdf_initialize_module_param_from_ini(void); +#else +static inline +void qdf_initialize_module_param_from_ini(void) +{ +} +#endif + /** * qdf_shared_print_ctrl_init() - Initialize the shared print ctrl obj with * all categories set to the default level @@ -1566,6 +1586,30 @@ bool qdf_print_get_node_flag(unsigned int idx); #endif +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +/** + * qdf_module_param_handler() - Function to store module params + * + * @context : NULL, unused. + * @key : Name of the module param + * @value: Value of the module param + * + * Handler function to be called from qdf_ini_parse() + * function when a valid parameter is found in a file. + * + * Return : QDF_STATUS_SUCCESS on Success + */ +QDF_STATUS qdf_module_param_handler(void *context, const char *key, + const char *value); +#else +static inline +QDF_STATUS qdf_module_param_handler(void *context, const char *key, + const char *value) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * qdf_logging_init() - Initialize msg logging functionality * diff --git a/qdf/linux/src/i_qdf_mem.h b/qdf/linux/src/i_qdf_mem.h index 8fd375958d..3fa74c39fd 100644 --- a/qdf/linux/src/i_qdf_mem.h +++ b/qdf/linux/src/i_qdf_mem.h @@ -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 @@ -495,6 +495,36 @@ void *__qdf_mem_malloc(qdf_size_t size, const char *func, uint32_t line); */ void __qdf_mem_free(void *ptr); +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +/** + * __qdf_untracked_mem_malloc() - allocates non-QDF memory + * @size: Number of bytes of memory to allocate. + * + * @func: Function name of the call site + * @line: line number of the call site + * + * This function will dynamically allocate the specified number of bytes of + * memory. Memory allocated is not tracked by qdf memory debug framework. + * + * Return: + * Upon successful allocation, 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_untracked_mem_malloc(qdf_size_t size, const char *func, + uint32_t line); + +/** + * __qdf_untracked_mem_free() - free non-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_untracked_mem_free(void *ptr); +#endif + /** * __qdf_mem_free_consistent() - free consistent qdf memory * @osdev: OS device handle diff --git a/qdf/linux/src/qdf_file.c b/qdf/linux/src/qdf_file.c index 22936116f1..b07f907d5c 100644 --- a/qdf/linux/src/qdf_file.c +++ b/qdf/linux/src/qdf_file.c @@ -82,3 +82,42 @@ void qdf_file_buf_free(char *file_buf) } qdf_export_symbol(qdf_file_buf_free); +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +QDF_STATUS qdf_module_param_file_read(const char *path, char **out_buf) +{ + int errno; + const struct firmware *fw; + char *buf; + + *out_buf = NULL; + errno = qdf_firmware_request_nowarn(&fw, path, NULL); + if (errno) { + qdf_err("Failed to read file %s", path); + return QDF_STATUS_E_FAILURE; + } + + /* qdf_untracked_mem_malloc zeros new memory; +1 size + * ensures null-termination + */ + buf = qdf_untracked_mem_malloc(fw->size + 1); + if (!buf) { + release_firmware(fw); + return QDF_STATUS_E_NOMEM; + } + + qdf_mem_copy(buf, fw->data, fw->size); + release_firmware(fw); + *out_buf = buf; + + return QDF_STATUS_SUCCESS; +} + +void qdf_module_param_file_free(char *file_buf) +{ + QDF_BUG(file_buf); + if (!file_buf) + return; + + qdf_untracked_mem_free(file_buf); +} +#endif diff --git a/qdf/linux/src/qdf_mem.c b/qdf/linux/src/qdf_mem.c index faababc9aa..4f08780599 100644 --- a/qdf/linux/src/qdf_mem.c +++ b/qdf/linux/src/qdf_mem.c @@ -493,10 +493,41 @@ static int qdf_err_printer(void *priv, const char *fmt, ...) #endif /* MEMORY_DEBUG */ -u_int8_t prealloc_disabled = 1; -qdf_declare_param(prealloc_disabled, byte); +bool prealloc_disabled = 1; +qdf_declare_param(prealloc_disabled, bool); qdf_export_symbol(prealloc_disabled); +/** + * qdf_prealloc_disabled_config_get() - Get the user configuration of + * prealloc_disabled + * + * Return: value of prealloc_disabled qdf module argument + */ +bool qdf_prealloc_disabled_config_get(void) +{ + return prealloc_disabled; +} + +qdf_export_symbol(qdf_prealloc_disabled_config_get); + +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +/** + * qdf_prealloc_disabled_config_set() - Set prealloc_disabled + * @str_value: value of the module param + * + * This function will set qdf module param prealloc_disabled + * + * Return: QDF_STATUS_SUCCESS on Success + */ +QDF_STATUS qdf_prealloc_disabled_config_set(const char *str_value) +{ + QDF_STATUS status; + + status = qdf_bool_parse(str_value, &prealloc_disabled); + return status; +} +#endif + #if defined WLAN_DEBUGFS /* Debugfs root directory for qdf_mem */ @@ -1404,6 +1435,24 @@ bool qdf_mem_debug_config_get(void) } #endif /* DISABLE_MEM_DBG_LOAD_CONFIG */ +/** + * qdf_mem_debug_disabled_set() - Set mem_debug_disabled + * @str_value: value of the module param + * + * This function will se qdf module param mem_debug_disabled + * + * Return: QDF_STATUS_SUCCESS on Success + */ +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +QDF_STATUS qdf_mem_debug_disabled_config_set(const char *str_value) +{ + QDF_STATUS status; + + status = qdf_bool_parse(str_value, &mem_debug_disabled); + return status; +} +#endif + /** * qdf_mem_debug_init() - initialize qdf memory debug functionality * @@ -2019,6 +2068,33 @@ void *__qdf_mem_malloc(size_t size, const char *func, uint32_t line) qdf_export_symbol(__qdf_mem_malloc); +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +void __qdf_untracked_mem_free(void *ptr) +{ + if (!ptr) + return; + + kfree(ptr); +} + +void *__qdf_untracked_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 = kzalloc(size, qdf_mem_malloc_flags()); + if (!ptr) + return NULL; + + return ptr; +} +#endif + void *qdf_aligned_malloc_fl(uint32_t *size, void **vaddr_unaligned, qdf_dma_addr_t *paddr_unaligned, diff --git a/qdf/linux/src/qdf_module.c b/qdf/linux/src/qdf_module.c index 01eba3d11f..013a96257a 100644 --- a/qdf/linux/src/qdf_module.c +++ b/qdf/linux/src/qdf_module.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, 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 @@ -48,6 +48,7 @@ static int __init qdf_mod_init(void) int qdf_mod_init(void) #endif { + qdf_initialize_module_param_from_ini(); qdf_shared_print_ctrl_init(); qdf_debugfs_init(); qdf_mem_init(); diff --git a/qdf/linux/src/qdf_trace.c b/qdf/linux/src/qdf_trace.c index 0ea4bf4cae..143cf5d278 100644 --- a/qdf/linux/src/qdf_trace.c +++ b/qdf/linux/src/qdf_trace.c @@ -25,8 +25,10 @@ /* Include Files */ #include "qdf_str.h" #include +#include #include #include +#include /* macro to map qdf trace levels into the bitmask */ #define QDF_TRACE_LEVEL_TO_MODULE_BITMASK(_level) ((1 << (_level))) @@ -103,6 +105,28 @@ static struct s_qdf_dp_trace_data g_qdf_dp_trace_data; static tp_qdf_dp_trace_cb qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX + 1]; #endif +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +#define QDF_PARAM_STR_LENGTH 40 + +enum qdf_num_module_param { + MEM_DEBUG_DISABLED, + QDF_DBG_MASK, + PREALLOC_DISABLED, + QDF_LOG_DUMP_AT_KERNEL_ENABLE, + QDF_DBG_ARR, + QDF_LOG_FLUSH_TIMER_PERIOD, + QDF_PARAM_MAX, +}; + +static char qdf_module_param[QDF_PARAM_MAX][QDF_PARAM_STR_LENGTH] = { + "mem_debug_disabled", + "qdf_dbg_mask", + "prealloc_disabled", + "qdf_log_dump_at_kernel_enable", + "qdf_dbg_arr", + "qdf_log_flush_timer_period", +}; +#endif /** * qdf_snprintf() - wrapper function to snprintf * @str_buffer: string Buffer @@ -3804,6 +3828,63 @@ void qdf_shared_print_ctrl_init(void) qdf_export_symbol(qdf_shared_print_ctrl_init); #endif +#ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI +QDF_STATUS qdf_module_param_handler(void *context, const char *str_param, + const char *str_value) +{ + QDF_STATUS status; + uint16_t param = 0; + + while (param < QDF_PARAM_MAX) { + if (qdf_str_eq(qdf_module_param[param], str_param)) { + switch (param) { + case MEM_DEBUG_DISABLED: + status = qdf_mem_debug_disabled_config_set(str_value); + break; + case QDF_DBG_MASK: + status = qdf_int32_parse(str_value, &qdf_dbg_mask); + break; + case PREALLOC_DISABLED: + status = qdf_prealloc_disabled_config_set(str_value); + break; + case QDF_LOG_DUMP_AT_KERNEL_ENABLE: + status = qdf_bool_parse(str_value, + &qdf_log_dump_at_kernel_enable); + break; + case QDF_DBG_ARR: + qdf_dbg_arr[0] = (char *)str_value; + break; + case QDF_LOG_FLUSH_TIMER_PERIOD: + status = qdf_uint32_parse(str_value, + &qdf_log_flush_timer_period); + break; + default: + break; + } + if (QDF_IS_STATUS_SUCCESS(status)) + return QDF_STATUS_SUCCESS; + } + param++; + } + + return QDF_STATUS_SUCCESS; +} + +void qdf_initialize_module_param_from_ini(void) +{ + QDF_STATUS status; + char *path = QDF_WIFI_MODULE_PARAMS_FILE; + + status = qdf_ini_parse(path, NULL, qdf_module_param_handler, NULL); + if (QDF_IS_STATUS_ERROR(status)) { + QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, + "Failed to parse *.ini file @ %s; status:%d", + path, status); + return; + } +} +#endif + QDF_STATUS qdf_print_set_category_verbose(unsigned int idx, QDF_MODULE_ID category, QDF_TRACE_LEVEL verbose, diff --git a/qdf/src/qdf_parse.c b/qdf/src/qdf_parse.c index c040843b56..ff0eece78e 100644 --- a/qdf/src/qdf_parse.c +++ b/qdf/src/qdf_parse.c @@ -32,7 +32,10 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context, char *cursor; int ini_read_count = 0; - status = qdf_file_read(ini_path, &fbuf); + if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path)) + status = qdf_module_param_file_read(ini_path, &fbuf); + else + status = qdf_file_read(ini_path, &fbuf); if (QDF_IS_STATUS_ERROR(status)) { qdf_err("Failed to read *.ini file @ %s", ini_path); return status; @@ -132,7 +135,10 @@ QDF_STATUS qdf_ini_parse(const char *ini_path, void *context, } free_fbuf: - qdf_file_buf_free(fbuf); + if (qdf_str_eq(QDF_WIFI_MODULE_PARAMS_FILE, ini_path)) + qdf_module_param_file_free(fbuf); + else + qdf_file_buf_free(fbuf); return status; }