Commit 7ebf721d authored by Kalle Valo's avatar Kalle Valo

ath10k: refactor firmware images to struct ath10k_fw_components

To make it easier to share ath10k_core_fetch_board_data_api_n() with testmode.c
refactor all firmware components to struct ath10k_fw_components. This structure
will hold firmware related files, for example firmware-N.bin and board-N.bin.

For firmware-N.bin create a new struct ath10k_fw_file which contains the actual
firmware image as well as the parsed data from the image.

Modify ath10k_core_start() to take struct ath10k_fw_components() as an argument
which makes it possible in following patches to drop some ugly hacks from
testmode.c.
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 3fb55c79
This diff is collapsed.
...@@ -627,6 +627,27 @@ enum ath10k_tx_pause_reason { ...@@ -627,6 +627,27 @@ enum ath10k_tx_pause_reason {
ATH10K_TX_PAUSE_MAX, ATH10K_TX_PAUSE_MAX,
}; };
struct ath10k_fw_file {
const struct firmware *firmware;
const void *firmware_data;
size_t firmware_len;
const void *otp_data;
size_t otp_len;
const void *codeswap_data;
size_t codeswap_len;
};
struct ath10k_fw_components {
const struct firmware *board;
const void *board_data;
size_t board_len;
struct ath10k_fw_file fw_file;
};
struct ath10k { struct ath10k {
struct ath_common ath_common; struct ath_common ath_common;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
...@@ -714,23 +735,18 @@ struct ath10k { ...@@ -714,23 +735,18 @@ struct ath10k {
} fw; } fw;
} hw_params; } hw_params;
const struct firmware *board; /* contains the firmware images used with ATH10K_FIRMWARE_MODE_NORMAL */
const void *board_data; struct ath10k_fw_components normal_mode_fw;
size_t board_len;
const void *otp_data; /* READ-ONLY images of the running firmware, which can be either
size_t otp_len; * normal or UTF. Do not modify, release etc!
*/
const struct firmware *firmware; const struct ath10k_fw_components *running_fw;
const void *firmware_data;
size_t firmware_len;
const struct firmware *pre_cal_file; const struct firmware *pre_cal_file;
const struct firmware *cal_file; const struct firmware *cal_file;
struct { struct {
const void *firmware_codeswap_data;
size_t firmware_codeswap_len;
struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info; struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
} swap; } swap;
...@@ -876,13 +892,12 @@ struct ath10k { ...@@ -876,13 +892,12 @@ struct ath10k {
struct { struct {
/* protected by conf_mutex */ /* protected by conf_mutex */
const struct firmware *utf; struct ath10k_fw_components utf_mode_fw;
char utf_version[32]; char utf_version[32];
const void *utf_firmware_data;
size_t utf_firmware_len;
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
enum ath10k_fw_wmi_op_version orig_wmi_op_version; enum ath10k_fw_wmi_op_version orig_wmi_op_version;
enum ath10k_fw_wmi_op_version op_version; enum ath10k_fw_wmi_op_version op_version;
/* protected by data_lock */ /* protected by data_lock */
bool utf_monitor; bool utf_monitor;
} testmode; } testmode;
...@@ -919,7 +934,8 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar, ...@@ -919,7 +934,8 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar,
char *buf, char *buf,
size_t max_len); size_t max_len);
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode); int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
const struct ath10k_fw_components *fw_components);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt); int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
void ath10k_core_stop(struct ath10k *ar); void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar, u32 chip_id); int ath10k_core_register(struct ath10k *ar, u32 chip_id);
......
...@@ -126,6 +126,7 @@ EXPORT_SYMBOL(ath10k_info); ...@@ -126,6 +126,7 @@ EXPORT_SYMBOL(ath10k_info);
void ath10k_debug_print_hwfw_info(struct ath10k *ar) void ath10k_debug_print_hwfw_info(struct ath10k *ar)
{ {
const struct firmware *firmware;
char fw_features[128] = {}; char fw_features[128] = {};
u32 crc = 0; u32 crc = 0;
...@@ -144,8 +145,9 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar) ...@@ -144,8 +145,9 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar)
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED), config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
config_enabled(CONFIG_NL80211_TESTMODE)); config_enabled(CONFIG_NL80211_TESTMODE));
if (ar->firmware) firmware = ar->normal_mode_fw.fw_file.firmware;
crc = crc32_le(0, ar->firmware->data, ar->firmware->size); if (firmware)
crc = crc32_le(0, firmware->data, firmware->size);
ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n", ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
ar->hw->wiphy->fw_version, ar->hw->wiphy->fw_version,
...@@ -167,7 +169,8 @@ void ath10k_debug_print_board_info(struct ath10k *ar) ...@@ -167,7 +169,8 @@ void ath10k_debug_print_board_info(struct ath10k *ar)
ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x", ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
ar->bd_api, ar->bd_api,
boardinfo, boardinfo,
crc32_le(0, ar->board->data, ar->board->size)); crc32_le(0, ar->normal_mode_fw.board->data,
ar->normal_mode_fw.board->size));
} }
void ath10k_debug_print_boot_info(struct ath10k *ar) void ath10k_debug_print_boot_info(struct ath10k *ar)
...@@ -2270,23 +2273,28 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file, ...@@ -2270,23 +2273,28 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
len += scnprintf(buf + len, buf_len - len, len += scnprintf(buf + len, buf_len - len,
"firmware-N.bin\t\t%08x\n", "firmware-N.bin\t\t%08x\n",
crc32_le(0, ar->firmware->data, ar->firmware->size)); crc32_le(0, ar->normal_mode_fw.fw_file.firmware->data,
ar->normal_mode_fw.fw_file.firmware->size));
len += scnprintf(buf + len, buf_len - len, len += scnprintf(buf + len, buf_len - len,
"athwlan\t\t\t%08x\n", "athwlan\t\t\t%08x\n",
crc32_le(0, ar->firmware_data, ar->firmware_len)); crc32_le(0, ar->normal_mode_fw.fw_file.firmware_data,
ar->normal_mode_fw.fw_file.firmware_len));
len += scnprintf(buf + len, buf_len - len, len += scnprintf(buf + len, buf_len - len,
"otp\t\t\t%08x\n", "otp\t\t\t%08x\n",
crc32_le(0, ar->otp_data, ar->otp_len)); crc32_le(0, ar->normal_mode_fw.fw_file.otp_data,
ar->normal_mode_fw.fw_file.otp_len));
len += scnprintf(buf + len, buf_len - len, len += scnprintf(buf + len, buf_len - len,
"codeswap\t\t%08x\n", "codeswap\t\t%08x\n",
crc32_le(0, ar->swap.firmware_codeswap_data, crc32_le(0, ar->normal_mode_fw.fw_file.codeswap_data,
ar->swap.firmware_codeswap_len)); ar->normal_mode_fw.fw_file.codeswap_len));
len += scnprintf(buf + len, buf_len - len, len += scnprintf(buf + len, buf_len - len,
"board-N.bin\t\t%08x\n", "board-N.bin\t\t%08x\n",
crc32_le(0, ar->board->data, ar->board->size)); crc32_le(0, ar->normal_mode_fw.board->data,
ar->normal_mode_fw.board->size));
len += scnprintf(buf + len, buf_len - len, len += scnprintf(buf + len, buf_len - len,
"board\t\t\t%08x\n", "board\t\t\t%08x\n",
crc32_le(0, ar->board_data, ar->board_len)); crc32_le(0, ar->normal_mode_fw.board_data,
ar->normal_mode_fw.board_len));
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
......
...@@ -4376,7 +4376,8 @@ static int ath10k_start(struct ieee80211_hw *hw) ...@@ -4376,7 +4376,8 @@ static int ath10k_start(struct ieee80211_hw *hw)
goto err_off; goto err_off;
} }
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL); ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL,
&ar->normal_mode_fw);
if (ret) { if (ret) {
ath10k_err(ar, "Could not init core: %d\n", ret); ath10k_err(ar, "Could not init core: %d\n", ret);
goto err_power_down; goto err_power_down;
......
...@@ -171,8 +171,13 @@ int ath10k_swap_code_seg_configure(struct ath10k *ar, ...@@ -171,8 +171,13 @@ int ath10k_swap_code_seg_configure(struct ath10k *ar,
void ath10k_swap_code_seg_release(struct ath10k *ar) void ath10k_swap_code_seg_release(struct ath10k *ar)
{ {
ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info); ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info);
ar->swap.firmware_codeswap_data = NULL;
ar->swap.firmware_codeswap_len = 0; /* FIXME: these two assignments look to bein wrong place! Shouldn't
* they be in ath10k_core_free_firmware_files() like the rest?
*/
ar->normal_mode_fw.fw_file.codeswap_data = NULL;
ar->normal_mode_fw.fw_file.codeswap_len = 0;
ar->swap.firmware_swap_code_seg_info = NULL; ar->swap.firmware_swap_code_seg_info = NULL;
} }
...@@ -180,20 +185,23 @@ int ath10k_swap_code_seg_init(struct ath10k *ar) ...@@ -180,20 +185,23 @@ int ath10k_swap_code_seg_init(struct ath10k *ar)
{ {
int ret; int ret;
struct ath10k_swap_code_seg_info *seg_info; struct ath10k_swap_code_seg_info *seg_info;
const void *codeswap_data;
size_t codeswap_len;
codeswap_data = ar->normal_mode_fw.fw_file.codeswap_data;
codeswap_len = ar->normal_mode_fw.fw_file.codeswap_len;
if (!ar->swap.firmware_codeswap_len || !ar->swap.firmware_codeswap_data) if (!codeswap_len || !codeswap_data)
return 0; return 0;
seg_info = ath10k_swap_code_seg_alloc(ar, seg_info = ath10k_swap_code_seg_alloc(ar, codeswap_len);
ar->swap.firmware_codeswap_len);
if (!seg_info) { if (!seg_info) {
ath10k_err(ar, "failed to allocate fw code swap segment\n"); ath10k_err(ar, "failed to allocate fw code swap segment\n");
return -ENOMEM; return -ENOMEM;
} }
ret = ath10k_swap_code_seg_fill(ar, seg_info, ret = ath10k_swap_code_seg_fill(ar, seg_info,
ar->swap.firmware_codeswap_data, codeswap_data, codeswap_len);
ar->swap.firmware_codeswap_len);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to initialize fw code swap segment: %d\n", ath10k_warn(ar, "failed to initialize fw code swap segment: %d\n",
......
...@@ -139,7 +139,8 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) ...@@ -139,7 +139,8 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
return cfg80211_testmode_reply(skb); return cfg80211_testmode_reply(skb);
} }
static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar,
struct ath10k_fw_file *fw_file)
{ {
size_t len, magic_len, ie_len; size_t len, magic_len, ie_len;
struct ath10k_fw_ie *hdr; struct ath10k_fw_ie *hdr;
...@@ -152,15 +153,15 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) ...@@ -152,15 +153,15 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE);
/* load utf firmware image */ /* load utf firmware image */
ret = request_firmware(&ar->testmode.utf, filename, ar->dev); ret = request_firmware(&fw_file->firmware, filename, ar->dev);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
filename, ret); filename, ret);
return ret; return ret;
} }
data = ar->testmode.utf->data; data = fw_file->firmware->data;
len = ar->testmode.utf->size; len = fw_file->firmware->size;
/* FIXME: call release_firmware() in error cases */ /* FIXME: call release_firmware() in error cases */
...@@ -222,8 +223,8 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) ...@@ -222,8 +223,8 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
"testmode found fw image ie (%zd B)\n", "testmode found fw image ie (%zd B)\n",
ie_len); ie_len);
ar->testmode.utf_firmware_data = data; fw_file->firmware_data = data;
ar->testmode.utf_firmware_len = ie_len; fw_file->firmware_len = ie_len;
break; break;
case ATH10K_FW_IE_WMI_OP_VERSION: case ATH10K_FW_IE_WMI_OP_VERSION:
if (ie_len != sizeof(u32)) if (ie_len != sizeof(u32))
...@@ -245,7 +246,7 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) ...@@ -245,7 +246,7 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
data += ie_len; data += ie_len;
} }
if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { if (!fw_file->firmware_data || !fw_file->firmware_len) {
ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n");
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
...@@ -254,12 +255,13 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) ...@@ -254,12 +255,13 @@ static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
return 0; return 0;
err: err:
release_firmware(ar->testmode.utf); release_firmware(fw_file->firmware);
return ret; return ret;
} }
static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar,
struct ath10k_fw_file *fw_file)
{ {
char filename[100]; char filename[100];
int ret; int ret;
...@@ -268,7 +270,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) ...@@ -268,7 +270,7 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
/* load utf firmware image */ /* load utf firmware image */
ret = request_firmware(&ar->testmode.utf, filename, ar->dev); ret = request_firmware(&fw_file->firmware, filename, ar->dev);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
filename, ret); filename, ret);
...@@ -282,23 +284,24 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) ...@@ -282,23 +284,24 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
*/ */
ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
ar->testmode.utf_firmware_data = ar->testmode.utf->data; fw_file->firmware_data = fw_file->firmware->data;
ar->testmode.utf_firmware_len = ar->testmode.utf->size; fw_file->firmware_len = fw_file->firmware->size;
return 0; return 0;
} }
static int ath10k_tm_fetch_firmware(struct ath10k *ar) static int ath10k_tm_fetch_firmware(struct ath10k *ar)
{ {
struct ath10k_fw_components *utf_mode_fw;
int ret; int ret;
ret = ath10k_tm_fetch_utf_firmware_api_2(ar); ret = ath10k_tm_fetch_utf_firmware_api_2(ar, &ar->testmode.utf_mode_fw.fw_file);
if (ret == 0) { if (ret == 0) {
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
return 0; goto out;
} }
ret = ath10k_tm_fetch_utf_firmware_api_1(ar); ret = ath10k_tm_fetch_utf_firmware_api_1(ar, &ar->testmode.utf_mode_fw.fw_file);
if (ret) { if (ret) {
ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret); ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
return ret; return ret;
...@@ -306,6 +309,21 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar) ...@@ -306,6 +309,21 @@ static int ath10k_tm_fetch_firmware(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1"); ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
out:
utf_mode_fw = &ar->testmode.utf_mode_fw;
/* Use the same board data file as the normal firmware uses (but
* it's still "owned" by normal_mode_fw so we shouldn't free it.
*/
utf_mode_fw->board_data = ar->normal_mode_fw.board_data;
utf_mode_fw->board_len = ar->normal_mode_fw.board_len;
if (!utf_mode_fw->fw_file.otp_data) {
ath10k_info(ar, "utf.bin didn't contain otp binary, taking it from the normal mode firmware");
utf_mode_fw->fw_file.otp_data = ar->normal_mode_fw.fw_file.otp_data;
utf_mode_fw->fw_file.otp_len = ar->normal_mode_fw.fw_file.otp_len;
}
return 0; return 0;
} }
...@@ -329,7 +347,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ...@@ -329,7 +347,7 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
goto err; goto err;
} }
if (WARN_ON(ar->testmode.utf != NULL)) { if (WARN_ON(ar->testmode.utf_mode_fw.fw_file.firmware != NULL)) {
/* utf image is already downloaded, it shouldn't be */ /* utf image is already downloaded, it shouldn't be */
ret = -EEXIST; ret = -EEXIST;
goto err; goto err;
...@@ -364,7 +382,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ...@@ -364,7 +382,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
goto err_fw_features; goto err_fw_features;
} }
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF); ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF,
&ar->testmode.utf_mode_fw);
if (ret) { if (ret) {
ath10k_err(ar, "failed to start core (testmode): %d\n", ret); ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
ar->state = ATH10K_STATE_OFF; ar->state = ATH10K_STATE_OFF;
...@@ -393,8 +412,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ...@@ -393,8 +412,8 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
sizeof(ar->fw_features)); sizeof(ar->fw_features));
ar->wmi.op_version = ar->testmode.orig_wmi_op_version; ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
release_firmware(ar->testmode.utf); release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
ar->testmode.utf = NULL; ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
err: err:
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
...@@ -420,8 +439,8 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar) ...@@ -420,8 +439,8 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
sizeof(ar->fw_features)); sizeof(ar->fw_features));
ar->wmi.op_version = ar->testmode.orig_wmi_op_version; ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
release_firmware(ar->testmode.utf); release_firmware(ar->testmode.utf_mode_fw.fw_file.firmware);
ar->testmode.utf = NULL; ar->testmode.utf_mode_fw.fw_file.firmware = NULL;
ar->state = ATH10K_STATE_OFF; ar->state = ATH10K_STATE_OFF;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment