]> err.no Git - linux-2.6/blobdiff - net/mac80211/sta_info.c
mac80211: consolidate TIM handling code
[linux-2.6] / net / mac80211 / sta_info.c
index ddc1f47194dd10228830d06f34030e2458acf070..b31a627ff97fecc4f0390e94c6a458d29819d8e8 100644 (file)
@@ -74,30 +74,6 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
 }
 EXPORT_SYMBOL(sta_info_get);
 
-int sta_info_min_txrate_get(struct ieee80211_local *local)
-{
-       struct sta_info *sta;
-       struct ieee80211_hw_mode *mode;
-       int min_txrate = 9999999;
-       int i;
-
-       read_lock_bh(&local->sta_lock);
-       mode = local->oper_hw_mode;
-       for (i = 0; i < STA_HASH_SIZE; i++) {
-               sta = local->sta_hash[i];
-               while (sta) {
-                       if (sta->txrate < min_txrate)
-                               min_txrate = sta->txrate;
-                       sta = sta->hnext;
-               }
-       }
-       read_unlock_bh(&local->sta_lock);
-       if (min_txrate == 9999999)
-               min_txrate = 0;
-
-       return mode->rates[min_txrate].rate;
-}
-
 
 static void sta_info_release(struct kref *kref)
 {
@@ -215,6 +191,64 @@ struct sta_info * sta_info_add(struct ieee80211_local *local,
        return sta;
 }
 
+static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
+{
+       /*
+        * This format has been mandated by the IEEE specifications,
+        * so this line may not be changed to use the __set_bit() format.
+        */
+       bss->tim[aid / 8] |= (1 << (aid % 8));
+}
+
+static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
+{
+       /*
+        * This format has been mandated by the IEEE specifications,
+        * so this line may not be changed to use the __clear_bit() format.
+        */
+       bss->tim[aid / 8] &= ~(1 << (aid % 8));
+}
+
+static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
+                                  struct sta_info *sta)
+{
+       if (bss)
+               __bss_tim_set(bss, sta->aid);
+       if (sta->local->ops->set_tim)
+               sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1);
+}
+
+void sta_info_set_tim_bit(struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+
+       read_lock_bh(&sta->local->sta_lock);
+       __sta_info_set_tim_bit(sdata->bss, sta);
+       read_unlock_bh(&sta->local->sta_lock);
+}
+
+static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
+                                    struct sta_info *sta)
+{
+       if (bss)
+               __bss_tim_clear(bss, sta->aid);
+       if (sta->local->ops->set_tim)
+               sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0);
+}
+
+void sta_info_clear_tim_bit(struct sta_info *sta)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+
+       read_lock_bh(&sta->local->sta_lock);
+       __sta_info_clear_tim_bit(sdata->bss, sta);
+       read_unlock_bh(&sta->local->sta_lock);
+}
+
 /* Caller must hold local->sta_lock */
 void sta_info_remove(struct sta_info *sta)
 {
@@ -231,10 +265,9 @@ void sta_info_remove(struct sta_info *sta)
                sta->flags &= ~WLAN_STA_PS;
                if (sdata->bss)
                        atomic_dec(&sdata->bss->num_sta_ps);
+               __sta_info_clear_tim_bit(sdata->bss, sta);
        }
        local->num_sta--;
-       sta_info_remove_aid_ptr(sta);
-
 }
 
 void sta_info_free(struct sta_info *sta)
@@ -310,6 +343,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
 {
        unsigned long flags;
        struct sk_buff *skb;
+       struct ieee80211_sub_if_data *sdata;
        DECLARE_MAC_BUF(mac);
 
        if (skb_queue_empty(&sta->ps_tx_buf))
@@ -318,21 +352,23 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local,
        for (;;) {
                spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
                skb = skb_peek(&sta->ps_tx_buf);
-               if (sta_info_buffer_expired(local, sta, skb)) {
+               if (sta_info_buffer_expired(local, sta, skb))
                        skb = __skb_dequeue(&sta->ps_tx_buf);
-                       if (skb_queue_empty(&sta->ps_tx_buf))
-                               sta->flags &= ~WLAN_STA_TIM;
-               } else
+               else
                        skb = NULL;
                spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
 
-               if (skb) {
-                       local->total_ps_buffered--;
-                       printk(KERN_DEBUG "Buffered frame expired (STA "
-                              "%s)\n", print_mac(mac, sta->addr));
-                       dev_kfree_skb(skb);
-               } else
+               if (!skb)
                        break;
+
+               sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
+               local->total_ps_buffered--;
+               printk(KERN_DEBUG "Buffered frame expired (STA "
+                      "%s)\n", print_mac(mac, sta->addr));
+               dev_kfree_skb(skb);
+
+               if (skb_queue_empty(&sta->ps_tx_buf))
+                       sta_info_clear_tim_bit(sta);
        }
 }
 
@@ -411,23 +447,6 @@ void sta_info_stop(struct ieee80211_local *local)
        sta_info_flush(local, NULL);
 }
 
-void sta_info_remove_aid_ptr(struct sta_info *sta)
-{
-       struct ieee80211_sub_if_data *sdata;
-
-       if (sta->aid <= 0)
-               return;
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-
-       if (sdata->local->ops->set_tim)
-               sdata->local->ops->set_tim(local_to_hw(sdata->local),
-                                         sta->aid, 0);
-       if (sdata->bss)
-               __bss_tim_clear(sdata->bss, sta->aid);
-}
-
-
 /**
  * sta_info_flush - flush matching STA entries from the STA table
  * @local: local interface data