From: Ping-Ke Shih <pkshih@xxxxxxxxxxx> This chip fails to reliably wake up from power off. Change-Id: I295de3c71fe91af37e8cc39b70728a8ba7e94b2f Reported-by: Marcin Ślusarz <marcin.slusarz@xxxxxxxxx> Signed-off-by: Ping-Ke Shih <pkshih@xxxxxxxxxxx> --- v2: no changes since v1 --- drivers/net/wireless/realtek/rtw88/mac80211.c | 2 +- drivers/net/wireless/realtek/rtw88/main.c | 10 ++++++++-- drivers/net/wireless/realtek/rtw88/main.h | 2 ++ drivers/net/wireless/realtek/rtw88/ps.c | 5 ++++- drivers/net/wireless/realtek/rtw88/ps.h | 2 +- drivers/net/wireless/realtek/rtw88/usb.c | 3 +++ drivers/net/wireless/realtek/rtw88/wow.c | 2 +- 7 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 0acebbfa13c4..0302af2ebe5b 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -98,7 +98,7 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) if ((changed & IEEE80211_CONF_CHANGE_IDLE) && (hw->conf.flags & IEEE80211_CONF_IDLE) && !test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) - rtw_enter_ips(rtwdev); + rtw_enter_ips(rtwdev, false); out: mutex_unlock(&rtwdev->mutex); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 7ab7a988b123..a48e919adddb 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -302,7 +302,7 @@ static void rtw_ips_work(struct work_struct *work) mutex_lock(&rtwdev->mutex); if (rtwdev->hw->conf.flags & IEEE80211_CONF_IDLE) - rtw_enter_ips(rtwdev); + rtw_enter_ips(rtwdev, false); mutex_unlock(&rtwdev->mutex); } @@ -647,7 +647,7 @@ static void __fw_recovery_work(struct rtw_dev *rtwdev) rtw_iterate_stas_atomic(rtwdev, rtw_reset_sta_iter, rtwdev); rtw_iterate_vifs_atomic(rtwdev, rtw_reset_vif_iter, rtwdev); bitmap_zero(rtwdev->hw_port, RTW_PORT_NUM); - rtw_enter_ips(rtwdev); + rtw_enter_ips(rtwdev, true); } static void rtw_fw_recovery_work(struct work_struct *work) @@ -1356,6 +1356,9 @@ static int rtw_power_on(struct rtw_dev *rtwdev) bool wifi_only; int ret; + if (rtwdev->always_power_on && test_bit(RTW_FLAG_POWERON, rtwdev->flags)) + return 0; + ret = rtw_hci_setup(rtwdev); if (ret) { rtw_err(rtwdev, "failed to setup hci\n"); @@ -1506,6 +1509,9 @@ int rtw_core_start(struct rtw_dev *rtwdev) static void rtw_power_off(struct rtw_dev *rtwdev) { + if (rtwdev->always_power_on) + return; + rtw_hci_stop(rtwdev); rtw_coex_power_off_setting(rtwdev); rtw_mac_power_off(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 49894331f7b4..a6125b5e7d53 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -2049,6 +2049,8 @@ struct rtw_dev { bool beacon_loss; struct completion lps_leave_check; + bool always_power_on; + struct dentry *debugfs; u8 sta_cnt; diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index add5a20b8432..a4092d424eda 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -24,8 +24,11 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev) return ret; } -int rtw_enter_ips(struct rtw_dev *rtwdev) +int rtw_enter_ips(struct rtw_dev *rtwdev, bool force) { + if (!force && rtwdev->always_power_on) + return 0; + if (!test_bit(RTW_FLAG_POWERON, rtwdev->flags)) return 0; diff --git a/drivers/net/wireless/realtek/rtw88/ps.h b/drivers/net/wireless/realtek/rtw88/ps.h index 5ae83d2526cf..92057d01cbec 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.h +++ b/drivers/net/wireless/realtek/rtw88/ps.h @@ -15,7 +15,7 @@ #define LEAVE_LPS_TRY_CNT 5 #define LEAVE_LPS_TIMEOUT msecs_to_jiffies(100) -int rtw_enter_ips(struct rtw_dev *rtwdev); +int rtw_enter_ips(struct rtw_dev *rtwdev, bool force); int rtw_leave_ips(struct rtw_dev *rtwdev); void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 98f81e3ae13e..e1b66f339cca 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -859,6 +859,9 @@ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) rtwdev->hci.ops = &rtw_usb_ops; rtwdev->hci.type = RTW_HCI_TYPE_USB; + if (rtwdev->chip->id == RTW_CHIP_TYPE_8821C) + rtwdev->always_power_on = true; + rtwusb = rtw_get_usb_priv(rtwdev); rtwusb->rtwdev = rtwdev; diff --git a/drivers/net/wireless/realtek/rtw88/wow.c b/drivers/net/wireless/realtek/rtw88/wow.c index 16ddee577efe..a90c8b388944 100644 --- a/drivers/net/wireless/realtek/rtw88/wow.c +++ b/drivers/net/wireless/realtek/rtw88/wow.c @@ -620,7 +620,7 @@ static int rtw_wow_restore_ps(struct rtw_dev *rtwdev) int ret = 0; if (rtw_wow_no_link(rtwdev) && rtwdev->wow.ips_enabled) - ret = rtw_enter_ips(rtwdev); + ret = rtw_enter_ips(rtwdev, false); return ret; } -- 2.25.1