| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | Date: Mon, 19 Apr 2021 14:59:56 +0800 |
| 2 | From: Ping-Ke Shih <pkshih@realtek.com> |
| 3 | To: <kvalo@codeaurora.org> |
| 4 | CC: <linux-wireless@vger.kernel.org>, <mail@maciej.szmigiero.name>, |
| 5 | <Larry.Finger@lwfinger.net> |
| 6 | Subject: [PATCH] rtlwifi: implement set_tim by update beacon content |
| 7 | |
| 8 | Once beacon content is changed, we update the content to wifi card by |
| 9 | send_beacon_frame(). Then, STA with PS can wake up properly to receive its |
| 10 | packets. |
| 11 | |
| 12 | Since we update beacon content to PCI wifi devices every beacon interval, |
| 13 | the only one usb device, 8192CU, needs to update beacon content when |
| 14 | mac80211 calling set_tim. |
| 15 | |
| 16 | Reported-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> |
| 17 | Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> |
| 18 | Tested-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> |
| 19 | --- |
| 20 | drivers/net/wireless/realtek/rtlwifi/core.c | 32 +++++++++++++++++++++ |
| 21 | drivers/net/wireless/realtek/rtlwifi/core.h | 1 + |
| 22 | drivers/net/wireless/realtek/rtlwifi/usb.c | 3 ++ |
| 23 | drivers/net/wireless/realtek/rtlwifi/wifi.h | 1 + |
| 24 | 4 files changed, 37 insertions(+) |
| 25 | |
| 26 | --- a/drivers/net/wireless/realtek/rtlwifi/core.c |
| 27 | +++ b/drivers/net/wireless/realtek/rtlwifi/core.c |
| 28 | @@ -1018,6 +1018,25 @@ static void send_beacon_frame(struct iee |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | +void rtl_update_beacon_work_callback(struct work_struct *work) |
| 33 | +{ |
| 34 | + struct rtl_works *rtlworks = |
| 35 | + container_of(work, struct rtl_works, update_beacon_work); |
| 36 | + struct ieee80211_hw *hw = rtlworks->hw; |
| 37 | + struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 38 | + struct ieee80211_vif *vif = rtlpriv->mac80211.vif; |
| 39 | + |
| 40 | + if (!vif) { |
| 41 | + WARN_ONCE(true, "no vif to update beacon\n"); |
| 42 | + return; |
| 43 | + } |
| 44 | + |
| 45 | + mutex_lock(&rtlpriv->locks.conf_mutex); |
| 46 | + send_beacon_frame(hw, vif); |
| 47 | + mutex_unlock(&rtlpriv->locks.conf_mutex); |
| 48 | +} |
| 49 | +EXPORT_SYMBOL_GPL(rtl_update_beacon_work_callback); |
| 50 | + |
| 51 | static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, |
| 52 | struct ieee80211_vif *vif, |
| 53 | struct ieee80211_bss_conf *bss_conf, |
| 54 | @@ -1747,6 +1766,18 @@ static void rtl_op_flush(struct ieee8021 |
| 55 | rtlpriv->intf_ops->flush(hw, queues, drop); |
| 56 | } |
| 57 | |
| 58 | +static int rtl_op_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
| 59 | + bool set) |
| 60 | +{ |
| 61 | + struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 62 | + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 63 | + |
| 64 | + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) |
| 65 | + schedule_work(&rtlpriv->works.update_beacon_work); |
| 66 | + |
| 67 | + return 0; |
| 68 | +} |
| 69 | + |
| 70 | /* Description: |
| 71 | * This routine deals with the Power Configuration CMD |
| 72 | * parsing for RTL8723/RTL8188E Series IC. |
| 73 | @@ -1903,6 +1934,7 @@ const struct ieee80211_ops rtl_ops = { |
| 74 | .sta_add = rtl_op_sta_add, |
| 75 | .sta_remove = rtl_op_sta_remove, |
| 76 | .flush = rtl_op_flush, |
| 77 | + .set_tim = rtl_op_set_tim, |
| 78 | }; |
| 79 | EXPORT_SYMBOL_GPL(rtl_ops); |
| 80 | |
| 81 | --- a/drivers/net/wireless/realtek/rtlwifi/core.h |
| 82 | +++ b/drivers/net/wireless/realtek/rtlwifi/core.h |
| 83 | @@ -60,5 +60,6 @@ void rtl_bb_delay(struct ieee80211_hw *h |
| 84 | bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); |
| 85 | bool rtl_btc_status_false(void); |
| 86 | void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igval); |
| 87 | +void rtl_update_beacon_work_callback(struct work_struct *work); |
| 88 | |
| 89 | #endif |
| 90 | --- a/drivers/net/wireless/realtek/rtlwifi/usb.c |
| 91 | +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c |
| 92 | @@ -807,6 +807,7 @@ static void rtl_usb_stop(struct ieee8021 |
| 93 | |
| 94 | tasklet_kill(&rtlusb->rx_work_tasklet); |
| 95 | cancel_work_sync(&rtlpriv->works.lps_change_work); |
| 96 | + cancel_work_sync(&rtlpriv->works.update_beacon_work); |
| 97 | |
| 98 | flush_workqueue(rtlpriv->works.rtl_wq); |
| 99 | |
| 100 | @@ -1033,6 +1034,8 @@ int rtl_usb_probe(struct usb_interface * |
| 101 | rtl_fill_h2c_cmd_work_callback); |
| 102 | INIT_WORK(&rtlpriv->works.lps_change_work, |
| 103 | rtl_lps_change_work_callback); |
| 104 | + INIT_WORK(&rtlpriv->works.update_beacon_work, |
| 105 | + rtl_update_beacon_work_callback); |
| 106 | |
| 107 | rtlpriv->usb_data_index = 0; |
| 108 | init_completion(&rtlpriv->firmware_loading_complete); |
| 109 | --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h |
| 110 | +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h |
| 111 | @@ -2487,6 +2487,7 @@ struct rtl_works { |
| 112 | |
| 113 | struct work_struct lps_change_work; |
| 114 | struct work_struct fill_h2c_cmd; |
| 115 | + struct work_struct update_beacon_work; |
| 116 | }; |
| 117 | |
| 118 | struct rtl_debug { |