|
@@ -237,8 +237,7 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
|
|
struct ieee80211_tx_queue_stats *stats);
|
|
|
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
|
|
|
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
|
|
|
-static int ath5k_beacon_update(struct ieee80211_hw *hw,
|
|
|
- struct sk_buff *skb);
|
|
|
+static int ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb);
|
|
|
|
|
|
static struct ieee80211_ops ath5k_hw_ops = {
|
|
|
.tx = ath5k_tx,
|
|
@@ -2137,8 +2136,6 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
|
|
|
*
|
|
|
* In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
|
|
|
* interrupts to detect TSF updates only.
|
|
|
- *
|
|
|
- * AP mode is missing.
|
|
|
*/
|
|
|
static void
|
|
|
ath5k_beacon_config(struct ath5k_softc *sc)
|
|
@@ -2151,7 +2148,8 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
|
|
|
|
|
if (sc->opmode == NL80211_IFTYPE_STATION) {
|
|
|
sc->imask |= AR5K_INT_BMISS;
|
|
|
- } else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
|
|
|
+ } else if (sc->opmode == NL80211_IFTYPE_ADHOC ||
|
|
|
+ sc->opmode == NL80211_IFTYPE_AP) {
|
|
|
/*
|
|
|
* In IBSS mode we use a self-linked tx descriptor and let the
|
|
|
* hardware send the beacons automatically. We have to load it
|
|
@@ -2163,13 +2161,15 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
|
|
|
|
|
sc->imask |= AR5K_INT_SWBA;
|
|
|
|
|
|
- if (ath5k_hw_hasveol(ah)) {
|
|
|
- spin_lock(&sc->block);
|
|
|
- ath5k_beacon_send(sc);
|
|
|
- spin_unlock(&sc->block);
|
|
|
- }
|
|
|
+ if (sc->opmode == NL80211_IFTYPE_ADHOC) {
|
|
|
+ if (ath5k_hw_hasveol(ah)) {
|
|
|
+ spin_lock(&sc->block);
|
|
|
+ ath5k_beacon_send(sc);
|
|
|
+ spin_unlock(&sc->block);
|
|
|
+ }
|
|
|
+ } else
|
|
|
+ ath5k_beacon_update_timers(sc, -1);
|
|
|
}
|
|
|
- /* TODO else AP */
|
|
|
|
|
|
ath5k_hw_set_imr(ah, sc->imask);
|
|
|
}
|
|
@@ -2740,6 +2740,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
|
|
|
sc->vif = conf->vif;
|
|
|
|
|
|
switch (conf->type) {
|
|
|
+ case NL80211_IFTYPE_AP:
|
|
|
case NL80211_IFTYPE_STATION:
|
|
|
case NL80211_IFTYPE_ADHOC:
|
|
|
case NL80211_IFTYPE_MONITOR:
|
|
@@ -2803,7 +2804,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
|
ret = -EIO;
|
|
|
goto unlock;
|
|
|
}
|
|
|
- if (conf->bssid) {
|
|
|
+ if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
|
|
|
/* Cache for later use during resets */
|
|
|
memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN);
|
|
|
/* XXX: assoc id is set to 0 for now, mac80211 doesn't have
|
|
@@ -2811,18 +2812,16 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
|
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
|
|
|
mmiowb();
|
|
|
}
|
|
|
-
|
|
|
if (conf->changed & IEEE80211_IFCC_BEACON &&
|
|
|
- vif->type == NL80211_IFTYPE_ADHOC) {
|
|
|
+ (vif->type == NL80211_IFTYPE_ADHOC ||
|
|
|
+ vif->type == NL80211_IFTYPE_AP)) {
|
|
|
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
|
|
|
if (!beacon) {
|
|
|
ret = -ENOMEM;
|
|
|
goto unlock;
|
|
|
}
|
|
|
- /* call old handler for now */
|
|
|
- ath5k_beacon_update(hw, beacon);
|
|
|
+ ath5k_beacon_update(sc, beacon);
|
|
|
}
|
|
|
-
|
|
|
mutex_unlock(&sc->lock);
|
|
|
|
|
|
return ath5k_reset_wake(sc);
|
|
@@ -3052,19 +3051,13 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|
|
+ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb)
|
|
|
{
|
|
|
- struct ath5k_softc *sc = hw->priv;
|
|
|
unsigned long flags;
|
|
|
int ret;
|
|
|
|
|
|
ath5k_debug_dump_skb(sc, skb, "BC ", 1);
|
|
|
|
|
|
- if (sc->opmode != NL80211_IFTYPE_ADHOC) {
|
|
|
- ret = -EIO;
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
spin_lock_irqsave(&sc->block, flags);
|
|
|
ath5k_txbuf_free(sc, sc->bbuf);
|
|
|
sc->bbuf->skb = skb;
|
|
@@ -3077,7 +3070,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|
|
mmiowb();
|
|
|
}
|
|
|
|
|
|
-end:
|
|
|
return ret;
|
|
|
}
|
|
|
|