ath: fix ath_buf leak if ath_tx_tag_crypto() returns an error
If ath_tx_tag_crypto() returns an error, then ath_tx_normal_setup() should consume the mbuf and return an error, so the caller knows to free the ath_buf. But it wasn't. This fixes issues I've seen locally where a an AP VAP constantly hits error conditions (due to other RF/PHY/MAC chipset issues which I haven't yet figured out) and encryption fails because the station goes away whilst something's being queued. Locally tested: * AR9380, AP mode (2G HT20, 5G HT20, 5G HT40)
This commit is contained in:
+11
-3
@@ -971,6 +971,12 @@ ath_legacy_xmit_handoff(struct ath_softc *sc, struct ath_txq *txq,
|
||||
ath_tx_handoff_hw(sc, txq, bf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup a frame for encryption.
|
||||
*
|
||||
* If this fails, then an non-zero error is returned. The mbuf
|
||||
* must be freed by the caller.
|
||||
*/
|
||||
static int
|
||||
ath_tx_tag_crypto(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
struct mbuf *m0, int iswep, int isfrag, int *hdrlen, int *pktlen,
|
||||
@@ -1547,6 +1553,10 @@ ath_tx_xmit_normal(struct ath_softc *sc, struct ath_txq *txq,
|
||||
*
|
||||
* Note that this may cause the mbuf to be reallocated, so
|
||||
* m0 may not be valid.
|
||||
*
|
||||
* If there's a problem then the mbuf is freed and an error
|
||||
* is returned. The ath_buf then needs to be freed by the
|
||||
* caller.
|
||||
*/
|
||||
static int
|
||||
ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
@@ -2073,9 +2083,8 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
|
||||
/* This also sets up the DMA map; crypto; frame parameters, etc */
|
||||
r = ath_tx_normal_setup(sc, ni, bf, m0, txq);
|
||||
|
||||
if (r != 0)
|
||||
goto done;
|
||||
return (r);
|
||||
|
||||
/* At this point m0 could have changed! */
|
||||
m0 = bf->bf_m;
|
||||
@@ -2132,7 +2141,6 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
ath_tx_leak_count_update(sc, tid, bf);
|
||||
ath_tx_xmit_normal(sc, txq, bf);
|
||||
#endif
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user