Under some condition, we now have to do early request full firmware when
rtw89_early_fw_feature_recognize(). In this case, we can avoid requesting
full firmware twice during probing driver. So, we pass out full firmware
from rtw89_early_fw_feature_recognize() if it's requested successfully.
And then, if firmware is settled, we have no need to request full firmware
again during normal initizating flow.
Setting firmware flow is updated to be as the following.
platform | early recognizing | normally initizating
-----------------------------------------------------------------------
deny reading | request full FW | (no more FW requesting)
partial file | | (obtain FW from early pahse)
-----------------------------------------------------------------------
able to read | request partial FW | async request full FW
partial file | (quite small chunk) |
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20221202060521.501512-3-pkshih@realtek.com
u32 bus_data_size,
const struct rtw89_chip_info *chip)
{
+ const struct firmware *firmware;
struct ieee80211_hw *hw;
struct rtw89_dev *rtwdev;
struct ieee80211_ops *ops;
u32 early_feat_map = 0;
bool no_chanctx;
- rtw89_early_fw_feature_recognize(device, chip, &early_feat_map);
+ firmware = rtw89_early_fw_feature_recognize(device, chip, &early_feat_map);
ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL);
if (!ops)
rtwdev->dev = device;
rtwdev->ops = ops;
rtwdev->chip = chip;
+ rtwdev->fw.firmware = firmware;
rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n",
no_chanctx ? "without" : "with");
err:
kfree(ops);
+ release_firmware(firmware);
return NULL;
}
EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw);
void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev)
{
kfree(rtwdev->ops);
+ release_firmware(rtwdev->fw.firmware);
ieee80211_free_hw(rtwdev->hw);
}
EXPORT_SYMBOL(rtw89_free_ieee80211_hw);
}
}
-void rtw89_early_fw_feature_recognize(struct device *device,
- const struct rtw89_chip_info *chip,
- u32 *early_feat_map)
+const struct firmware *
+rtw89_early_fw_feature_recognize(struct device *device,
+ const struct rtw89_chip_info *chip,
+ u32 *early_feat_map)
{
union rtw89_compat_fw_hdr buf = {};
const struct firmware *firmware;
if (ret) {
dev_err(device, "failed to early request firmware: %d\n", ret);
- return;
+ return NULL;
}
if (full_req)
}
out:
+ if (full_req)
+ return firmware;
+
release_firmware(firmware);
+ return NULL;
}
int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
fw->rtwdev = rtwdev;
init_completion(&fw->completion);
+ if (fw->firmware) {
+ rtw89_debug(rtwdev, RTW89_DBG_FW,
+ "full firmware has been early requested\n");
+ complete_all(&fw->completion);
+ return 0;
+ }
+
ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev,
GFP_KERNEL, fw, rtw89_load_firmware_cb);
if (ret) {
rtw89_wait_firmware_completion(rtwdev);
- if (fw->firmware)
+ if (fw->firmware) {
release_firmware(fw->firmware);
+
+ /* assign NULL back in case rtw89_free_ieee80211_hw()
+ * try to release the same one again.
+ */
+ fw->firmware = NULL;
+ }
}
#define H2C_CAM_LEN 60
int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev);
int rtw89_fw_recognize(struct rtw89_dev *rtwdev);
-void rtw89_early_fw_feature_recognize(struct device *device,
- const struct rtw89_chip_info *chip,
- u32 *early_feat_map);
+const struct firmware *
+rtw89_early_fw_feature_recognize(struct device *device,
+ const struct rtw89_chip_info *chip,
+ u32 *early_feat_map);
int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type);
int rtw89_load_firmware(struct rtw89_dev *rtwdev);
void rtw89_unload_firmware(struct rtw89_dev *rtwdev);