summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLihua Liu <lihual@codeaurora.org>2018-12-13 15:58:58 +0800
committerGerrit - the friendly Code Review server <code-review@localhost>2019-02-24 23:09:35 -0800
commita1514e75f2fc5e91ce5fa50a07506f201558fe3f (patch)
treea117ede66ee3927b8b08759d42a2a1577d49c841
parent27e17fa1aafcf0e962f638b86ef66ca16c646c0b (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.c4
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c5
-rw-r--r--CORE/SERVICES/BMI/ol_fw.c6
-rw-r--r--CORE/VOSS/inc/vos_api.h8
-rw-r--r--CORE/VOSS/src/vos_api.c162
-rw-r--r--Kbuild4
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
+}
+
diff --git a/Kbuild b/Kbuild
index af953e919614..efa914aeeddc 100644
--- a/Kbuild
+++ b/Kbuild
@@ -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