diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/beacon.c | 141 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 48 |
3 files changed, 47 insertions, 146 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 3e7a5726652b..9dd8fbb847fd 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -416,8 +416,8 @@ struct ath_beacon { | |||
416 | 416 | ||
417 | void ath_beacon_tasklet(unsigned long data); | 417 | void ath_beacon_tasklet(unsigned long data); |
418 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); | 418 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); |
419 | int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); | 419 | void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif); |
420 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); | 420 | void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); |
421 | int ath_beaconq_config(struct ath_softc *sc); | 421 | int ath_beaconq_config(struct ath_softc *sc); |
422 | void ath_set_beacon(struct ath_softc *sc); | 422 | void ath_set_beacon(struct ath_softc *sc); |
423 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); | 423 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 40775da8941e..d35700287d68 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -222,132 +222,57 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
222 | return bf; | 222 | return bf; |
223 | } | 223 | } |
224 | 224 | ||
225 | int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) | 225 | void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif) |
226 | { | 226 | { |
227 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 227 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
228 | struct ath_vif *avp; | 228 | struct ath_vif *avp = (void *)vif->drv_priv; |
229 | struct ath_buf *bf; | 229 | int slot; |
230 | struct sk_buff *skb; | ||
231 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | ||
232 | __le64 tstamp; | ||
233 | 230 | ||
234 | avp = (void *)vif->drv_priv; | 231 | avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, struct ath_buf, list); |
232 | list_del(&avp->av_bcbuf->list); | ||
235 | 233 | ||
236 | /* Allocate a beacon descriptor if we haven't done so. */ | 234 | for (slot = 0; slot < ATH_BCBUF; slot++) { |
237 | if (!avp->av_bcbuf) { | 235 | if (sc->beacon.bslot[slot] == NULL) { |
238 | /* Allocate beacon state for hostap/ibss. We know | 236 | avp->av_bslot = slot; |
239 | * a buffer is available. */ | 237 | avp->is_bslot_active = false; |
240 | avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, | 238 | break; |
241 | struct ath_buf, list); | ||
242 | list_del(&avp->av_bcbuf->list); | ||
243 | |||
244 | if (ath9k_uses_beacons(vif->type)) { | ||
245 | int slot; | ||
246 | /* | ||
247 | * Assign the vif to a beacon xmit slot. As | ||
248 | * above, this cannot fail to find one. | ||
249 | */ | ||
250 | avp->av_bslot = 0; | ||
251 | for (slot = 0; slot < ATH_BCBUF; slot++) | ||
252 | if (sc->beacon.bslot[slot] == NULL) { | ||
253 | avp->av_bslot = slot; | ||
254 | avp->is_bslot_active = false; | ||
255 | |||
256 | /* NB: keep looking for a double slot */ | ||
257 | if (slot == 0 || !sc->beacon.bslot[slot-1]) | ||
258 | break; | ||
259 | } | ||
260 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); | ||
261 | sc->beacon.bslot[avp->av_bslot] = vif; | ||
262 | sc->nbcnvifs++; | ||
263 | } | 239 | } |
264 | } | 240 | } |
265 | 241 | ||
266 | /* release the previous beacon frame, if it already exists. */ | 242 | sc->beacon.bslot[avp->av_bslot] = vif; |
267 | bf = avp->av_bcbuf; | 243 | sc->nbcnvifs++; |
268 | if (bf->bf_mpdu != NULL) { | ||
269 | skb = bf->bf_mpdu; | ||
270 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | ||
271 | skb->len, DMA_TO_DEVICE); | ||
272 | dev_kfree_skb_any(skb); | ||
273 | bf->bf_mpdu = NULL; | ||
274 | bf->bf_buf_addr = 0; | ||
275 | } | ||
276 | |||
277 | /* NB: the beacon data buffer must be 32-bit aligned. */ | ||
278 | skb = ieee80211_beacon_get(sc->hw, vif); | ||
279 | if (skb == NULL) | ||
280 | return -ENOMEM; | ||
281 | |||
282 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | ||
283 | sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp); | ||
284 | /* Calculate a TSF adjustment factor required for staggered beacons. */ | ||
285 | if (avp->av_bslot > 0) { | ||
286 | u64 tsfadjust; | ||
287 | int intval; | ||
288 | 244 | ||
289 | intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; | 245 | ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n", |
246 | avp->av_bslot); | ||
247 | } | ||
290 | 248 | ||
291 | /* | 249 | void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif) |
292 | * Calculate the TSF offset for this beacon slot, i.e., the | 250 | { |
293 | * number of usecs that need to be added to the timestamp field | 251 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
294 | * in Beacon and Probe Response frames. Beacon slot 0 is | 252 | struct ath_vif *avp = (void *)vif->drv_priv; |
295 | * processed at the correct offset, so it does not require TSF | 253 | struct ath_buf *bf = avp->av_bcbuf; |
296 | * adjustment. Other slots are adjusted to get the timestamp | ||
297 | * close to the TBTT for the BSS. | ||
298 | */ | ||
299 | tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF; | ||
300 | avp->tsf_adjust = cpu_to_le64(tsfadjust); | ||
301 | 254 | ||
302 | ath_dbg(common, BEACON, | 255 | ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n", |
303 | "stagger beacons, bslot %d intval %u tsfadjust %llu\n", | 256 | avp->av_bslot); |
304 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | ||
305 | 257 | ||
306 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = | 258 | tasklet_disable(&sc->bcon_tasklet); |
307 | avp->tsf_adjust; | ||
308 | } else | ||
309 | avp->tsf_adjust = cpu_to_le64(0); | ||
310 | 259 | ||
311 | bf->bf_mpdu = skb; | 260 | if (bf && bf->bf_mpdu) { |
312 | bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, | 261 | struct sk_buff *skb = bf->bf_mpdu; |
313 | skb->len, DMA_TO_DEVICE); | 262 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
314 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { | 263 | skb->len, DMA_TO_DEVICE); |
315 | dev_kfree_skb_any(skb); | 264 | dev_kfree_skb_any(skb); |
316 | bf->bf_mpdu = NULL; | 265 | bf->bf_mpdu = NULL; |
317 | bf->bf_buf_addr = 0; | 266 | bf->bf_buf_addr = 0; |
318 | ath_err(common, "dma_mapping_error on beacon alloc\n"); | ||
319 | return -ENOMEM; | ||
320 | } | 267 | } |
321 | avp->is_bslot_active = true; | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) | ||
327 | { | ||
328 | if (avp->av_bcbuf != NULL) { | ||
329 | struct ath_buf *bf; | ||
330 | |||
331 | avp->is_bslot_active = false; | ||
332 | if (avp->av_bslot != -1) { | ||
333 | sc->beacon.bslot[avp->av_bslot] = NULL; | ||
334 | sc->nbcnvifs--; | ||
335 | avp->av_bslot = -1; | ||
336 | } | ||
337 | 268 | ||
338 | bf = avp->av_bcbuf; | 269 | avp->av_bcbuf = NULL; |
339 | if (bf->bf_mpdu != NULL) { | 270 | avp->is_bslot_active = false; |
340 | struct sk_buff *skb = bf->bf_mpdu; | 271 | sc->beacon.bslot[avp->av_bslot] = NULL; |
341 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | 272 | sc->nbcnvifs--; |
342 | skb->len, DMA_TO_DEVICE); | 273 | list_add_tail(&bf->list, &sc->beacon.bbuf); |
343 | dev_kfree_skb_any(skb); | ||
344 | bf->bf_mpdu = NULL; | ||
345 | bf->bf_buf_addr = 0; | ||
346 | } | ||
347 | list_add_tail(&bf->list, &sc->beacon.bbuf); | ||
348 | 274 | ||
349 | avp->av_bcbuf = NULL; | 275 | tasklet_enable(&sc->bcon_tasklet); |
350 | } | ||
351 | } | 276 | } |
352 | 277 | ||
353 | void ath_beacon_tasklet(unsigned long data) | 278 | void ath_beacon_tasklet(unsigned long data) |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a07f69c1e9e9..f7d92e0ba4dd 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -852,16 +852,6 @@ bool ath9k_uses_beacons(int type) | |||
852 | } | 852 | } |
853 | } | 853 | } |
854 | 854 | ||
855 | static void ath9k_reclaim_beacon(struct ath_softc *sc, | ||
856 | struct ieee80211_vif *vif) | ||
857 | { | ||
858 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
859 | |||
860 | ath9k_set_beaconing_status(sc, false); | ||
861 | ath_beacon_return(sc, avp); | ||
862 | ath9k_set_beaconing_status(sc, true); | ||
863 | } | ||
864 | |||
865 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | 855 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
866 | { | 856 | { |
867 | struct ath9k_vif_iter_data *iter_data = data; | 857 | struct ath9k_vif_iter_data *iter_data = data; |
@@ -977,22 +967,6 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
977 | } | 967 | } |
978 | } | 968 | } |
979 | 969 | ||
980 | /* Called with sc->mutex held, vif counts set up properly. */ | ||
981 | static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | ||
982 | struct ieee80211_vif *vif) | ||
983 | { | ||
984 | struct ath_softc *sc = hw->priv; | ||
985 | |||
986 | ath9k_calculate_summary_state(hw, vif); | ||
987 | |||
988 | if (ath9k_uses_beacons(vif->type)) { | ||
989 | /* Reserve a beacon slot for the vif */ | ||
990 | ath9k_set_beaconing_status(sc, false); | ||
991 | ath_beacon_alloc(sc, vif); | ||
992 | ath9k_set_beaconing_status(sc, true); | ||
993 | } | ||
994 | } | ||
995 | |||
996 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 970 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
997 | struct ieee80211_vif *vif) | 971 | struct ieee80211_vif *vif) |
998 | { | 972 | { |
@@ -1032,7 +1006,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1032 | 1006 | ||
1033 | sc->nvifs++; | 1007 | sc->nvifs++; |
1034 | 1008 | ||
1035 | ath9k_do_vif_add_setup(hw, vif); | 1009 | ath9k_calculate_summary_state(hw, vif); |
1010 | if (ath9k_uses_beacons(vif->type)) | ||
1011 | ath9k_beacon_assign_slot(sc, vif); | ||
1012 | |||
1036 | out: | 1013 | out: |
1037 | mutex_unlock(&sc->mutex); | 1014 | mutex_unlock(&sc->mutex); |
1038 | ath9k_ps_restore(sc); | 1015 | ath9k_ps_restore(sc); |
@@ -1049,6 +1026,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw, | |||
1049 | int ret = 0; | 1026 | int ret = 0; |
1050 | 1027 | ||
1051 | ath_dbg(common, CONFIG, "Change Interface\n"); | 1028 | ath_dbg(common, CONFIG, "Change Interface\n"); |
1029 | |||
1052 | mutex_lock(&sc->mutex); | 1030 | mutex_lock(&sc->mutex); |
1053 | ath9k_ps_wakeup(sc); | 1031 | ath9k_ps_wakeup(sc); |
1054 | 1032 | ||
@@ -1061,15 +1039,16 @@ static int ath9k_change_interface(struct ieee80211_hw *hw, | |||
1061 | } | 1039 | } |
1062 | } | 1040 | } |
1063 | 1041 | ||
1064 | /* Clean up old vif stuff */ | ||
1065 | if (ath9k_uses_beacons(vif->type)) | 1042 | if (ath9k_uses_beacons(vif->type)) |
1066 | ath9k_reclaim_beacon(sc, vif); | 1043 | ath9k_beacon_remove_slot(sc, vif); |
1067 | 1044 | ||
1068 | /* Add new settings */ | ||
1069 | vif->type = new_type; | 1045 | vif->type = new_type; |
1070 | vif->p2p = p2p; | 1046 | vif->p2p = p2p; |
1071 | 1047 | ||
1072 | ath9k_do_vif_add_setup(hw, vif); | 1048 | ath9k_calculate_summary_state(hw, vif); |
1049 | if (ath9k_uses_beacons(vif->type)) | ||
1050 | ath9k_beacon_assign_slot(sc, vif); | ||
1051 | |||
1073 | out: | 1052 | out: |
1074 | ath9k_ps_restore(sc); | 1053 | ath9k_ps_restore(sc); |
1075 | mutex_unlock(&sc->mutex); | 1054 | mutex_unlock(&sc->mutex); |
@@ -1089,9 +1068,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1089 | 1068 | ||
1090 | sc->nvifs--; | 1069 | sc->nvifs--; |
1091 | 1070 | ||
1092 | /* Reclaim beacon resources */ | ||
1093 | if (ath9k_uses_beacons(vif->type)) | 1071 | if (ath9k_uses_beacons(vif->type)) |
1094 | ath9k_reclaim_beacon(sc, vif); | 1072 | ath9k_beacon_remove_slot(sc, vif); |
1095 | 1073 | ||
1096 | ath9k_calculate_summary_state(hw, NULL); | 1074 | ath9k_calculate_summary_state(hw, NULL); |
1097 | 1075 | ||
@@ -1610,9 +1588,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1610 | (changed & BSS_CHANGED_BEACON_ENABLED) || | 1588 | (changed & BSS_CHANGED_BEACON_ENABLED) || |
1611 | (changed & BSS_CHANGED_BEACON_INT))) { | 1589 | (changed & BSS_CHANGED_BEACON_INT))) { |
1612 | ath9k_set_beaconing_status(sc, false); | 1590 | ath9k_set_beaconing_status(sc, false); |
1613 | if (bss_conf->enable_beacon) | 1591 | if (!bss_conf->enable_beacon) |
1614 | ath_beacon_alloc(sc, vif); | ||
1615 | else | ||
1616 | avp->is_bslot_active = false; | 1592 | avp->is_bslot_active = false; |
1617 | ath_beacon_config(sc, vif); | 1593 | ath_beacon_config(sc, vif); |
1618 | ath9k_set_beaconing_status(sc, true); | 1594 | ath9k_set_beaconing_status(sc, true); |