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
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
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.
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>
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(+)
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
32 +void rtl_update_beacon_work_callback(struct work_struct *work)
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;
41 + WARN_ONCE(true, "no vif to update beacon\n");
45 + mutex_lock(&rtlpriv->locks.conf_mutex);
46 + send_beacon_frame(hw, vif);
47 + mutex_unlock(&rtlpriv->locks.conf_mutex);
49 +EXPORT_SYMBOL_GPL(rtl_update_beacon_work_callback);
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);
58 +static int rtl_op_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
61 + struct rtl_priv *rtlpriv = rtl_priv(hw);
62 + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
64 + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU)
65 + schedule_work(&rtlpriv->works.update_beacon_work);
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,
79 EXPORT_SYMBOL_GPL(rtl_ops);
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);
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
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);
98 flush_workqueue(rtlpriv->works.rtl_wq);
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);
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 {
113 struct work_struct lps_change_work;
114 struct work_struct fill_h2c_cmd;
115 + struct work_struct update_beacon_work;