include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / net / mac80211 / agg-tx.c
index 6ddd114..96d2534 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/ieee80211.h>
+#include <linux/slab.h>
 #include <net/mac80211.h>
 #include "ieee80211_i.h"
 #include "driver-ops.h"
@@ -58,17 +59,17 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
 
        if (!skb) {
                printk(KERN_ERR "%s: failed to allocate buffer "
-                               "for addba request frame\n", sdata->dev->name);
+                               "for addba request frame\n", sdata->name);
                return;
        }
        skb_reserve(skb, local->hw.extra_tx_headroom);
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
        memset(mgmt, 0, 24);
        memcpy(mgmt->da, da, ETH_ALEN);
-       memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
+       memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
            sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-               memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
+               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
 
@@ -91,7 +92,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
        mgmt->u.action.u.addba_req.start_seq_num =
                                        cpu_to_le16(start_seq_num << 4);
 
-       ieee80211_tx_skb(sdata, skb, 1);
+       ieee80211_tx_skb(sdata, skb);
 }
 
 void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
@@ -104,7 +105,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
        skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
        if (!skb) {
                printk(KERN_ERR "%s: failed to allocate buffer for "
-                       "bar frame\n", sdata->dev->name);
+                       "bar frame\n", sdata->name);
                return;
        }
        skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -113,23 +114,29 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
        bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
                                         IEEE80211_STYPE_BACK_REQ);
        memcpy(bar->ra, ra, ETH_ALEN);
-       memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
+       memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);
        bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
        bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
        bar_control |= (u16)(tid << 12);
        bar->control = cpu_to_le16(bar_control);
        bar->start_seq_num = cpu_to_le16(ssn);
 
-       ieee80211_tx_skb(sdata, skb, 0);
+       IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+       ieee80211_tx_skb(sdata, skb);
 }
 
-static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
-                                          enum ieee80211_back_parties initiator)
+int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
+                                   enum ieee80211_back_parties initiator)
 {
        struct ieee80211_local *local = sta->local;
        int ret;
        u8 *state;
 
+#ifdef CONFIG_MAC80211_HT_DEBUG
+       printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
+              sta->sta.addr, tid);
+#endif /* CONFIG_MAC80211_HT_DEBUG */
+
        state = &sta->ampdu_mlme.tid_state_tx[tid];
 
        if (*state == HT_AGG_STATE_OPERATIONAL)
@@ -138,13 +145,12 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
        *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
                (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
 
-       ret = drv_ampdu_action(local, &sta->sdata->vif,
+       ret = drv_ampdu_action(local, sta->sdata,
                               IEEE80211_AMPDU_TX_STOP,
                               &sta->sta, tid, NULL);
 
        /* HW shall not deny going back to legacy */
        if (WARN_ON(ret)) {
-               *state = HT_AGG_STATE_OPERATIONAL;
                /*
                 * We may have pending packets get stuck in this case...
                 * Not bothering with a workaround for now.
@@ -174,12 +180,15 @@ static void sta_addba_resp_timer_expired(unsigned long data)
 
        /* check if the TID waits for addBA response */
        spin_lock_bh(&sta->lock);
-       if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
+       if ((*state & (HT_ADDBA_REQUESTED_MSK | HT_ADDBA_RECEIVED_MSK |
+                      HT_AGG_STATE_REQ_STOP_BA_MSK)) !=
+                                               HT_ADDBA_REQUESTED_MSK) {
                spin_unlock_bh(&sta->lock);
                *state = HT_AGG_STATE_IDLE;
 #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "timer expired on tid %d but we are not "
-                               "expecting addBA response there", tid);
+                               "(or no longer) expecting addBA response there",
+                       tid);
 #endif
                return;
        }
@@ -229,6 +238,14 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
            sdata->vif.type != NL80211_IFTYPE_AP)
                return -EINVAL;
 
+       if (test_sta_flags(sta, WLAN_STA_DISASSOC)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
+               printk(KERN_DEBUG "Disassociation is in progress. "
+                      "Denying BA session request\n");
+#endif
+               return -EINVAL;
+       }
+
        if (test_sta_flags(sta, WLAN_STA_SUSPEND)) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Suspend in progress. "
@@ -294,10 +311,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
         * call back right away, it must see that the flow has begun */
        *state |= HT_ADDBA_REQUESTED_MSK;
 
-       start_seq_num = sta->tid_seq[tid];
+       start_seq_num = sta->tid_seq[tid] >> 4;
 
-       ret = drv_ampdu_action(local, &sdata->vif,
-                              IEEE80211_AMPDU_TX_START,
+       ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
                               pubsta, tid, &start_seq_num);
 
        if (ret) {
@@ -413,7 +429,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
        ieee80211_agg_splice_finish(local, sta, tid);
        spin_unlock(&local->ampdu_lock);
 
-       drv_ampdu_action(local, &sta->sdata->vif,
+       drv_ampdu_action(local, sta->sdata,
                         IEEE80211_AMPDU_TX_OPERATIONAL,
                         &sta->sta, tid, NULL);
 }
@@ -434,7 +450,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
        }
 
        rcu_read_lock();
-       sta = sta_info_get(local, ra);
+       sta = sta_info_get(sdata, ra);
        if (!sta) {
                rcu_read_unlock();
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -482,13 +498,14 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
 #ifdef CONFIG_MAC80211_HT_DEBUG
                if (net_ratelimit())
                        printk(KERN_WARNING "%s: Not enough memory, "
-                              "dropping start BA session", skb->dev->name);
+                              "dropping start BA session", sdata->name);
 #endif
                return;
        }
        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
        memcpy(&ra_tid->ra, ra, ETH_ALEN);
        ra_tid->tid = tid;
+       ra_tid->vif = vif;
 
        skb->pkt_type = IEEE80211_ADDBA_MSG;
        skb_queue_tail(&local->skb_queue, skb);
@@ -511,11 +528,6 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                goto unlock;
        }
 
-#ifdef CONFIG_MAC80211_HT_DEBUG
-       printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
-              sta->sta.addr, tid);
-#endif /* CONFIG_MAC80211_HT_DEBUG */
-
        ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator);
 
  unlock:
@@ -530,7 +542,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct ieee80211_local *local = sdata->local;
 
-       if (WARN_ON(!local->ops->ampdu_action))
+       if (!local->ops->ampdu_action)
                return -EINVAL;
 
        if (tid >= STA_TID_NUM)
@@ -561,7 +573,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
        rcu_read_lock();
-       sta = sta_info_get(local, ra);
+       sta = sta_info_get(sdata, ra);
        if (!sta) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "Could not find station: %pM\n", ra);
@@ -618,13 +630,14 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
 #ifdef CONFIG_MAC80211_HT_DEBUG
                if (net_ratelimit())
                        printk(KERN_WARNING "%s: Not enough memory, "
-                              "dropping stop BA session", skb->dev->name);
+                              "dropping stop BA session", sdata->name);
 #endif
                return;
        }
        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
        memcpy(&ra_tid->ra, ra, ETH_ALEN);
        ra_tid->tid = tid;
+       ra_tid->vif = vif;
 
        skb->pkt_type = IEEE80211_DELBA_MSG;
        skb_queue_tail(&local->skb_queue, skb);
@@ -646,21 +659,21 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 
        state = &sta->ampdu_mlme.tid_state_tx[tid];
 
-       del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
-
        spin_lock_bh(&sta->lock);
 
        if (!(*state & HT_ADDBA_REQUESTED_MSK))
-               goto timer_still_needed;
+               goto out;
 
        if (mgmt->u.action.u.addba_resp.dialog_token !=
                sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
                printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
-               goto timer_still_needed;
+               goto out;
        }
 
+       del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
+
 #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
@@ -679,10 +692,6 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
                ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
        }
 
-       goto out;
-
- timer_still_needed:
-       add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
  out:
        spin_unlock_bh(&sta->lock);
 }