diff options
author | adrian <adrian@FreeBSD.org> | 2015-10-12 03:27:08 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2015-10-12 03:27:08 +0000 |
commit | 9c9f0d74e16010325bf5e43d168ce604b10a6943 (patch) | |
tree | 1b2473150d991e361c2b7c638b1825555a2fff7c | |
parent | 2b83d5a980404ddde25f082a1515d59a921b7f4b (diff) | |
download | FreeBSD-src-9c9f0d74e16010325bf5e43d168ce604b10a6943.zip FreeBSD-src-9c9f0d74e16010325bf5e43d168ce604b10a6943.tar.gz |
net80211: separate mbuf cleanup from ieee80211_fragment()
* Create ieee80211_free_mbuf() which frees a list of mbufs.
* Use it in the fragment transmit path and ath / uath transmit paths.
* Call it in xmit_pkt() if the transmission fails; otherwise fragments
may be leaked.
This should be a big no-op.
Submitted by: <s3erios@gmail.com>
Differential Revision: https://reviews.freebsd.org/D3769
-rw-r--r-- | sys/dev/ath/if_ath.c | 4 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_tx.c | 32 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_tx.h | 1 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_uath.c | 20 | ||||
-rw-r--r-- | sys/net80211/ieee80211_freebsd.c | 2 | ||||
-rw-r--r-- | sys/net80211/ieee80211_output.c | 23 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.h | 1 |
7 files changed, 31 insertions, 52 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 8ba0958..4166bb7 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -3262,7 +3262,7 @@ ath_transmit(struct ieee80211com *ic, struct mbuf *m) * XXXGL: is mbuf valid after ath_txfrag_setup? If yes, * we shouldn't free it but return back. */ - ath_freetx(m); + ieee80211_free_mbuf(m); m = NULL; goto bad; } @@ -3356,7 +3356,7 @@ reclaim: __func__, ieee80211_state_name[ni->ni_vap->iv_state]); /* XXX dmamap */ - ath_freetx(next); + ieee80211_free_mbuf(next); goto reclaim; } m = next; diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index bee6320..27a17d2 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -283,22 +283,6 @@ ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, return !TAILQ_EMPTY(frags); } -/* - * Reclaim mbuf resources. For fragmented frames we - * need to claim each frag chained with m_nextpkt. - */ -void -ath_freetx(struct mbuf *m) -{ - struct mbuf *next; - - do { - next = m->m_nextpkt; - m->m_nextpkt = NULL; - m_freem(m); - } while ((m = next) != NULL); -} - static int ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) { @@ -317,7 +301,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) bf->bf_nseg = ATH_MAX_SCATTER + 1; } else if (error != 0) { sc->sc_stats.ast_tx_busdma++; - ath_freetx(m0); + ieee80211_free_mbuf(m0); return error; } /* @@ -329,7 +313,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) sc->sc_stats.ast_tx_linear++; m = m_collapse(m0, M_NOWAIT, ATH_MAX_SCATTER); if (m == NULL) { - ath_freetx(m0); + ieee80211_free_mbuf(m0); sc->sc_stats.ast_tx_nombuf++; return ENOMEM; } @@ -339,14 +323,14 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) BUS_DMA_NOWAIT); if (error != 0) { sc->sc_stats.ast_tx_busdma++; - ath_freetx(m0); + ieee80211_free_mbuf(m0); return error; } KASSERT(bf->bf_nseg <= ATH_MAX_SCATTER, ("too many segments after defrag; nseg %u", bf->bf_nseg)); } else if (bf->bf_nseg == 0) { /* null packet, discard */ sc->sc_stats.ast_tx_nodata++; - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n", @@ -1581,7 +1565,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, /* Handle encryption twiddling if needed */ if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) { - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } @@ -1693,7 +1677,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); /* XXX statistic */ /* XXX free tx dmamap */ - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } @@ -1749,7 +1733,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, "%s: discard frame, ACK required w/ TDMA\n", __func__); sc->sc_stats.ast_tdma_ack++; /* XXX free tx dmamap */ - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } #endif @@ -2133,7 +2117,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, &hdrlen, &pktlen, &keyix)) { - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } /* packet header may have moved, reset our local pointer */ diff --git a/sys/dev/ath/if_ath_tx.h b/sys/dev/ath/if_ath_tx.h index 281dbcb..19f7707 100644 --- a/sys/dev/ath/if_ath_tx.h +++ b/sys/dev/ath/if_ath_tx.h @@ -85,7 +85,6 @@ */ #define ATH_AGGR_MAXSIZE 65530 -extern void ath_freetx(struct mbuf *m); extern void ath_tx_node_flush(struct ath_softc *sc, struct ath_node *an); extern void ath_tx_txq_drain(struct ath_softc *sc, struct ath_txq *txq); extern void ath_txfrag_cleanup(struct ath_softc *sc, ath_bufhead *frags, diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 39fa71b..292bb9f 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -1663,22 +1663,6 @@ uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags, return !STAILQ_EMPTY(frags); } -/* - * Reclaim mbuf resources. For fragmented frames we need to claim each frag - * chained with m_nextpkt. - */ -static void -uath_freetx(struct mbuf *m) -{ - struct mbuf *next; - - do { - next = m->m_nextpkt; - m->m_nextpkt = NULL; - m_freem(m); - } while ((m = next) != NULL); -} - static int uath_transmit(struct ieee80211com *ic, struct mbuf *m) { @@ -1735,7 +1719,7 @@ uath_start(struct uath_softc *sc) !uath_txfrag_setup(sc, &frags, m, ni)) { DPRINTF(sc, UATH_DEBUG_XMIT, "%s: out of txfrag buffers\n", __func__); - uath_freetx(m); + ieee80211_free_mbuf(m); goto bad; } sc->sc_seqnum = 0; @@ -1770,7 +1754,7 @@ uath_start(struct uath_softc *sc) "%s: flush fragmented packet, state %s\n", __func__, ieee80211_state_name[ni->ni_vap->iv_state]); - uath_freetx(next); + ieee80211_free_mbuf(next); goto reclaim; } m = next; diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 6fdfb5c..5b2c103 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -545,7 +545,7 @@ ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m) IEEE80211_TX_LOCK_ASSERT(ic); error = ic->ic_transmit(ic, m); if (error) - m_freem(m); + ieee80211_free_mbuf(m); return (error); } diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 19af613..149b726 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -1583,6 +1583,21 @@ bad: #undef MC01 } +void +ieee80211_free_mbuf(struct mbuf *m) +{ + struct mbuf *next; + + if (m == NULL) + return; + + do { + next = m->m_nextpkt; + m->m_nextpkt = NULL; + m_freem(m); + } while ((m = next) != NULL); +} + /* * Fragment the frame according to the specified mtu. * The size of the 802.11 header (w/o padding) is provided @@ -1597,7 +1612,7 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0, { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_frame *wh, *whf; - struct mbuf *m, *prev, *next; + struct mbuf *m, *prev; u_int totalhdrsize, fragno, fragsize, off, remainder, payload; u_int hdrspace; @@ -1692,11 +1707,7 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0, return 1; bad: /* reclaim fragments but leave original frame for caller to free */ - for (m = m0->m_nextpkt; m != NULL; m = next) { - next = m->m_nextpkt; - m->m_nextpkt = NULL; /* XXX paranoid */ - m_freem(m); - } + ieee80211_free_mbuf(m0->m_nextpkt); m0->m_nextpkt = NULL; return 0; } diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 4305863..38bd3d6 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -93,6 +93,7 @@ struct mbuf *ieee80211_mbuf_adjust(struct ieee80211vap *, int, struct ieee80211_key *, struct mbuf *); struct mbuf *ieee80211_encap(struct ieee80211vap *, struct ieee80211_node *, struct mbuf *); +void ieee80211_free_mbuf(struct mbuf *); int ieee80211_send_mgmt(struct ieee80211_node *, int, int); struct ieee80211_appie; int ieee80211_send_probereq(struct ieee80211_node *ni, |