rtw88: add C2H response for checking firmware leave lps
Originally driver checks if firmware has left lps via reading the setting of REG_TCR register. But this way may fail when firmware is frequently changing power state. Therefore, firmware provides a safer option for driver. When firmware leaves lps successfully, it sends a C2H response to inform driver. Signed-off-by: Chin-Yen Lee <timlee@realtek.com> Signed-off-by: Tzu-En Huang <tehuang@realtek.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/20201030084826.9034-4-tehuang@realtek.com
This commit is contained in:
parent
a959496068
commit
f31e039fab
6 changed files with 54 additions and 5 deletions
|
@ -183,6 +183,9 @@ void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
|
|||
case C2H_BT_MP_INFO:
|
||||
rtw_coex_info_response(rtwdev, skb);
|
||||
break;
|
||||
case C2H_WLAN_RFON:
|
||||
complete(&rtwdev->lps_leave_check);
|
||||
break;
|
||||
default:
|
||||
/* pass offset for further operation */
|
||||
*((u32 *)skb->cb) = pkt_offset;
|
||||
|
|
|
@ -31,6 +31,7 @@ enum rtw_c2h_cmd_id {
|
|||
C2H_RA_RPT = 0x0c,
|
||||
C2H_HW_FEATURE_REPORT = 0x19,
|
||||
C2H_WLAN_INFO = 0x27,
|
||||
C2H_WLAN_RFON = 0x32,
|
||||
C2H_HW_FEATURE_DUMP = 0xfd,
|
||||
C2H_HALMAC = 0xff,
|
||||
};
|
||||
|
|
|
@ -1652,6 +1652,7 @@ int rtw_core_init(struct rtw_dev *rtwdev)
|
|||
mutex_init(&rtwdev->hal.tx_power_mutex);
|
||||
|
||||
init_waitqueue_head(&rtwdev->coex.wait);
|
||||
init_completion(&rtwdev->lps_leave_check);
|
||||
|
||||
rtwdev->sec.total_cam_num = 32;
|
||||
rtwdev->hal.current_channel = 1;
|
||||
|
|
|
@ -1741,6 +1741,7 @@ struct rtw_dev {
|
|||
/* lps power state & handler work */
|
||||
struct rtw_lps_conf lps_conf;
|
||||
bool ps_enabled;
|
||||
struct completion lps_leave_check;
|
||||
|
||||
struct dentry *debugfs;
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev)
|
|||
rtw_hci_deep_ps(rtwdev, false);
|
||||
}
|
||||
|
||||
static void rtw_fw_leave_lps_state_check(struct rtw_dev *rtwdev)
|
||||
static int __rtw_fw_leave_lps_check_reg(struct rtw_dev *rtwdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -127,12 +127,53 @@ static void rtw_fw_leave_lps_state_check(struct rtw_dev *rtwdev)
|
|||
*/
|
||||
for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) {
|
||||
if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0)
|
||||
return;
|
||||
return 0;
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
rtw_write32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN, 0);
|
||||
rtw_warn(rtwdev, "firmware failed to restore hardware setting\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int __rtw_fw_leave_lps_check_c2h(struct rtw_dev *rtwdev)
|
||||
{
|
||||
if (wait_for_completion_timeout(&rtwdev->lps_leave_check,
|
||||
LEAVE_LPS_TIMEOUT))
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static void rtw_fw_leave_lps_check(struct rtw_dev *rtwdev)
|
||||
{
|
||||
bool ret = false;
|
||||
struct rtw_fw_state *fw;
|
||||
|
||||
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
|
||||
fw = &rtwdev->wow_fw;
|
||||
else
|
||||
fw = &rtwdev->fw;
|
||||
|
||||
if (fw->feature & FW_FEATURE_LPS_C2H)
|
||||
ret = __rtw_fw_leave_lps_check_c2h(rtwdev);
|
||||
else
|
||||
ret = __rtw_fw_leave_lps_check_reg(rtwdev);
|
||||
|
||||
if (ret) {
|
||||
rtw_write32_clr(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN);
|
||||
rtw_warn(rtwdev, "firmware failed to leave lps state\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void rtw_fw_leave_lps_check_prepare(struct rtw_dev *rtwdev)
|
||||
{
|
||||
struct rtw_fw_state *fw;
|
||||
|
||||
if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
|
||||
fw = &rtwdev->wow_fw;
|
||||
else
|
||||
fw = &rtwdev->fw;
|
||||
|
||||
if (fw->feature & FW_FEATURE_LPS_C2H)
|
||||
reinit_completion(&rtwdev->lps_leave_check);
|
||||
}
|
||||
|
||||
static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
|
||||
|
@ -145,8 +186,9 @@ static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
|
|||
conf->smart_ps = 0;
|
||||
|
||||
rtw_hci_link_ps(rtwdev, false);
|
||||
rtw_fw_leave_lps_check_prepare(rtwdev);
|
||||
rtw_fw_set_pwr_mode(rtwdev);
|
||||
rtw_fw_leave_lps_state_check(rtwdev);
|
||||
rtw_fw_leave_lps_check(rtwdev);
|
||||
|
||||
clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define POWER_MODE_LCLK BIT(0)
|
||||
|
||||
#define LEAVE_LPS_TRY_CNT 5
|
||||
#define LEAVE_LPS_TIMEOUT msecs_to_jiffies(100)
|
||||
|
||||
int rtw_enter_ips(struct rtw_dev *rtwdev);
|
||||
int rtw_leave_ips(struct rtw_dev *rtwdev);
|
||||
|
|
Loading…
Add table
Reference in a new issue