Commit 1071db86 authored by Bob Copeland's avatar Bob Copeland Committed by John W. Linville

ath5k: update beacons in AP mode

ath5k only generated the beacon when bss_info_changed() was called,
but for AP mode this is not enough, because the TIM IE would never
get updated and consequently PS mode clients wouldn't know about
buffered frames.  Instead, get a new beacon on every SWBA interrupt.
Signed-off-by: default avatarBob Copeland <me@bobcopeland.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 4de2dc74
...@@ -242,8 +242,8 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw, ...@@ -242,8 +242,8 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
static u64 ath5k_get_tsf(struct ieee80211_hw *hw); static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
static void ath5k_reset_tsf(struct ieee80211_hw *hw); static void ath5k_reset_tsf(struct ieee80211_hw *hw);
static int ath5k_beacon_update(struct ath5k_softc *sc, static int ath5k_beacon_update(struct ieee80211_hw *hw,
struct sk_buff *skb); struct ieee80211_vif *vif);
static void ath5k_bss_info_changed(struct ieee80211_hw *hw, static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
...@@ -2127,8 +2127,10 @@ ath5k_beacon_send(struct ath5k_softc *sc) ...@@ -2127,8 +2127,10 @@ ath5k_beacon_send(struct ath5k_softc *sc)
/* NB: hw still stops DMA, so proceed */ /* NB: hw still stops DMA, so proceed */
} }
/* Note: Beacon buffer is updated on beacon_update when mac80211 /* refresh the beacon for AP mode */
* calls config_interface */ if (sc->opmode == NL80211_IFTYPE_AP)
ath5k_beacon_update(sc->hw, sc->vif);
ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
ath5k_hw_start_tx_dma(ah, sc->bhalq); ath5k_hw_start_tx_dma(ah, sc->bhalq);
ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
...@@ -3047,28 +3049,55 @@ ath5k_reset_tsf(struct ieee80211_hw *hw) ...@@ -3047,28 +3049,55 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
ath5k_hw_reset_tsf(sc->ah); ath5k_hw_reset_tsf(sc->ah);
} }
/*
* Updates the beacon that is sent by ath5k_beacon_send. For adhoc,
* this is called only once at config_bss time, for AP we do it every
* SWBA interrupt so that the TIM will reflect buffered frames.
*
* Called with the beacon lock.
*/
static int static int
ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb) ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{ {
unsigned long flags;
int ret; int ret;
struct ath5k_softc *sc = hw->priv;
struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
if (!skb) {
ret = -ENOMEM;
goto out;
}
ath5k_debug_dump_skb(sc, skb, "BC ", 1); ath5k_debug_dump_skb(sc, skb, "BC ", 1);
spin_lock_irqsave(&sc->block, flags);
ath5k_txbuf_free(sc, sc->bbuf); ath5k_txbuf_free(sc, sc->bbuf);
sc->bbuf->skb = skb; sc->bbuf->skb = skb;
ret = ath5k_beacon_setup(sc, sc->bbuf); ret = ath5k_beacon_setup(sc, sc->bbuf);
if (ret) if (ret)
sc->bbuf->skb = NULL; sc->bbuf->skb = NULL;
out:
return ret;
}
/*
* Update the beacon and reconfigure the beacon queues.
*/
static void
ath5k_beacon_reconfig(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
int ret;
unsigned long flags;
struct ath5k_softc *sc = hw->priv;
spin_lock_irqsave(&sc->block, flags);
ret = ath5k_beacon_update(hw, vif);
spin_unlock_irqrestore(&sc->block, flags); spin_unlock_irqrestore(&sc->block, flags);
if (!ret) { if (ret == 0) {
ath5k_beacon_config(sc); ath5k_beacon_config(sc);
mmiowb(); mmiowb();
} }
return ret;
} }
static void static void
set_beacon_filter(struct ieee80211_hw *hw, bool enable) set_beacon_filter(struct ieee80211_hw *hw, bool enable)
{ {
...@@ -3118,10 +3147,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -3118,10 +3147,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
(vif->type == NL80211_IFTYPE_ADHOC || (vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_AP)) { vif->type == NL80211_IFTYPE_AP)) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); ath5k_beacon_reconfig(hw, vif);
if (beacon)
ath5k_beacon_update(sc, beacon);
} }
unlock: unlock:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment