diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2008-10-12 16:54:10 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:00:17 -0400 |
commit | da966bcae70e4012b7d999820b728dd6502047e0 (patch) | |
tree | b746632bc1d67d9cd68e81efd30874669888889d /drivers/net/wireless/ath5k | |
parent | 7eb27af766e4a1db3dbc02a5b3d175885bf2ce93 (diff) |
Ath5k: add AP mode
Add support for AP mode. This involves:
- enablement in ath5k_beacon_config -- initialize beacon timer
- add AP to the supported modes in ath5k_add_interface
- handle beacon change even for AP in ath5k_config_interface
- remove useless test for IBSS in ath5k_beacon_update
Note that it doesn't enable the AP mode for the driver. It must
be enabled by NL80211_IFTYPE_AP bit added to interface_modes.
v2:
Fixed opmode constant (IEEE80211_ to NL80211_)
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Nick Kossifidis <mickflemm@gmail.com>
Cc: Luis R. Rodriguez <mcgrof@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k')
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 42 |
1 files changed, 17 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index fcd688765d04..c98380845fa7 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -237,8 +237,7 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw, | |||
237 | struct ieee80211_tx_queue_stats *stats); | 237 | struct ieee80211_tx_queue_stats *stats); |
238 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | 238 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); |
239 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | 239 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); |
240 | static int ath5k_beacon_update(struct ieee80211_hw *hw, | 240 | static int ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb); |
241 | struct sk_buff *skb); | ||
242 | 241 | ||
243 | static struct ieee80211_ops ath5k_hw_ops = { | 242 | static struct ieee80211_ops ath5k_hw_ops = { |
244 | .tx = ath5k_tx, | 243 | .tx = ath5k_tx, |
@@ -2137,8 +2136,6 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2137 | * | 2136 | * |
2138 | * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA | 2137 | * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA |
2139 | * interrupts to detect TSF updates only. | 2138 | * interrupts to detect TSF updates only. |
2140 | * | ||
2141 | * AP mode is missing. | ||
2142 | */ | 2139 | */ |
2143 | static void | 2140 | static void |
2144 | ath5k_beacon_config(struct ath5k_softc *sc) | 2141 | ath5k_beacon_config(struct ath5k_softc *sc) |
@@ -2151,7 +2148,8 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2151 | 2148 | ||
2152 | if (sc->opmode == NL80211_IFTYPE_STATION) { | 2149 | if (sc->opmode == NL80211_IFTYPE_STATION) { |
2153 | sc->imask |= AR5K_INT_BMISS; | 2150 | sc->imask |= AR5K_INT_BMISS; |
2154 | } else if (sc->opmode == NL80211_IFTYPE_ADHOC) { | 2151 | } else if (sc->opmode == NL80211_IFTYPE_ADHOC || |
2152 | sc->opmode == NL80211_IFTYPE_AP) { | ||
2155 | /* | 2153 | /* |
2156 | * In IBSS mode we use a self-linked tx descriptor and let the | 2154 | * In IBSS mode we use a self-linked tx descriptor and let the |
2157 | * hardware send the beacons automatically. We have to load it | 2155 | * hardware send the beacons automatically. We have to load it |
@@ -2163,13 +2161,15 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2163 | 2161 | ||
2164 | sc->imask |= AR5K_INT_SWBA; | 2162 | sc->imask |= AR5K_INT_SWBA; |
2165 | 2163 | ||
2166 | if (ath5k_hw_hasveol(ah)) { | 2164 | if (sc->opmode == NL80211_IFTYPE_ADHOC) { |
2167 | spin_lock(&sc->block); | 2165 | if (ath5k_hw_hasveol(ah)) { |
2168 | ath5k_beacon_send(sc); | 2166 | spin_lock(&sc->block); |
2169 | spin_unlock(&sc->block); | 2167 | ath5k_beacon_send(sc); |
2170 | } | 2168 | spin_unlock(&sc->block); |
2169 | } | ||
2170 | } else | ||
2171 | ath5k_beacon_update_timers(sc, -1); | ||
2171 | } | 2172 | } |
2172 | /* TODO else AP */ | ||
2173 | 2173 | ||
2174 | ath5k_hw_set_imr(ah, sc->imask); | 2174 | ath5k_hw_set_imr(ah, sc->imask); |
2175 | } | 2175 | } |
@@ -2740,6 +2740,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2740 | sc->vif = conf->vif; | 2740 | sc->vif = conf->vif; |
2741 | 2741 | ||
2742 | switch (conf->type) { | 2742 | switch (conf->type) { |
2743 | case NL80211_IFTYPE_AP: | ||
2743 | case NL80211_IFTYPE_STATION: | 2744 | case NL80211_IFTYPE_STATION: |
2744 | case NL80211_IFTYPE_ADHOC: | 2745 | case NL80211_IFTYPE_ADHOC: |
2745 | case NL80211_IFTYPE_MONITOR: | 2746 | case NL80211_IFTYPE_MONITOR: |
@@ -2803,7 +2804,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
2803 | ret = -EIO; | 2804 | ret = -EIO; |
2804 | goto unlock; | 2805 | goto unlock; |
2805 | } | 2806 | } |
2806 | if (conf->bssid) { | 2807 | if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) { |
2807 | /* Cache for later use during resets */ | 2808 | /* Cache for later use during resets */ |
2808 | memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN); | 2809 | memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN); |
2809 | /* XXX: assoc id is set to 0 for now, mac80211 doesn't have | 2810 | /* 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, | |||
2811 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | 2812 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); |
2812 | mmiowb(); | 2813 | mmiowb(); |
2813 | } | 2814 | } |
2814 | |||
2815 | if (conf->changed & IEEE80211_IFCC_BEACON && | 2815 | if (conf->changed & IEEE80211_IFCC_BEACON && |
2816 | vif->type == NL80211_IFTYPE_ADHOC) { | 2816 | (vif->type == NL80211_IFTYPE_ADHOC || |
2817 | vif->type == NL80211_IFTYPE_AP)) { | ||
2817 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 2818 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
2818 | if (!beacon) { | 2819 | if (!beacon) { |
2819 | ret = -ENOMEM; | 2820 | ret = -ENOMEM; |
2820 | goto unlock; | 2821 | goto unlock; |
2821 | } | 2822 | } |
2822 | /* call old handler for now */ | 2823 | ath5k_beacon_update(sc, beacon); |
2823 | ath5k_beacon_update(hw, beacon); | ||
2824 | } | 2824 | } |
2825 | |||
2826 | mutex_unlock(&sc->lock); | 2825 | mutex_unlock(&sc->lock); |
2827 | 2826 | ||
2828 | return ath5k_reset_wake(sc); | 2827 | return ath5k_reset_wake(sc); |
@@ -3052,19 +3051,13 @@ ath5k_reset_tsf(struct ieee80211_hw *hw) | |||
3052 | } | 3051 | } |
3053 | 3052 | ||
3054 | static int | 3053 | static int |
3055 | ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | 3054 | ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb) |
3056 | { | 3055 | { |
3057 | struct ath5k_softc *sc = hw->priv; | ||
3058 | unsigned long flags; | 3056 | unsigned long flags; |
3059 | int ret; | 3057 | int ret; |
3060 | 3058 | ||
3061 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | 3059 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); |
3062 | 3060 | ||
3063 | if (sc->opmode != NL80211_IFTYPE_ADHOC) { | ||
3064 | ret = -EIO; | ||
3065 | goto end; | ||
3066 | } | ||
3067 | |||
3068 | spin_lock_irqsave(&sc->block, flags); | 3061 | spin_lock_irqsave(&sc->block, flags); |
3069 | ath5k_txbuf_free(sc, sc->bbuf); | 3062 | ath5k_txbuf_free(sc, sc->bbuf); |
3070 | sc->bbuf->skb = skb; | 3063 | sc->bbuf->skb = skb; |
@@ -3077,7 +3070,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3077 | mmiowb(); | 3070 | mmiowb(); |
3078 | } | 3071 | } |
3079 | 3072 | ||
3080 | end: | ||
3081 | return ret; | 3073 | return ret; |
3082 | } | 3074 | } |
3083 | 3075 | ||