This cleans up error handling for the beacon in case of dma mapping
failure.  We need to free the skb when dma mapping fails instead of
nulling and leaking the pointer, and we should bail out to avoid
giving the hardware the bad descriptor.

Finally, we need to perform the null check after trying to update
the beacon, or else beacons will never be sent after a single
mapping failure.

(Backported from commit bdc71bc59231f5542af13b5061b9ab124d093050.)

Cc: sta...@kernel.org
Signed-off-by: Bob Copeland <m...@bobcopeland.com>
Signed-off-by: John W. Linville <linvi...@tuxdriver.com>
---
On Fri, Aug 12, 2011 at 11:55:24AM -0700, gre...@suse.de wrote:
> 
> The patch below does not apply to the 3.0-stable tree.
> If someone wants it applied there, or to any other stable or longterm
> tree, then please email the backport, including the original git commit
> id to <sta...@kernel.org>.

Hi Greg,

Here's a backport to 3.0.1 - thanks!

 drivers/net/wireless/ath/ath5k/base.c |   23 ++++++++++++++---------
 1 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c 
b/drivers/net/wireless/ath/ath5k/base.c
index b6c5d37..1ae8913 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1748,6 +1748,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct 
ath5k_buf *bf)
 
        if (dma_mapping_error(sc->dev, bf->skbaddr)) {
                ATH5K_ERR(sc, "beacon DMA mapping failed\n");
+               dev_kfree_skb_any(skb);
+               bf->skb = NULL;
                return -EIO;
        }
 
@@ -1832,8 +1834,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif)
        ath5k_txbuf_free_skb(sc, avf->bbuf);
        avf->bbuf->skb = skb;
        ret = ath5k_beacon_setup(sc, avf->bbuf);
-       if (ret)
-               avf->bbuf->skb = NULL;
 out:
        return ret;
 }
@@ -1854,6 +1854,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
        struct ath5k_vif *avf;
        struct ath5k_buf *bf;
        struct sk_buff *skb;
+       int err;
 
        ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n");
 
@@ -1902,11 +1903,6 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 
        avf = (void *)vif->drv_priv;
        bf = avf->bbuf;
-       if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
-                       sc->opmode == NL80211_IFTYPE_MONITOR)) {
-               ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
-               return;
-       }
 
        /*
         * Stop any current dma and put the new frame on the queue.
@@ -1920,8 +1916,17 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 
        /* refresh the beacon for AP or MESH mode */
        if (sc->opmode == NL80211_IFTYPE_AP ||
-                       sc->opmode == NL80211_IFTYPE_MESH_POINT)
-               ath5k_beacon_update(sc->hw, vif);
+                       sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+               err = ath5k_beacon_update(sc->hw, vif);
+               if (err)
+                       return;
+       }
+
+       if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION ||
+                       sc->opmode == NL80211_IFTYPE_MONITOR)) {
+               ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf->skb);
+               return;
+       }
 
        trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]);
 
-- 
1.7.2.5
-- 
Bob Copeland %% www.bobcopeland.com

_______________________________________________
stable mailing list
stable@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to