From: Felix Fietkau Date: Wed, 3 Oct 2012 18:57:31 +0000 (+0000) Subject: ath9k: use ieee80211_free_txskb, might fix hostapd stability issues X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=15c884fdb2b8c604d816e22a4f983653aee7c6df;p=openwrt%2Fstaging%2Frobimarko.git ath9k: use ieee80211_free_txskb, might fix hostapd stability issues SVN-Revision: 33611 --- diff --git a/package/mac80211/patches/566-ath9k_use_ieee80211_free_txskb.patch b/package/mac80211/patches/566-ath9k_use_ieee80211_free_txskb.patch new file mode 100644 index 0000000000..dd484662b4 --- /dev/null +++ b/package/mac80211/patches/566-ath9k_use_ieee80211_free_txskb.patch @@ -0,0 +1,149 @@ +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -66,8 +66,7 @@ static void ath_tx_update_baw(struct ath + static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, + struct ath_txq *txq, + struct ath_atx_tid *tid, +- struct sk_buff *skb, +- bool dequeue); ++ struct sk_buff *skb); + + enum { + MCS_HT20, +@@ -176,7 +175,15 @@ static void ath_tx_flush_tid(struct ath_ + fi = get_frame_info(skb); + bf = fi->bf; + +- if (bf && fi->retries) { ++ if (!bf) { ++ bf = ath_tx_setup_buffer(sc, txq, tid, skb); ++ if (!bf) { ++ ieee80211_free_txskb(sc->hw, skb); ++ continue; ++ } ++ } ++ ++ if (fi->retries) { + list_add_tail(&bf->list, &bf_head); + ath_tx_update_baw(sc, tid, bf->bf_state.seqno); + ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); +@@ -785,10 +792,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_ + fi = get_frame_info(skb); + bf = fi->bf; + if (!fi->bf) +- bf = ath_tx_setup_buffer(sc, txq, tid, skb, true); ++ bf = ath_tx_setup_buffer(sc, txq, tid, skb); + +- if (!bf) ++ if (!bf) { ++ __skb_unlink(skb, &tid->buf_q); ++ ieee80211_free_txskb(sc->hw, skb); + continue; ++ } + + bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; + seqno = bf->bf_state.seqno; +@@ -1731,9 +1741,11 @@ static void ath_tx_send_ampdu(struct ath + return; + } + +- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); +- if (!bf) ++ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); ++ if (!bf) { ++ ieee80211_free_txskb(sc->hw, skb); + return; ++ } + + bf->bf_state.bf_type = BUF_AMPDU; + INIT_LIST_HEAD(&bf_head); +@@ -1757,11 +1769,6 @@ static void ath_tx_send_normal(struct at + struct ath_buf *bf; + + bf = fi->bf; +- if (!bf) +- bf = ath_tx_setup_buffer(sc, txq, tid, skb, false); +- +- if (!bf) +- return; + + INIT_LIST_HEAD(&bf_head); + list_add_tail(&bf->list, &bf_head); +@@ -1835,8 +1842,7 @@ u8 ath_txchainmask_reduction(struct ath_ + static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, + struct ath_txq *txq, + struct ath_atx_tid *tid, +- struct sk_buff *skb, +- bool dequeue) ++ struct sk_buff *skb) + { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_frame_info *fi = get_frame_info(skb); +@@ -1848,7 +1854,7 @@ static struct ath_buf *ath_tx_setup_buff + bf = ath_tx_get_buffer(sc); + if (!bf) { + ath_dbg(common, XMIT, "TX buffers are full\n"); +- goto error; ++ return NULL; + } + + ATH_TXBUF_RESET(bf); +@@ -1877,18 +1883,12 @@ static struct ath_buf *ath_tx_setup_buff + ath_err(ath9k_hw_common(sc->sc_ah), + "dma_mapping_error() on TX\n"); + ath_tx_return_buffer(sc, bf); +- goto error; ++ return NULL; + } + + fi->bf = bf; + + return bf; +- +-error: +- if (dequeue) +- __skb_unlink(skb, &tid->buf_q); +- dev_kfree_skb_any(skb); +- return NULL; + } + + /* FIXME: tx power */ +@@ -1917,9 +1917,14 @@ static void ath_tx_start_dma(struct ath_ + */ + ath_tx_send_ampdu(sc, tid, skb, txctl); + } else { +- bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); +- if (!bf) ++ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); ++ if (!bf) { ++ if (txctl->paprd) ++ dev_kfree_skb_any(skb); ++ else ++ ieee80211_free_txskb(sc->hw, skb); + return; ++ } + + bf->bf_state.bfs_paprd = txctl->paprd; + +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -775,7 +775,7 @@ static void ath9k_tx(struct ieee80211_hw + + return; + exit: +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + } + + static void ath9k_stop(struct ieee80211_hw *hw) +--- a/drivers/net/wireless/ath/ath9k/beacon.c ++++ b/drivers/net/wireless/ath/ath9k/beacon.c +@@ -120,7 +120,7 @@ static void ath9k_tx_cabq(struct ieee802 + + if (ath_tx_start(hw, skb, &txctl) != 0) { + ath_dbg(common, XMIT, "CABQ TX failed\n"); +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + } + } +