Commit c17f2716 authored by Po-Hao Huang's avatar Po-Hao Huang Committed by Kalle Valo

rtw88: fix idle mode flow for hw scan

Upon hw scan completion, idle mode is not re-entered. This might
increase power consumption under no link mode. Fix this by adding the
re-enter flow. We need another work for this since enter_ips waits
for c2h_work to finish, which might lead to deadlock if caller is in
the same work.

Fixes: 10d162b2 ("rtw88: 8822c: add ieee80211_ops::hw_scan")
Signed-off-by: default avatarPo-Hao Huang <phhuang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20220121070813.9656-3-pkshih@realtek.com
parent a12f8099
...@@ -2030,7 +2030,7 @@ void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, ...@@ -2030,7 +2030,7 @@ void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
rtwdev->hal.rcr |= BIT_CBSSID_BCN; rtwdev->hal.rcr |= BIT_CBSSID_BCN;
rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr); rtw_write32(rtwdev, REG_RCR, rtwdev->hal.rcr);
rtw_core_scan_complete(rtwdev, vif); rtw_core_scan_complete(rtwdev, vif, true);
ieee80211_wake_queues(rtwdev->hw); ieee80211_wake_queues(rtwdev->hw);
ieee80211_scan_completed(rtwdev->hw, &info); ieee80211_scan_completed(rtwdev->hw, &info);
......
...@@ -72,6 +72,9 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) ...@@ -72,6 +72,9 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
struct rtw_dev *rtwdev = hw->priv; struct rtw_dev *rtwdev = hw->priv;
int ret = 0; int ret = 0;
/* let previous ips work finish to ensure we don't leave ips twice */
cancel_work_sync(&rtwdev->ips_work);
mutex_lock(&rtwdev->mutex); mutex_lock(&rtwdev->mutex);
rtw_leave_lps_deep(rtwdev); rtw_leave_lps_deep(rtwdev);
...@@ -614,7 +617,7 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, ...@@ -614,7 +617,7 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw,
struct rtw_dev *rtwdev = hw->priv; struct rtw_dev *rtwdev = hw->priv;
mutex_lock(&rtwdev->mutex); mutex_lock(&rtwdev->mutex);
rtw_core_scan_complete(rtwdev, vif); rtw_core_scan_complete(rtwdev, vif, false);
mutex_unlock(&rtwdev->mutex); mutex_unlock(&rtwdev->mutex);
} }
......
...@@ -272,6 +272,15 @@ static void rtw_c2h_work(struct work_struct *work) ...@@ -272,6 +272,15 @@ static void rtw_c2h_work(struct work_struct *work)
} }
} }
static void rtw_ips_work(struct work_struct *work)
{
struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ips_work);
mutex_lock(&rtwdev->mutex);
rtw_enter_ips(rtwdev);
mutex_unlock(&rtwdev->mutex);
}
static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
{ {
unsigned long mac_id; unsigned long mac_id;
...@@ -1339,7 +1348,8 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, ...@@ -1339,7 +1348,8 @@ void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
set_bit(RTW_FLAG_SCANNING, rtwdev->flags); set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
} }
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool hw_scan)
{ {
struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
u32 config = 0; u32 config = 0;
...@@ -1354,6 +1364,9 @@ void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif) ...@@ -1354,6 +1364,9 @@ void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
rtw_vif_port_config(rtwdev, rtwvif, config); rtw_vif_port_config(rtwdev, rtwvif, config);
rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH); rtw_coex_scan_notify(rtwdev, COEX_SCAN_FINISH);
if (rtwvif->net_type == RTW_NET_NO_LINK && hw_scan)
ieee80211_queue_work(rtwdev->hw, &rtwdev->ips_work);
} }
int rtw_core_start(struct rtw_dev *rtwdev) int rtw_core_start(struct rtw_dev *rtwdev)
...@@ -1919,6 +1932,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) ...@@ -1919,6 +1932,7 @@ int rtw_core_init(struct rtw_dev *rtwdev)
INIT_DELAYED_WORK(&coex->wl_ccklock_work, rtw_coex_wl_ccklock_work); INIT_DELAYED_WORK(&coex->wl_ccklock_work, rtw_coex_wl_ccklock_work);
INIT_WORK(&rtwdev->tx_work, rtw_tx_work); INIT_WORK(&rtwdev->tx_work, rtw_tx_work);
INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work); INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work);
INIT_WORK(&rtwdev->ips_work, rtw_ips_work);
INIT_WORK(&rtwdev->fw_recovery_work, rtw_fw_recovery_work); INIT_WORK(&rtwdev->fw_recovery_work, rtw_fw_recovery_work);
INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work); INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work);
skb_queue_head_init(&rtwdev->c2h_queue); skb_queue_head_init(&rtwdev->c2h_queue);
......
...@@ -1960,6 +1960,7 @@ struct rtw_dev { ...@@ -1960,6 +1960,7 @@ struct rtw_dev {
/* c2h cmd queue & handler work */ /* c2h cmd queue & handler work */
struct sk_buff_head c2h_queue; struct sk_buff_head c2h_queue;
struct work_struct c2h_work; struct work_struct c2h_work;
struct work_struct ips_work;
struct work_struct fw_recovery_work; struct work_struct fw_recovery_work;
/* used to protect txqs list */ /* used to protect txqs list */
...@@ -2101,7 +2102,8 @@ void rtw_tx_report_purge_timer(struct timer_list *t); ...@@ -2101,7 +2102,8 @@ void rtw_tx_report_purge_timer(struct timer_list *t);
void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si); void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, void rtw_core_scan_start(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
const u8 *mac_addr, bool hw_scan); const u8 *mac_addr, bool hw_scan);
void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif); void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
bool hw_scan);
int rtw_core_start(struct rtw_dev *rtwdev); int rtw_core_start(struct rtw_dev *rtwdev);
void rtw_core_stop(struct rtw_dev *rtwdev); void rtw_core_stop(struct rtw_dev *rtwdev);
int rtw_chip_info_setup(struct rtw_dev *rtwdev); int rtw_chip_info_setup(struct rtw_dev *rtwdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment