diff options
author | David S. Miller <davem@davemloft.net> | 2008-03-27 21:01:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-27 21:01:13 -0400 |
commit | ed85f2c3b2b72bd20f617ac749f5c22be8d0f66e (patch) | |
tree | cb077293e1b36a5d6e2a138deb9663078a2d850e /net/mac80211 | |
parent | bc09dff198e67a98a82c42000006b39f6d502031 (diff) | |
parent | e5225b397308f9eea86327293b73dc88068e0179 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.26
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/debugfs_sta.c | 19 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 64 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 50 | ||||
-rw-r--r-- | net/mac80211/ieee80211_ioctl.c | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 84 | ||||
-rw-r--r-- | net/mac80211/rx.c | 10 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 30 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 49 |
8 files changed, 182 insertions, 127 deletions
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index fc2c1a192ed2..256ea880d28b 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -169,27 +169,30 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
169 | p += scnprintf(p, sizeof(buf)+buf-p, "\n RX :"); | 169 | p += scnprintf(p, sizeof(buf)+buf-p, "\n RX :"); |
170 | for (i = 0; i < STA_TID_NUM; i++) | 170 | for (i = 0; i < STA_TID_NUM; i++) |
171 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", | 171 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", |
172 | sta->ampdu_mlme.tid_rx[i].state); | 172 | sta->ampdu_mlme.tid_state_rx[i]); |
173 | 173 | ||
174 | p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:"); | 174 | p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:"); |
175 | for (i = 0; i < STA_TID_NUM; i++) | 175 | for (i = 0; i < STA_TID_NUM; i++) |
176 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", | 176 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", |
177 | sta->ampdu_mlme.tid_rx[i].dialog_token); | 177 | sta->ampdu_mlme.tid_state_rx[i]? |
178 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | ||
178 | 179 | ||
179 | p += scnprintf(p, sizeof(buf)+buf-p, "\n TX :"); | 180 | p += scnprintf(p, sizeof(buf)+buf-p, "\n TX :"); |
180 | for (i = 0; i < STA_TID_NUM; i++) | 181 | for (i = 0; i < STA_TID_NUM; i++) |
181 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", | 182 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", |
182 | sta->ampdu_mlme.tid_tx[i].state); | 183 | sta->ampdu_mlme.tid_state_tx[i]); |
183 | 184 | ||
184 | p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:"); | 185 | p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:"); |
185 | for (i = 0; i < STA_TID_NUM; i++) | 186 | for (i = 0; i < STA_TID_NUM; i++) |
186 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", | 187 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", |
187 | sta->ampdu_mlme.tid_tx[i].dialog_token); | 188 | sta->ampdu_mlme.tid_state_tx[i]? |
189 | sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); | ||
188 | 190 | ||
189 | p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :"); | 191 | p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :"); |
190 | for (i = 0; i < STA_TID_NUM; i++) | 192 | for (i = 0; i < STA_TID_NUM; i++) |
191 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", | 193 | p += scnprintf(p, sizeof(buf)+buf-p, "%5d", |
192 | sta->ampdu_mlme.tid_tx[i].ssn); | 194 | sta->ampdu_mlme.tid_state_tx[i]? |
195 | sta->ampdu_mlme.tid_tx[i]->ssn : 0); | ||
193 | 196 | ||
194 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); | 197 | p += scnprintf(p, sizeof(buf)+buf-p, "\n"); |
195 | 198 | ||
@@ -230,11 +233,13 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
230 | strcpy(state, "off "); | 233 | strcpy(state, "off "); |
231 | ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0, | 234 | ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0, |
232 | WLAN_REASON_QSTA_REQUIRE_SETUP); | 235 | WLAN_REASON_QSTA_REQUIRE_SETUP); |
233 | sta->ampdu_mlme.tid_rx[tid_num].buf_size = 0xFF; | 236 | sta->ampdu_mlme.tid_state_rx[tid_num] |= |
237 | HT_AGG_STATE_DEBUGFS_CTL; | ||
234 | tid_static_rx[tid_num] = 0; | 238 | tid_static_rx[tid_num] = 0; |
235 | } else { | 239 | } else { |
236 | strcpy(state, "on "); | 240 | strcpy(state, "on "); |
237 | sta->ampdu_mlme.tid_rx[tid_num].buf_size = 0x00; | 241 | sta->ampdu_mlme.tid_state_rx[tid_num] &= |
242 | ~HT_AGG_STATE_DEBUGFS_CTL; | ||
238 | tid_static_rx[tid_num] = 1; | 243 | tid_static_rx[tid_num] = 1; |
239 | } | 244 | } |
240 | printk(KERN_DEBUG "debugfs - try switching tid %u %s\n", | 245 | printk(KERN_DEBUG "debugfs - try switching tid %u %s\n", |
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 616ce10d2a38..8c0f782d21e3 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -569,12 +569,12 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
569 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 569 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
570 | 570 | ||
571 | /* we have tried too many times, receiver does not want A-MPDU */ | 571 | /* we have tried too many times, receiver does not want A-MPDU */ |
572 | if (sta->ampdu_mlme.tid_tx[tid].addba_req_num > HT_AGG_MAX_RETRIES) { | 572 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { |
573 | ret = -EBUSY; | 573 | ret = -EBUSY; |
574 | goto start_ba_exit; | 574 | goto start_ba_exit; |
575 | } | 575 | } |
576 | 576 | ||
577 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 577 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
578 | /* check if the TID is not in aggregation flow already */ | 578 | /* check if the TID is not in aggregation flow already */ |
579 | if (*state != HT_AGG_STATE_IDLE) { | 579 | if (*state != HT_AGG_STATE_IDLE) { |
580 | #ifdef CONFIG_MAC80211_HT_DEBUG | 580 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -585,6 +585,23 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
585 | goto start_ba_exit; | 585 | goto start_ba_exit; |
586 | } | 586 | } |
587 | 587 | ||
588 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
589 | sta->ampdu_mlme.tid_tx[tid] = | ||
590 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
591 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
592 | if (net_ratelimit()) | ||
593 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
594 | tid); | ||
595 | ret = -ENOMEM; | ||
596 | goto start_ba_exit; | ||
597 | } | ||
598 | /* Tx timer */ | ||
599 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
600 | sta_addba_resp_timer_expired; | ||
601 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
602 | (unsigned long)&sta->timer_to_tid[tid]; | ||
603 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
604 | |||
588 | /* ensure that TX flow won't interrupt us | 605 | /* ensure that TX flow won't interrupt us |
589 | * until the end of the call to requeue function */ | 606 | * until the end of the call to requeue function */ |
590 | spin_lock_bh(&local->mdev->queue_lock); | 607 | spin_lock_bh(&local->mdev->queue_lock); |
@@ -596,11 +613,10 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
596 | * don't switch to aggregation */ | 613 | * don't switch to aggregation */ |
597 | if (ret) { | 614 | if (ret) { |
598 | #ifdef CONFIG_MAC80211_HT_DEBUG | 615 | #ifdef CONFIG_MAC80211_HT_DEBUG |
599 | printk(KERN_DEBUG "BA request denied - no queue available for" | 616 | printk(KERN_DEBUG "BA request denied - queue unavailable for" |
600 | " tid %d\n", tid); | 617 | " tid %d\n", tid); |
601 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 618 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
602 | spin_unlock_bh(&local->mdev->queue_lock); | 619 | goto start_ba_err; |
603 | goto start_ba_exit; | ||
604 | } | 620 | } |
605 | sdata = sta->sdata; | 621 | sdata = sta->sdata; |
606 | 622 | ||
@@ -618,38 +634,40 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
618 | * allocated queue */ | 634 | * allocated queue */ |
619 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | 635 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); |
620 | #ifdef CONFIG_MAC80211_HT_DEBUG | 636 | #ifdef CONFIG_MAC80211_HT_DEBUG |
621 | printk(KERN_DEBUG "BA request denied - HW or queue unavailable" | 637 | printk(KERN_DEBUG "BA request denied - HW unavailable for" |
622 | " for tid %d\n", tid); | 638 | " tid %d\n", tid); |
623 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 639 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
624 | spin_unlock_bh(&local->mdev->queue_lock); | ||
625 | *state = HT_AGG_STATE_IDLE; | 640 | *state = HT_AGG_STATE_IDLE; |
626 | goto start_ba_exit; | 641 | goto start_ba_err; |
627 | } | 642 | } |
628 | 643 | ||
629 | /* Will put all the packets in the new SW queue */ | 644 | /* Will put all the packets in the new SW queue */ |
630 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | 645 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); |
631 | spin_unlock_bh(&local->mdev->queue_lock); | 646 | spin_unlock_bh(&local->mdev->queue_lock); |
632 | 647 | ||
633 | /* We have most probably almost emptied the legacy queue */ | ||
634 | /* ieee80211_wake_queue(local_to_hw(local), ieee802_1d_to_ac[tid]); */ | ||
635 | |||
636 | /* send an addBA request */ | 648 | /* send an addBA request */ |
637 | sta->ampdu_mlme.dialog_token_allocator++; | 649 | sta->ampdu_mlme.dialog_token_allocator++; |
638 | sta->ampdu_mlme.tid_tx[tid].dialog_token = | 650 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = |
639 | sta->ampdu_mlme.dialog_token_allocator; | 651 | sta->ampdu_mlme.dialog_token_allocator; |
640 | sta->ampdu_mlme.tid_tx[tid].ssn = start_seq_num; | 652 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; |
641 | 653 | ||
642 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, | 654 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, |
643 | sta->ampdu_mlme.tid_tx[tid].dialog_token, | 655 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, |
644 | sta->ampdu_mlme.tid_tx[tid].ssn, | 656 | sta->ampdu_mlme.tid_tx[tid]->ssn, |
645 | 0x40, 5000); | 657 | 0x40, 5000); |
646 | 658 | ||
647 | /* activate the timer for the recipient's addBA response */ | 659 | /* activate the timer for the recipient's addBA response */ |
648 | sta->ampdu_mlme.tid_tx[tid].addba_resp_timer.expires = | 660 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = |
649 | jiffies + ADDBA_RESP_INTERVAL; | 661 | jiffies + ADDBA_RESP_INTERVAL; |
650 | add_timer(&sta->ampdu_mlme.tid_tx[tid].addba_resp_timer); | 662 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
651 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | 663 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); |
664 | goto start_ba_exit; | ||
652 | 665 | ||
666 | start_ba_err: | ||
667 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
668 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
669 | spin_unlock_bh(&local->mdev->queue_lock); | ||
670 | ret = -EBUSY; | ||
653 | start_ba_exit: | 671 | start_ba_exit: |
654 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 672 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
655 | rcu_read_unlock(); | 673 | rcu_read_unlock(); |
@@ -683,7 +701,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
683 | } | 701 | } |
684 | 702 | ||
685 | /* check if the TID is in aggregation */ | 703 | /* check if the TID is in aggregation */ |
686 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 704 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
687 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 705 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
688 | 706 | ||
689 | if (*state != HT_AGG_STATE_OPERATIONAL) { | 707 | if (*state != HT_AGG_STATE_OPERATIONAL) { |
@@ -741,7 +759,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
741 | return; | 759 | return; |
742 | } | 760 | } |
743 | 761 | ||
744 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 762 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
745 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 763 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
746 | 764 | ||
747 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 765 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
@@ -790,7 +808,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
790 | rcu_read_unlock(); | 808 | rcu_read_unlock(); |
791 | return; | 809 | return; |
792 | } | 810 | } |
793 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 811 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
794 | 812 | ||
795 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 813 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
796 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | 814 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { |
@@ -819,7 +837,9 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
819 | * necessarily stopped */ | 837 | * necessarily stopped */ |
820 | netif_schedule(local->mdev); | 838 | netif_schedule(local->mdev); |
821 | *state = HT_AGG_STATE_IDLE; | 839 | *state = HT_AGG_STATE_IDLE; |
822 | sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0; | 840 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
841 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
842 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
823 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 843 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
824 | 844 | ||
825 | rcu_read_unlock(); | 845 | rcu_read_unlock(); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a6485f01b3c8..7ab806602183 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -73,11 +73,12 @@ struct ieee80211_fragment_entry { | |||
73 | struct ieee80211_sta_bss { | 73 | struct ieee80211_sta_bss { |
74 | struct list_head list; | 74 | struct list_head list; |
75 | struct ieee80211_sta_bss *hnext; | 75 | struct ieee80211_sta_bss *hnext; |
76 | size_t ssid_len; | ||
77 | |||
76 | atomic_t users; | 78 | atomic_t users; |
77 | 79 | ||
78 | u8 bssid[ETH_ALEN]; | 80 | u8 bssid[ETH_ALEN]; |
79 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 81 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
80 | size_t ssid_len; | ||
81 | u16 capability; /* host byte order */ | 82 | u16 capability; /* host byte order */ |
82 | enum ieee80211_band band; | 83 | enum ieee80211_band band; |
83 | int freq; | 84 | int freq; |
@@ -98,8 +99,8 @@ struct ieee80211_sta_bss { | |||
98 | #define IEEE80211_MAX_SUPP_RATES 32 | 99 | #define IEEE80211_MAX_SUPP_RATES 32 |
99 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 100 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
100 | size_t supp_rates_len; | 101 | size_t supp_rates_len; |
101 | int beacon_int; | ||
102 | u64 timestamp; | 102 | u64 timestamp; |
103 | int beacon_int; | ||
103 | 104 | ||
104 | int probe_resp; | 105 | int probe_resp; |
105 | unsigned long last_update; | 106 | unsigned long last_update; |
@@ -154,9 +155,7 @@ struct ieee80211_tx_data { | |||
154 | struct ieee80211_local *local; | 155 | struct ieee80211_local *local; |
155 | struct ieee80211_sub_if_data *sdata; | 156 | struct ieee80211_sub_if_data *sdata; |
156 | struct sta_info *sta; | 157 | struct sta_info *sta; |
157 | u16 fc, ethertype; | ||
158 | struct ieee80211_key *key; | 158 | struct ieee80211_key *key; |
159 | unsigned int flags; | ||
160 | 159 | ||
161 | struct ieee80211_tx_control *control; | 160 | struct ieee80211_tx_control *control; |
162 | struct ieee80211_channel *channel; | 161 | struct ieee80211_channel *channel; |
@@ -168,8 +167,11 @@ struct ieee80211_tx_data { | |||
168 | 167 | ||
169 | /* Extra fragments (in addition to the first fragment | 168 | /* Extra fragments (in addition to the first fragment |
170 | * in skb) */ | 169 | * in skb) */ |
171 | int num_extra_frag; | ||
172 | struct sk_buff **extra_frag; | 170 | struct sk_buff **extra_frag; |
171 | int num_extra_frag; | ||
172 | |||
173 | u16 fc, ethertype; | ||
174 | unsigned int flags; | ||
173 | }; | 175 | }; |
174 | 176 | ||
175 | 177 | ||
@@ -192,12 +194,12 @@ struct ieee80211_rx_data { | |||
192 | struct ieee80211_local *local; | 194 | struct ieee80211_local *local; |
193 | struct ieee80211_sub_if_data *sdata; | 195 | struct ieee80211_sub_if_data *sdata; |
194 | struct sta_info *sta; | 196 | struct sta_info *sta; |
195 | u16 fc, ethertype; | ||
196 | struct ieee80211_key *key; | 197 | struct ieee80211_key *key; |
197 | unsigned int flags; | ||
198 | |||
199 | struct ieee80211_rx_status *status; | 198 | struct ieee80211_rx_status *status; |
200 | struct ieee80211_rate *rate; | 199 | struct ieee80211_rate *rate; |
200 | |||
201 | u16 fc, ethertype; | ||
202 | unsigned int flags; | ||
201 | int sent_ps_buffered; | 203 | int sent_ps_buffered; |
202 | int queue; | 204 | int queue; |
203 | int load; | 205 | int load; |
@@ -222,9 +224,9 @@ struct ieee80211_tx_packet_data { | |||
222 | struct ieee80211_tx_stored_packet { | 224 | struct ieee80211_tx_stored_packet { |
223 | struct ieee80211_tx_control control; | 225 | struct ieee80211_tx_control control; |
224 | struct sk_buff *skb; | 226 | struct sk_buff *skb; |
225 | int num_extra_frag; | ||
226 | struct sk_buff **extra_frag; | 227 | struct sk_buff **extra_frag; |
227 | struct ieee80211_rate *last_frag_rate; | 228 | struct ieee80211_rate *last_frag_rate; |
229 | int num_extra_frag; | ||
228 | unsigned int last_frag_rate_ctrl_probe; | 230 | unsigned int last_frag_rate_ctrl_probe; |
229 | }; | 231 | }; |
230 | 232 | ||
@@ -246,8 +248,8 @@ struct ieee80211_if_ap { | |||
246 | * bitmap_empty :) | 248 | * bitmap_empty :) |
247 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ | 249 | * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */ |
248 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; | 250 | u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)]; |
249 | atomic_t num_sta_ps; /* number of stations in PS mode */ | ||
250 | struct sk_buff_head ps_bc_buf; | 251 | struct sk_buff_head ps_bc_buf; |
252 | atomic_t num_sta_ps; /* number of stations in PS mode */ | ||
251 | int dtim_count; | 253 | int dtim_count; |
252 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | 254 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ |
253 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | 255 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ |
@@ -255,8 +257,8 @@ struct ieee80211_if_ap { | |||
255 | }; | 257 | }; |
256 | 258 | ||
257 | struct ieee80211_if_wds { | 259 | struct ieee80211_if_wds { |
258 | u8 remote_addr[ETH_ALEN]; | ||
259 | struct sta_info *sta; | 260 | struct sta_info *sta; |
261 | u8 remote_addr[ETH_ALEN]; | ||
260 | }; | 262 | }; |
261 | 263 | ||
262 | struct ieee80211_if_vlan { | 264 | struct ieee80211_if_vlan { |
@@ -290,12 +292,12 @@ struct mesh_config { | |||
290 | u8 dot11MeshTTL; | 292 | u8 dot11MeshTTL; |
291 | bool auto_open_plinks; | 293 | bool auto_open_plinks; |
292 | /* HWMP parameters */ | 294 | /* HWMP parameters */ |
293 | u32 dot11MeshHWMPactivePathTimeout; | ||
294 | u16 dot11MeshHWMPpreqMinInterval; | ||
295 | u16 dot11MeshHWMPnetDiameterTraversalTime; | ||
296 | u8 dot11MeshHWMPmaxPREQretries; | 295 | u8 dot11MeshHWMPmaxPREQretries; |
297 | u32 path_refresh_time; | 296 | u32 path_refresh_time; |
298 | u16 min_discovery_timeout; | 297 | u16 min_discovery_timeout; |
298 | u32 dot11MeshHWMPactivePathTimeout; | ||
299 | u16 dot11MeshHWMPpreqMinInterval; | ||
300 | u16 dot11MeshHWMPnetDiameterTraversalTime; | ||
299 | }; | 301 | }; |
300 | 302 | ||
301 | 303 | ||
@@ -314,23 +316,22 @@ struct mesh_config { | |||
314 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) | 316 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) |
315 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) | 317 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) |
316 | struct ieee80211_if_sta { | 318 | struct ieee80211_if_sta { |
319 | struct timer_list timer; | ||
320 | struct work_struct work; | ||
321 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | ||
322 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
317 | enum { | 323 | enum { |
318 | IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, | 324 | IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, |
319 | IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, | 325 | IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, |
320 | IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED, | 326 | IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED, |
321 | IEEE80211_MESH_UP | 327 | IEEE80211_MESH_UP |
322 | } state; | 328 | } state; |
323 | struct timer_list timer; | ||
324 | struct work_struct work; | ||
325 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | ||
326 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
327 | size_t ssid_len; | 329 | size_t ssid_len; |
328 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 330 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
329 | size_t scan_ssid_len; | 331 | size_t scan_ssid_len; |
330 | #ifdef CONFIG_MAC80211_MESH | 332 | #ifdef CONFIG_MAC80211_MESH |
331 | struct timer_list mesh_path_timer; | 333 | struct timer_list mesh_path_timer; |
332 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | 334 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; |
333 | bool accepting_plinks; | ||
334 | size_t mesh_id_len; | 335 | size_t mesh_id_len; |
335 | /* Active Path Selection Protocol Identifier */ | 336 | /* Active Path Selection Protocol Identifier */ |
336 | u8 mesh_pp_id[4]; | 337 | u8 mesh_pp_id[4]; |
@@ -354,6 +355,7 @@ struct ieee80211_if_sta { | |||
354 | struct mesh_stats mshstats; | 355 | struct mesh_stats mshstats; |
355 | struct mesh_config mshcfg; | 356 | struct mesh_config mshcfg; |
356 | u8 mesh_seqnum[3]; | 357 | u8 mesh_seqnum[3]; |
358 | bool accepting_plinks; | ||
357 | #endif | 359 | #endif |
358 | u16 aid; | 360 | u16 aid; |
359 | u16 ap_capab, capab; | 361 | u16 ap_capab, capab; |
@@ -364,16 +366,18 @@ struct ieee80211_if_sta { | |||
364 | u8 *assocreq_ies, *assocresp_ies; | 366 | u8 *assocreq_ies, *assocresp_ies; |
365 | size_t assocreq_ies_len, assocresp_ies_len; | 367 | size_t assocreq_ies_len, assocresp_ies_len; |
366 | 368 | ||
369 | struct sk_buff_head skb_queue; | ||
370 | |||
367 | int auth_tries, assoc_tries; | 371 | int auth_tries, assoc_tries; |
368 | 372 | ||
373 | unsigned long request; | ||
374 | |||
375 | unsigned long last_probe; | ||
376 | |||
369 | unsigned int flags; | 377 | unsigned int flags; |
370 | #define IEEE80211_STA_REQ_SCAN 0 | 378 | #define IEEE80211_STA_REQ_SCAN 0 |
371 | #define IEEE80211_STA_REQ_AUTH 1 | 379 | #define IEEE80211_STA_REQ_AUTH 1 |
372 | #define IEEE80211_STA_REQ_RUN 2 | 380 | #define IEEE80211_STA_REQ_RUN 2 |
373 | unsigned long request; | ||
374 | struct sk_buff_head skb_queue; | ||
375 | |||
376 | unsigned long last_probe; | ||
377 | 381 | ||
378 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | 382 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) |
379 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) | 383 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) |
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 5af23d318726..b047eebb6330 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c | |||
@@ -55,9 +55,6 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, | |||
55 | key = sta->key; | 55 | key = sta->key; |
56 | } | 56 | } |
57 | 57 | ||
58 | if (!key) | ||
59 | return -ENOENT; | ||
60 | |||
61 | ieee80211_key_free(key); | 58 | ieee80211_key_free(key); |
62 | return 0; | 59 | return 0; |
63 | } else { | 60 | } else { |
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index cf51ca6804dd..f9cf2f187893 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -1216,12 +1216,11 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1216 | buf_size = buf_size << sband->ht_info.ampdu_factor; | 1216 | buf_size = buf_size << sband->ht_info.ampdu_factor; |
1217 | } | 1217 | } |
1218 | 1218 | ||
1219 | tid_agg_rx = &sta->ampdu_mlme.tid_rx[tid]; | ||
1220 | 1219 | ||
1221 | /* examine state machine */ | 1220 | /* examine state machine */ |
1222 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1221 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); |
1223 | 1222 | ||
1224 | if (tid_agg_rx->state != HT_AGG_STATE_IDLE) { | 1223 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { |
1225 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1224 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1226 | if (net_ratelimit()) | 1225 | if (net_ratelimit()) |
1227 | printk(KERN_DEBUG "unexpected AddBA Req from " | 1226 | printk(KERN_DEBUG "unexpected AddBA Req from " |
@@ -1231,6 +1230,24 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1231 | goto end; | 1230 | goto end; |
1232 | } | 1231 | } |
1233 | 1232 | ||
1233 | /* prepare A-MPDU MLME for Rx aggregation */ | ||
1234 | sta->ampdu_mlme.tid_rx[tid] = | ||
1235 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
1236 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
1237 | if (net_ratelimit()) | ||
1238 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
1239 | tid); | ||
1240 | goto end; | ||
1241 | } | ||
1242 | /* rx timer */ | ||
1243 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
1244 | sta_rx_agg_session_timer_expired; | ||
1245 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
1246 | (unsigned long)&sta->timer_to_tid[tid]; | ||
1247 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
1248 | |||
1249 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
1250 | |||
1234 | /* prepare reordering buffer */ | 1251 | /* prepare reordering buffer */ |
1235 | tid_agg_rx->reorder_buf = | 1252 | tid_agg_rx->reorder_buf = |
1236 | kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC); | 1253 | kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC); |
@@ -1238,6 +1255,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1238 | if (net_ratelimit()) | 1255 | if (net_ratelimit()) |
1239 | printk(KERN_ERR "can not allocate reordering buffer " | 1256 | printk(KERN_ERR "can not allocate reordering buffer " |
1240 | "to tid %d\n", tid); | 1257 | "to tid %d\n", tid); |
1258 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1241 | goto end; | 1259 | goto end; |
1242 | } | 1260 | } |
1243 | memset(tid_agg_rx->reorder_buf, 0, | 1261 | memset(tid_agg_rx->reorder_buf, 0, |
@@ -1252,11 +1270,13 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1252 | 1270 | ||
1253 | if (ret) { | 1271 | if (ret) { |
1254 | kfree(tid_agg_rx->reorder_buf); | 1272 | kfree(tid_agg_rx->reorder_buf); |
1273 | kfree(tid_agg_rx); | ||
1274 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1255 | goto end; | 1275 | goto end; |
1256 | } | 1276 | } |
1257 | 1277 | ||
1258 | /* change state and send addba resp */ | 1278 | /* change state and send addba resp */ |
1259 | tid_agg_rx->state = HT_AGG_STATE_OPERATIONAL; | 1279 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; |
1260 | tid_agg_rx->dialog_token = dialog_token; | 1280 | tid_agg_rx->dialog_token = dialog_token; |
1261 | tid_agg_rx->ssn = start_seq_num; | 1281 | tid_agg_rx->ssn = start_seq_num; |
1262 | tid_agg_rx->head_seq_num = start_seq_num; | 1282 | tid_agg_rx->head_seq_num = start_seq_num; |
@@ -1295,39 +1315,37 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1295 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 1315 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
1296 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 1316 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
1297 | 1317 | ||
1298 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 1318 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1299 | 1319 | ||
1300 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1320 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
1301 | 1321 | ||
1322 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
1323 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
1324 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" | ||
1325 | "%d\n", *state); | ||
1326 | goto addba_resp_exit; | ||
1327 | } | ||
1328 | |||
1302 | if (mgmt->u.action.u.addba_resp.dialog_token != | 1329 | if (mgmt->u.action.u.addba_resp.dialog_token != |
1303 | sta->ampdu_mlme.tid_tx[tid].dialog_token) { | 1330 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { |
1304 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1331 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
1305 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1332 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1306 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | 1333 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); |
1307 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1334 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
1308 | rcu_read_unlock(); | 1335 | goto addba_resp_exit; |
1309 | return; | ||
1310 | } | 1336 | } |
1311 | 1337 | ||
1312 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid].addba_resp_timer); | 1338 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
1313 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1339 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1314 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | 1340 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); |
1315 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1341 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
1316 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 1342 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
1317 | == WLAN_STATUS_SUCCESS) { | 1343 | == WLAN_STATUS_SUCCESS) { |
1318 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
1319 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
1320 | printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:" | ||
1321 | "%d\n", *state); | ||
1322 | rcu_read_unlock(); | ||
1323 | return; | ||
1324 | } | ||
1325 | |||
1326 | if (*state & HT_ADDBA_RECEIVED_MSK) | 1344 | if (*state & HT_ADDBA_RECEIVED_MSK) |
1327 | printk(KERN_DEBUG "double addBA response\n"); | 1345 | printk(KERN_DEBUG "double addBA response\n"); |
1328 | 1346 | ||
1329 | *state |= HT_ADDBA_RECEIVED_MSK; | 1347 | *state |= HT_ADDBA_RECEIVED_MSK; |
1330 | sta->ampdu_mlme.tid_tx[tid].addba_req_num = 0; | 1348 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
1331 | 1349 | ||
1332 | if (*state == HT_AGG_STATE_OPERATIONAL) { | 1350 | if (*state == HT_AGG_STATE_OPERATIONAL) { |
1333 | printk(KERN_DEBUG "Aggregation on for tid %d \n", tid); | 1351 | printk(KERN_DEBUG "Aggregation on for tid %d \n", tid); |
@@ -1339,13 +1357,15 @@ static void ieee80211_sta_process_addba_resp(struct net_device *dev, | |||
1339 | } else { | 1357 | } else { |
1340 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); | 1358 | printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid); |
1341 | 1359 | ||
1342 | sta->ampdu_mlme.tid_tx[tid].addba_req_num++; | 1360 | sta->ampdu_mlme.addba_req_num[tid]++; |
1343 | /* this will allow the state check in stop_BA_session */ | 1361 | /* this will allow the state check in stop_BA_session */ |
1344 | *state = HT_AGG_STATE_OPERATIONAL; | 1362 | *state = HT_AGG_STATE_OPERATIONAL; |
1345 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1363 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
1346 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, | 1364 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, |
1347 | WLAN_BACK_INITIATOR); | 1365 | WLAN_BACK_INITIATOR); |
1348 | } | 1366 | } |
1367 | |||
1368 | addba_resp_exit: | ||
1349 | rcu_read_unlock(); | 1369 | rcu_read_unlock(); |
1350 | } | 1370 | } |
1351 | 1371 | ||
@@ -1411,13 +1431,13 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | |||
1411 | 1431 | ||
1412 | /* check if TID is in operational state */ | 1432 | /* check if TID is in operational state */ |
1413 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); | 1433 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); |
1414 | if (sta->ampdu_mlme.tid_rx[tid].state | 1434 | if (sta->ampdu_mlme.tid_state_rx[tid] |
1415 | != HT_AGG_STATE_OPERATIONAL) { | 1435 | != HT_AGG_STATE_OPERATIONAL) { |
1416 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1436 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); |
1417 | rcu_read_unlock(); | 1437 | rcu_read_unlock(); |
1418 | return; | 1438 | return; |
1419 | } | 1439 | } |
1420 | sta->ampdu_mlme.tid_rx[tid].state = | 1440 | sta->ampdu_mlme.tid_state_rx[tid] = |
1421 | HT_AGG_STATE_REQ_STOP_BA_MSK | | 1441 | HT_AGG_STATE_REQ_STOP_BA_MSK | |
1422 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 1442 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
1423 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | 1443 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); |
@@ -1434,25 +1454,27 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | |||
1434 | 1454 | ||
1435 | /* shutdown timer has not expired */ | 1455 | /* shutdown timer has not expired */ |
1436 | if (initiator != WLAN_BACK_TIMER) | 1456 | if (initiator != WLAN_BACK_TIMER) |
1437 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]. | 1457 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); |
1438 | session_timer); | ||
1439 | 1458 | ||
1440 | /* check if this is a self generated aggregation halt */ | 1459 | /* check if this is a self generated aggregation halt */ |
1441 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | 1460 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) |
1442 | ieee80211_send_delba(dev, ra, tid, 0, reason); | 1461 | ieee80211_send_delba(dev, ra, tid, 0, reason); |
1443 | 1462 | ||
1444 | /* free the reordering buffer */ | 1463 | /* free the reordering buffer */ |
1445 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid].buf_size; i++) { | 1464 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { |
1446 | if (sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]) { | 1465 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { |
1447 | /* release the reordered frames */ | 1466 | /* release the reordered frames */ |
1448 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]); | 1467 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); |
1449 | sta->ampdu_mlme.tid_rx[tid].stored_mpdu_num--; | 1468 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; |
1450 | sta->ampdu_mlme.tid_rx[tid].reorder_buf[i] = NULL; | 1469 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; |
1451 | } | 1470 | } |
1452 | } | 1471 | } |
1453 | kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf); | 1472 | /* free resources */ |
1473 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
1474 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1475 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1476 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
1454 | 1477 | ||
1455 | sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE; | ||
1456 | rcu_read_unlock(); | 1478 | rcu_read_unlock(); |
1457 | } | 1479 | } |
1458 | 1480 | ||
@@ -1491,7 +1513,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev, | |||
1491 | WLAN_BACK_INITIATOR, 0); | 1513 | WLAN_BACK_INITIATOR, 0); |
1492 | else { /* WLAN_BACK_RECIPIENT */ | 1514 | else { /* WLAN_BACK_RECIPIENT */ |
1493 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1515 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
1494 | sta->ampdu_mlme.tid_tx[tid].state = | 1516 | sta->ampdu_mlme.tid_state_tx[tid] = |
1495 | HT_AGG_STATE_OPERATIONAL; | 1517 | HT_AGG_STATE_OPERATIONAL; |
1496 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | 1518 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); |
1497 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, | 1519 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, |
@@ -1528,7 +1550,7 @@ void sta_addba_resp_timer_expired(unsigned long data) | |||
1528 | return; | 1550 | return; |
1529 | } | 1551 | } |
1530 | 1552 | ||
1531 | state = &sta->ampdu_mlme.tid_tx[tid].state; | 1553 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
1532 | /* check if the TID waits for addBA response */ | 1554 | /* check if the TID waits for addBA response */ |
1533 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | 1555 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); |
1534 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 1556 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 644d2774469d..d9c6ed5be4fc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1514,9 +1514,10 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1514 | if (!rx->sta) | 1514 | if (!rx->sta) |
1515 | return RX_CONTINUE; | 1515 | return RX_CONTINUE; |
1516 | tid = le16_to_cpu(bar->control) >> 12; | 1516 | tid = le16_to_cpu(bar->control) >> 12; |
1517 | tid_agg_rx = &(rx->sta->ampdu_mlme.tid_rx[tid]); | 1517 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] |
1518 | if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL) | 1518 | != HT_AGG_STATE_OPERATIONAL) |
1519 | return RX_CONTINUE; | 1519 | return RX_CONTINUE; |
1520 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | ||
1520 | 1521 | ||
1521 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1522 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
1522 | 1523 | ||
@@ -2123,11 +2124,12 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2123 | 2124 | ||
2124 | qc = skb->data + ieee80211_get_hdrlen(fc) - QOS_CONTROL_LEN; | 2125 | qc = skb->data + ieee80211_get_hdrlen(fc) - QOS_CONTROL_LEN; |
2125 | tid = qc[0] & QOS_CONTROL_TID_MASK; | 2126 | tid = qc[0] & QOS_CONTROL_TID_MASK; |
2126 | tid_agg_rx = &(sta->ampdu_mlme.tid_rx[tid]); | ||
2127 | 2127 | ||
2128 | if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL) | 2128 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) |
2129 | goto end_reorder; | 2129 | goto end_reorder; |
2130 | 2130 | ||
2131 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
2132 | |||
2131 | /* null data frames are excluded */ | 2133 | /* null data frames are excluded */ |
2132 | if (unlikely(fc & IEEE80211_STYPE_NULLFUNC)) | 2134 | if (unlikely(fc & IEEE80211_STYPE_NULLFUNC)) |
2133 | goto end_reorder; | 2135 | goto end_reorder; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 3b84c16cf054..f708367092d1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -170,9 +170,16 @@ void sta_info_destroy(struct sta_info *sta) | |||
170 | dev_kfree_skb_any(skb); | 170 | dev_kfree_skb_any(skb); |
171 | 171 | ||
172 | for (i = 0; i < STA_TID_NUM; i++) { | 172 | for (i = 0; i < STA_TID_NUM; i++) { |
173 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i].session_timer); | 173 | spin_lock_bh(&sta->ampdu_mlme.ampdu_rx); |
174 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i].addba_resp_timer); | 174 | if (sta->ampdu_mlme.tid_rx[i]) |
175 | del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer); | ||
176 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx); | ||
177 | spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
178 | if (sta->ampdu_mlme.tid_tx[i]) | ||
179 | del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer); | ||
180 | spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); | ||
175 | } | 181 | } |
182 | |||
176 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | 183 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); |
177 | rate_control_put(sta->rate_ctrl); | 184 | rate_control_put(sta->rate_ctrl); |
178 | 185 | ||
@@ -227,18 +234,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
227 | sta->timer_to_tid[i] = i; | 234 | sta->timer_to_tid[i] = i; |
228 | /* tid to tx queue: initialize according to HW (0 is valid) */ | 235 | /* tid to tx queue: initialize according to HW (0 is valid) */ |
229 | sta->tid_to_tx_q[i] = local->hw.queues; | 236 | sta->tid_to_tx_q[i] = local->hw.queues; |
230 | /* rx timers */ | 237 | /* rx */ |
231 | sta->ampdu_mlme.tid_rx[i].session_timer.function = | 238 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; |
232 | sta_rx_agg_session_timer_expired; | 239 | sta->ampdu_mlme.tid_rx[i] = NULL; |
233 | sta->ampdu_mlme.tid_rx[i].session_timer.data = | 240 | /* tx */ |
234 | (unsigned long)&sta->timer_to_tid[i]; | 241 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; |
235 | init_timer(&sta->ampdu_mlme.tid_rx[i].session_timer); | 242 | sta->ampdu_mlme.tid_tx[i] = NULL; |
236 | /* tx timers */ | 243 | sta->ampdu_mlme.addba_req_num[i] = 0; |
237 | sta->ampdu_mlme.tid_tx[i].addba_resp_timer.function = | ||
238 | sta_addba_resp_timer_expired; | ||
239 | sta->ampdu_mlme.tid_tx[i].addba_resp_timer.data = | ||
240 | (unsigned long)&sta->timer_to_tid[i]; | ||
241 | init_timer(&sta->ampdu_mlme.tid_tx[i].addba_resp_timer); | ||
242 | } | 244 | } |
243 | skb_queue_head_init(&sta->ps_tx_buf); | 245 | skb_queue_head_init(&sta->ps_tx_buf); |
244 | skb_queue_head_init(&sta->tx_filtered); | 246 | skb_queue_head_init(&sta->tx_filtered); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index f166c8039f2b..5e39a4164b9b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -63,47 +63,42 @@ enum ieee80211_sta_info_flags { | |||
63 | #define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \ | 63 | #define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \ |
64 | HT_ADDBA_DRV_READY_MSK | \ | 64 | HT_ADDBA_DRV_READY_MSK | \ |
65 | HT_ADDBA_RECEIVED_MSK) | 65 | HT_ADDBA_RECEIVED_MSK) |
66 | #define HT_AGG_STATE_DEBUGFS_CTL BIT(7) | ||
66 | 67 | ||
67 | /** | 68 | /** |
68 | * struct tid_ampdu_tx - TID aggregation information (Tx). | 69 | * struct tid_ampdu_tx - TID aggregation information (Tx). |
69 | * | 70 | * |
70 | * @state: TID's state in session state machine. | ||
71 | * @dialog_token: dialog token for aggregation session | ||
72 | * @ssn: Starting Sequence Number expected to be aggregated. | ||
73 | * @addba_resp_timer: timer for peer's response to addba request | 71 | * @addba_resp_timer: timer for peer's response to addba request |
74 | * @addba_req_num: number of times addBA request has been sent. | 72 | * @ssn: Starting Sequence Number expected to be aggregated. |
73 | * @dialog_token: dialog token for aggregation session | ||
75 | */ | 74 | */ |
76 | struct tid_ampdu_tx { | 75 | struct tid_ampdu_tx { |
77 | u8 state; | ||
78 | u8 dialog_token; | ||
79 | u16 ssn; | ||
80 | struct timer_list addba_resp_timer; | 76 | struct timer_list addba_resp_timer; |
81 | u8 addba_req_num; | 77 | u16 ssn; |
78 | u8 dialog_token; | ||
82 | }; | 79 | }; |
83 | 80 | ||
84 | /** | 81 | /** |
85 | * struct tid_ampdu_rx - TID aggregation information (Rx). | 82 | * struct tid_ampdu_rx - TID aggregation information (Rx). |
86 | * | 83 | * |
87 | * @state: TID's state in session state machine. | 84 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs |
88 | * @dialog_token: dialog token for aggregation session | 85 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
86 | * @head_seq_num: head sequence number in reordering buffer. | ||
87 | * @stored_mpdu_num: number of MPDUs in reordering buffer | ||
89 | * @ssn: Starting Sequence Number expected to be aggregated. | 88 | * @ssn: Starting Sequence Number expected to be aggregated. |
90 | * @buf_size: buffer size for incoming A-MPDUs | 89 | * @buf_size: buffer size for incoming A-MPDUs |
91 | * @timeout: reset timer value. | 90 | * @timeout: reset timer value. |
92 | * @head_seq_num: head sequence number in reordering buffer. | 91 | * @dialog_token: dialog token for aggregation session |
93 | * @stored_mpdu_num: number of MPDUs in reordering buffer | ||
94 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | ||
95 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | ||
96 | */ | 92 | */ |
97 | struct tid_ampdu_rx { | 93 | struct tid_ampdu_rx { |
98 | u8 state; | 94 | struct sk_buff **reorder_buf; |
99 | u8 dialog_token; | 95 | struct timer_list session_timer; |
96 | u16 head_seq_num; | ||
97 | u16 stored_mpdu_num; | ||
100 | u16 ssn; | 98 | u16 ssn; |
101 | u16 buf_size; | 99 | u16 buf_size; |
102 | u16 timeout; | 100 | u16 timeout; |
103 | u16 head_seq_num; | 101 | u8 dialog_token; |
104 | u16 stored_mpdu_num; | ||
105 | struct sk_buff **reorder_buf; | ||
106 | struct timer_list session_timer; | ||
107 | }; | 102 | }; |
108 | 103 | ||
109 | /** | 104 | /** |
@@ -132,16 +127,24 @@ enum plink_state { | |||
132 | /** | 127 | /** |
133 | * struct sta_ampdu_mlme - STA aggregation information. | 128 | * struct sta_ampdu_mlme - STA aggregation information. |
134 | * | 129 | * |
130 | * @tid_state_rx: TID's state in Rx session state machine. | ||
135 | * @tid_rx: aggregation info for Rx per TID | 131 | * @tid_rx: aggregation info for Rx per TID |
136 | * @tid_tx: aggregation info for Tx per TID | ||
137 | * @ampdu_rx: for locking sections in aggregation Rx flow | 132 | * @ampdu_rx: for locking sections in aggregation Rx flow |
133 | * @tid_state_tx: TID's state in Tx session state machine. | ||
134 | * @tid_tx: aggregation info for Tx per TID | ||
135 | * @addba_req_num: number of times addBA request has been sent. | ||
138 | * @ampdu_tx: for locking sectionsi in aggregation Tx flow | 136 | * @ampdu_tx: for locking sectionsi in aggregation Tx flow |
139 | * @dialog_token_allocator: dialog token enumerator for each new session; | 137 | * @dialog_token_allocator: dialog token enumerator for each new session; |
140 | */ | 138 | */ |
141 | struct sta_ampdu_mlme { | 139 | struct sta_ampdu_mlme { |
142 | struct tid_ampdu_rx tid_rx[STA_TID_NUM]; | 140 | /* rx */ |
143 | struct tid_ampdu_tx tid_tx[STA_TID_NUM]; | 141 | u8 tid_state_rx[STA_TID_NUM]; |
142 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | ||
144 | spinlock_t ampdu_rx; | 143 | spinlock_t ampdu_rx; |
144 | /* tx */ | ||
145 | u8 tid_state_tx[STA_TID_NUM]; | ||
146 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; | ||
147 | u8 addba_req_num[STA_TID_NUM]; | ||
145 | spinlock_t ampdu_tx; | 148 | spinlock_t ampdu_tx; |
146 | u8 dialog_token_allocator; | 149 | u8 dialog_token_allocator; |
147 | }; | 150 | }; |