From a4e0b4cc115c938f75ca7cf24b0a739da846a6c7 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sun, 7 Aug 2011 19:36:07 -0400 Subject: [PATCH] ath5k: fix error handling in ath5k_beacon_send commit bdc71bc59231f5542af13b5061b9ab124d093050 upstream. 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. Signed-off-by: Bob Copeland Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/ath5k/base.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b6c5d3715b96..1ae8913c085c 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]); -- 2.39.5