Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

wifi: rtw89: fw: adapt to new firmware format of dynamic header

Since firmware size is limited, we create variant firmwares for variant
application areas. To help driver to know firmware's capabilities, firmware
dynamic header is introduced to have more information, such as firmware
features and firmware compile flags.

Since this driver rtw89 only uses single one specific firmware at runtime,
this patch is just to ignore this dynamic header, not actually use the
content.

This patch can be backward compatible, and no this kind of firmware is
added to linux-firmware yet, so I can prepare this in advance.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20221020052549.33783-1-pkshih@realtek.com

authored by

Ping-Ke Shih and committed by
Kalle Valo
4feda7f3 a9501019

+31 -3
+19 -3
drivers/net/wireless/realtek/rtw89/fw.c
··· 85 85 { 86 86 struct rtw89_fw_hdr_section_info *section_info; 87 87 const u8 *fw_end = fw + len; 88 + const u8 *fwdynhdr; 88 89 const u8 *bin; 90 + u32 base_hdr_len; 89 91 u32 i; 90 92 91 93 if (!info) 92 94 return -EINVAL; 93 95 94 96 info->section_num = GET_FW_HDR_SEC_NUM(fw); 95 - info->hdr_len = RTW89_FW_HDR_SIZE + 96 - info->section_num * RTW89_FW_SECTION_HDR_SIZE; 97 + base_hdr_len = RTW89_FW_HDR_SIZE + 98 + info->section_num * RTW89_FW_SECTION_HDR_SIZE; 99 + info->dynamic_hdr_en = GET_FW_HDR_DYN_HDR(fw); 100 + 101 + if (info->dynamic_hdr_en) { 102 + info->hdr_len = GET_FW_HDR_LEN(fw); 103 + info->dynamic_hdr_len = info->hdr_len - base_hdr_len; 104 + fwdynhdr = fw + base_hdr_len; 105 + if (GET_FW_DYNHDR_LEN(fwdynhdr) != info->dynamic_hdr_len) { 106 + rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n"); 107 + return -EINVAL; 108 + } 109 + } else { 110 + info->hdr_len = base_hdr_len; 111 + info->dynamic_hdr_len = 0; 112 + } 97 113 98 114 bin = fw + info->hdr_len; 99 115 ··· 550 534 goto fwdl_err; 551 535 } 552 536 553 - ret = rtw89_fw_download_hdr(rtwdev, fw, info.hdr_len); 537 + ret = rtw89_fw_download_hdr(rtwdev, fw, info.hdr_len - info.dynamic_hdr_len); 554 538 if (ret) { 555 539 ret = -EBUSY; 556 540 goto fwdl_err;
+12
drivers/net/wireless/realtek/rtw89/fw.h
··· 176 176 struct rtw89_fw_bin_info { 177 177 u8 section_num; 178 178 u32 hdr_len; 179 + bool dynamic_hdr_en; 180 + u32 dynamic_hdr_len; 179 181 struct rtw89_fw_hdr_section_info section_info[FWDL_SECTION_MAX_NUM]; 180 182 }; 181 183 ··· 497 495 le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(23, 16)) 498 496 #define GET_FW_HDR_SUBINDEX(fwhdr) \ 499 497 le32_get_bits(*((const __le32 *)(fwhdr) + 1), GENMASK(31, 24)) 498 + #define GET_FW_HDR_LEN(fwhdr) \ 499 + le32_get_bits(*((const __le32 *)(fwhdr) + 3), GENMASK(23, 16)) 500 500 #define GET_FW_HDR_MONTH(fwhdr) \ 501 501 le32_get_bits(*((const __le32 *)(fwhdr) + 4), GENMASK(7, 0)) 502 502 #define GET_FW_HDR_DATE(fwhdr) \ ··· 511 507 le32_get_bits(*((const __le32 *)(fwhdr) + 5), GENMASK(31, 0)) 512 508 #define GET_FW_HDR_SEC_NUM(fwhdr) \ 513 509 le32_get_bits(*((const __le32 *)(fwhdr) + 6), GENMASK(15, 8)) 510 + #define GET_FW_HDR_DYN_HDR(fwhdr) \ 511 + le32_get_bits(*((const __le32 *)(fwhdr) + 7), BIT(16)) 514 512 #define GET_FW_HDR_CMD_VERSERION(fwhdr) \ 515 513 le32_get_bits(*((const __le32 *)(fwhdr) + 7), GENMASK(31, 24)) 514 + 515 + #define GET_FW_DYNHDR_LEN(fwdynhdr) \ 516 + le32_get_bits(*((const __le32 *)(fwdynhdr)), GENMASK(31, 0)) 517 + #define GET_FW_DYNHDR_COUNT(fwdynhdr) \ 518 + le32_get_bits(*((const __le32 *)(fwdynhdr) + 1), GENMASK(31, 0)) 519 + 516 520 static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val) 517 521 { 518 522 le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0));