Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca369eb4 authored by Vasanthakumar Thiagarajan's avatar Vasanthakumar Thiagarajan Committed by John W. Linville
Browse files

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: default avatarVasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 75f64dd5
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
};
@@ -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);

+3 −2
Original line number Diff line number Diff line
@@ -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))
@@ -334,6 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work)
		ath_paprd_activate(sc);
	}

fail_paprd:
	ath9k_ps_restore(sc);
}

+10 −2
Original line number Diff line number Diff line
@@ -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);
@@ -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) {
		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);