mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-09 16:41:16 +00:00
wifi: rtw89: add firmware format version to backward compatible with older drivers
In the discuss threads [1] [2], new firmware format break user space because older drivers can't recognize new firmware format. To avoid this, the new format will be named rtw89/rtw8852b_fw-1.bin and only new driver try to load it. Old drivers only load original and understandable firmware rtw89/rtw8852b_fw.bin. More, new driver will be still backward compatible with old firmware, so original firmware can be used by new driver. If there is newer firmware format is introduced, rtw89/rtw8852b_fw-2.bin will be given. The same rules will be applied like above. So, we will have firmware like below in linux-firmware in the future. rtw89/rtw8852b_fw-2.bin rtw89/rtw8852b_fw-1.bin rtw89/rtw8852b_fw.bin After this patch, MODULE_FIRMWARE() of 8852A/B/C become rtw89/rtw8852a_fw.bin rtw89/rtw8852b_fw-1.bin rtw89/rtw8852c_fw.bin [1] https://lore.kernel.org/linux-wireless/df1ce994-3368-a57e-7078-8bdcccf4a1fd@gmail.com/T/#m24cb43be31a762d0ea70bf07f27ae96c59f6931b [2] https://bugzilla.kernel.org/show_bug.cgi?id=217207 Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20230320130606.20777-4-pkshih@realtek.com
This commit is contained in:
parent
b80ad23a8f
commit
ffde7f3476
@ -3759,9 +3759,10 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
|||||||
struct rtw89_dev *rtwdev;
|
struct rtw89_dev *rtwdev;
|
||||||
struct ieee80211_ops *ops;
|
struct ieee80211_ops *ops;
|
||||||
u32 driver_data_size;
|
u32 driver_data_size;
|
||||||
|
int fw_format = -1;
|
||||||
bool no_chanctx;
|
bool no_chanctx;
|
||||||
|
|
||||||
firmware = rtw89_early_fw_feature_recognize(device, chip, &early_fw);
|
firmware = rtw89_early_fw_feature_recognize(device, chip, &early_fw, &fw_format);
|
||||||
|
|
||||||
ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL);
|
ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL);
|
||||||
if (!ops)
|
if (!ops)
|
||||||
@ -3792,6 +3793,7 @@ struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
|
|||||||
rtwdev->ops = ops;
|
rtwdev->ops = ops;
|
||||||
rtwdev->chip = chip;
|
rtwdev->chip = chip;
|
||||||
rtwdev->fw.req.firmware = firmware;
|
rtwdev->fw.req.firmware = firmware;
|
||||||
|
rtwdev->fw.fw_format = fw_format;
|
||||||
|
|
||||||
rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n",
|
rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n",
|
||||||
no_chanctx ? "without" : "with");
|
no_chanctx ? "without" : "with");
|
||||||
|
@ -3080,7 +3080,8 @@ struct rtw89_phy_ul_tb_info {
|
|||||||
struct rtw89_chip_info {
|
struct rtw89_chip_info {
|
||||||
enum rtw89_core_chip_id chip_id;
|
enum rtw89_core_chip_id chip_id;
|
||||||
const struct rtw89_chip_ops *ops;
|
const struct rtw89_chip_ops *ops;
|
||||||
const char *fw_name;
|
const char *fw_basename;
|
||||||
|
u8 fw_format_max;
|
||||||
bool try_ce_fw;
|
bool try_ce_fw;
|
||||||
u32 fifo_size;
|
u32 fifo_size;
|
||||||
u32 dle_scc_rsvd_size;
|
u32 dle_scc_rsvd_size;
|
||||||
@ -3304,6 +3305,7 @@ struct rtw89_fw_req_info {
|
|||||||
|
|
||||||
struct rtw89_fw_info {
|
struct rtw89_fw_info {
|
||||||
struct rtw89_fw_req_info req;
|
struct rtw89_fw_req_info req;
|
||||||
|
int fw_format;
|
||||||
u8 h2c_seq;
|
u8 h2c_seq;
|
||||||
u8 rec_seq;
|
u8 rec_seq;
|
||||||
u8 h2c_counter;
|
u8 h2c_counter;
|
||||||
|
@ -302,11 +302,14 @@ static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
|
|||||||
const struct firmware *
|
const struct firmware *
|
||||||
rtw89_early_fw_feature_recognize(struct device *device,
|
rtw89_early_fw_feature_recognize(struct device *device,
|
||||||
const struct rtw89_chip_info *chip,
|
const struct rtw89_chip_info *chip,
|
||||||
struct rtw89_fw_info *early_fw)
|
struct rtw89_fw_info *early_fw,
|
||||||
|
int *used_fw_format)
|
||||||
{
|
{
|
||||||
union rtw89_compat_fw_hdr buf = {};
|
union rtw89_compat_fw_hdr buf = {};
|
||||||
const struct firmware *firmware;
|
const struct firmware *firmware;
|
||||||
bool full_req = false;
|
bool full_req = false;
|
||||||
|
char fw_name[64];
|
||||||
|
int fw_format;
|
||||||
u32 ver_code;
|
u32 ver_code;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -317,12 +320,22 @@ rtw89_early_fw_feature_recognize(struct device *device,
|
|||||||
if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE))
|
if (IS_ENABLED(CONFIG_SECURITY_LOADPIN_ENFORCE))
|
||||||
full_req = true;
|
full_req = true;
|
||||||
|
|
||||||
if (full_req)
|
for (fw_format = chip->fw_format_max; fw_format >= 0; fw_format--) {
|
||||||
ret = request_firmware(&firmware, chip->fw_name, device);
|
rtw89_fw_get_filename(fw_name, sizeof(fw_name),
|
||||||
else
|
chip->fw_basename, fw_format);
|
||||||
ret = request_partial_firmware_into_buf(&firmware, chip->fw_name,
|
|
||||||
device, &buf, sizeof(buf),
|
if (full_req)
|
||||||
0);
|
ret = request_firmware(&firmware, fw_name, device);
|
||||||
|
else
|
||||||
|
ret = request_partial_firmware_into_buf(&firmware, fw_name,
|
||||||
|
device, &buf, sizeof(buf),
|
||||||
|
0);
|
||||||
|
if (!ret) {
|
||||||
|
dev_info(device, "loaded firmware %s\n", fw_name);
|
||||||
|
*used_fw_format = fw_format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(device, "failed to early request firmware: %d\n", ret);
|
dev_err(device, "failed to early request firmware: %d\n", ret);
|
||||||
@ -666,7 +679,11 @@ void rtw89_load_firmware_work(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct rtw89_dev *rtwdev =
|
struct rtw89_dev *rtwdev =
|
||||||
container_of(work, struct rtw89_dev, load_firmware_work);
|
container_of(work, struct rtw89_dev, load_firmware_work);
|
||||||
const char *fw_name = rtwdev->chip->fw_name;
|
const struct rtw89_chip_info *chip = rtwdev->chip;
|
||||||
|
char fw_name[64];
|
||||||
|
|
||||||
|
rtw89_fw_get_filename(fw_name, sizeof(fw_name),
|
||||||
|
chip->fw_basename, rtwdev->fw.fw_format);
|
||||||
|
|
||||||
rtw89_load_firmware_req(rtwdev, &rtwdev->fw.req, fw_name, false);
|
rtw89_load_firmware_req(rtwdev, &rtwdev->fw.req, fw_name, false);
|
||||||
}
|
}
|
||||||
|
@ -3515,6 +3515,15 @@ static inline u32 rtw89_compat_fw_hdr_ver_code(const void *fw_buf)
|
|||||||
return RTW89_FW_HDR_VER_CODE(&compat->fw_hdr);
|
return RTW89_FW_HDR_VER_CODE(&compat->fw_hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void rtw89_fw_get_filename(char *buf, size_t size,
|
||||||
|
const char *fw_basename, int fw_format)
|
||||||
|
{
|
||||||
|
if (fw_format <= 0)
|
||||||
|
snprintf(buf, size, "%s.bin", fw_basename);
|
||||||
|
else
|
||||||
|
snprintf(buf, size, "%s-%d.bin", fw_basename, fw_format);
|
||||||
|
}
|
||||||
|
|
||||||
#define RTW89_H2C_RF_PAGE_SIZE 500
|
#define RTW89_H2C_RF_PAGE_SIZE 500
|
||||||
#define RTW89_H2C_RF_PAGE_NUM 3
|
#define RTW89_H2C_RF_PAGE_NUM 3
|
||||||
struct rtw89_fw_h2c_rf_reg_info {
|
struct rtw89_fw_h2c_rf_reg_info {
|
||||||
@ -3658,7 +3667,8 @@ int rtw89_fw_recognize(struct rtw89_dev *rtwdev);
|
|||||||
const struct firmware *
|
const struct firmware *
|
||||||
rtw89_early_fw_feature_recognize(struct device *device,
|
rtw89_early_fw_feature_recognize(struct device *device,
|
||||||
const struct rtw89_chip_info *chip,
|
const struct rtw89_chip_info *chip,
|
||||||
struct rtw89_fw_info *early_fw);
|
struct rtw89_fw_info *early_fw,
|
||||||
|
int *used_fw_format);
|
||||||
int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type);
|
int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type);
|
||||||
void rtw89_load_firmware_work(struct work_struct *work);
|
void rtw89_load_firmware_work(struct work_struct *work);
|
||||||
void rtw89_unload_firmware(struct rtw89_dev *rtwdev);
|
void rtw89_unload_firmware(struct rtw89_dev *rtwdev);
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
#include "rtw8852a_table.h"
|
#include "rtw8852a_table.h"
|
||||||
#include "txrx.h"
|
#include "txrx.h"
|
||||||
|
|
||||||
|
#define RTW8852A_FW_FORMAT_MAX 0
|
||||||
|
#define RTW8852A_FW_BASENAME "rtw89/rtw8852a_fw"
|
||||||
|
#define RTW8852A_MODULE_FIRMWARE \
|
||||||
|
RTW8852A_FW_BASENAME ".bin"
|
||||||
|
|
||||||
static const struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_pcie[] = {
|
static const struct rtw89_hfc_ch_cfg rtw8852a_hfc_chcfg_pcie[] = {
|
||||||
{128, 1896, grp_0}, /* ACH 0 */
|
{128, 1896, grp_0}, /* ACH 0 */
|
||||||
{128, 1896, grp_0}, /* ACH 1 */
|
{128, 1896, grp_0}, /* ACH 1 */
|
||||||
@ -2059,7 +2064,8 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
|
|||||||
const struct rtw89_chip_info rtw8852a_chip_info = {
|
const struct rtw89_chip_info rtw8852a_chip_info = {
|
||||||
.chip_id = RTL8852A,
|
.chip_id = RTL8852A,
|
||||||
.ops = &rtw8852a_chip_ops,
|
.ops = &rtw8852a_chip_ops,
|
||||||
.fw_name = "rtw89/rtw8852a_fw.bin",
|
.fw_basename = RTW8852A_FW_BASENAME,
|
||||||
|
.fw_format_max = RTW8852A_FW_FORMAT_MAX,
|
||||||
.try_ce_fw = false,
|
.try_ce_fw = false,
|
||||||
.fifo_size = 458752,
|
.fifo_size = 458752,
|
||||||
.dle_scc_rsvd_size = 0,
|
.dle_scc_rsvd_size = 0,
|
||||||
@ -2156,7 +2162,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL(rtw8852a_chip_info);
|
EXPORT_SYMBOL(rtw8852a_chip_info);
|
||||||
|
|
||||||
MODULE_FIRMWARE("rtw89/rtw8852a_fw.bin");
|
MODULE_FIRMWARE(RTW8852A_MODULE_FIRMWARE);
|
||||||
MODULE_AUTHOR("Realtek Corporation");
|
MODULE_AUTHOR("Realtek Corporation");
|
||||||
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852A driver");
|
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852A driver");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
#include "rtw8852b_table.h"
|
#include "rtw8852b_table.h"
|
||||||
#include "txrx.h"
|
#include "txrx.h"
|
||||||
|
|
||||||
|
#define RTW8852B_FW_FORMAT_MAX 1
|
||||||
|
#define RTW8852B_FW_BASENAME "rtw89/rtw8852b_fw"
|
||||||
|
#define RTW8852B_MODULE_FIRMWARE \
|
||||||
|
RTW8852B_FW_BASENAME "-" __stringify(RTW8852B_FW_FORMAT_MAX) ".bin"
|
||||||
|
|
||||||
static const struct rtw89_hfc_ch_cfg rtw8852b_hfc_chcfg_pcie[] = {
|
static const struct rtw89_hfc_ch_cfg rtw8852b_hfc_chcfg_pcie[] = {
|
||||||
{5, 343, grp_0}, /* ACH 0 */
|
{5, 343, grp_0}, /* ACH 0 */
|
||||||
{5, 343, grp_0}, /* ACH 1 */
|
{5, 343, grp_0}, /* ACH 1 */
|
||||||
@ -2480,7 +2485,8 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
|
|||||||
const struct rtw89_chip_info rtw8852b_chip_info = {
|
const struct rtw89_chip_info rtw8852b_chip_info = {
|
||||||
.chip_id = RTL8852B,
|
.chip_id = RTL8852B,
|
||||||
.ops = &rtw8852b_chip_ops,
|
.ops = &rtw8852b_chip_ops,
|
||||||
.fw_name = "rtw89/rtw8852b_fw.bin",
|
.fw_basename = RTW8852B_FW_BASENAME,
|
||||||
|
.fw_format_max = RTW8852B_FW_FORMAT_MAX,
|
||||||
.try_ce_fw = true,
|
.try_ce_fw = true,
|
||||||
.fifo_size = 196608,
|
.fifo_size = 196608,
|
||||||
.dle_scc_rsvd_size = 98304,
|
.dle_scc_rsvd_size = 98304,
|
||||||
@ -2576,7 +2582,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL(rtw8852b_chip_info);
|
EXPORT_SYMBOL(rtw8852b_chip_info);
|
||||||
|
|
||||||
MODULE_FIRMWARE("rtw89/rtw8852b_fw.bin");
|
MODULE_FIRMWARE(RTW8852B_MODULE_FIRMWARE);
|
||||||
MODULE_AUTHOR("Realtek Corporation");
|
MODULE_AUTHOR("Realtek Corporation");
|
||||||
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852B driver");
|
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852B driver");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
@ -13,6 +13,11 @@
|
|||||||
#include "rtw8852c_table.h"
|
#include "rtw8852c_table.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#define RTW8852C_FW_FORMAT_MAX 0
|
||||||
|
#define RTW8852C_FW_BASENAME "rtw89/rtw8852c_fw"
|
||||||
|
#define RTW8852C_MODULE_FIRMWARE \
|
||||||
|
RTW8852C_FW_BASENAME ".bin"
|
||||||
|
|
||||||
static const struct rtw89_hfc_ch_cfg rtw8852c_hfc_chcfg_pcie[] = {
|
static const struct rtw89_hfc_ch_cfg rtw8852c_hfc_chcfg_pcie[] = {
|
||||||
{13, 1614, grp_0}, /* ACH 0 */
|
{13, 1614, grp_0}, /* ACH 0 */
|
||||||
{13, 1614, grp_0}, /* ACH 1 */
|
{13, 1614, grp_0}, /* ACH 1 */
|
||||||
@ -2791,7 +2796,8 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
|
|||||||
const struct rtw89_chip_info rtw8852c_chip_info = {
|
const struct rtw89_chip_info rtw8852c_chip_info = {
|
||||||
.chip_id = RTL8852C,
|
.chip_id = RTL8852C,
|
||||||
.ops = &rtw8852c_chip_ops,
|
.ops = &rtw8852c_chip_ops,
|
||||||
.fw_name = "rtw89/rtw8852c_fw.bin",
|
.fw_basename = RTW8852C_FW_BASENAME,
|
||||||
|
.fw_format_max = RTW8852C_FW_FORMAT_MAX,
|
||||||
.try_ce_fw = false,
|
.try_ce_fw = false,
|
||||||
.fifo_size = 458752,
|
.fifo_size = 458752,
|
||||||
.dle_scc_rsvd_size = 0,
|
.dle_scc_rsvd_size = 0,
|
||||||
@ -2892,7 +2898,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL(rtw8852c_chip_info);
|
EXPORT_SYMBOL(rtw8852c_chip_info);
|
||||||
|
|
||||||
MODULE_FIRMWARE("rtw89/rtw8852c_fw.bin");
|
MODULE_FIRMWARE(RTW8852C_MODULE_FIRMWARE);
|
||||||
MODULE_AUTHOR("Realtek Corporation");
|
MODULE_AUTHOR("Realtek Corporation");
|
||||||
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852C driver");
|
MODULE_DESCRIPTION("Realtek 802.11ax wireless 8852C driver");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
Loading…
Reference in New Issue
Block a user