aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorBruno Randolf <br1@einfach.org>2010-12-22 05:20:32 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-04 14:35:11 -0500
commitcd2c5486526b744fb505e18c9d981b35feaf283a (patch)
tree6d9a11b28b6da7a0a593f06a4da3cbaead71ec49 /drivers/net/wireless/ath
parent0511af9e9a43c64dd7e23e642c9087710688768c (diff)
ath5k: Move mac80211 functions into new file
Move mac80211 functions into new file mac80211-ops.c to have a better separation and to make base.c smaller. Signed-off-by: Bruno Randolf <br1@einfach.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath5k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c763
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c774
3 files changed, 825 insertions, 713 deletions
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index 67dd9fd0650e..f60b3899afc4 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -14,6 +14,7 @@ ath5k-y += led.o
14ath5k-y += rfkill.o 14ath5k-y += rfkill.o
15ath5k-y += ani.o 15ath5k-y += ani.o
16ath5k-y += sysfs.o 16ath5k-y += sysfs.o
17ath5k-y += mac80211-ops.o
17ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o 18ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
18ath5k-$(CONFIG_ATH5K_AHB) += ahb.o 19ath5k-$(CONFIG_ATH5K_AHB) += ahb.o
19ath5k-$(CONFIG_ATH5K_PCI) += pci.o 20ath5k-$(CONFIG_ATH5K_PCI) += pci.o
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index e4ec40c63396..56baee00ea0b 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -61,7 +61,7 @@
61#include "debug.h" 61#include "debug.h"
62#include "ani.h" 62#include "ani.h"
63 63
64static int modparam_nohwcrypt; 64int modparam_nohwcrypt;
65module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); 65module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
66MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); 66MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
67 67
@@ -79,9 +79,8 @@ MODULE_LICENSE("Dual BSD/GPL");
79static int ath5k_init(struct ieee80211_hw *hw); 79static int ath5k_init(struct ieee80211_hw *hw);
80static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, 80static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
81 bool skip_pcu); 81 bool skip_pcu);
82static int ath5k_beacon_update(struct ieee80211_hw *hw, 82int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
83 struct ieee80211_vif *vif); 83void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
84static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
85 84
86/* Known SREVs */ 85/* Known SREVs */
87static const struct ath5k_srev_name srev_names[] = { 86static const struct ath5k_srev_name srev_names[] = {
@@ -177,38 +176,6 @@ static const struct ieee80211_rate ath5k_rates[] = {
177 /* XR missing */ 176 /* XR missing */
178}; 177};
179 178
180static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc,
181 struct ath5k_buf *bf)
182{
183 BUG_ON(!bf);
184 if (!bf->skb)
185 return;
186 dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len,
187 DMA_TO_DEVICE);
188 dev_kfree_skb_any(bf->skb);
189 bf->skb = NULL;
190 bf->skbaddr = 0;
191 bf->desc->ds_data = 0;
192}
193
194static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc,
195 struct ath5k_buf *bf)
196{
197 struct ath5k_hw *ah = sc->ah;
198 struct ath_common *common = ath5k_hw_common(ah);
199
200 BUG_ON(!bf);
201 if (!bf->skb)
202 return;
203 dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize,
204 DMA_FROM_DEVICE);
205 dev_kfree_skb_any(bf->skb);
206 bf->skb = NULL;
207 bf->skbaddr = 0;
208 bf->desc->ds_data = 0;
209}
210
211
212static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) 179static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
213{ 180{
214 u64 tsf = ath5k_hw_get_tsf64(ah); 181 u64 tsf = ath5k_hw_get_tsf64(ah);
@@ -462,7 +429,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
462 * 429 *
463 * Called with sc->lock. 430 * Called with sc->lock.
464 */ 431 */
465static int 432int
466ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) 433ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
467{ 434{
468 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, 435 ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
@@ -537,8 +504,9 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
537 iter_data->opmode = avf->opmode; 504 iter_data->opmode = avf->opmode;
538} 505}
539 506
540static void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, 507void
541 struct ieee80211_vif *vif) 508ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
509 struct ieee80211_vif *vif)
542{ 510{
543 struct ath_common *common = ath5k_hw_common(sc->ah); 511 struct ath_common *common = ath5k_hw_common(sc->ah);
544 struct ath_vif_iter_data iter_data; 512 struct ath_vif_iter_data iter_data;
@@ -577,7 +545,7 @@ static void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
577 ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); 545 ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
578} 546}
579 547
580static void 548void
581ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif) 549ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
582{ 550{
583 struct ath5k_hw *ah = sc->ah; 551 struct ath5k_hw *ah = sc->ah;
@@ -887,6 +855,37 @@ err:
887 return ret; 855 return ret;
888} 856}
889 857
858void
859ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
860{
861 BUG_ON(!bf);
862 if (!bf->skb)
863 return;
864 dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len,
865 DMA_TO_DEVICE);
866 dev_kfree_skb_any(bf->skb);
867 bf->skb = NULL;
868 bf->skbaddr = 0;
869 bf->desc->ds_data = 0;
870}
871
872void
873ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf)
874{
875 struct ath5k_hw *ah = sc->ah;
876 struct ath_common *common = ath5k_hw_common(ah);
877
878 BUG_ON(!bf);
879 if (!bf->skb)
880 return;
881 dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize,
882 DMA_FROM_DEVICE);
883 dev_kfree_skb_any(bf->skb);
884 bf->skb = NULL;
885 bf->skbaddr = 0;
886 bf->desc->ds_data = 0;
887}
888
890static void 889static void
891ath5k_desc_free(struct ath5k_softc *sc) 890ath5k_desc_free(struct ath5k_softc *sc)
892{ 891{
@@ -1534,8 +1533,9 @@ unlock:
1534* TX Handling * 1533* TX Handling *
1535\*************/ 1534\*************/
1536 1535
1537static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, 1536int
1538 struct ath5k_txq *txq) 1537ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
1538 struct ath5k_txq *txq)
1539{ 1539{
1540 struct ath5k_softc *sc = hw->priv; 1540 struct ath5k_softc *sc = hw->priv;
1541 struct ath5k_buf *bf; 1541 struct ath5k_buf *bf;
@@ -1801,7 +1801,7 @@ err_unmap:
1801 * 1801 *
1802 * Called with the beacon lock. 1802 * Called with the beacon lock.
1803 */ 1803 */
1804static int 1804int
1805ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) 1805ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1806{ 1806{
1807 int ret; 1807 int ret;
@@ -1947,7 +1947,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
1947 * when we otherwise know we have to update the timers, but we keep it in this 1947 * when we otherwise know we have to update the timers, but we keep it in this
1948 * function to have it all together in one place. 1948 * function to have it all together in one place.
1949 */ 1949 */
1950static void 1950void
1951ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) 1951ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
1952{ 1952{
1953 struct ath5k_hw *ah = sc->ah; 1953 struct ath5k_hw *ah = sc->ah;
@@ -2049,7 +2049,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
2049 * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA 2049 * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
2050 * interrupts to detect TSF updates only. 2050 * interrupts to detect TSF updates only.
2051 */ 2051 */
2052static void 2052void
2053ath5k_beacon_config(struct ath5k_softc *sc) 2053ath5k_beacon_config(struct ath5k_softc *sc)
2054{ 2054{
2055 struct ath5k_hw *ah = sc->ah; 2055 struct ath5k_hw *ah = sc->ah;
@@ -2525,7 +2525,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
2525 return 0; 2525 return 0;
2526} 2526}
2527 2527
2528static int 2528int
2529ath5k_init_hw(struct ath5k_softc *sc) 2529ath5k_init_hw(struct ath5k_softc *sc)
2530{ 2530{
2531 struct ath5k_hw *ah = sc->ah; 2531 struct ath5k_hw *ah = sc->ah;
@@ -2601,7 +2601,7 @@ static void stop_tasklets(struct ath5k_softc *sc)
2601 * if another thread does a system call and the thread doing the 2601 * if another thread does a system call and the thread doing the
2602 * stop is preempted). 2602 * stop is preempted).
2603 */ 2603 */
2604static int 2604int
2605ath5k_stop_hw(struct ath5k_softc *sc) 2605ath5k_stop_hw(struct ath5k_softc *sc)
2606{ 2606{
2607 int ret; 2607 int ret;
@@ -2939,230 +2939,8 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
2939 free_irq(sc->irq, sc); 2939 free_irq(sc->irq, sc);
2940} 2940}
2941 2941
2942/********************\ 2942bool
2943* Mac80211 functions * 2943ath_any_vif_assoc(struct ath5k_softc *sc)
2944\********************/
2945
2946static int
2947ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2948{
2949 struct ath5k_softc *sc = hw->priv;
2950 u16 qnum = skb_get_queue_mapping(skb);
2951
2952 if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
2953 dev_kfree_skb_any(skb);
2954 return 0;
2955 }
2956
2957 return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
2958}
2959
2960static int ath5k_start(struct ieee80211_hw *hw)
2961{
2962 return ath5k_init_hw(hw->priv);
2963}
2964
2965static void ath5k_stop(struct ieee80211_hw *hw)
2966{
2967 ath5k_stop_hw(hw->priv);
2968}
2969
2970static int ath5k_add_interface(struct ieee80211_hw *hw,
2971 struct ieee80211_vif *vif)
2972{
2973 struct ath5k_softc *sc = hw->priv;
2974 int ret;
2975 struct ath5k_vif *avf = (void *)vif->drv_priv;
2976
2977 mutex_lock(&sc->lock);
2978
2979 if ((vif->type == NL80211_IFTYPE_AP ||
2980 vif->type == NL80211_IFTYPE_ADHOC)
2981 && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
2982 ret = -ELNRNG;
2983 goto end;
2984 }
2985
2986 /* Don't allow other interfaces if one ad-hoc is configured.
2987 * TODO: Fix the problems with ad-hoc and multiple other interfaces.
2988 * We would need to operate the HW in ad-hoc mode to allow TSF updates
2989 * for the IBSS, but this breaks with additional AP or STA interfaces
2990 * at the moment. */
2991 if (sc->num_adhoc_vifs ||
2992 (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
2993 ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
2994 ret = -ELNRNG;
2995 goto end;
2996 }
2997
2998 switch (vif->type) {
2999 case NL80211_IFTYPE_AP:
3000 case NL80211_IFTYPE_STATION:
3001 case NL80211_IFTYPE_ADHOC:
3002 case NL80211_IFTYPE_MESH_POINT:
3003 avf->opmode = vif->type;
3004 break;
3005 default:
3006 ret = -EOPNOTSUPP;
3007 goto end;
3008 }
3009
3010 sc->nvifs++;
3011 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
3012
3013 /* Assign the vap/adhoc to a beacon xmit slot. */
3014 if ((avf->opmode == NL80211_IFTYPE_AP) ||
3015 (avf->opmode == NL80211_IFTYPE_ADHOC) ||
3016 (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
3017 int slot;
3018
3019 WARN_ON(list_empty(&sc->bcbuf));
3020 avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
3021 list);
3022 list_del(&avf->bbuf->list);
3023
3024 avf->bslot = 0;
3025 for (slot = 0; slot < ATH_BCBUF; slot++) {
3026 if (!sc->bslot[slot]) {
3027 avf->bslot = slot;
3028 break;
3029 }
3030 }
3031 BUG_ON(sc->bslot[avf->bslot] != NULL);
3032 sc->bslot[avf->bslot] = vif;
3033 if (avf->opmode == NL80211_IFTYPE_AP)
3034 sc->num_ap_vifs++;
3035 else if (avf->opmode == NL80211_IFTYPE_ADHOC)
3036 sc->num_adhoc_vifs++;
3037 }
3038
3039 /* Any MAC address is fine, all others are included through the
3040 * filter.
3041 */
3042 memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
3043 ath5k_hw_set_lladdr(sc->ah, vif->addr);
3044
3045 memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
3046
3047 ath5k_mode_setup(sc, vif);
3048
3049 ret = 0;
3050end:
3051 mutex_unlock(&sc->lock);
3052 return ret;
3053}
3054
3055static void
3056ath5k_remove_interface(struct ieee80211_hw *hw,
3057 struct ieee80211_vif *vif)
3058{
3059 struct ath5k_softc *sc = hw->priv;
3060 struct ath5k_vif *avf = (void *)vif->drv_priv;
3061 unsigned int i;
3062
3063 mutex_lock(&sc->lock);
3064 sc->nvifs--;
3065
3066 if (avf->bbuf) {
3067 ath5k_txbuf_free_skb(sc, avf->bbuf);
3068 list_add_tail(&avf->bbuf->list, &sc->bcbuf);
3069 for (i = 0; i < ATH_BCBUF; i++) {
3070 if (sc->bslot[i] == vif) {
3071 sc->bslot[i] = NULL;
3072 break;
3073 }
3074 }
3075 avf->bbuf = NULL;
3076 }
3077 if (avf->opmode == NL80211_IFTYPE_AP)
3078 sc->num_ap_vifs--;
3079 else if (avf->opmode == NL80211_IFTYPE_ADHOC)
3080 sc->num_adhoc_vifs--;
3081
3082 ath5k_update_bssid_mask_and_opmode(sc, NULL);
3083 mutex_unlock(&sc->lock);
3084}
3085
3086/*
3087 * TODO: Phy disable/diversity etc
3088 */
3089static int
3090ath5k_config(struct ieee80211_hw *hw, u32 changed)
3091{
3092 struct ath5k_softc *sc = hw->priv;
3093 struct ath5k_hw *ah = sc->ah;
3094 struct ieee80211_conf *conf = &hw->conf;
3095 int ret = 0;
3096
3097 mutex_lock(&sc->lock);
3098
3099 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
3100 ret = ath5k_chan_set(sc, conf->channel);
3101 if (ret < 0)
3102 goto unlock;
3103 }
3104
3105 if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
3106 (sc->power_level != conf->power_level)) {
3107 sc->power_level = conf->power_level;
3108
3109 /* Half dB steps */
3110 ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
3111 }
3112
3113 /* TODO:
3114 * 1) Move this on config_interface and handle each case
3115 * separately eg. when we have only one STA vif, use
3116 * AR5K_ANTMODE_SINGLE_AP
3117 *
3118 * 2) Allow the user to change antenna mode eg. when only
3119 * one antenna is present
3120 *
3121 * 3) Allow the user to set default/tx antenna when possible
3122 *
3123 * 4) Default mode should handle 90% of the cases, together
3124 * with fixed a/b and single AP modes we should be able to
3125 * handle 99%. Sectored modes are extreme cases and i still
3126 * haven't found a usage for them. If we decide to support them,
3127 * then we must allow the user to set how many tx antennas we
3128 * have available
3129 */
3130 ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
3131
3132unlock:
3133 mutex_unlock(&sc->lock);
3134 return ret;
3135}
3136
3137static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
3138 struct netdev_hw_addr_list *mc_list)
3139{
3140 u32 mfilt[2], val;
3141 u8 pos;
3142 struct netdev_hw_addr *ha;
3143
3144 mfilt[0] = 0;
3145 mfilt[1] = 1;
3146
3147 netdev_hw_addr_list_for_each(ha, mc_list) {
3148 /* calculate XOR of eight 6-bit values */
3149 val = get_unaligned_le32(ha->addr + 0);
3150 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
3151 val = get_unaligned_le32(ha->addr + 3);
3152 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
3153 pos &= 0x3f;
3154 mfilt[pos / 32] |= (1 << (pos % 32));
3155 /* XXX: we might be able to just do this instead,
3156 * but not sure, needs testing, if we do use this we'd
3157 * neet to inform below to not reset the mcast */
3158 /* ath5k_hw_set_mcast_filterindex(ah,
3159 * ha->addr[5]); */
3160 }
3161
3162 return ((u64)(mfilt[1]) << 32) | mfilt[0];
3163}
3164
3165static bool ath_any_vif_assoc(struct ath5k_softc *sc)
3166{ 2944{
3167 struct ath_vif_iter_data iter_data; 2945 struct ath_vif_iter_data iter_data;
3168 iter_data.hw_macaddr = NULL; 2946 iter_data.hw_macaddr = NULL;
@@ -3175,262 +2953,7 @@ static bool ath_any_vif_assoc(struct ath5k_softc *sc)
3175 return iter_data.any_assoc; 2953 return iter_data.any_assoc;
3176} 2954}
3177 2955
3178#define SUPPORTED_FIF_FLAGS \ 2956void
3179 FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
3180 FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
3181 FIF_BCN_PRBRESP_PROMISC
3182/*
3183 * o always accept unicast, broadcast, and multicast traffic
3184 * o multicast traffic for all BSSIDs will be enabled if mac80211
3185 * says it should be
3186 * o maintain current state of phy ofdm or phy cck error reception.
3187 * If the hardware detects any of these type of errors then
3188 * ath5k_hw_get_rx_filter() will pass to us the respective
3189 * hardware filters to be able to receive these type of frames.
3190 * o probe request frames are accepted only when operating in
3191 * hostap, adhoc, or monitor modes
3192 * o enable promiscuous mode according to the interface state
3193 * o accept beacons:
3194 * - when operating in adhoc mode so the 802.11 layer creates
3195 * node table entries for peers,
3196 * - when operating in station mode for collecting rssi data when
3197 * the station is otherwise quiet, or
3198 * - when scanning
3199 */
3200static void ath5k_configure_filter(struct ieee80211_hw *hw,
3201 unsigned int changed_flags,
3202 unsigned int *new_flags,
3203 u64 multicast)
3204{
3205 struct ath5k_softc *sc = hw->priv;
3206 struct ath5k_hw *ah = sc->ah;
3207 u32 mfilt[2], rfilt;
3208
3209 mutex_lock(&sc->lock);
3210
3211 mfilt[0] = multicast;
3212 mfilt[1] = multicast >> 32;
3213
3214 /* Only deal with supported flags */
3215 changed_flags &= SUPPORTED_FIF_FLAGS;
3216 *new_flags &= SUPPORTED_FIF_FLAGS;
3217
3218 /* If HW detects any phy or radar errors, leave those filters on.
3219 * Also, always enable Unicast, Broadcasts and Multicast
3220 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
3221 rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
3222 (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
3223 AR5K_RX_FILTER_MCAST);
3224
3225 if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
3226 if (*new_flags & FIF_PROMISC_IN_BSS) {
3227 __set_bit(ATH_STAT_PROMISC, sc->status);
3228 } else {
3229 __clear_bit(ATH_STAT_PROMISC, sc->status);
3230 }
3231 }
3232
3233 if (test_bit(ATH_STAT_PROMISC, sc->status))
3234 rfilt |= AR5K_RX_FILTER_PROM;
3235
3236 /* Note, AR5K_RX_FILTER_MCAST is already enabled */
3237 if (*new_flags & FIF_ALLMULTI) {
3238 mfilt[0] = ~0;
3239 mfilt[1] = ~0;
3240 }
3241
3242 /* This is the best we can do */
3243 if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
3244 rfilt |= AR5K_RX_FILTER_PHYERR;
3245
3246 /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
3247 * and probes for any BSSID */
3248 if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
3249 rfilt |= AR5K_RX_FILTER_BEACON;
3250
3251 /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
3252 * set we should only pass on control frames for this
3253 * station. This needs testing. I believe right now this
3254 * enables *all* control frames, which is OK.. but
3255 * but we should see if we can improve on granularity */
3256 if (*new_flags & FIF_CONTROL)
3257 rfilt |= AR5K_RX_FILTER_CONTROL;
3258
3259 /* Additional settings per mode -- this is per ath5k */
3260
3261 /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
3262
3263 switch (sc->opmode) {
3264 case NL80211_IFTYPE_MESH_POINT:
3265 rfilt |= AR5K_RX_FILTER_CONTROL |
3266 AR5K_RX_FILTER_BEACON |
3267 AR5K_RX_FILTER_PROBEREQ |
3268 AR5K_RX_FILTER_PROM;
3269 break;
3270 case NL80211_IFTYPE_AP:
3271 case NL80211_IFTYPE_ADHOC:
3272 rfilt |= AR5K_RX_FILTER_PROBEREQ |
3273 AR5K_RX_FILTER_BEACON;
3274 break;
3275 case NL80211_IFTYPE_STATION:
3276 if (sc->assoc)
3277 rfilt |= AR5K_RX_FILTER_BEACON;
3278 default:
3279 break;
3280 }
3281
3282 /* Set filters */
3283 ath5k_hw_set_rx_filter(ah, rfilt);
3284
3285 /* Set multicast bits */
3286 ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
3287 /* Set the cached hw filter flags, this will later actually
3288 * be set in HW */
3289 sc->filter_flags = rfilt;
3290
3291 mutex_unlock(&sc->lock);
3292}
3293
3294static int
3295ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3296 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
3297 struct ieee80211_key_conf *key)
3298{
3299 struct ath5k_softc *sc = hw->priv;
3300 struct ath5k_hw *ah = sc->ah;
3301 struct ath_common *common = ath5k_hw_common(ah);
3302 int ret = 0;
3303
3304 if (modparam_nohwcrypt)
3305 return -EOPNOTSUPP;
3306
3307 switch (key->cipher) {
3308 case WLAN_CIPHER_SUITE_WEP40:
3309 case WLAN_CIPHER_SUITE_WEP104:
3310 case WLAN_CIPHER_SUITE_TKIP:
3311 break;
3312 case WLAN_CIPHER_SUITE_CCMP:
3313 if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)
3314 break;
3315 return -EOPNOTSUPP;
3316 default:
3317 WARN_ON(1);
3318 return -EINVAL;
3319 }
3320
3321 mutex_lock(&sc->lock);
3322
3323 switch (cmd) {
3324 case SET_KEY:
3325 ret = ath_key_config(common, vif, sta, key);
3326 if (ret >= 0) {
3327 key->hw_key_idx = ret;
3328 /* push IV and Michael MIC generation to stack */
3329 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
3330 if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
3331 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
3332 if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
3333 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
3334 ret = 0;
3335 }
3336 break;
3337 case DISABLE_KEY:
3338 ath_key_delete(common, key);
3339 break;
3340 default:
3341 ret = -EINVAL;
3342 }
3343
3344 mmiowb();
3345 mutex_unlock(&sc->lock);
3346 return ret;
3347}
3348
3349static int
3350ath5k_get_stats(struct ieee80211_hw *hw,
3351 struct ieee80211_low_level_stats *stats)
3352{
3353 struct ath5k_softc *sc = hw->priv;
3354
3355 /* Force update */
3356 ath5k_hw_update_mib_counters(sc->ah);
3357
3358 stats->dot11ACKFailureCount = sc->stats.ack_fail;
3359 stats->dot11RTSFailureCount = sc->stats.rts_fail;
3360 stats->dot11RTSSuccessCount = sc->stats.rts_ok;
3361 stats->dot11FCSErrorCount = sc->stats.fcs_error;
3362
3363 return 0;
3364}
3365
3366static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
3367 struct survey_info *survey)
3368{
3369 struct ath5k_softc *sc = hw->priv;
3370 struct ieee80211_conf *conf = &hw->conf;
3371 struct ath_common *common = ath5k_hw_common(sc->ah);
3372 struct ath_cycle_counters *cc = &common->cc_survey;
3373 unsigned int div = common->clockrate * 1000;
3374
3375 if (idx != 0)
3376 return -ENOENT;
3377
3378 spin_lock_bh(&common->cc_lock);
3379 ath_hw_cycle_counters_update(common);
3380 if (cc->cycles > 0) {
3381 sc->survey.channel_time += cc->cycles / div;
3382 sc->survey.channel_time_busy += cc->rx_busy / div;
3383 sc->survey.channel_time_rx += cc->rx_frame / div;
3384 sc->survey.channel_time_tx += cc->tx_frame / div;
3385 }
3386 memset(cc, 0, sizeof(*cc));
3387 spin_unlock_bh(&common->cc_lock);
3388
3389 memcpy(survey, &sc->survey, sizeof(*survey));
3390
3391 survey->channel = conf->channel;
3392 survey->noise = sc->ah->ah_noise_floor;
3393 survey->filled = SURVEY_INFO_NOISE_DBM |
3394 SURVEY_INFO_CHANNEL_TIME |
3395 SURVEY_INFO_CHANNEL_TIME_BUSY |
3396 SURVEY_INFO_CHANNEL_TIME_RX |
3397 SURVEY_INFO_CHANNEL_TIME_TX;
3398
3399 return 0;
3400}
3401
3402static u64
3403ath5k_get_tsf(struct ieee80211_hw *hw)
3404{
3405 struct ath5k_softc *sc = hw->priv;
3406
3407 return ath5k_hw_get_tsf64(sc->ah);
3408}
3409
3410static void
3411ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
3412{
3413 struct ath5k_softc *sc = hw->priv;
3414
3415 ath5k_hw_set_tsf64(sc->ah, tsf);
3416}
3417
3418static void
3419ath5k_reset_tsf(struct ieee80211_hw *hw)
3420{
3421 struct ath5k_softc *sc = hw->priv;
3422
3423 /*
3424 * in IBSS mode we need to update the beacon timers too.
3425 * this will also reset the TSF if we call it with 0
3426 */
3427 if (sc->opmode == NL80211_IFTYPE_ADHOC)
3428 ath5k_beacon_update_timers(sc, 0);
3429 else
3430 ath5k_hw_reset_tsf(sc->ah);
3431}
3432
3433static void
3434set_beacon_filter(struct ieee80211_hw *hw, bool enable) 2957set_beacon_filter(struct ieee80211_hw *hw, bool enable)
3435{ 2958{
3436 struct ath5k_softc *sc = hw->priv; 2959 struct ath5k_softc *sc = hw->priv;
@@ -3444,189 +2967,3 @@ set_beacon_filter(struct ieee80211_hw *hw, bool enable)
3444 ath5k_hw_set_rx_filter(ah, rfilt); 2967 ath5k_hw_set_rx_filter(ah, rfilt);
3445 sc->filter_flags = rfilt; 2968 sc->filter_flags = rfilt;
3446} 2969}
3447
3448static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
3449 struct ieee80211_vif *vif,
3450 struct ieee80211_bss_conf *bss_conf,
3451 u32 changes)
3452{
3453 struct ath5k_vif *avf = (void *)vif->drv_priv;
3454 struct ath5k_softc *sc = hw->priv;
3455 struct ath5k_hw *ah = sc->ah;
3456 struct ath_common *common = ath5k_hw_common(ah);
3457 unsigned long flags;
3458
3459 mutex_lock(&sc->lock);
3460
3461 if (changes & BSS_CHANGED_BSSID) {
3462 /* Cache for later use during resets */
3463 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
3464 common->curaid = 0;
3465 ath5k_hw_set_bssid(ah);
3466 mmiowb();
3467 }
3468
3469 if (changes & BSS_CHANGED_BEACON_INT)
3470 sc->bintval = bss_conf->beacon_int;
3471
3472 if (changes & BSS_CHANGED_ASSOC) {
3473 avf->assoc = bss_conf->assoc;
3474 if (bss_conf->assoc)
3475 sc->assoc = bss_conf->assoc;
3476 else
3477 sc->assoc = ath_any_vif_assoc(sc);
3478
3479 if (sc->opmode == NL80211_IFTYPE_STATION)
3480 set_beacon_filter(hw, sc->assoc);
3481 ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
3482 AR5K_LED_ASSOC : AR5K_LED_INIT);
3483 if (bss_conf->assoc) {
3484 ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
3485 "Bss Info ASSOC %d, bssid: %pM\n",
3486 bss_conf->aid, common->curbssid);
3487 common->curaid = bss_conf->aid;
3488 ath5k_hw_set_bssid(ah);
3489 /* Once ANI is available you would start it here */
3490 }
3491 }
3492
3493 if (changes & BSS_CHANGED_BEACON) {
3494 spin_lock_irqsave(&sc->block, flags);
3495 ath5k_beacon_update(hw, vif);
3496 spin_unlock_irqrestore(&sc->block, flags);
3497 }
3498
3499 if (changes & BSS_CHANGED_BEACON_ENABLED)
3500 sc->enable_beacon = bss_conf->enable_beacon;
3501
3502 if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
3503 BSS_CHANGED_BEACON_INT))
3504 ath5k_beacon_config(sc);
3505
3506 mutex_unlock(&sc->lock);
3507}
3508
3509static void ath5k_sw_scan_start(struct ieee80211_hw *hw)
3510{
3511 struct ath5k_softc *sc = hw->priv;
3512 if (!sc->assoc)
3513 ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
3514}
3515
3516static void ath5k_sw_scan_complete(struct ieee80211_hw *hw)
3517{
3518 struct ath5k_softc *sc = hw->priv;
3519 ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
3520 AR5K_LED_ASSOC : AR5K_LED_INIT);
3521}
3522
3523/**
3524 * ath5k_set_coverage_class - Set IEEE 802.11 coverage class
3525 *
3526 * @hw: struct ieee80211_hw pointer
3527 * @coverage_class: IEEE 802.11 coverage class number
3528 *
3529 * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
3530 * coverage class. The values are persistent, they are restored after device
3531 * reset.
3532 */
3533static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
3534{
3535 struct ath5k_softc *sc = hw->priv;
3536
3537 mutex_lock(&sc->lock);
3538 ath5k_hw_set_coverage_class(sc->ah, coverage_class);
3539 mutex_unlock(&sc->lock);
3540}
3541
3542static int ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
3543 const struct ieee80211_tx_queue_params *params)
3544{
3545 struct ath5k_softc *sc = hw->priv;
3546 struct ath5k_hw *ah = sc->ah;
3547 struct ath5k_txq_info qi;
3548 int ret = 0;
3549
3550 if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
3551 return 0;
3552
3553 mutex_lock(&sc->lock);
3554
3555 ath5k_hw_get_tx_queueprops(ah, queue, &qi);
3556
3557 qi.tqi_aifs = params->aifs;
3558 qi.tqi_cw_min = params->cw_min;
3559 qi.tqi_cw_max = params->cw_max;
3560 qi.tqi_burst_time = params->txop;
3561
3562 ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
3563 "Configure tx [queue %d], "
3564 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
3565 queue, params->aifs, params->cw_min,
3566 params->cw_max, params->txop);
3567
3568 if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
3569 ATH5K_ERR(sc,
3570 "Unable to update hardware queue %u!\n", queue);
3571 ret = -EIO;
3572 } else
3573 ath5k_hw_reset_tx_queue(ah, queue);
3574
3575 mutex_unlock(&sc->lock);
3576
3577 return ret;
3578}
3579
3580static int ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
3581{
3582 struct ath5k_softc *sc = hw->priv;
3583
3584 if (tx_ant == 1 && rx_ant == 1)
3585 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
3586 else if (tx_ant == 2 && rx_ant == 2)
3587 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
3588 else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3)
3589 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
3590 else
3591 return -EINVAL;
3592 return 0;
3593}
3594
3595static int ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
3596{
3597 struct ath5k_softc *sc = hw->priv;
3598
3599 switch (sc->ah->ah_ant_mode) {
3600 case AR5K_ANTMODE_FIXED_A:
3601 *tx_ant = 1; *rx_ant = 1; break;
3602 case AR5K_ANTMODE_FIXED_B:
3603 *tx_ant = 2; *rx_ant = 2; break;
3604 case AR5K_ANTMODE_DEFAULT:
3605 *tx_ant = 3; *rx_ant = 3; break;
3606 }
3607 return 0;
3608}
3609
3610const struct ieee80211_ops ath5k_hw_ops = {
3611 .tx = ath5k_tx,
3612 .start = ath5k_start,
3613 .stop = ath5k_stop,
3614 .add_interface = ath5k_add_interface,
3615 .remove_interface = ath5k_remove_interface,
3616 .config = ath5k_config,
3617 .prepare_multicast = ath5k_prepare_multicast,
3618 .configure_filter = ath5k_configure_filter,
3619 .set_key = ath5k_set_key,
3620 .get_stats = ath5k_get_stats,
3621 .get_survey = ath5k_get_survey,
3622 .conf_tx = ath5k_conf_tx,
3623 .get_tsf = ath5k_get_tsf,
3624 .set_tsf = ath5k_set_tsf,
3625 .reset_tsf = ath5k_reset_tsf,
3626 .bss_info_changed = ath5k_bss_info_changed,
3627 .sw_scan_start = ath5k_sw_scan_start,
3628 .sw_scan_complete = ath5k_sw_scan_complete,
3629 .set_coverage_class = ath5k_set_coverage_class,
3630 .set_antenna = ath5k_set_antenna,
3631 .get_antenna = ath5k_get_antenna,
3632};
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
new file mode 100644
index 000000000000..de257a3430be
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -0,0 +1,774 @@
1/*-
2 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
3 * Copyright (c) 2004-2005 Atheros Communications, Inc.
4 * Copyright (c) 2006 Devicescape Software, Inc.
5 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
6 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
7 * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
19 * redistribution must be conditioned upon including a substantially
20 * similar Disclaimer requirement for further binary redistribution.
21 * 3. Neither the names of the above-listed copyright holders nor the names
22 * of any contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * Alternatively, this software may be distributed under the terms of the
26 * GNU General Public License ("GPL") version 2 as published by the Free
27 * Software Foundation.
28 *
29 * NO WARRANTY
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
33 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
34 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
35 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
38 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
40 * THE POSSIBILITY OF SUCH DAMAGES.
41 *
42 */
43
44#include <asm/unaligned.h>
45
46#include "base.h"
47#include "reg.h"
48
49extern int modparam_nohwcrypt;
50
51/* functions used from base.c */
52void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
53bool ath_any_vif_assoc(struct ath5k_softc *sc);
54int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
55 struct ath5k_txq *txq);
56int ath5k_init_hw(struct ath5k_softc *sc);
57int ath5k_stop_hw(struct ath5k_softc *sc);
58void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
59void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
60 struct ieee80211_vif *vif);
61int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
62void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
63int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
64void ath5k_beacon_config(struct ath5k_softc *sc);
65void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
66void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
67
68/********************\
69* Mac80211 functions *
70\********************/
71
72static int
73ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
74{
75 struct ath5k_softc *sc = hw->priv;
76 u16 qnum = skb_get_queue_mapping(skb);
77
78 if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
79 dev_kfree_skb_any(skb);
80 return 0;
81 }
82
83 return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
84}
85
86
87static int
88ath5k_start(struct ieee80211_hw *hw)
89{
90 return ath5k_init_hw(hw->priv);
91}
92
93
94static void
95ath5k_stop(struct ieee80211_hw *hw)
96{
97 ath5k_stop_hw(hw->priv);
98}
99
100
101static int
102ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
103{
104 struct ath5k_softc *sc = hw->priv;
105 int ret;
106 struct ath5k_vif *avf = (void *)vif->drv_priv;
107
108 mutex_lock(&sc->lock);
109
110 if ((vif->type == NL80211_IFTYPE_AP ||
111 vif->type == NL80211_IFTYPE_ADHOC)
112 && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) {
113 ret = -ELNRNG;
114 goto end;
115 }
116
117 /* Don't allow other interfaces if one ad-hoc is configured.
118 * TODO: Fix the problems with ad-hoc and multiple other interfaces.
119 * We would need to operate the HW in ad-hoc mode to allow TSF updates
120 * for the IBSS, but this breaks with additional AP or STA interfaces
121 * at the moment. */
122 if (sc->num_adhoc_vifs ||
123 (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
124 ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
125 ret = -ELNRNG;
126 goto end;
127 }
128
129 switch (vif->type) {
130 case NL80211_IFTYPE_AP:
131 case NL80211_IFTYPE_STATION:
132 case NL80211_IFTYPE_ADHOC:
133 case NL80211_IFTYPE_MESH_POINT:
134 avf->opmode = vif->type;
135 break;
136 default:
137 ret = -EOPNOTSUPP;
138 goto end;
139 }
140
141 sc->nvifs++;
142 ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode);
143
144 /* Assign the vap/adhoc to a beacon xmit slot. */
145 if ((avf->opmode == NL80211_IFTYPE_AP) ||
146 (avf->opmode == NL80211_IFTYPE_ADHOC) ||
147 (avf->opmode == NL80211_IFTYPE_MESH_POINT)) {
148 int slot;
149
150 WARN_ON(list_empty(&sc->bcbuf));
151 avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf,
152 list);
153 list_del(&avf->bbuf->list);
154
155 avf->bslot = 0;
156 for (slot = 0; slot < ATH_BCBUF; slot++) {
157 if (!sc->bslot[slot]) {
158 avf->bslot = slot;
159 break;
160 }
161 }
162 BUG_ON(sc->bslot[avf->bslot] != NULL);
163 sc->bslot[avf->bslot] = vif;
164 if (avf->opmode == NL80211_IFTYPE_AP)
165 sc->num_ap_vifs++;
166 else if (avf->opmode == NL80211_IFTYPE_ADHOC)
167 sc->num_adhoc_vifs++;
168 }
169
170 /* Any MAC address is fine, all others are included through the
171 * filter.
172 */
173 memcpy(&sc->lladdr, vif->addr, ETH_ALEN);
174 ath5k_hw_set_lladdr(sc->ah, vif->addr);
175
176 memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
177
178 ath5k_mode_setup(sc, vif);
179
180 ret = 0;
181end:
182 mutex_unlock(&sc->lock);
183 return ret;
184}
185
186
187static void
188ath5k_remove_interface(struct ieee80211_hw *hw,
189 struct ieee80211_vif *vif)
190{
191 struct ath5k_softc *sc = hw->priv;
192 struct ath5k_vif *avf = (void *)vif->drv_priv;
193 unsigned int i;
194
195 mutex_lock(&sc->lock);
196 sc->nvifs--;
197
198 if (avf->bbuf) {
199 ath5k_txbuf_free_skb(sc, avf->bbuf);
200 list_add_tail(&avf->bbuf->list, &sc->bcbuf);
201 for (i = 0; i < ATH_BCBUF; i++) {
202 if (sc->bslot[i] == vif) {
203 sc->bslot[i] = NULL;
204 break;
205 }
206 }
207 avf->bbuf = NULL;
208 }
209 if (avf->opmode == NL80211_IFTYPE_AP)
210 sc->num_ap_vifs--;
211 else if (avf->opmode == NL80211_IFTYPE_ADHOC)
212 sc->num_adhoc_vifs--;
213
214 ath5k_update_bssid_mask_and_opmode(sc, NULL);
215 mutex_unlock(&sc->lock);
216}
217
218
219/*
220 * TODO: Phy disable/diversity etc
221 */
222static int
223ath5k_config(struct ieee80211_hw *hw, u32 changed)
224{
225 struct ath5k_softc *sc = hw->priv;
226 struct ath5k_hw *ah = sc->ah;
227 struct ieee80211_conf *conf = &hw->conf;
228 int ret = 0;
229
230 mutex_lock(&sc->lock);
231
232 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
233 ret = ath5k_chan_set(sc, conf->channel);
234 if (ret < 0)
235 goto unlock;
236 }
237
238 if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
239 (sc->power_level != conf->power_level)) {
240 sc->power_level = conf->power_level;
241
242 /* Half dB steps */
243 ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
244 }
245
246 /* TODO:
247 * 1) Move this on config_interface and handle each case
248 * separately eg. when we have only one STA vif, use
249 * AR5K_ANTMODE_SINGLE_AP
250 *
251 * 2) Allow the user to change antenna mode eg. when only
252 * one antenna is present
253 *
254 * 3) Allow the user to set default/tx antenna when possible
255 *
256 * 4) Default mode should handle 90% of the cases, together
257 * with fixed a/b and single AP modes we should be able to
258 * handle 99%. Sectored modes are extreme cases and i still
259 * haven't found a usage for them. If we decide to support them,
260 * then we must allow the user to set how many tx antennas we
261 * have available
262 */
263 ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
264
265unlock:
266 mutex_unlock(&sc->lock);
267 return ret;
268}
269
270
271static void
272ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
273 struct ieee80211_bss_conf *bss_conf, u32 changes)
274{
275 struct ath5k_vif *avf = (void *)vif->drv_priv;
276 struct ath5k_softc *sc = hw->priv;
277 struct ath5k_hw *ah = sc->ah;
278 struct ath_common *common = ath5k_hw_common(ah);
279 unsigned long flags;
280
281 mutex_lock(&sc->lock);
282
283 if (changes & BSS_CHANGED_BSSID) {
284 /* Cache for later use during resets */
285 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
286 common->curaid = 0;
287 ath5k_hw_set_bssid(ah);
288 mmiowb();
289 }
290
291 if (changes & BSS_CHANGED_BEACON_INT)
292 sc->bintval = bss_conf->beacon_int;
293
294 if (changes & BSS_CHANGED_ASSOC) {
295 avf->assoc = bss_conf->assoc;
296 if (bss_conf->assoc)
297 sc->assoc = bss_conf->assoc;
298 else
299 sc->assoc = ath_any_vif_assoc(sc);
300
301 if (sc->opmode == NL80211_IFTYPE_STATION)
302 set_beacon_filter(hw, sc->assoc);
303 ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
304 AR5K_LED_ASSOC : AR5K_LED_INIT);
305 if (bss_conf->assoc) {
306 ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
307 "Bss Info ASSOC %d, bssid: %pM\n",
308 bss_conf->aid, common->curbssid);
309 common->curaid = bss_conf->aid;
310 ath5k_hw_set_bssid(ah);
311 /* Once ANI is available you would start it here */
312 }
313 }
314
315 if (changes & BSS_CHANGED_BEACON) {
316 spin_lock_irqsave(&sc->block, flags);
317 ath5k_beacon_update(hw, vif);
318 spin_unlock_irqrestore(&sc->block, flags);
319 }
320
321 if (changes & BSS_CHANGED_BEACON_ENABLED)
322 sc->enable_beacon = bss_conf->enable_beacon;
323
324 if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
325 BSS_CHANGED_BEACON_INT))
326 ath5k_beacon_config(sc);
327
328 mutex_unlock(&sc->lock);
329}
330
331
332static u64
333ath5k_prepare_multicast(struct ieee80211_hw *hw,
334 struct netdev_hw_addr_list *mc_list)
335{
336 u32 mfilt[2], val;
337 u8 pos;
338 struct netdev_hw_addr *ha;
339
340 mfilt[0] = 0;
341 mfilt[1] = 1;
342
343 netdev_hw_addr_list_for_each(ha, mc_list) {
344 /* calculate XOR of eight 6-bit values */
345 val = get_unaligned_le32(ha->addr + 0);
346 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
347 val = get_unaligned_le32(ha->addr + 3);
348 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
349 pos &= 0x3f;
350 mfilt[pos / 32] |= (1 << (pos % 32));
351 /* XXX: we might be able to just do this instead,
352 * but not sure, needs testing, if we do use this we'd
353 * neet to inform below to not reset the mcast */
354 /* ath5k_hw_set_mcast_filterindex(ah,
355 * ha->addr[5]); */
356 }
357
358 return ((u64)(mfilt[1]) << 32) | mfilt[0];
359}
360
361
362/*
363 * o always accept unicast, broadcast, and multicast traffic
364 * o multicast traffic for all BSSIDs will be enabled if mac80211
365 * says it should be
366 * o maintain current state of phy ofdm or phy cck error reception.
367 * If the hardware detects any of these type of errors then
368 * ath5k_hw_get_rx_filter() will pass to us the respective
369 * hardware filters to be able to receive these type of frames.
370 * o probe request frames are accepted only when operating in
371 * hostap, adhoc, or monitor modes
372 * o enable promiscuous mode according to the interface state
373 * o accept beacons:
374 * - when operating in adhoc mode so the 802.11 layer creates
375 * node table entries for peers,
376 * - when operating in station mode for collecting rssi data when
377 * the station is otherwise quiet, or
378 * - when scanning
379 */
380static void
381ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
382 unsigned int *new_flags, u64 multicast)
383{
384#define SUPPORTED_FIF_FLAGS \
385 (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
386 FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
387 FIF_BCN_PRBRESP_PROMISC)
388
389 struct ath5k_softc *sc = hw->priv;
390 struct ath5k_hw *ah = sc->ah;
391 u32 mfilt[2], rfilt;
392
393 mutex_lock(&sc->lock);
394
395 mfilt[0] = multicast;
396 mfilt[1] = multicast >> 32;
397
398 /* Only deal with supported flags */
399 changed_flags &= SUPPORTED_FIF_FLAGS;
400 *new_flags &= SUPPORTED_FIF_FLAGS;
401
402 /* If HW detects any phy or radar errors, leave those filters on.
403 * Also, always enable Unicast, Broadcasts and Multicast
404 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
405 rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
406 (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
407 AR5K_RX_FILTER_MCAST);
408
409 if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
410 if (*new_flags & FIF_PROMISC_IN_BSS)
411 __set_bit(ATH_STAT_PROMISC, sc->status);
412 else
413 __clear_bit(ATH_STAT_PROMISC, sc->status);
414 }
415
416 if (test_bit(ATH_STAT_PROMISC, sc->status))
417 rfilt |= AR5K_RX_FILTER_PROM;
418
419 /* Note, AR5K_RX_FILTER_MCAST is already enabled */
420 if (*new_flags & FIF_ALLMULTI) {
421 mfilt[0] = ~0;
422 mfilt[1] = ~0;
423 }
424
425 /* This is the best we can do */
426 if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
427 rfilt |= AR5K_RX_FILTER_PHYERR;
428
429 /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
430 * and probes for any BSSID */
431 if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1))
432 rfilt |= AR5K_RX_FILTER_BEACON;
433
434 /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
435 * set we should only pass on control frames for this
436 * station. This needs testing. I believe right now this
437 * enables *all* control frames, which is OK.. but
438 * but we should see if we can improve on granularity */
439 if (*new_flags & FIF_CONTROL)
440 rfilt |= AR5K_RX_FILTER_CONTROL;
441
442 /* Additional settings per mode -- this is per ath5k */
443
444 /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
445
446 switch (sc->opmode) {
447 case NL80211_IFTYPE_MESH_POINT:
448 rfilt |= AR5K_RX_FILTER_CONTROL |
449 AR5K_RX_FILTER_BEACON |
450 AR5K_RX_FILTER_PROBEREQ |
451 AR5K_RX_FILTER_PROM;
452 break;
453 case NL80211_IFTYPE_AP:
454 case NL80211_IFTYPE_ADHOC:
455 rfilt |= AR5K_RX_FILTER_PROBEREQ |
456 AR5K_RX_FILTER_BEACON;
457 break;
458 case NL80211_IFTYPE_STATION:
459 if (sc->assoc)
460 rfilt |= AR5K_RX_FILTER_BEACON;
461 default:
462 break;
463 }
464
465 /* Set filters */
466 ath5k_hw_set_rx_filter(ah, rfilt);
467
468 /* Set multicast bits */
469 ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
470 /* Set the cached hw filter flags, this will later actually
471 * be set in HW */
472 sc->filter_flags = rfilt;
473
474 mutex_unlock(&sc->lock);
475}
476
477
478static int
479ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
480 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
481 struct ieee80211_key_conf *key)
482{
483 struct ath5k_softc *sc = hw->priv;
484 struct ath5k_hw *ah = sc->ah;
485 struct ath_common *common = ath5k_hw_common(ah);
486 int ret = 0;
487
488 if (modparam_nohwcrypt)
489 return -EOPNOTSUPP;
490
491 switch (key->cipher) {
492 case WLAN_CIPHER_SUITE_WEP40:
493 case WLAN_CIPHER_SUITE_WEP104:
494 case WLAN_CIPHER_SUITE_TKIP:
495 break;
496 case WLAN_CIPHER_SUITE_CCMP:
497 if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)
498 break;
499 return -EOPNOTSUPP;
500 default:
501 WARN_ON(1);
502 return -EINVAL;
503 }
504
505 mutex_lock(&sc->lock);
506
507 switch (cmd) {
508 case SET_KEY:
509 ret = ath_key_config(common, vif, sta, key);
510 if (ret >= 0) {
511 key->hw_key_idx = ret;
512 /* push IV and Michael MIC generation to stack */
513 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
514 if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
515 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
516 if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
517 key->flags |= IEEE80211_KEY_FLAG_SW_MGMT;
518 ret = 0;
519 }
520 break;
521 case DISABLE_KEY:
522 ath_key_delete(common, key);
523 break;
524 default:
525 ret = -EINVAL;
526 }
527
528 mmiowb();
529 mutex_unlock(&sc->lock);
530 return ret;
531}
532
533
534static void
535ath5k_sw_scan_start(struct ieee80211_hw *hw)
536{
537 struct ath5k_softc *sc = hw->priv;
538 if (!sc->assoc)
539 ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN);
540}
541
542
543static void
544ath5k_sw_scan_complete(struct ieee80211_hw *hw)
545{
546 struct ath5k_softc *sc = hw->priv;
547 ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
548 AR5K_LED_ASSOC : AR5K_LED_INIT);
549}
550
551
552static int
553ath5k_get_stats(struct ieee80211_hw *hw,
554 struct ieee80211_low_level_stats *stats)
555{
556 struct ath5k_softc *sc = hw->priv;
557
558 /* Force update */
559 ath5k_hw_update_mib_counters(sc->ah);
560
561 stats->dot11ACKFailureCount = sc->stats.ack_fail;
562 stats->dot11RTSFailureCount = sc->stats.rts_fail;
563 stats->dot11RTSSuccessCount = sc->stats.rts_ok;
564 stats->dot11FCSErrorCount = sc->stats.fcs_error;
565
566 return 0;
567}
568
569
570static int
571ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
572 const struct ieee80211_tx_queue_params *params)
573{
574 struct ath5k_softc *sc = hw->priv;
575 struct ath5k_hw *ah = sc->ah;
576 struct ath5k_txq_info qi;
577 int ret = 0;
578
579 if (queue >= ah->ah_capabilities.cap_queues.q_tx_num)
580 return 0;
581
582 mutex_lock(&sc->lock);
583
584 ath5k_hw_get_tx_queueprops(ah, queue, &qi);
585
586 qi.tqi_aifs = params->aifs;
587 qi.tqi_cw_min = params->cw_min;
588 qi.tqi_cw_max = params->cw_max;
589 qi.tqi_burst_time = params->txop;
590
591 ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
592 "Configure tx [queue %d], "
593 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
594 queue, params->aifs, params->cw_min,
595 params->cw_max, params->txop);
596
597 if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) {
598 ATH5K_ERR(sc,
599 "Unable to update hardware queue %u!\n", queue);
600 ret = -EIO;
601 } else
602 ath5k_hw_reset_tx_queue(ah, queue);
603
604 mutex_unlock(&sc->lock);
605
606 return ret;
607}
608
609
610static u64
611ath5k_get_tsf(struct ieee80211_hw *hw)
612{
613 struct ath5k_softc *sc = hw->priv;
614
615 return ath5k_hw_get_tsf64(sc->ah);
616}
617
618
619static void
620ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
621{
622 struct ath5k_softc *sc = hw->priv;
623
624 ath5k_hw_set_tsf64(sc->ah, tsf);
625}
626
627
628static void
629ath5k_reset_tsf(struct ieee80211_hw *hw)
630{
631 struct ath5k_softc *sc = hw->priv;
632
633 /*
634 * in IBSS mode we need to update the beacon timers too.
635 * this will also reset the TSF if we call it with 0
636 */
637 if (sc->opmode == NL80211_IFTYPE_ADHOC)
638 ath5k_beacon_update_timers(sc, 0);
639 else
640 ath5k_hw_reset_tsf(sc->ah);
641}
642
643
644static int
645ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey)
646{
647 struct ath5k_softc *sc = hw->priv;
648 struct ieee80211_conf *conf = &hw->conf;
649 struct ath_common *common = ath5k_hw_common(sc->ah);
650 struct ath_cycle_counters *cc = &common->cc_survey;
651 unsigned int div = common->clockrate * 1000;
652
653 if (idx != 0)
654 return -ENOENT;
655
656 spin_lock_bh(&common->cc_lock);
657 ath_hw_cycle_counters_update(common);
658 if (cc->cycles > 0) {
659 sc->survey.channel_time += cc->cycles / div;
660 sc->survey.channel_time_busy += cc->rx_busy / div;
661 sc->survey.channel_time_rx += cc->rx_frame / div;
662 sc->survey.channel_time_tx += cc->tx_frame / div;
663 }
664 memset(cc, 0, sizeof(*cc));
665 spin_unlock_bh(&common->cc_lock);
666
667 memcpy(survey, &sc->survey, sizeof(*survey));
668
669 survey->channel = conf->channel;
670 survey->noise = sc->ah->ah_noise_floor;
671 survey->filled = SURVEY_INFO_NOISE_DBM |
672 SURVEY_INFO_CHANNEL_TIME |
673 SURVEY_INFO_CHANNEL_TIME_BUSY |
674 SURVEY_INFO_CHANNEL_TIME_RX |
675 SURVEY_INFO_CHANNEL_TIME_TX;
676
677 return 0;
678}
679
680
681/**
682 * ath5k_set_coverage_class - Set IEEE 802.11 coverage class
683 *
684 * @hw: struct ieee80211_hw pointer
685 * @coverage_class: IEEE 802.11 coverage class number
686 *
687 * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
688 * coverage class. The values are persistent, they are restored after device
689 * reset.
690 */
691static void
692ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
693{
694 struct ath5k_softc *sc = hw->priv;
695
696 mutex_lock(&sc->lock);
697 ath5k_hw_set_coverage_class(sc->ah, coverage_class);
698 mutex_unlock(&sc->lock);
699}
700
701
702static int
703ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
704{
705 struct ath5k_softc *sc = hw->priv;
706
707 if (tx_ant == 1 && rx_ant == 1)
708 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A);
709 else if (tx_ant == 2 && rx_ant == 2)
710 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B);
711 else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3)
712 ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT);
713 else
714 return -EINVAL;
715 return 0;
716}
717
718
719static int
720ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
721{
722 struct ath5k_softc *sc = hw->priv;
723
724 switch (sc->ah->ah_ant_mode) {
725 case AR5K_ANTMODE_FIXED_A:
726 *tx_ant = 1; *rx_ant = 1; break;
727 case AR5K_ANTMODE_FIXED_B:
728 *tx_ant = 2; *rx_ant = 2; break;
729 case AR5K_ANTMODE_DEFAULT:
730 *tx_ant = 3; *rx_ant = 3; break;
731 }
732 return 0;
733}
734
735
736const struct ieee80211_ops ath5k_hw_ops = {
737 .tx = ath5k_tx,
738 .start = ath5k_start,
739 .stop = ath5k_stop,
740 .add_interface = ath5k_add_interface,
741 /* .change_interface = not implemented */
742 .remove_interface = ath5k_remove_interface,
743 .config = ath5k_config,
744 .bss_info_changed = ath5k_bss_info_changed,
745 .prepare_multicast = ath5k_prepare_multicast,
746 .configure_filter = ath5k_configure_filter,
747 /* .set_tim = not implemented */
748 .set_key = ath5k_set_key,
749 /* .update_tkip_key = not implemented */
750 /* .hw_scan = not implemented */
751 .sw_scan_start = ath5k_sw_scan_start,
752 .sw_scan_complete = ath5k_sw_scan_complete,
753 .get_stats = ath5k_get_stats,
754 /* .get_tkip_seq = not implemented */
755 /* .set_frag_threshold = not implemented */
756 /* .set_rts_threshold = not implemented */
757 /* .sta_add = not implemented */
758 /* .sta_remove = not implemented */
759 /* .sta_notify = not implemented */
760 .conf_tx = ath5k_conf_tx,
761 .get_tsf = ath5k_get_tsf,
762 .set_tsf = ath5k_set_tsf,
763 .reset_tsf = ath5k_reset_tsf,
764 /* .tx_last_beacon = not implemented */
765 /* .ampdu_action = not needed */
766 .get_survey = ath5k_get_survey,
767 .set_coverage_class = ath5k_set_coverage_class,
768 /* .rfkill_poll = not implemented */
769 /* .flush = not implemented */
770 /* .channel_switch = not implemented */
771 /* .napi_poll = not implemented */
772 .set_antenna = ath5k_set_antenna,
773 .get_antenna = ath5k_get_antenna,
774};