aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vasanth@atheros.com>2010-06-24 05:42:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-24 15:42:39 -0400
commitca369eb494e45a3e3b8960775f88125fe1fbb0f2 (patch)
tree2a53c84c5d848e73a271005df56b754334e5d1a2
parent75f64dd54a185150ebfc45e99351c890d4a2252f (diff)
ath9k: Fix bug in paprd
It is possbile that the transmission of paprd test frame might not get completed in 100ms if tx is stuck. Freeing this skb upon timeout in ath_paprd_calibrate() will result in accessing already freed memory when the associated pending buffer is drained in txq. This patch fixes this issue. Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c12
3 files changed, 16 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 3a14630e808e..ce74af6ef08c 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -226,6 +226,7 @@ struct ath_buf_state {
226 int bfs_retries; 226 int bfs_retries;
227 u8 bf_type; 227 u8 bf_type;
228 u8 bfs_paprd; 228 u8 bfs_paprd;
229 unsigned long bfs_paprd_timestamp;
229 u32 bfs_keyix; 230 u32 bfs_keyix;
230 enum ath9k_key_type bfs_keytype; 231 enum ath9k_key_type bfs_keytype;
231}; 232};
@@ -425,6 +426,8 @@ int ath_beaconq_config(struct ath_softc *sc);
425#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ 426#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
426#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ 427#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
427 428
429#define ATH_PAPRD_TIMEOUT 100 /* msecs */
430
428void ath_paprd_calibrate(struct work_struct *work); 431void ath_paprd_calibrate(struct work_struct *work);
429void ath_ani_calibrate(unsigned long data); 432void ath_ani_calibrate(unsigned long data);
430 433
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 5af259644bf6..c070e01c8de3 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -310,13 +310,13 @@ void ath_paprd_calibrate(struct work_struct *work)
310 break; 310 break;
311 311
312 time_left = wait_for_completion_timeout(&sc->paprd_complete, 312 time_left = wait_for_completion_timeout(&sc->paprd_complete,
313 100); 313 msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
314 if (!time_left) { 314 if (!time_left) {
315 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 315 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
316 "Timeout waiting for paprd training on " 316 "Timeout waiting for paprd training on "
317 "TX chain %d\n", 317 "TX chain %d\n",
318 chain); 318 chain);
319 break; 319 goto fail_paprd;
320 } 320 }
321 321
322 if (!ar9003_paprd_is_done(ah)) 322 if (!ar9003_paprd_is_done(ah))
@@ -334,6 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work)
334 ath_paprd_activate(sc); 334 ath_paprd_activate(sc);
335 } 335 }
336 336
337fail_paprd:
337 ath9k_ps_restore(sc); 338 ath9k_ps_restore(sc);
338} 339}
339 340
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 20221b8c04fd..edbeffb14a1c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1644,6 +1644,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1644 } 1644 }
1645 1645
1646 bf->bf_state.bfs_paprd = txctl->paprd; 1646 bf->bf_state.bfs_paprd = txctl->paprd;
1647 if (txctl->paprd)
1648 bf->bf_state.bfs_paprd_timestamp = jiffies;
1647 bf->bf_flags = setup_tx_flags(skb, use_ldpc); 1649 bf->bf_flags = setup_tx_flags(skb, use_ldpc);
1648 1650
1649 bf->bf_keytype = get_hw_crypto_keytype(skb); 1651 bf->bf_keytype = get_hw_crypto_keytype(skb);
@@ -1944,8 +1946,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
1944 dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); 1946 dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
1945 1947
1946 if (bf->bf_state.bfs_paprd) { 1948 if (bf->bf_state.bfs_paprd) {
1947 sc->paprd_txok = txok; 1949 if (time_after(jiffies,
1948 complete(&sc->paprd_complete); 1950 bf->bf_state.bfs_paprd_timestamp +
1951 msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) {
1952 dev_kfree_skb_any(skb);
1953 } else {
1954 sc->paprd_txok = txok;
1955 complete(&sc->paprd_complete);
1956 }
1949 } else { 1957 } else {
1950 ath_tx_complete(sc, skb, bf->aphy, tx_flags); 1958 ath_tx_complete(sc, skb, bf->aphy, tx_flags);
1951 ath_debug_stat_tx(sc, txq, bf, ts); 1959 ath_debug_stat_tx(sc, txq, bf, ts);