aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c14
-rw-r--r--include/net/mac80211.h34
-rw-r--r--net/mac80211/sta_info.c8
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);
340void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); 340void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
341 341
342void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); 342void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an);
343bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); 343void 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
1156bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) 1156void 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
1192void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) 1192void 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
2374void 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 */
2391void 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}
1118EXPORT_SYMBOL(ieee80211_sta_block_awake); 1118EXPORT_SYMBOL(ieee80211_sta_block_awake);
1119 1119
1120void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) 1120void 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}
1127EXPORT_SYMBOL(ieee80211_sta_set_tim); 1131EXPORT_SYMBOL(ieee80211_sta_set_buffered);