aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-06 05:35:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-06 16:49:10 -0500
commitaf81858172cc0f3da81946aab919c26e4b364efc (patch)
tree8e7a4bf30ff7c23636d810c5a912ff7e3ddb7333 /net/mac80211/main.c
parent70d9f405d09e334b609702d88ee03b6119c4b45e (diff)
mac80211: async station powersave handling
Some devices require that all frames to a station are flushed when that station goes into powersave mode before being able to send frames to that station again when it wakes up or polls -- all in order to avoid reordering and too many or too few frames being sent to the station when it polls. Normally, this is the case unless the station goes to sleep and wakes up very quickly again. But in that case, frames for it may be pending on the hardware queues, and thus races could happen in the case of multiple hardware queues used for QoS/WMM. Normally this isn't a problem, but with the iwlwifi mechanism we need to make sure the race doesn't happen. This makes mac80211 able to cope with the race with driver help by a new WLAN_STA_PS_DRIVER per-station flag that can be controlled by the driver and tells mac80211 whether it can transmit frames or not. This flag must be set according to very specific rules outlined in the documentation for the function that controls it. When we buffer new frames for the station, we normally set the TIM bit right away, but while the driver has blocked transmission to that sta we need to avoid that as well since we cannot respond to the station if it wakes up due to the TIM bit. Once the driver unblocks, we can set the TIM bit. Similarly, when the station just wakes up, we need to wait until all other frames are flushed before we can transmit frames to that station, so the same applies here, we need to wait for the driver to give the OK. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 9e6703ff7fbb..beb8718d905e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -385,13 +385,13 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
385 * can be unknown, for example with different interrupt status 385 * can be unknown, for example with different interrupt status
386 * bits. 386 * bits.
387 */ 387 */
388 if (test_sta_flags(sta, WLAN_STA_PS) && 388 if (test_sta_flags(sta, WLAN_STA_PS_STA) &&
389 skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { 389 skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
390 skb_queue_tail(&sta->tx_filtered, skb); 390 skb_queue_tail(&sta->tx_filtered, skb);
391 return; 391 return;
392 } 392 }
393 393
394 if (!test_sta_flags(sta, WLAN_STA_PS) && 394 if (!test_sta_flags(sta, WLAN_STA_PS_STA) &&
395 !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { 395 !(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
396 /* Software retry the packet once */ 396 /* Software retry the packet once */
397 info->flags |= IEEE80211_TX_INTFL_RETRIED; 397 info->flags |= IEEE80211_TX_INTFL_RETRIED;
@@ -406,7 +406,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
406 "queue_len=%d PS=%d @%lu\n", 406 "queue_len=%d PS=%d @%lu\n",
407 wiphy_name(local->hw.wiphy), 407 wiphy_name(local->hw.wiphy),
408 skb_queue_len(&sta->tx_filtered), 408 skb_queue_len(&sta->tx_filtered),
409 !!test_sta_flags(sta, WLAN_STA_PS), jiffies); 409 !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies);
410#endif 410#endif
411 dev_kfree_skb(skb); 411 dev_kfree_skb(skb);
412} 412}
@@ -446,7 +446,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
446 446
447 if (sta) { 447 if (sta) {
448 if (!(info->flags & IEEE80211_TX_STAT_ACK) && 448 if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
449 test_sta_flags(sta, WLAN_STA_PS)) { 449 test_sta_flags(sta, WLAN_STA_PS_STA)) {
450 /* 450 /*
451 * The STA is in power save mode, so assume 451 * The STA is in power save mode, so assume
452 * that this TX packet failed because of that. 452 * that this TX packet failed because of that.