aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2009-01-27 03:00:37 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-01-30 13:38:24 -0500
commit1286ec6d63c557aa203ab5af56962a3d37181771 (patch)
tree26b501e0bdf5d64962175cce852330ffd38dde48 /drivers/net/wireless/ath9k
parent1f7d6cbfa2a993ea0d714e8552c784eea75a046b (diff)
ath9k: Fix station access in aggregation completion
The ieee80211_sta pointer in the SKB's TX control info area is not guaranteed to be valid after returning from the tx() callback. Use ieee80211_find_sta() instead and return early if the station is no longer present. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k')
-rw-r--r--drivers/net/wireless/ath9k/xmit.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 1b83673c3df6..007ca91188d1 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -268,7 +268,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
268{ 268{
269 struct ath_node *an = NULL; 269 struct ath_node *an = NULL;
270 struct sk_buff *skb; 270 struct sk_buff *skb;
271 struct ieee80211_tx_info *tx_info; 271 struct ieee80211_sta *sta;
272 struct ieee80211_hdr *hdr;
272 struct ath_atx_tid *tid = NULL; 273 struct ath_atx_tid *tid = NULL;
273 struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; 274 struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
274 struct ath_desc *ds = bf_last->bf_desc; 275 struct ath_desc *ds = bf_last->bf_desc;
@@ -278,13 +279,19 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
278 int isaggr, txfail, txpending, sendbar = 0, needreset = 0; 279 int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
279 280
280 skb = (struct sk_buff *)bf->bf_mpdu; 281 skb = (struct sk_buff *)bf->bf_mpdu;
281 tx_info = IEEE80211_SKB_CB(skb); 282 hdr = (struct ieee80211_hdr *)skb->data;
282 283
283 if (tx_info->control.sta) { 284 rcu_read_lock();
284 an = (struct ath_node *)tx_info->control.sta->drv_priv; 285
285 tid = ATH_AN_2_TID(an, bf->bf_tidno); 286 sta = ieee80211_find_sta(sc->hw, hdr->addr1);
287 if (!sta) {
288 rcu_read_unlock();
289 return;
286 } 290 }
287 291
292 an = (struct ath_node *)sta->drv_priv;
293 tid = ATH_AN_2_TID(an, bf->bf_tidno);
294
288 isaggr = bf_isaggr(bf); 295 isaggr = bf_isaggr(bf);
289 memset(ba, 0, WME_BA_BMP_SIZE >> 3); 296 memset(ba, 0, WME_BA_BMP_SIZE >> 3);
290 297
@@ -391,6 +398,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
391 /* send buffered frames as singles */ 398 /* send buffered frames as singles */
392 ath_tx_flush_tid(sc, tid); 399 ath_tx_flush_tid(sc, tid);
393 } 400 }
401 rcu_read_unlock();
394 return; 402 return;
395 } 403 }
396 404
@@ -402,6 +410,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
402 spin_unlock_bh(&txq->axq_lock); 410 spin_unlock_bh(&txq->axq_lock);
403 } 411 }
404 412
413 rcu_read_unlock();
414
405 if (needreset) 415 if (needreset)
406 ath_reset(sc, false); 416 ath_reset(sc, false);
407} 417}