Message ID | 20191002063531.18135-2-yhchuang@realtek.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 3a2dd6b7cadfc627378d2c3af065f82ebb1d4cbf |
Delegated to: | Kalle Valo |
Headers | show |
Series | [01/14] rtw88: check firmware leave lps successfully | expand |
<yhchuang@realtek.com> wrote: > From: Chin-Yen Lee <timlee@realtek.com> > > Driver needs to wait for firmware to restore hardware setting > to active mode after leaving lps. > > After getting H2C from driver for leaving lps, firmware will > issue null packet without PS bit to inform AP driver is active, > and then restore REG_TCR Register if AP has receiced null packet. > > But the transmission of null packet may cost much more time > in noisy environment. If driver does not wait for firmware, > null packet with PS bit could be sent due to incorrect REG_TCR setting. > And AP will be confused. > > In our test, 100ms is enough for firmware to send null packet > to AP. If REG_TCR Register is still wrong after 100ms, we will > modify it directly, force the PS bit to be cleared > > Signed-off-by: Chin-Yen Lee <timlee@realtek.com> > Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com> 14 patches applied to wireless-drivers-next.git, thanks. 3a2dd6b7cadf rtw88: check firmware leave lps successfully 942e2a5d39a9 rtw88: allows to set RTS in TX descriptor 3745d3e550d1 rtw88: add driver TX queue support 46ebb1743f33 rtw88: take over rate control from mac80211 699c7730cf23 rtw88: report tx rate to mac80211 stack 127eef1d46f8 rtw88: add TX-AMSDU support 1131ad7fe575 rtw88: flush hardware tx queues c3594559f49c rtw88: fix beaconing mode rsvd_page memory violation issue 0649ff58a0f6 rtw88: Don't set RX_FLAG_DECRYPTED if packet has no encryption bf06c7ec4508 rtw88: configure TX queue EDCA parameters bc3696e0a436 rtw88: raise firmware version debug level cc20a7139836 rtw88: use struct rtw_fw_hdr to access firmware header 4f5bb7ff8b8d rtw88: fix NSS of hw_cap f4268729eb1e rtw88: fix error handling when setup efuse info
diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index 83db6cf6a219..bf149956b04e 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -9,6 +9,7 @@ #include "mac.h" #include "coex.h" #include "debug.h" +#include "reg.h" static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) { @@ -118,6 +119,32 @@ 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) +{ + int i; + + /* Driver needs to wait for firmware to leave LPS state + * successfully. Firmware will send null packet to inform AP, + * and see if AP sends an ACK back, then firmware will restore + * the REG_TCR register. + * + * If driver does not wait for firmware, null packet with + * PS bit could be sent due to incorrect REG_TCR setting. + * + * In our test, 100ms should be enough for firmware to finish + * the flow. If REG_TCR Register is still incorrect after 100ms, + * just modify it directly, and throw a warn message. + */ + for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) { + if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0) + return; + msleep(20); + } + + rtw_write32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN, 0); + rtw_warn(rtwdev, "firmware failed to restore hardware setting\n"); +} + static void rtw_leave_lps_core(struct rtw_dev *rtwdev) { struct rtw_lps_conf *conf = &rtwdev->lps_conf; @@ -128,6 +155,8 @@ static void rtw_leave_lps_core(struct rtw_dev *rtwdev) conf->smart_ps = 0; rtw_fw_set_pwr_mode(rtwdev); + rtw_fw_leave_lps_state_check(rtwdev); + clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags); rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE); diff --git a/drivers/net/wireless/realtek/rtw88/ps.h b/drivers/net/wireless/realtek/rtw88/ps.h index 18f687cfe211..25925eedbad4 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.h +++ b/drivers/net/wireless/realtek/rtw88/ps.h @@ -11,6 +11,8 @@ #define POWER_MODE_PG BIT(4) #define POWER_MODE_LCLK BIT(0) +#define LEAVE_LPS_TRY_CNT 5 + int rtw_enter_ips(struct rtw_dev *rtwdev); int rtw_leave_ips(struct rtw_dev *rtwdev); diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index fe793e270d22..60014077de77 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -271,6 +271,7 @@ #define BIT_TSFT_SEL_TIMER0 (BIT(4) | BIT(5) | BIT(6)) #define REG_TCR 0x0604 +#define BIT_PWRMGT_HWDATA_EN BIT(7) #define REG_RCR 0x0608 #define BIT_APP_FCS BIT(31) #define BIT_APP_MIC BIT(30)