mirror of https://gitee.com/openkylin/linux.git
ath5k: rework beacon configuration
Using the enable_beacon flag allows some simplifications and fixes some corner cases in beacon handling. This change adds a state variable for beaconing in ath5k_beacon_config and handles both enabling and disabling, thus eliminating the need for ath5k_beacon_disable. We also now configure the beacon when any of the beacon parameters change, so ath5k_beacon_reconfig is no longer needed (its mmiowb gets moved to ath5k_beacon_config). Finally, by locking around the whole config function, we don't need to worry about clearing the interrupt mask register before installing the new mask. The upshot is this correctly disables beaconing when the interfaces are taken down, it fixes a potential restarting of beaconing when ath5k_reset() is called, and ensures that updates to the beacon interval take effect immediately. Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
cec8db2301
commit
21800491cc
|
@ -2093,13 +2093,6 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath5k_beacon_disable(struct ath5k_softc *sc)
|
||||
{
|
||||
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
|
||||
ath5k_hw_set_imr(sc->ah, sc->imask);
|
||||
ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmit a beacon frame at SWBA. Dynamic updates to the
|
||||
* frame contents are done as needed and the slot time is
|
||||
|
@ -2293,13 +2286,11 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
|||
struct ath5k_hw *ah = sc->ah;
|
||||
unsigned long flags;
|
||||
|
||||
ath5k_hw_set_imr(ah, 0);
|
||||
spin_lock_irqsave(&sc->block, flags);
|
||||
sc->bmisscount = 0;
|
||||
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
|
||||
|
||||
if (sc->opmode == NL80211_IFTYPE_ADHOC ||
|
||||
sc->opmode == NL80211_IFTYPE_MESH_POINT ||
|
||||
sc->opmode == NL80211_IFTYPE_AP) {
|
||||
if (sc->enable_beacon) {
|
||||
/*
|
||||
* In IBSS mode we use a self-linked tx descriptor and let the
|
||||
* hardware send the beacons automatically. We have to load it
|
||||
|
@ -2312,16 +2303,17 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
|||
sc->imask |= AR5K_INT_SWBA;
|
||||
|
||||
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (ath5k_hw_hasveol(ah)) {
|
||||
spin_lock_irqsave(&sc->block, flags);
|
||||
if (ath5k_hw_hasveol(ah))
|
||||
ath5k_beacon_send(sc);
|
||||
spin_unlock_irqrestore(&sc->block, flags);
|
||||
}
|
||||
} else
|
||||
ath5k_beacon_update_timers(sc, -1);
|
||||
} else {
|
||||
ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
|
||||
}
|
||||
|
||||
ath5k_hw_set_imr(ah, sc->imask);
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&sc->block, flags);
|
||||
}
|
||||
|
||||
static void ath5k_tasklet_beacon(unsigned long data)
|
||||
|
@ -2806,7 +2798,6 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
|
|||
goto end;
|
||||
|
||||
ath5k_hw_set_lladdr(sc->ah, mac);
|
||||
ath5k_beacon_disable(sc);
|
||||
sc->vif = NULL;
|
||||
end:
|
||||
mutex_unlock(&sc->lock);
|
||||
|
@ -3135,25 +3126,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
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);
|
||||
if (ret == 0) {
|
||||
ath5k_beacon_config(sc);
|
||||
mmiowb();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_beacon_filter(struct ieee80211_hw *hw, bool enable)
|
||||
{
|
||||
|
@ -3176,6 +3148,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&sc->lock);
|
||||
if (WARN_ON(sc->vif != vif))
|
||||
|
@ -3201,13 +3174,19 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
AR5K_LED_ASSOC : AR5K_LED_INIT);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON &&
|
||||
(vif->type == NL80211_IFTYPE_ADHOC ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT ||
|
||||
vif->type == NL80211_IFTYPE_AP)) {
|
||||
ath5k_beacon_reconfig(hw, vif);
|
||||
if (changes & BSS_CHANGED_BEACON) {
|
||||
spin_lock_irqsave(&sc->block, flags);
|
||||
ath5k_beacon_update(hw, vif);
|
||||
spin_unlock_irqrestore(&sc->block, flags);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_ENABLED)
|
||||
sc->enable_beacon = bss_conf->enable_beacon;
|
||||
|
||||
if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
|
||||
BSS_CHANGED_BEACON_INT))
|
||||
ath5k_beacon_config(sc);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&sc->lock);
|
||||
}
|
||||
|
|
|
@ -190,6 +190,7 @@ struct ath5k_softc {
|
|||
struct timer_list calib_tim; /* calibration timer */
|
||||
int power_level; /* Requested tx power in dbm */
|
||||
bool assoc; /* assocate state */
|
||||
bool enable_beacon; /* true if beacons are on */
|
||||
};
|
||||
|
||||
#define ath5k_hw_hasbssidmask(_ah) \
|
||||
|
|
Loading…
Reference in New Issue