Update beacon content if TIM bitmap maintained by mac80211 is changed. Since .set_tim must be atomic but driver uses mutex lock, we add a work. Otherwise, kernel says "sched: RT throttling activated" and lock down. Signed-off-by: Ping-Ke Shih <pkshih@xxxxxxxxxxx> --- drivers/net/wireless/realtek/rtw89/core.c | 15 +++++++++++++++ drivers/net/wireless/realtek/rtw89/core.h | 3 +++ drivers/net/wireless/realtek/rtw89/mac80211.c | 17 +++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 7c5e9bc309706..7fee45d8b82a1 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -2238,6 +2238,21 @@ static void rtw89_core_ppdu_sts_init(struct rtw89_dev *rtwdev) rtwdev->ppdu_sts.curr_rx_ppdu_cnt[i] = U8_MAX; } +void rtw89_core_update_beacon_work(struct work_struct *work) +{ + struct rtw89_dev *rtwdev; + struct rtw89_vif *rtwvif = container_of(work, struct rtw89_vif, + update_beacon_work); + + if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE) + return; + + rtwdev = rtwvif->rtwdev; + mutex_lock(&rtwdev->mutex); + rtw89_fw_h2c_update_beacon(rtwdev, rtwvif); + mutex_unlock(&rtwdev->mutex); +} + int rtw89_core_start(struct rtw89_dev *rtwdev) { int ret; diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index defa0ceebc20e..542afe2133b0f 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -1928,6 +1928,7 @@ struct rtw89_phy_rate_pattern { struct rtw89_vif { struct list_head list; + struct rtw89_dev *rtwdev; u8 mac_id; u8 port; u8 mac_addr[ETH_ALEN]; @@ -1949,6 +1950,7 @@ struct rtw89_vif { bool wowlan_magic; bool is_hesta; bool last_a_ctrl; + struct work_struct update_beacon_work; struct rtw89_addr_cam_entry addr_cam; struct rtw89_bssid_cam_entry bssid_cam; struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS]; @@ -3396,5 +3398,6 @@ void rtw89_traffic_stats_init(struct rtw89_dev *rtwdev, struct rtw89_traffic_stats *stats); int rtw89_core_start(struct rtw89_dev *rtwdev); void rtw89_core_stop(struct rtw89_dev *rtwdev); +void rtw89_core_update_beacon_work(struct work_struct *work); #endif diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 682680e18ff46..26abbe7aa17d8 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -102,7 +102,9 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, int ret = 0; mutex_lock(&rtwdev->mutex); + rtwvif->rtwdev = rtwdev; list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list); + INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work); rtw89_leave_ps_mode(rtwdev); rtw89_traffic_stats_init(rtwdev, &rtwvif->stats); @@ -141,6 +143,8 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, struct rtw89_dev *rtwdev = hw->priv; struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + cancel_work_sync(&rtwvif->update_beacon_work); + mutex_lock(&rtwdev->mutex); rtw89_leave_ps_mode(rtwdev); rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_STOP); @@ -364,6 +368,18 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw, mutex_unlock(&rtwdev->mutex); } +static int rtw89_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + bool set) +{ + struct rtw89_dev *rtwdev = hw->priv; + struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; + struct rtw89_vif *rtwvif = rtwsta->rtwvif; + + ieee80211_queue_work(rtwdev->hw, &rtwvif->update_beacon_work); + + return 0; +} + static int rtw89_ops_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 ac, const struct ieee80211_tx_queue_params *params) @@ -680,6 +696,7 @@ const struct ieee80211_ops rtw89_ops = { .remove_interface = rtw89_ops_remove_interface, .configure_filter = rtw89_ops_configure_filter, .bss_info_changed = rtw89_ops_bss_info_changed, + .set_tim = rtw89_ops_set_tim, .conf_tx = rtw89_ops_conf_tx, .sta_state = rtw89_ops_sta_state, .set_key = rtw89_ops_set_key, -- 2.25.1