Commit f2217968 authored by Po-Hao Huang's avatar Po-Hao Huang Committed by Kalle Valo
Browse files

rtw88: Add update beacon flow for AP mode



To support stations in power saving mode, AP should notify stations
that there are frames buffered at the AP via TIM during beacons.
Driver used to transmit identical beacons that were downloaded to
hardware during the initiation phase. This beacon will become
obsolete over time.

If the beacon does not contain sufficient information, station would
not be able to percept that there is data to receive. Hence it won't
wake up and start the PS-poll procedure, this could lead to timeout
and/or lost data segments. In order to resolve this issue, driver will
now download beacon to hardware whenever the content is updated.

Enable hardware to update dtim_count for more efficiency, this reduces
the overhead of downloading beacon at every beacon interval since most
of the time only the dtim_count needs to be updated.

Change queue mapping for broadcast/multicast frames to high queue, so
these frames can be prioritized and sent when dtim_count is zero.

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/20220407095858.46807-4-pkshih@realtek.com
parent 6723c0cd
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1047,6 +1047,7 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
	struct rtw_vif *rtwvif;
	struct sk_buff *skb_new;
	struct cfg80211_ssid *ssid;
	u16 tim_offset;

	if (rsvd_pkt->type == RSVD_DUMMY) {
		skb_new = alloc_skb(1, GFP_KERNEL);
@@ -1065,7 +1066,8 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,

	switch (rsvd_pkt->type) {
	case RSVD_BEACON:
		skb_new = ieee80211_beacon_get(hw, vif);
		skb_new = ieee80211_beacon_get_tim(hw, vif, &tim_offset, NULL);
		rsvd_pkt->tim_offset = tim_offset;
		break;
	case RSVD_PS_POLL:
		skb_new = ieee80211_pspoll_get(hw, vif);
+1 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ struct rtw_rsvd_page {
	struct sk_buff *skb;
	enum rtw_rsvd_packet_type type;
	u8 page;
	u16 tim_offset;
	bool add_txdesc;
	struct cfg80211_ssid *ssid;
	u16 probe_req_size;
+16 −1
Original line number Diff line number Diff line
@@ -402,8 +402,10 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
			coex_stat->wl_beacon_interval = conf->beacon_int;
	}

	if (changed & BSS_CHANGED_BEACON)
	if (changed & BSS_CHANGED_BEACON) {
		rtw_set_dtim_period(rtwdev, conf->dtim_period);
		rtw_fw_download_rsvd_page(rtwdev);
	}

	if (changed & BSS_CHANGED_BEACON_ENABLED) {
		if (conf->enable_beacon)
@@ -474,6 +476,18 @@ static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
	return 0;
}

static int rtw_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
			   bool set)
{
	struct rtw_dev *rtwdev = hw->priv;

	mutex_lock(&rtwdev->mutex);
	rtw_fw_download_rsvd_page(rtwdev);
	mutex_unlock(&rtwdev->mutex);

	return 0;
}

static int rtw_ops_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
			   struct ieee80211_vif *vif, struct ieee80211_sta *sta,
			   struct ieee80211_key_conf *key)
@@ -875,6 +889,7 @@ const struct ieee80211_ops rtw_ops = {
	.conf_tx		= rtw_ops_conf_tx,
	.sta_add		= rtw_ops_sta_add,
	.sta_remove		= rtw_ops_sta_remove,
	.set_tim		= rtw_ops_set_tim,
	.set_key		= rtw_ops_set_key,
	.ampdu_action		= rtw_ops_ampdu_action,
	.can_aggregate_in_amsdu	= rtw_ops_can_aggregate_in_amsdu,
+6 −0
Original line number Diff line number Diff line
@@ -664,6 +664,12 @@ void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel)
}
EXPORT_SYMBOL(rtw_set_rx_freq_band);

void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period)
{
	rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_TIMIE);
	rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period - 1);
}

void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
			    struct rtw_channel_params *chan_params)
{
+2 −0
Original line number Diff line number Diff line
@@ -580,6 +580,7 @@ struct rtw_tx_pkt_info {
	u32 tx_pkt_size;
	u8 offset;
	u8 pkt_offset;
	u8 tim_offset;
	u8 mac_id;
	u8 rate_id;
	u8 rate;
@@ -2131,6 +2132,7 @@ static inline int rtw_chip_dump_fw_crash(struct rtw_dev *rtwdev)
}

void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel);
void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period);
void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
			    struct rtw_channel_params *ch_param);
bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target);
Loading