Commit dcf55fb5 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

mac80211: add a function for setting the TIM bit for a specific station

This allows a driver to buffer frames for a PS station and tell mac80211
to wake it up even though mac80211 does not have any buffered frames for
it.
This is necessary for properly handling aggregation related buffering,
in ath9k, because the driver needs to keep its frames in order to keep
track of the Block-ACK window.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent cea3235c
...@@ -2226,6 +2226,18 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, ...@@ -2226,6 +2226,18 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
*/ */
#define IEEE80211_TX_STATUS_HEADROOM 13 #define IEEE80211_TX_STATUS_HEADROOM 13
/**
* ieee80211_sta_set_tim - set the TIM bit for a sleeping station
*
* If a driver buffers frames for a powersave station instead of passing
* them back to mac80211 for retransmission, the station needs to be told
* to wake up using the TIM bitmap in the beacon.
*
* This function sets the station's TIM bit - it will be cleared when the
* station wakes up.
*/
void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
/** /**
* ieee80211_tx_status - transmit status callback * ieee80211_tx_status - transmit status callback
* *
......
...@@ -612,7 +612,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, ...@@ -612,7 +612,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
#endif #endif
dev_kfree_skb(skb); dev_kfree_skb(skb);
if (skb_queue_empty(&sta->ps_tx_buf)) if (skb_queue_empty(&sta->ps_tx_buf) &&
!test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF))
sta_info_clear_tim_bit(sta); sta_info_clear_tim_bit(sta);
} }
...@@ -896,6 +897,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) ...@@ -896,6 +897,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
int sent, buffered; int sent, buffered;
clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
...@@ -988,3 +990,12 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, ...@@ -988,3 +990,12 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
ieee80211_queue_work(hw, &sta->drv_unblock_wk); ieee80211_queue_work(hw, &sta->drv_unblock_wk);
} }
EXPORT_SYMBOL(ieee80211_sta_block_awake); EXPORT_SYMBOL(ieee80211_sta_block_awake);
void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta)
{
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF);
sta_info_set_tim_bit(sta);
}
EXPORT_SYMBOL(ieee80211_sta_set_tim);
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
* be in the queues * be in the queues
* @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
* station in power-save mode, reply when the driver unblocks. * station in power-save mode, reply when the driver unblocks.
* @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
* buffers. Automatically cleared on station wake-up.
*/ */
enum ieee80211_sta_info_flags { enum ieee80211_sta_info_flags {
WLAN_STA_AUTH = 1<<0, WLAN_STA_AUTH = 1<<0,
...@@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags { ...@@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags {
WLAN_STA_BLOCK_BA = 1<<11, WLAN_STA_BLOCK_BA = 1<<11,
WLAN_STA_PS_DRIVER = 1<<12, WLAN_STA_PS_DRIVER = 1<<12,
WLAN_STA_PSPOLL = 1<<13, WLAN_STA_PSPOLL = 1<<13,
WLAN_STA_PS_DRIVER_BUF = 1<<14,
}; };
#define STA_TID_NUM 16 #define STA_TID_NUM 16
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment