Fix up error path handling after the recent churn.
* Don't free the mbuf in the tx path - it uses the transmit path now, so the caller frees the mbuf. * Don't decrement the node ref upon error - that's up to the caller to do as well. Tested: * Intel 5300 3x3 wifi, station mode Noticed by: <s3erios@gmail.com>
This commit is contained in:
+8
-10
@@ -4368,7 +4368,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
|||||||
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
|
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
|
||||||
|
|
||||||
if (!IEEE80211_AMPDU_RUNNING(tap)) {
|
if (!IEEE80211_AMPDU_RUNNING(tap)) {
|
||||||
m_freem(m);
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4420,7 +4419,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
|||||||
/* Retrieve key for TX. */
|
/* Retrieve key for TX. */
|
||||||
k = ieee80211_crypto_encap(ni, m);
|
k = ieee80211_crypto_encap(ni, m);
|
||||||
if (k == NULL) {
|
if (k == NULL) {
|
||||||
m_freem(m);
|
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
}
|
}
|
||||||
/* 802.11 header may have moved. */
|
/* 802.11 header may have moved. */
|
||||||
@@ -4551,7 +4549,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
|||||||
if (error != EFBIG) {
|
if (error != EFBIG) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: can't map mbuf (error %d)\n", __func__, error);
|
"%s: can't map mbuf (error %d)\n", __func__, error);
|
||||||
m_freem(m);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
/* Too many DMA segments, linearize mbuf. */
|
/* Too many DMA segments, linearize mbuf. */
|
||||||
@@ -4559,7 +4556,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
|||||||
if (m1 == NULL) {
|
if (m1 == NULL) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: could not defrag mbuf\n", __func__);
|
"%s: could not defrag mbuf\n", __func__);
|
||||||
m_freem(m);
|
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
}
|
}
|
||||||
m = m1;
|
m = m1;
|
||||||
@@ -4569,7 +4565,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
|||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: can't map mbuf (error %d)\n", __func__, error);
|
"%s: can't map mbuf (error %d)\n", __func__, error);
|
||||||
m_freem(m);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4755,7 +4750,6 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
|
|||||||
if (error != EFBIG) {
|
if (error != EFBIG) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: can't map mbuf (error %d)\n", __func__, error);
|
"%s: can't map mbuf (error %d)\n", __func__, error);
|
||||||
m_freem(m);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
/* Too many DMA segments, linearize mbuf. */
|
/* Too many DMA segments, linearize mbuf. */
|
||||||
@@ -4763,7 +4757,6 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
|
|||||||
if (m1 == NULL) {
|
if (m1 == NULL) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: could not defrag mbuf\n", __func__);
|
"%s: could not defrag mbuf\n", __func__);
|
||||||
m_freem(m);
|
|
||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
}
|
}
|
||||||
m = m1;
|
m = m1;
|
||||||
@@ -4773,7 +4766,6 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
|
|||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: can't map mbuf (error %d)\n", __func__, error);
|
"%s: can't map mbuf (error %d)\n", __func__, error);
|
||||||
m_freem(m);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4869,6 +4861,9 @@ iwn_xmit_task(void *arg0, int pending)
|
|||||||
IWN_UNLOCK(sc);
|
IWN_UNLOCK(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* raw frame xmit - free node/reference if failed.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||||
const struct ieee80211_bpf_params *params)
|
const struct ieee80211_bpf_params *params)
|
||||||
@@ -4931,6 +4926,9 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* transmit - don't free mbuf if failed; don't free node ref if failed.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
iwn_transmit(struct ieee80211com *ic, struct mbuf *m)
|
iwn_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||||
{
|
{
|
||||||
@@ -4938,6 +4936,8 @@ iwn_transmit(struct ieee80211com *ic, struct mbuf *m)
|
|||||||
struct ieee80211_node *ni;
|
struct ieee80211_node *ni;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||||
|
|
||||||
IWN_LOCK(sc);
|
IWN_LOCK(sc);
|
||||||
if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0 || sc->sc_beacon_wait) {
|
if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0 || sc->sc_beacon_wait) {
|
||||||
IWN_UNLOCK(sc);
|
IWN_UNLOCK(sc);
|
||||||
@@ -4949,11 +4949,9 @@ iwn_transmit(struct ieee80211com *ic, struct mbuf *m)
|
|||||||
return (ENOBUFS);
|
return (ENOBUFS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
|
||||||
error = iwn_tx_data(sc, m, ni);
|
error = iwn_tx_data(sc, m, ni);
|
||||||
if (error) {
|
if (error) {
|
||||||
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
|
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
|
||||||
ieee80211_free_node(ni);
|
|
||||||
} else
|
} else
|
||||||
sc->sc_tx_timer = 5;
|
sc->sc_tx_timer = 5;
|
||||||
IWN_UNLOCK(sc);
|
IWN_UNLOCK(sc);
|
||||||
|
|||||||
Reference in New Issue
Block a user