1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
10 static int ath11k_fw_request_firmware_api_n(struct ath11k_base *ab,
13 size_t magic_len, len, ie_len;
14 int ie_id, i, index, bit, ret;
15 struct ath11k_fw_ie *hdr;
19 ab->fw.fw = ath11k_core_firmware_request(ab, name);
20 if (IS_ERR(ab->fw.fw)) {
21 ret = PTR_ERR(ab->fw.fw);
22 ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to load %s: %d\n", name, ret);
27 data = ab->fw.fw->data;
28 len = ab->fw.fw->size;
30 /* magic also includes the null byte, check that as well */
31 magic_len = strlen(ATH11K_FIRMWARE_MAGIC) + 1;
33 if (len < magic_len) {
34 ath11k_err(ab, "firmware image too small to contain magic: %zu\n",
40 if (memcmp(data, ATH11K_FIRMWARE_MAGIC, magic_len) != 0) {
41 ath11k_err(ab, "Invalid firmware magic\n");
46 /* jump over the padding */
47 magic_len = ALIGN(magic_len, 4);
49 /* make sure there's space for padding */
50 if (magic_len > len) {
51 ath11k_err(ab, "No space for padding after magic\n");
60 while (len > sizeof(struct ath11k_fw_ie)) {
61 hdr = (struct ath11k_fw_ie *)data;
63 ie_id = le32_to_cpu(hdr->id);
64 ie_len = le32_to_cpu(hdr->len);
70 ath11k_err(ab, "Invalid length for FW IE %d (%zu < %zu)\n",
77 case ATH11K_FW_IE_TIMESTAMP:
78 if (ie_len != sizeof(u32))
81 timestamp = (__le32 *)data;
83 ath11k_dbg(ab, ATH11K_DBG_BOOT, "found fw timestamp %d\n",
84 le32_to_cpup(timestamp));
86 case ATH11K_FW_IE_FEATURES:
87 ath11k_dbg(ab, ATH11K_DBG_BOOT,
88 "found firmware features ie (%zd B)\n",
91 for (i = 0; i < ATH11K_FW_FEATURE_COUNT; i++) {
98 if (data[index] & (1 << bit))
99 __set_bit(i, ab->fw.fw_features);
102 ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "features", "",
104 sizeof(ab->fw.fw_features));
106 case ATH11K_FW_IE_AMSS_IMAGE:
107 ath11k_dbg(ab, ATH11K_DBG_BOOT,
108 "found fw image ie (%zd B)\n",
111 ab->fw.amss_data = data;
112 ab->fw.amss_len = ie_len;
114 case ATH11K_FW_IE_M3_IMAGE:
115 ath11k_dbg(ab, ATH11K_DBG_BOOT,
116 "found m3 image ie (%zd B)\n",
119 ab->fw.m3_data = data;
120 ab->fw.m3_len = ie_len;
123 ath11k_warn(ab, "Unknown FW IE: %u\n", ie_id);
127 /* jump over the padding */
128 ie_len = ALIGN(ie_len, 4);
130 /* make sure there's space for padding */
141 release_firmware(ab->fw.fw);
146 int ath11k_fw_pre_init(struct ath11k_base *ab)
150 ret = ath11k_fw_request_firmware_api_n(ab, ATH11K_FW_API2_FILE);
152 ab->fw.api_version = 2;
156 ab->fw.api_version = 1;
159 ath11k_dbg(ab, ATH11K_DBG_BOOT, "using fw api %d\n",
165 void ath11k_fw_destroy(struct ath11k_base *ab)
167 release_firmware(ab->fw.fw);