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
);