]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
wifi: rtw88: use RTW_FLAG_POWERON flag to prevent to power on/off twice
authorPing-Ke Shih <pkshih@realtek.com>
Thu, 16 Feb 2023 05:36:33 +0000 (13:36 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2023 08:34:21 +0000 (09:34 +0100)
commit 4a267bc5ea8f159b614d0549030216d0434eccca upstream.

Use power state to decide whether we can enter or leave IPS accurately,
and then prevent to power on/off twice.

The commit 6bf3a083407b ("wifi: rtw88: add flag check before enter or leave IPS")
would like to prevent this as well, but it still can't entirely handle all
cases. The exception is that WiFi gets connected and does suspend/resume,
it will power on twice and cause it failed to power on after resuming,
like:

  rtw_8723de 0000:03:00.0: failed to poll offset=0x6 mask=0x2 value=0x2
  rtw_8723de 0000:03:00.0: mac power on failed
  rtw_8723de 0000:03:00.0: failed to power on mac
  rtw_8723de 0000:03:00.0: leave idle state failed
  rtw_8723de 0000:03:00.0: failed to leave ips state
  rtw_8723de 0000:03:00.0: failed to leave idle state
  rtw_8723de 0000:03:00.0: failed to send h2c command

To fix this, introduce new flag RTW_FLAG_POWERON to reflect power state,
and call rtw_mac_pre_system_cfg() to configure registers properly between
power-off/-on.

Reported-by: Paul Gover <pmw.gover@yahoo.co.uk>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=217016
Fixes: 6bf3a083407b ("wifi: rtw88: add flag check before enter or leave IPS")
Cc: <Stable@vger.kernel.org>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230216053633.20366-1-pkshih@realtek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/realtek/rtw88/coex.c
drivers/net/wireless/realtek/rtw88/mac.c
drivers/net/wireless/realtek/rtw88/main.h
drivers/net/wireless/realtek/rtw88/ps.c
drivers/net/wireless/realtek/rtw88/wow.c

index 6276ad6242991ae15ece36b1b2cd42940b5193ad..a82476f47a7c472b2e4251b8e0b6cf278fdb2aa2 100644 (file)
@@ -4057,7 +4057,7 @@ void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
                   rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
        seq_printf(m, "%-40s = %u/ %u/ %u\n",
                   "IPS/ Low Power/ PS mode",
-                  test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
+                  !test_bit(RTW_FLAG_POWERON, rtwdev->flags),
                   test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
                   rtwdev->lps_conf.mode);
 
index 52076e89d59a33b0db5747eacfc697b79adc1473..2afe64f2abe69961dc4ae334fc9052d7661da33b 100644 (file)
@@ -273,6 +273,11 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
        if (rtw_pwr_seq_parser(rtwdev, pwr_seq))
                return -EINVAL;
 
+       if (pwr_on)
+               set_bit(RTW_FLAG_POWERON, rtwdev->flags);
+       else
+               clear_bit(RTW_FLAG_POWERON, rtwdev->flags);
+
        return 0;
 }
 
@@ -335,6 +340,11 @@ int rtw_mac_power_on(struct rtw_dev *rtwdev)
        ret = rtw_mac_power_switch(rtwdev, true);
        if (ret == -EALREADY) {
                rtw_mac_power_switch(rtwdev, false);
+
+               ret = rtw_mac_pre_system_cfg(rtwdev);
+               if (ret)
+                       goto err;
+
                ret = rtw_mac_power_switch(rtwdev, true);
                if (ret)
                        goto err;
index bccd7b28f60c7b75ede6abc943ae22a6a4fda13f..cd9c068ae1a7823a1f7823f570eadb2ed37816bc 100644 (file)
@@ -356,7 +356,7 @@ enum rtw_flags {
        RTW_FLAG_RUNNING,
        RTW_FLAG_FW_RUNNING,
        RTW_FLAG_SCANNING,
-       RTW_FLAG_INACTIVE_PS,
+       RTW_FLAG_POWERON,
        RTW_FLAG_LEISURE_PS,
        RTW_FLAG_LEISURE_PS_DEEP,
        RTW_FLAG_DIG_DISABLE,
index c93da743681fc51954f635f4c1455f70a6e77196..dc0d852182454426646b31c5c73f63e540fada51 100644 (file)
@@ -25,7 +25,7 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
 
 int rtw_enter_ips(struct rtw_dev *rtwdev)
 {
-       if (test_and_set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags))
+       if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags))
                return 0;
 
        rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
@@ -50,7 +50,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
 {
        int ret;
 
-       if (!test_and_clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags))
+       if (test_bit(RTW_FLAG_POWERON, rtwdev->flags))
                return 0;
 
        rtw_hci_link_ps(rtwdev, false);
index 89dc595094d5cc36056ffcb34d77eb72d6e2ec4d..16ddee577efec446f89a6024b338261e4ad9c261 100644 (file)
@@ -592,7 +592,7 @@ static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev)
                if (rtw_get_lps_deep_mode(rtwdev) != LPS_DEEP_MODE_NONE)
                        rtw_leave_lps_deep(rtwdev);
        } else {
-               if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) {
+               if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) {
                        rtw_wow->ips_enabled = true;
                        ret = rtw_leave_ips(rtwdev);
                        if (ret)