Skip to content

Commit

Permalink
ath9k: Fix bug in paprd
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vasanthakumar Thiagarajan authored and John W. Linville committed Jun 24, 2010
1 parent 75f64dd commit ca369eb
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 4 deletions.
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ struct ath_buf_state {
int bfs_retries;
u8 bf_type;
u8 bfs_paprd;
unsigned long bfs_paprd_timestamp;
u32 bfs_keyix;
enum ath9k_key_type bfs_keytype;
};
Expand Down Expand Up @@ -425,6 +426,8 @@ int ath_beaconq_config(struct ath_softc *sc);
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */

#define ATH_PAPRD_TIMEOUT 100 /* msecs */

void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);

Expand Down
5 changes: 3 additions & 2 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,13 @@ void ath_paprd_calibrate(struct work_struct *work)
break;

time_left = wait_for_completion_timeout(&sc->paprd_complete,
100);
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
if (!time_left) {
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on "
"TX chain %d\n",
chain);
break;
goto fail_paprd;
}

if (!ar9003_paprd_is_done(ah))
Expand All @@ -334,6 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work)
ath_paprd_activate(sc);
}

fail_paprd:
ath9k_ps_restore(sc);
}

Expand Down
12 changes: 10 additions & 2 deletions drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
}

bf->bf_state.bfs_paprd = txctl->paprd;
if (txctl->paprd)
bf->bf_state.bfs_paprd_timestamp = jiffies;
bf->bf_flags = setup_tx_flags(skb, use_ldpc);

bf->bf_keytype = get_hw_crypto_keytype(skb);
Expand Down Expand Up @@ -1944,8 +1946,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);

if (bf->bf_state.bfs_paprd) {
sc->paprd_txok = txok;
complete(&sc->paprd_complete);
if (time_after(jiffies,
bf->bf_state.bfs_paprd_timestamp +
msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) {
dev_kfree_skb_any(skb);
} else {
sc->paprd_txok = txok;
complete(&sc->paprd_complete);
}
} else {
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
ath_debug_stat_tx(sc, txq, bf, ts);
Expand Down

0 comments on commit ca369eb

Please sign in to comment.