aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2009-05-18 10:59:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-20 14:46:28 -0400
commit1071db863b129847cedb65339d1e87ecf5952a8b (patch)
treef383e088fe7d19bf4f8a59ada10bcd6deb196464
parent4de2dc74a1c7dedcfbe8290316f1a239a7c86554 (diff)
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: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c54
1 files changed, 40 insertions, 14 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index dbfe9f45050e..fb5193764afa 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -242,8 +242,8 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
242static u64 ath5k_get_tsf(struct ieee80211_hw *hw); 242static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
243static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); 243static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
244static void ath5k_reset_tsf(struct ieee80211_hw *hw); 244static void ath5k_reset_tsf(struct ieee80211_hw *hw);
245static int ath5k_beacon_update(struct ath5k_softc *sc, 245static int ath5k_beacon_update(struct ieee80211_hw *hw,
246 struct sk_buff *skb); 246 struct ieee80211_vif *vif);
247static void ath5k_bss_info_changed(struct ieee80211_hw *hw, 247static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
248 struct ieee80211_vif *vif, 248 struct ieee80211_vif *vif,
249 struct ieee80211_bss_conf *bss_conf, 249 struct ieee80211_bss_conf *bss_conf,
@@ -2127,8 +2127,10 @@ ath5k_beacon_send(struct ath5k_softc *sc)
2127 /* NB: hw still stops DMA, so proceed */ 2127 /* NB: hw still stops DMA, so proceed */
2128 } 2128 }
2129 2129
2130 /* Note: Beacon buffer is updated on beacon_update when mac80211 2130 /* refresh the beacon for AP mode */
2131 * calls config_interface */ 2131 if (sc->opmode == NL80211_IFTYPE_AP)
2132 ath5k_beacon_update(sc->hw, sc->vif);
2133
2132 ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); 2134 ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
2133 ath5k_hw_start_tx_dma(ah, sc->bhalq); 2135 ath5k_hw_start_tx_dma(ah, sc->bhalq);
2134 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", 2136 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
@@ -3047,28 +3049,55 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
3047 ath5k_hw_reset_tsf(sc->ah); 3049 ath5k_hw_reset_tsf(sc->ah);
3048} 3050}
3049 3051
3052/*
3053 * Updates the beacon that is sent by ath5k_beacon_send. For adhoc,
3054 * this is called only once at config_bss time, for AP we do it every
3055 * SWBA interrupt so that the TIM will reflect buffered frames.
3056 *
3057 * Called with the beacon lock.
3058 */
3050static int 3059static int
3051ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb) 3060ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
3052{ 3061{
3053 unsigned long flags;
3054 int ret; 3062 int ret;
3063 struct ath5k_softc *sc = hw->priv;
3064 struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
3065
3066 if (!skb) {
3067 ret = -ENOMEM;
3068 goto out;
3069 }
3055 3070
3056 ath5k_debug_dump_skb(sc, skb, "BC ", 1); 3071 ath5k_debug_dump_skb(sc, skb, "BC ", 1);
3057 3072
3058 spin_lock_irqsave(&sc->block, flags);
3059 ath5k_txbuf_free(sc, sc->bbuf); 3073 ath5k_txbuf_free(sc, sc->bbuf);
3060 sc->bbuf->skb = skb; 3074 sc->bbuf->skb = skb;
3061 ret = ath5k_beacon_setup(sc, sc->bbuf); 3075 ret = ath5k_beacon_setup(sc, sc->bbuf);
3062 if (ret) 3076 if (ret)
3063 sc->bbuf->skb = NULL; 3077 sc->bbuf->skb = NULL;
3078out:
3079 return ret;
3080}
3081
3082/*
3083 * Update the beacon and reconfigure the beacon queues.
3084 */
3085static void
3086ath5k_beacon_reconfig(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
3087{
3088 int ret;
3089 unsigned long flags;
3090 struct ath5k_softc *sc = hw->priv;
3091
3092 spin_lock_irqsave(&sc->block, flags);
3093 ret = ath5k_beacon_update(hw, vif);
3064 spin_unlock_irqrestore(&sc->block, flags); 3094 spin_unlock_irqrestore(&sc->block, flags);
3065 if (!ret) { 3095 if (ret == 0) {
3066 ath5k_beacon_config(sc); 3096 ath5k_beacon_config(sc);
3067 mmiowb(); 3097 mmiowb();
3068 } 3098 }
3069
3070 return ret;
3071} 3099}
3100
3072static void 3101static void
3073set_beacon_filter(struct ieee80211_hw *hw, bool enable) 3102set_beacon_filter(struct ieee80211_hw *hw, bool enable)
3074{ 3103{
@@ -3118,10 +3147,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
3118 (vif->type == NL80211_IFTYPE_ADHOC || 3147 (vif->type == NL80211_IFTYPE_ADHOC ||
3119 vif->type == NL80211_IFTYPE_MESH_POINT || 3148 vif->type == NL80211_IFTYPE_MESH_POINT ||
3120 vif->type == NL80211_IFTYPE_AP)) { 3149 vif->type == NL80211_IFTYPE_AP)) {
3121 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); 3150 ath5k_beacon_reconfig(hw, vif);
3122
3123 if (beacon)
3124 ath5k_beacon_update(sc, beacon);
3125 } 3151 }
3126 3152
3127 unlock: 3153 unlock: