aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-02-20 05:21:35 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:37:26 -0500
commit004c872e78d433f84f0a5cd4db7a6c780c0946e1 (patch)
treebd9e7cd0b69e720738d49e170e4f4f64e9111e1a
parent836341a70471ba77657b0b420dd7eea3c30a038b (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.h36
-rw-r--r--net/mac80211/rx.c29
-rw-r--r--net/mac80211/sta_info.c87
-rw-r--r--net/mac80211/sta_info.h4
-rw-r--r--net/mac80211/tx.c11
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
643static 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
652static 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
660static 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
669static 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
677static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) 643static 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
194static 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
203static 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
212static 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
221void 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
232static 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
241void 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 */
195void sta_info_remove(struct sta_info *sta) 253void 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
216void sta_info_free(struct sta_info *sta) 273void 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
398void 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);
244void sta_info_init(struct ieee80211_local *local); 244void sta_info_init(struct ieee80211_local *local);
245int sta_info_start(struct ieee80211_local *local); 245int sta_info_start(struct ieee80211_local *local);
246void sta_info_stop(struct ieee80211_local *local); 246void sta_info_stop(struct ieee80211_local *local);
247void sta_info_remove_aid_ptr(struct sta_info *sta);
248void sta_info_flush(struct ieee80211_local *local, struct net_device *dev); 247void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
249 248
249void sta_info_set_tim_bit(struct sta_info *sta);
250void 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);