diff options
| author | Lihua Liu <lihual@codeaurora.org> | 2018-12-13 15:58:58 +0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2019-02-24 23:09:35 -0800 |
| commit | a1514e75f2fc5e91ce5fa50a07506f201558fe3f (patch) | |
| tree | a117ede66ee3927b8b08759d42a2a1577d49c841 | |
| parent | 27e17fa1aafcf0e962f638b86ef66ca16c646c0b (diff) | |
qcacld-2.0: Add support for customized firmware path
Add new interface customized_request_firmware instead of
request_firmware to support customized path of firmware.
Change-Id: I33f58966de58660afc9ddaeb49ac261ac9dc3540
CRs-Fixed: 2384905
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg.c | 4 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_main.c | 5 | ||||
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.c | 6 | ||||
| -rw-r--r-- | CORE/VOSS/inc/vos_api.h | 8 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_api.c | 162 | ||||
| -rw-r--r-- | Kbuild | 4 |
6 files changed, 181 insertions, 8 deletions
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c index 7c00814f86c3..9e517ef5a683 100644 --- a/CORE/HDD/src/wlan_hdd_cfg.c +++ b/CORE/HDD/src/wlan_hdd_cfg.c @@ -5619,7 +5619,7 @@ VOS_STATUS hdd_parse_config_ini(hdd_context_t* pHddCtx) memset(cfgIniTable, 0, sizeof(cfgIniTable)); - status = request_firmware(&fw, WLAN_INI_FILE, pHddCtx->parent_dev); + status = qca_request_firmware(&fw, WLAN_INI_FILE, pHddCtx->parent_dev); if(status) { @@ -6583,7 +6583,7 @@ VOS_STATUS hdd_update_mac_config(hdd_context_t *pHddCtx) VOS_STATUS vos_status = VOS_STATUS_SUCCESS; memset(macTable, 0, sizeof(macTable)); - status = request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); + status = qca_request_firmware(&fw, WLAN_MAC_FILE, pHddCtx->parent_dev); if (status) { diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c index f123262a7cad..f42bd901e5e4 100644 --- a/CORE/HDD/src/wlan_hdd_main.c +++ b/CORE/HDD/src/wlan_hdd_main.c @@ -10576,7 +10576,7 @@ VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBuf ENTER(); - status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); + status = qca_request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); if(status || !pHddCtx->fw || !pHddCtx->fw->data) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__); @@ -10617,7 +10617,7 @@ VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName, ENTER(); - status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); + status = qca_request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev); if(status || !pHddCtx->fw || !pHddCtx->fw->data) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__); @@ -20861,3 +20861,4 @@ module_param(enable_11d, int, module_param(country_code, charp, S_IRUSR | S_IRGRP | S_IROTH); + diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c index 4289a7e041ca..c08a8a7a1871 100644 --- a/CORE/SERVICES/BMI/ol_fw.c +++ b/CORE/SERVICES/BMI/ol_fw.c @@ -257,7 +257,7 @@ static int ol_transfer_single_bin_file(struct ol_softc *scn, __func__)); } - if (request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) + if (qca_request_firmware(&fw_entry, filename, scn->sc_osdev->device) != 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Failed to get %s\n", @@ -751,7 +751,7 @@ defined(CONFIG_NON_QC_PLATFORM_PCI) break; } - status = request_firmware(&fw_entry, filename, scn->sc_osdev->device); + status = qca_request_firmware(&fw_entry, filename, scn->sc_osdev->device); if (status) { pr_err("%s: Failed to get %s:%d\n", __func__, filename, status); @@ -772,7 +772,7 @@ defined(CONFIG_NON_QC_PLATFORM_PCI) pr_info("%s: Trying to load default %s\n", __func__, filename); - status = request_firmware(&fw_entry, filename, + status = qca_request_firmware(&fw_entry, filename, scn->sc_osdev->device); if (status) { pr_err("%s: Failed to get %s:%d\n", diff --git a/CORE/VOSS/inc/vos_api.h b/CORE/VOSS/inc/vos_api.h index 416b35b6d1c2..2fab5cc8df84 100644 --- a/CORE/VOSS/inc/vos_api.h +++ b/CORE/VOSS/inc/vos_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -72,6 +72,7 @@ #include <vos_threads.h> #include <vos_timer.h> #include <vos_pack_align.h> +#include <linux/firmware.h> #define VOS_WDA_TIMEOUT 15000 @@ -463,4 +464,9 @@ v_BOOL_t vos_is_ch_switch_with_csa_enabled(void); #ifdef FEATURE_WLAN_DISABLE_CHANNEL_SWITCH bool vos_is_chan_ok_for_dnbs(uint8_t channel); #endif + +int qca_request_firmware(const struct firmware **firmware_p, + const char *name, + struct device *device); + #endif // if !defined __VOS_API_H diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c index 15f878e0fc4e..ff597ed77c6e 100644 --- a/CORE/VOSS/src/vos_api.c +++ b/CORE/VOSS/src/vos_api.c @@ -93,6 +93,7 @@ #include "wma.h" #include "vos_utils.h" +#include<adf_os_module.h> /*--------------------------------------------------------------------------- * Preprocessor Definitions and Constants @@ -3548,3 +3549,164 @@ bool vos_is_chan_ok_for_dnbs(uint8_t channel) return true; } #endif + +#ifdef CUSTOMIZED_FIRMWARE_PATH + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +#define GET_INODE_FROM_FILEP(filp) \ + (filp)->f_path.dentry->d_inode +#else +#define GET_INODE_FROM_FILEP(filp) \ + (filp)->f_dentry->d_inode +#endif +#define A_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) +char *qca_fw_path= ""; +#define DEFAULT_QCA_FW_PATH "/system/etc/wifi/qca9379" +static int qca_readwrite_file(const char *filename, + char *rbuf, + const char *wbuf, + size_t length) +{ + int ret = 0; + struct file *filp = (struct file *)-ENOENT; + mm_segment_t oldfs; + oldfs = get_fs(); + set_fs(KERNEL_DS); + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: filename %s \n", __func__, filename); + + do { + int mode = (wbuf) ? O_RDWR : O_RDONLY; + filp = filp_open(filename, mode, S_IRUSR); + if (IS_ERR(filp) || !filp->f_op) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: filename %s \n", __func__, filename); + ret = -ENOENT; + break; + } + + if (length == 0) { + /* Read the length of the file only */ + struct inode *inode; + + inode = GET_INODE_FROM_FILEP(filp); + if (!inode) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Get inode from %s failed \n", + __func__, filename); + ret = -ENOENT; + break; + } + ret = i_size_read(inode->i_mapping->host); + break; + } + + if (wbuf) { + if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Write %u bytes to file %s error %d\n", + __FUNCTION__, + (unsigned int)length, filename, ret); + break; + } + } else { + if ( (ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Read %u bytes from file %s error %d\n", + __FUNCTION__, + (unsigned int)length, filename, ret); + break; + } + } + } while (0); + + if (!IS_ERR(filp)) { + filp_close(filp, NULL); + } + set_fs(oldfs); + + return ret; +} + +static int customized_request_firmware(const struct firmware **firmware_p, + const char *name, + struct device *device) +{ + int ret = 0; + struct firmware *firmware; + char filename[256]; + const char *raw_filename = name; + int customized = 1; + *firmware_p = firmware = A_MALLOC(sizeof(*firmware)); + if (!firmware) + return -ENOMEM; + A_MEMZERO(firmware, sizeof(*firmware)); + do { + size_t length, bufsize, bmisize; + + if (strcmp(qca_fw_path, "") == 0) + customized = 0; + if (snprintf(filename, sizeof(filename), "%s/%s", + customized?qca_fw_path:DEFAULT_QCA_FW_PATH, + raw_filename) >= sizeof(filename)) { + hddLog(VOS_TRACE_LEVEL_ERROR, "snprintf: %s/%s\n", + customized?qca_fw_path:DEFAULT_QCA_FW_PATH, raw_filename); + ret = -1; + break; + } + if ( (ret=qca_readwrite_file(filename, NULL, NULL, 0)) < 0) { + break; + } else { + length = ret; + } + + if (strcmp(raw_filename, "softmac") == 0) { + bufsize = length = 17; + } else { + bufsize = ALIGN(length, PAGE_SIZE); + bmisize = A_ROUND_UP(length, 4); + bufsize = max(bmisize, bufsize); + } + firmware->data = vmalloc(bufsize); + firmware->size = length; + + if (!firmware->data) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Cannot allocate buffer for firmware\n", + __FUNCTION__); + ret = -ENOMEM; + break; + } + + if ( (ret=qca_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: file read error, ret %d request %d\n", + __FUNCTION__,ret,(int)length); + ret = -1; + break; + } + + } while (0); + + if (ret<0) { + if (firmware) { + if (firmware->data) + vfree(firmware->data); + A_FREE(firmware); + } + *firmware_p = NULL; + } else { + ret = 0; + } + return ret; +} + +module_param(qca_fw_path, charp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +#endif + +int qca_request_firmware(const struct firmware **firmware_p, + const char *name, + struct device *device) +{ +#ifdef CUSTOMIZED_FIRMWARE_PATH + return customized_request_firmware(firmware_p, name,device); +#else + return request_firmware(firmware_p, name,device); +#endif +} + @@ -1147,6 +1147,10 @@ CDEFINES += -DCONFIG_IXC_TIMER \ endif endif +ifeq ($(CONFIG_CUSTOMIZED_FIRMWARE_PATH), y) +CDEFINES += -DCUSTOMIZED_FIRMWARE_PATH +endif + ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) CDEFINES += -DWLAN_FEATURE_DSRC endif |
