| Date: Mon, 19 Apr 2021 14:59:56 +0800 |
| From: Ping-Ke Shih <pkshih@realtek.com> |
| To: <kvalo@codeaurora.org> |
| CC: <linux-wireless@vger.kernel.org>, <mail@maciej.szmigiero.name>, |
| <Larry.Finger@lwfinger.net> |
| Subject: [PATCH] rtlwifi: implement set_tim by update beacon content |
| |
| Once beacon content is changed, we update the content to wifi card by |
| send_beacon_frame(). Then, STA with PS can wake up properly to receive its |
| packets. |
| |
| Since we update beacon content to PCI wifi devices every beacon interval, |
| the only one usb device, 8192CU, needs to update beacon content when |
| mac80211 calling set_tim. |
| |
| Reported-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> |
| Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> |
| Tested-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> |
| --- |
| drivers/net/wireless/realtek/rtlwifi/core.c | 32 +++++++++++++++++++++ |
| drivers/net/wireless/realtek/rtlwifi/core.h | 1 + |
| drivers/net/wireless/realtek/rtlwifi/usb.c | 3 ++ |
| drivers/net/wireless/realtek/rtlwifi/wifi.h | 1 + |
| 4 files changed, 37 insertions(+) |
| |
| --- a/drivers/net/wireless/realtek/rtlwifi/core.c |
| +++ b/drivers/net/wireless/realtek/rtlwifi/core.c |
| @@ -1018,6 +1018,25 @@ static void send_beacon_frame(struct iee |
| } |
| } |
| |
| +void rtl_update_beacon_work_callback(struct work_struct *work) |
| +{ |
| + struct rtl_works *rtlworks = |
| + container_of(work, struct rtl_works, update_beacon_work); |
| + struct ieee80211_hw *hw = rtlworks->hw; |
| + struct rtl_priv *rtlpriv = rtl_priv(hw); |
| + struct ieee80211_vif *vif = rtlpriv->mac80211.vif; |
| + |
| + if (!vif) { |
| + WARN_ONCE(true, "no vif to update beacon\n"); |
| + return; |
| + } |
| + |
| + mutex_lock(&rtlpriv->locks.conf_mutex); |
| + send_beacon_frame(hw, vif); |
| + mutex_unlock(&rtlpriv->locks.conf_mutex); |
| +} |
| +EXPORT_SYMBOL_GPL(rtl_update_beacon_work_callback); |
| + |
| static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, |
| struct ieee80211_vif *vif, |
| struct ieee80211_bss_conf *bss_conf, |
| @@ -1747,6 +1766,18 @@ static void rtl_op_flush(struct ieee8021 |
| rtlpriv->intf_ops->flush(hw, queues, drop); |
| } |
| |
| +static int rtl_op_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
| + bool set) |
| +{ |
| + struct rtl_priv *rtlpriv = rtl_priv(hw); |
| + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| + |
| + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) |
| + schedule_work(&rtlpriv->works.update_beacon_work); |
| + |
| + return 0; |
| +} |
| + |
| /* Description: |
| * This routine deals with the Power Configuration CMD |
| * parsing for RTL8723/RTL8188E Series IC. |
| @@ -1903,6 +1934,7 @@ const struct ieee80211_ops rtl_ops = { |
| .sta_add = rtl_op_sta_add, |
| .sta_remove = rtl_op_sta_remove, |
| .flush = rtl_op_flush, |
| + .set_tim = rtl_op_set_tim, |
| }; |
| EXPORT_SYMBOL_GPL(rtl_ops); |
| |
| --- a/drivers/net/wireless/realtek/rtlwifi/core.h |
| +++ b/drivers/net/wireless/realtek/rtlwifi/core.h |
| @@ -60,5 +60,6 @@ void rtl_bb_delay(struct ieee80211_hw *h |
| bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); |
| bool rtl_btc_status_false(void); |
| void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igval); |
| +void rtl_update_beacon_work_callback(struct work_struct *work); |
| |
| #endif |
| --- a/drivers/net/wireless/realtek/rtlwifi/usb.c |
| +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c |
| @@ -807,6 +807,7 @@ static void rtl_usb_stop(struct ieee8021 |
| |
| tasklet_kill(&rtlusb->rx_work_tasklet); |
| cancel_work_sync(&rtlpriv->works.lps_change_work); |
| + cancel_work_sync(&rtlpriv->works.update_beacon_work); |
| |
| flush_workqueue(rtlpriv->works.rtl_wq); |
| |
| @@ -1033,6 +1034,8 @@ int rtl_usb_probe(struct usb_interface * |
| rtl_fill_h2c_cmd_work_callback); |
| INIT_WORK(&rtlpriv->works.lps_change_work, |
| rtl_lps_change_work_callback); |
| + INIT_WORK(&rtlpriv->works.update_beacon_work, |
| + rtl_update_beacon_work_callback); |
| |
| rtlpriv->usb_data_index = 0; |
| init_completion(&rtlpriv->firmware_loading_complete); |
| --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h |
| +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h |
| @@ -2487,6 +2487,7 @@ struct rtl_works { |
| |
| struct work_struct lps_change_work; |
| struct work_struct fill_h2c_cmd; |
| + struct work_struct update_beacon_work; |
| }; |
| |
| struct rtl_debug { |