1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

rtw88: load wowlan firmware if wowlan is supported

Driver used to download normal firmware only,
but some devices support wowlan and require to
download wowlan firmware when system suspends.
So modify rtw_load_firmware() and its callback to
allow driver to download both normal and wowlan firmware.

Signed-off-by: Chin-Yen Lee <timlee@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Chin-Yen Lee 2019-12-19 16:58:13 +08:00 committed by Kalle Valo
parent 786221048e
commit c8e5695eae
2 changed files with 70 additions and 12 deletions

View file

@ -793,6 +793,26 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
rtw_fw_send_ra_info(rtwdev, si); rtw_fw_send_ra_info(rtwdev, si);
} }
static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
{
struct rtw_chip_info *chip = rtwdev->chip;
struct rtw_fw_state *fw;
fw = &rtwdev->fw;
wait_for_completion(&fw->completion);
if (!fw->firmware)
return -EINVAL;
if (chip->wow_fw_name) {
fw = &rtwdev->wow_fw;
wait_for_completion(&fw->completion);
if (!fw->firmware)
return -EINVAL;
}
return 0;
}
static int rtw_power_on(struct rtw_dev *rtwdev) static int rtw_power_on(struct rtw_dev *rtwdev)
{ {
struct rtw_chip_info *chip = rtwdev->chip; struct rtw_chip_info *chip = rtwdev->chip;
@ -813,11 +833,10 @@ static int rtw_power_on(struct rtw_dev *rtwdev)
goto err; goto err;
} }
wait_for_completion(&fw->completion); ret = rtw_wait_firmware_completion(rtwdev);
if (!fw->firmware) { if (ret) {
ret = -EINVAL; rtw_err(rtwdev, "failed to wait firmware completion\n");
rtw_err(rtwdev, "failed to load firmware\n"); goto err_off;
goto err;
} }
ret = rtw_download_firmware(rtwdev, fw); ret = rtw_download_firmware(rtwdev, fw);
@ -1020,8 +1039,8 @@ static void rtw_unset_supported_band(struct ieee80211_hw *hw,
static void rtw_load_firmware_cb(const struct firmware *firmware, void *context) static void rtw_load_firmware_cb(const struct firmware *firmware, void *context)
{ {
struct rtw_dev *rtwdev = context; struct rtw_fw_state *fw = context;
struct rtw_fw_state *fw = &rtwdev->fw; struct rtw_dev *rtwdev = fw->rtwdev;
const struct rtw_fw_hdr *fw_hdr; const struct rtw_fw_hdr *fw_hdr;
if (!firmware || !firmware->data) { if (!firmware || !firmware->data) {
@ -1043,17 +1062,35 @@ static void rtw_load_firmware_cb(const struct firmware *firmware, void *context)
fw->version, fw->sub_version, fw->sub_index, fw->h2c_version); fw->version, fw->sub_version, fw->sub_index, fw->h2c_version);
} }
static int rtw_load_firmware(struct rtw_dev *rtwdev, const char *fw_name) static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type)
{ {
struct rtw_fw_state *fw = &rtwdev->fw; const char *fw_name;
struct rtw_fw_state *fw;
int ret; int ret;
switch (type) {
case RTW_WOWLAN_FW:
fw = &rtwdev->wow_fw;
fw_name = rtwdev->chip->wow_fw_name;
break;
case RTW_NORMAL_FW:
fw = &rtwdev->fw;
fw_name = rtwdev->chip->fw_name;
break;
default:
rtw_warn(rtwdev, "unsupported firmware type\n");
return -ENOENT;
}
fw->rtwdev = rtwdev;
init_completion(&fw->completion); init_completion(&fw->completion);
ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev, ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev,
GFP_KERNEL, rtwdev, rtw_load_firmware_cb); GFP_KERNEL, fw, rtw_load_firmware_cb);
if (ret) { if (ret) {
rtw_err(rtwdev, "async firmware request failed\n"); rtw_err(rtwdev, "failed to async firmware request\n");
return ret; return ret;
} }
@ -1372,12 +1409,19 @@ int rtw_core_init(struct rtw_dev *rtwdev)
BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS | BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS |
BIT_AB | BIT_AM | BIT_APM; BIT_AB | BIT_AM | BIT_APM;
ret = rtw_load_firmware(rtwdev, rtwdev->chip->fw_name); ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW);
if (ret) { if (ret) {
rtw_warn(rtwdev, "no firmware loaded\n"); rtw_warn(rtwdev, "no firmware loaded\n");
return ret; return ret;
} }
if (chip->wow_fw_name) {
ret = rtw_load_firmware(rtwdev, RTW_WOWLAN_FW);
if (ret) {
rtw_warn(rtwdev, "no wow firmware loaded\n");
return ret;
}
}
return 0; return 0;
} }
EXPORT_SYMBOL(rtw_core_init); EXPORT_SYMBOL(rtw_core_init);
@ -1385,12 +1429,16 @@ EXPORT_SYMBOL(rtw_core_init);
void rtw_core_deinit(struct rtw_dev *rtwdev) void rtw_core_deinit(struct rtw_dev *rtwdev)
{ {
struct rtw_fw_state *fw = &rtwdev->fw; struct rtw_fw_state *fw = &rtwdev->fw;
struct rtw_fw_state *wow_fw = &rtwdev->wow_fw;
struct rtw_rsvd_page *rsvd_pkt, *tmp; struct rtw_rsvd_page *rsvd_pkt, *tmp;
unsigned long flags; unsigned long flags;
if (fw->firmware) if (fw->firmware)
release_firmware(fw->firmware); release_firmware(fw->firmware);
if (wow_fw->firmware)
release_firmware(wow_fw->firmware);
tasklet_kill(&rtwdev->tx_tasklet); tasklet_kill(&rtwdev->tx_tasklet);
spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags); spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags);
skb_queue_purge(&rtwdev->tx_report.queue); skb_queue_purge(&rtwdev->tx_report.queue);

View file

@ -193,6 +193,11 @@ enum rtw_rx_queue_type {
RTK_MAX_RX_QUEUE_NUM RTK_MAX_RX_QUEUE_NUM
}; };
enum rtw_fw_type {
RTW_NORMAL_FW = 0x0,
RTW_WOWLAN_FW = 0x1,
};
enum rtw_rate_index { enum rtw_rate_index {
RTW_RATEID_BGN_40M_2SS = 0, RTW_RATEID_BGN_40M_2SS = 0,
RTW_RATEID_BGN_40M_1SS = 1, RTW_RATEID_BGN_40M_1SS = 1,
@ -1030,6 +1035,8 @@ struct rtw_chip_info {
u8 bfer_su_max_num; u8 bfer_su_max_num;
u8 bfer_mu_max_num; u8 bfer_mu_max_num;
const char *wow_fw_name;
/* coex paras */ /* coex paras */
u32 coex_para_ver; u32 coex_para_ver;
u8 bt_desired_ver; u8 bt_desired_ver;
@ -1456,6 +1463,7 @@ struct rtw_fifo_conf {
struct rtw_fw_state { struct rtw_fw_state {
const struct firmware *firmware; const struct firmware *firmware;
struct rtw_dev *rtwdev;
struct completion completion; struct completion completion;
u16 version; u16 version;
u8 sub_version; u8 sub_version;
@ -1580,6 +1588,8 @@ struct rtw_dev {
u8 mp_mode; u8 mp_mode;
struct rtw_fw_state wow_fw;
/* hci related data, must be last */ /* hci related data, must be last */
u8 priv[0] __aligned(sizeof(void *)); u8 priv[0] __aligned(sizeof(void *));
}; };