diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-02-20 05:21:35 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-02-29 15:37:26 -0500 |
commit | 004c872e78d433f84f0a5cd4db7a6c780c0946e1 (patch) | |
tree | bd9e7cd0b69e720738d49e170e4f4f64e9111e1a | |
parent | 836341a70471ba77657b0b420dd7eea3c30a038b (diff) |
mac80211: consolidate TIM handling code
This consolidates all TIM handling code to avoid re-introducing
errors with the bitmap/set_tim order and to reduce code. While
reading the code I noticed a possible problem so I also added
a comment about that.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | net/mac80211/ieee80211_i.h | 36 | ||||
-rw-r--r-- | net/mac80211/rx.c | 29 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 87 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 4 | ||||
-rw-r--r-- | net/mac80211/tx.c | 11 |
5 files changed, 84 insertions, 83 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1b4a4497030d..b07b3cbfd039 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -207,7 +207,7 @@ struct ieee80211_if_ap { | |||
207 | 207 | ||
208 | /* yes, this looks ugly, but guarantees that we can later use | 208 | /* yes, this looks ugly, but guarantees that we can later use |
209 | * bitmap_empty :) | 209 | * bitmap_empty :) |
210 | * NB: don't ever use set_bit, use bss_tim_set/bss_tim_clear! */ | 210 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ |
211 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 211 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; |
212 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 212 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
213 | struct sk_buff_head ps_bc_buf; | 213 | struct sk_buff_head ps_bc_buf; |
@@ -640,40 +640,6 @@ struct sta_attribute { | |||
640 | ssize_t (*store)(struct sta_info *, const char *buf, size_t count); | 640 | ssize_t (*store)(struct sta_info *, const char *buf, size_t count); |
641 | }; | 641 | }; |
642 | 642 | ||
643 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | ||
644 | { | ||
645 | /* | ||
646 | * This format has been mandated by the IEEE specifications, | ||
647 | * so this line may not be changed to use the __set_bit() format. | ||
648 | */ | ||
649 | bss->tim[aid / 8] |= (1 << (aid % 8)); | ||
650 | } | ||
651 | |||
652 | static inline void bss_tim_set(struct ieee80211_local *local, | ||
653 | struct ieee80211_if_ap *bss, u16 aid) | ||
654 | { | ||
655 | read_lock_bh(&local->sta_lock); | ||
656 | __bss_tim_set(bss, aid); | ||
657 | read_unlock_bh(&local->sta_lock); | ||
658 | } | ||
659 | |||
660 | static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) | ||
661 | { | ||
662 | /* | ||
663 | * This format has been mandated by the IEEE specifications, | ||
664 | * so this line may not be changed to use the __clear_bit() format. | ||
665 | */ | ||
666 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); | ||
667 | } | ||
668 | |||
669 | static inline void bss_tim_clear(struct ieee80211_local *local, | ||
670 | struct ieee80211_if_ap *bss, u16 aid) | ||
671 | { | ||
672 | read_lock_bh(&local->sta_lock); | ||
673 | __bss_tim_clear(bss, aid); | ||
674 | read_unlock_bh(&local->sta_lock); | ||
675 | } | ||
676 | |||
677 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | 643 | static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) |
678 | { | 644 | { |
679 | return compare_ether_addr(raddr, addr) == 0 || | 645 | return compare_ether_addr(raddr, addr) == 0 || |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0e8a371496b3..48574f6c0e74 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -596,19 +596,20 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
596 | DECLARE_MAC_BUF(mac); | 596 | DECLARE_MAC_BUF(mac); |
597 | 597 | ||
598 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | 598 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); |
599 | |||
599 | if (sdata->bss) | 600 | if (sdata->bss) |
600 | atomic_dec(&sdata->bss->num_sta_ps); | 601 | atomic_dec(&sdata->bss->num_sta_ps); |
602 | |||
601 | sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL); | 603 | sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL); |
602 | if (!skb_queue_empty(&sta->ps_tx_buf)) { | 604 | |
603 | if (sdata->bss) | 605 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
604 | bss_tim_clear(local, sdata->bss, sta->aid); | 606 | sta_info_clear_tim_bit(sta); |
605 | if (local->ops->set_tim) | 607 | |
606 | local->ops->set_tim(local_to_hw(local), sta->aid, 0); | ||
607 | } | ||
608 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 608 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
609 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", | 609 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", |
610 | dev->name, print_mac(mac, sta->addr), sta->aid); | 610 | dev->name, print_mac(mac, sta->addr), sta->aid); |
611 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 611 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
612 | |||
612 | /* Send all buffered frames to the station */ | 613 | /* Send all buffered frames to the station */ |
613 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 614 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { |
614 | pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; | 615 | pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; |
@@ -945,20 +946,20 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx) | |||
945 | 946 | ||
946 | dev_queue_xmit(skb); | 947 | dev_queue_xmit(skb); |
947 | 948 | ||
948 | if (no_pending_pkts) { | 949 | if (no_pending_pkts) |
949 | if (rx->sdata->bss) | 950 | sta_info_clear_tim_bit(rx->sta); |
950 | bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid); | ||
951 | if (rx->local->ops->set_tim) | ||
952 | rx->local->ops->set_tim(local_to_hw(rx->local), | ||
953 | rx->sta->aid, 0); | ||
954 | } | ||
955 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 951 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
956 | } else if (!rx->u.rx.sent_ps_buffered) { | 952 | } else if (!rx->u.rx.sent_ps_buffered) { |
953 | /* | ||
954 | * FIXME: This can be the result of a race condition between | ||
955 | * us expiring a frame and the station polling for it. | ||
956 | * Should we send it a null-func frame indicating we | ||
957 | * have nothing buffered for it? | ||
958 | */ | ||
957 | printk(KERN_DEBUG "%s: STA %s sent PS Poll even " | 959 | printk(KERN_DEBUG "%s: STA %s sent PS Poll even " |
958 | "though there is no buffered frames for it\n", | 960 | "though there is no buffered frames for it\n", |
959 | rx->dev->name, print_mac(mac, rx->sta->addr)); | 961 | rx->dev->name, print_mac(mac, rx->sta->addr)); |
960 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 962 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
961 | |||
962 | } | 963 | } |
963 | 964 | ||
964 | /* Free PS Poll skb here instead of returning RX_DROP that would | 965 | /* Free PS Poll skb here instead of returning RX_DROP that would |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a843bb7dd2d3..b31a627ff97f 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -191,6 +191,64 @@ struct sta_info * sta_info_add(struct ieee80211_local *local, | |||
191 | return sta; | 191 | return sta; |
192 | } | 192 | } |
193 | 193 | ||
194 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) | ||
195 | { | ||
196 | /* | ||
197 | * This format has been mandated by the IEEE specifications, | ||
198 | * so this line may not be changed to use the __set_bit() format. | ||
199 | */ | ||
200 | bss->tim[aid / 8] |= (1 << (aid % 8)); | ||
201 | } | ||
202 | |||
203 | static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) | ||
204 | { | ||
205 | /* | ||
206 | * This format has been mandated by the IEEE specifications, | ||
207 | * so this line may not be changed to use the __clear_bit() format. | ||
208 | */ | ||
209 | bss->tim[aid / 8] &= ~(1 << (aid % 8)); | ||
210 | } | ||
211 | |||
212 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | ||
213 | struct sta_info *sta) | ||
214 | { | ||
215 | if (bss) | ||
216 | __bss_tim_set(bss, sta->aid); | ||
217 | if (sta->local->ops->set_tim) | ||
218 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | ||
219 | } | ||
220 | |||
221 | void sta_info_set_tim_bit(struct sta_info *sta) | ||
222 | { | ||
223 | struct ieee80211_sub_if_data *sdata; | ||
224 | |||
225 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | ||
226 | |||
227 | read_lock_bh(&sta->local->sta_lock); | ||
228 | __sta_info_set_tim_bit(sdata->bss, sta); | ||
229 | read_unlock_bh(&sta->local->sta_lock); | ||
230 | } | ||
231 | |||
232 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | ||
233 | struct sta_info *sta) | ||
234 | { | ||
235 | if (bss) | ||
236 | __bss_tim_clear(bss, sta->aid); | ||
237 | if (sta->local->ops->set_tim) | ||
238 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | ||
239 | } | ||
240 | |||
241 | void sta_info_clear_tim_bit(struct sta_info *sta) | ||
242 | { | ||
243 | struct ieee80211_sub_if_data *sdata; | ||
244 | |||
245 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | ||
246 | |||
247 | read_lock_bh(&sta->local->sta_lock); | ||
248 | __sta_info_clear_tim_bit(sdata->bss, sta); | ||
249 | read_unlock_bh(&sta->local->sta_lock); | ||
250 | } | ||
251 | |||
194 | /* Caller must hold local->sta_lock */ | 252 | /* Caller must hold local->sta_lock */ |
195 | void sta_info_remove(struct sta_info *sta) | 253 | void sta_info_remove(struct sta_info *sta) |
196 | { | 254 | { |
@@ -207,10 +265,9 @@ void sta_info_remove(struct sta_info *sta) | |||
207 | sta->flags &= ~WLAN_STA_PS; | 265 | sta->flags &= ~WLAN_STA_PS; |
208 | if (sdata->bss) | 266 | if (sdata->bss) |
209 | atomic_dec(&sdata->bss->num_sta_ps); | 267 | atomic_dec(&sdata->bss->num_sta_ps); |
268 | __sta_info_clear_tim_bit(sdata->bss, sta); | ||
210 | } | 269 | } |
211 | local->num_sta--; | 270 | local->num_sta--; |
212 | sta_info_remove_aid_ptr(sta); | ||
213 | |||
214 | } | 271 | } |
215 | 272 | ||
216 | void sta_info_free(struct sta_info *sta) | 273 | void sta_info_free(struct sta_info *sta) |
@@ -310,13 +367,8 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
310 | "%s)\n", print_mac(mac, sta->addr)); | 367 | "%s)\n", print_mac(mac, sta->addr)); |
311 | dev_kfree_skb(skb); | 368 | dev_kfree_skb(skb); |
312 | 369 | ||
313 | if (skb_queue_empty(&sta->ps_tx_buf)) { | 370 | if (skb_queue_empty(&sta->ps_tx_buf)) |
314 | if (sdata->bss) | 371 | sta_info_clear_tim_bit(sta); |
315 | bss_tim_set(sta->local, sdata->bss, sta->aid); | ||
316 | if (sta->local->ops->set_tim) | ||
317 | sta->local->ops->set_tim(local_to_hw(sta->local), | ||
318 | sta->aid, 0); | ||
319 | } | ||
320 | } | 372 | } |
321 | } | 373 | } |
322 | 374 | ||
@@ -395,23 +447,6 @@ void sta_info_stop(struct ieee80211_local *local) | |||
395 | sta_info_flush(local, NULL); | 447 | sta_info_flush(local, NULL); |
396 | } | 448 | } |
397 | 449 | ||
398 | void sta_info_remove_aid_ptr(struct sta_info *sta) | ||
399 | { | ||
400 | struct ieee80211_sub_if_data *sdata; | ||
401 | |||
402 | if (sta->aid <= 0) | ||
403 | return; | ||
404 | |||
405 | sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); | ||
406 | |||
407 | if (sdata->bss) | ||
408 | __bss_tim_clear(sdata->bss, sta->aid); | ||
409 | if (sdata->local->ops->set_tim) | ||
410 | sdata->local->ops->set_tim(local_to_hw(sdata->local), | ||
411 | sta->aid, 0); | ||
412 | } | ||
413 | |||
414 | |||
415 | /** | 450 | /** |
416 | * sta_info_flush - flush matching STA entries from the STA table | 451 | * sta_info_flush - flush matching STA entries from the STA table |
417 | * @local: local interface data | 452 | * @local: local interface data |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index f3d9f872db4a..4099ece143ef 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -244,7 +244,9 @@ void sta_info_free(struct sta_info *sta); | |||
244 | void sta_info_init(struct ieee80211_local *local); | 244 | void sta_info_init(struct ieee80211_local *local); |
245 | int sta_info_start(struct ieee80211_local *local); | 245 | int sta_info_start(struct ieee80211_local *local); |
246 | void sta_info_stop(struct ieee80211_local *local); | 246 | void sta_info_stop(struct ieee80211_local *local); |
247 | void sta_info_remove_aid_ptr(struct sta_info *sta); | ||
248 | void sta_info_flush(struct ieee80211_local *local, struct net_device *dev); | 247 | void sta_info_flush(struct ieee80211_local *local, struct net_device *dev); |
249 | 248 | ||
249 | void sta_info_set_tim_bit(struct sta_info *sta); | ||
250 | void sta_info_clear_tim_bit(struct sta_info *sta); | ||
251 | |||
250 | #endif /* STA_INFO_H */ | 252 | #endif /* STA_INFO_H */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index db6a871b51ed..69fdb763aa8b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -416,14 +416,11 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx) | |||
416 | dev_kfree_skb(old); | 416 | dev_kfree_skb(old); |
417 | } else | 417 | } else |
418 | tx->local->total_ps_buffered++; | 418 | tx->local->total_ps_buffered++; |
419 | |||
419 | /* Queue frame to be sent after STA sends an PS Poll frame */ | 420 | /* Queue frame to be sent after STA sends an PS Poll frame */ |
420 | if (skb_queue_empty(&sta->ps_tx_buf)) { | 421 | if (skb_queue_empty(&sta->ps_tx_buf)) |
421 | if (tx->sdata->bss) | 422 | sta_info_set_tim_bit(sta); |
422 | bss_tim_set(tx->local, tx->sdata->bss, sta->aid); | 423 | |
423 | if (tx->local->ops->set_tim) | ||
424 | tx->local->ops->set_tim(local_to_hw(tx->local), | ||
425 | sta->aid, 1); | ||
426 | } | ||
427 | pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb; | 424 | pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb; |
428 | pkt_data->jiffies = jiffies; | 425 | pkt_data->jiffies = jiffies; |
429 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); | 426 | skb_queue_tail(&sta->ps_tx_buf, tx->skb); |