2019-10-02 07:08:20

by Tony Chuang

[permalink] [raw]
Subject: [PATCH 01/14] rtw88: check firmware leave lps successfully

From: Chin-Yen Lee <[email protected]>

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 <[email protected]>
Signed-off-by: Yan-Hsuan Chuang <[email protected]>
---
drivers/net/wireless/realtek/rtw88/ps.c | 29 ++++++++++++++++++++++++
drivers/net/wireless/realtek/rtw88/ps.h | 2 ++
drivers/net/wireless/realtek/rtw88/reg.h | 1 +
3 files changed, 32 insertions(+)

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)
--
2.17.1


2019-10-04 13:46:29

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 01/14] rtw88: check firmware leave lps successfully

<[email protected]> wrote:

> From: Chin-Yen Lee <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Yan-Hsuan Chuang <[email protected]>

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

--
https://patchwork.kernel.org/patch/11170463/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches