diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 14 | ||||
-rw-r--r-- | include/net/mac80211.h | 34 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 8 |
5 files changed, 42 insertions, 20 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 94d887b65e69..1e8614783181 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -340,7 +340,8 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | |||
340 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 340 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
341 | 341 | ||
342 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); | 342 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); |
343 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); | 343 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
344 | struct ath_node *an); | ||
344 | 345 | ||
345 | /********/ | 346 | /********/ |
346 | /* VIFs */ | 347 | /* VIFs */ |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index edaa7843bf4c..0ebf7321df12 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1833,8 +1833,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, | |||
1833 | switch (cmd) { | 1833 | switch (cmd) { |
1834 | case STA_NOTIFY_SLEEP: | 1834 | case STA_NOTIFY_SLEEP: |
1835 | an->sleeping = true; | 1835 | an->sleeping = true; |
1836 | if (ath_tx_aggr_sleep(sc, an)) | 1836 | ath_tx_aggr_sleep(sta, sc, an); |
1837 | ieee80211_sta_set_tim(sta); | ||
1838 | break; | 1837 | break; |
1839 | case STA_NOTIFY_AWAKE: | 1838 | case STA_NOTIFY_AWAKE: |
1840 | an->sleeping = false; | 1839 | an->sleeping = false; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index f5d4764888b9..c2bfc57958d8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -542,7 +542,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
542 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 542 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
543 | if (!skb_queue_empty(&bf_pending)) { | 543 | if (!skb_queue_empty(&bf_pending)) { |
544 | if (an->sleeping) | 544 | if (an->sleeping) |
545 | ieee80211_sta_set_tim(sta); | 545 | ieee80211_sta_set_buffered(sta, tid->tidno, true); |
546 | 546 | ||
547 | spin_lock_bh(&txq->axq_lock); | 547 | spin_lock_bh(&txq->axq_lock); |
548 | if (clear_filter) | 548 | if (clear_filter) |
@@ -1153,12 +1153,13 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
1153 | ath_tx_flush_tid(sc, txtid); | 1153 | ath_tx_flush_tid(sc, txtid); |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | 1156 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
1157 | struct ath_node *an) | ||
1157 | { | 1158 | { |
1158 | struct ath_atx_tid *tid; | 1159 | struct ath_atx_tid *tid; |
1159 | struct ath_atx_ac *ac; | 1160 | struct ath_atx_ac *ac; |
1160 | struct ath_txq *txq; | 1161 | struct ath_txq *txq; |
1161 | bool buffered = false; | 1162 | bool buffered; |
1162 | int tidno; | 1163 | int tidno; |
1163 | 1164 | ||
1164 | for (tidno = 0, tid = &an->tid[tidno]; | 1165 | for (tidno = 0, tid = &an->tid[tidno]; |
@@ -1172,8 +1173,7 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | |||
1172 | 1173 | ||
1173 | spin_lock_bh(&txq->axq_lock); | 1174 | spin_lock_bh(&txq->axq_lock); |
1174 | 1175 | ||
1175 | if (!skb_queue_empty(&tid->buf_q)) | 1176 | buffered = !skb_queue_empty(&tid->buf_q); |
1176 | buffered = true; | ||
1177 | 1177 | ||
1178 | tid->sched = false; | 1178 | tid->sched = false; |
1179 | list_del(&tid->list); | 1179 | list_del(&tid->list); |
@@ -1184,9 +1184,9 @@ bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | |||
1184 | } | 1184 | } |
1185 | 1185 | ||
1186 | spin_unlock_bh(&txq->axq_lock); | 1186 | spin_unlock_bh(&txq->axq_lock); |
1187 | } | ||
1188 | 1187 | ||
1189 | return buffered; | 1188 | ieee80211_sta_set_buffered(sta, tidno, buffered); |
1189 | } | ||
1190 | } | 1190 | } |
1191 | 1191 | ||
1192 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | 1192 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b5f7ada2f87b..e66638e749c6 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -2361,17 +2361,35 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, | |||
2361 | #define IEEE80211_TX_STATUS_HEADROOM 13 | 2361 | #define IEEE80211_TX_STATUS_HEADROOM 13 |
2362 | 2362 | ||
2363 | /** | 2363 | /** |
2364 | * ieee80211_sta_set_tim - set the TIM bit for a sleeping station | 2364 | * ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames |
2365 | * @sta: &struct ieee80211_sta pointer for the sleeping station | 2365 | * @sta: &struct ieee80211_sta pointer for the sleeping station |
2366 | * @tid: the TID that has buffered frames | ||
2367 | * @buffered: indicates whether or not frames are buffered for this TID | ||
2366 | * | 2368 | * |
2367 | * If a driver buffers frames for a powersave station instead of passing | 2369 | * If a driver buffers frames for a powersave station instead of passing |
2368 | * them back to mac80211 for retransmission, the station needs to be told | 2370 | * them back to mac80211 for retransmission, the station may still need |
2369 | * to wake up using the TIM bitmap in the beacon. | 2371 | * to be told that there are buffered frames via the TIM bit. |
2370 | * | 2372 | * |
2371 | * This function sets the station's TIM bit - it will be cleared when the | 2373 | * This function informs mac80211 whether or not there are frames that are |
2372 | * station wakes up. | 2374 | * buffered in the driver for a given TID; mac80211 can then use this data |
2373 | */ | 2375 | * to set the TIM bit (NOTE: This may call back into the driver's set_tim |
2374 | void ieee80211_sta_set_tim(struct ieee80211_sta *sta); | 2376 | * call! Beware of the locking!) |
2377 | * | ||
2378 | * If all frames are released to the station (due to PS-poll or uAPSD) | ||
2379 | * then the driver needs to inform mac80211 that there no longer are | ||
2380 | * frames buffered. However, when the station wakes up mac80211 assumes | ||
2381 | * that all buffered frames will be transmitted and clears this data, | ||
2382 | * drivers need to make sure they inform mac80211 about all buffered | ||
2383 | * frames on the sleep transition (sta_notify() with %STA_NOTIFY_SLEEP). | ||
2384 | * | ||
2385 | * Note that technically mac80211 only needs to know this per AC, not per | ||
2386 | * TID, but since driver buffering will inevitably happen per TID (since | ||
2387 | * it is related to aggregation) it is easier to make mac80211 map the | ||
2388 | * TID to the AC as required instead of keeping track in all drivers that | ||
2389 | * use this API. | ||
2390 | */ | ||
2391 | void ieee80211_sta_set_buffered(struct ieee80211_sta *sta, | ||
2392 | u8 tid, bool buffered); | ||
2375 | 2393 | ||
2376 | /** | 2394 | /** |
2377 | * ieee80211_tx_status - transmit status callback | 2395 | * ieee80211_tx_status - transmit status callback |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c52e58c0a979..016742d4c48e 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1117,11 +1117,15 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
1117 | } | 1117 | } |
1118 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 1118 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
1119 | 1119 | ||
1120 | void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) | 1120 | void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta, |
1121 | u8 tid, bool buffered) | ||
1121 | { | 1122 | { |
1122 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 1123 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
1123 | 1124 | ||
1125 | if (!buffered) | ||
1126 | return; | ||
1127 | |||
1124 | set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); | 1128 | set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); |
1125 | sta_info_set_tim_bit(sta); | 1129 | sta_info_set_tim_bit(sta); |
1126 | } | 1130 | } |
1127 | EXPORT_SYMBOL(ieee80211_sta_set_tim); | 1131 | EXPORT_SYMBOL(ieee80211_sta_set_buffered); |