diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-tx.c | 42 | ||||
-rw-r--r-- | net/mac80211/debugfs_sta.c | 4 | ||||
-rw-r--r-- | net/mac80211/main.c | 6 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 9 | ||||
-rw-r--r-- | net/mac80211/status.c | 8 | ||||
-rw-r--r-- | net/mac80211/util.c | 5 |
7 files changed, 62 insertions, 14 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 266cc871c72d..2c2e9519a2e7 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -162,6 +162,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
162 | return -ENOENT; | 162 | return -ENOENT; |
163 | } | 163 | } |
164 | 164 | ||
165 | /* if we're already stopping ignore any new requests to stop */ | ||
166 | if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | ||
167 | spin_unlock_bh(&sta->lock); | ||
168 | return -EALREADY; | ||
169 | } | ||
170 | |||
165 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 171 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
166 | /* not even started yet! */ | 172 | /* not even started yet! */ |
167 | ieee80211_assign_tid_tx(sta, tid, NULL); | 173 | ieee80211_assign_tid_tx(sta, tid, NULL); |
@@ -170,6 +176,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
170 | return 0; | 176 | return 0; |
171 | } | 177 | } |
172 | 178 | ||
179 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | ||
180 | |||
173 | spin_unlock_bh(&sta->lock); | 181 | spin_unlock_bh(&sta->lock); |
174 | 182 | ||
175 | #ifdef CONFIG_MAC80211_HT_DEBUG | 183 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -177,8 +185,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
177 | sta->sta.addr, tid); | 185 | sta->sta.addr, tid); |
178 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 186 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
179 | 187 | ||
180 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | ||
181 | |||
182 | del_timer_sync(&tid_tx->addba_resp_timer); | 188 | del_timer_sync(&tid_tx->addba_resp_timer); |
183 | del_timer_sync(&tid_tx->session_timer); | 189 | del_timer_sync(&tid_tx->session_timer); |
184 | 190 | ||
@@ -189,6 +195,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
189 | */ | 195 | */ |
190 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | 196 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
191 | 197 | ||
198 | /* | ||
199 | * There might be a few packets being processed right now (on | ||
200 | * another CPU) that have already gotten past the aggregation | ||
201 | * check when it was still OPERATIONAL and consequently have | ||
202 | * IEEE80211_TX_CTL_AMPDU set. In that case, this code might | ||
203 | * call into the driver at the same time or even before the | ||
204 | * TX paths calls into it, which could confuse the driver. | ||
205 | * | ||
206 | * Wait for all currently running TX paths to finish before | ||
207 | * telling the driver. New packets will not go through since | ||
208 | * the aggregation session is no longer OPERATIONAL. | ||
209 | */ | ||
210 | synchronize_net(); | ||
211 | |||
192 | tid_tx->stop_initiator = initiator; | 212 | tid_tx->stop_initiator = initiator; |
193 | tid_tx->tx_stop = tx; | 213 | tid_tx->tx_stop = tx; |
194 | 214 | ||
@@ -781,11 +801,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
781 | goto out; | 801 | goto out; |
782 | } | 802 | } |
783 | 803 | ||
784 | del_timer(&tid_tx->addba_resp_timer); | 804 | del_timer_sync(&tid_tx->addba_resp_timer); |
785 | 805 | ||
786 | #ifdef CONFIG_MAC80211_HT_DEBUG | 806 | #ifdef CONFIG_MAC80211_HT_DEBUG |
787 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | 807 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
788 | #endif | 808 | #endif |
809 | |||
810 | /* | ||
811 | * addba_resp_timer may have fired before we got here, and | ||
812 | * caused WANT_STOP to be set. If the stop then was already | ||
813 | * processed further, STOPPING might be set. | ||
814 | */ | ||
815 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || | ||
816 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | ||
817 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
818 | printk(KERN_DEBUG | ||
819 | "got addBA resp for tid %d but we already gave up\n", | ||
820 | tid); | ||
821 | #endif | ||
822 | goto out; | ||
823 | } | ||
824 | |||
789 | /* | 825 | /* |
790 | * IEEE 802.11-2007 7.3.1.14: | 826 | * IEEE 802.11-2007 7.3.1.14: |
791 | * In an ADDBA Response frame, when the Status Code field | 827 | * In an ADDBA Response frame, when the Status Code field |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index edfdd74d4351..2406b3e7393f 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -274,9 +274,9 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
274 | 274 | ||
275 | PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack"); | 275 | PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack"); |
276 | 276 | ||
277 | PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: " | ||
278 | "3839 bytes"); | ||
279 | PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: " | 277 | PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: " |
278 | "3839 bytes"); | ||
279 | PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: " | ||
280 | "7935 bytes"); | 280 | "7935 bytes"); |
281 | 281 | ||
282 | /* | 282 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 944bed35d923..24cc50b963a9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -738,6 +738,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
738 | if (!local->int_scan_req) | 738 | if (!local->int_scan_req) |
739 | return -ENOMEM; | 739 | return -ENOMEM; |
740 | 740 | ||
741 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
742 | if (!local->hw.wiphy->bands[band]) | ||
743 | continue; | ||
744 | local->int_scan_req->rates[band] = (u32) -1; | ||
745 | } | ||
746 | |||
741 | /* if low-level driver supports AP, we also support VLAN */ | 747 | /* if low-level driver supports AP, we also support VLAN */ |
742 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { | 748 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { |
743 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | 749 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a6ad19757bac..09019d135942 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2301,6 +2301,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
2301 | 2301 | ||
2302 | cancel_work_sync(&ifmgd->request_smps_work); | 2302 | cancel_work_sync(&ifmgd->request_smps_work); |
2303 | 2303 | ||
2304 | cancel_work_sync(&ifmgd->monitor_work); | ||
2304 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | 2305 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
2305 | if (del_timer_sync(&ifmgd->timer)) | 2306 | if (del_timer_sync(&ifmgd->timer)) |
2306 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 2307 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
@@ -2309,7 +2310,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
2309 | if (del_timer_sync(&ifmgd->chswitch_timer)) | 2310 | if (del_timer_sync(&ifmgd->chswitch_timer)) |
2310 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | 2311 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); |
2311 | 2312 | ||
2312 | cancel_work_sync(&ifmgd->monitor_work); | ||
2313 | /* these will just be re-established on connection */ | 2313 | /* these will just be re-established on connection */ |
2314 | del_timer_sync(&ifmgd->conn_mon_timer); | 2314 | del_timer_sync(&ifmgd->conn_mon_timer); |
2315 | del_timer_sync(&ifmgd->bcn_mon_timer); | 2315 | del_timer_sync(&ifmgd->bcn_mon_timer); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 1e231e95f466..daf5cde65b30 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -141,8 +141,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
141 | pos++; | 141 | pos++; |
142 | 142 | ||
143 | /* IEEE80211_RADIOTAP_RATE */ | 143 | /* IEEE80211_RADIOTAP_RATE */ |
144 | if (status->flag & RX_FLAG_HT) { | 144 | if (!rate || status->flag & RX_FLAG_HT) { |
145 | /* | 145 | /* |
146 | * Without rate information don't add it. If we have, | ||
146 | * MCS information is a separate field in radiotap, | 147 | * MCS information is a separate field in radiotap, |
147 | * added below. The byte here is needed as padding | 148 | * added below. The byte here is needed as padding |
148 | * for the channel though, so initialise it to 0. | 149 | * for the channel though, so initialise it to 0. |
@@ -163,12 +164,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
163 | else if (status->flag & RX_FLAG_HT) | 164 | else if (status->flag & RX_FLAG_HT) |
164 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, | 165 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, |
165 | pos); | 166 | pos); |
166 | else if (rate->flags & IEEE80211_RATE_ERP_G) | 167 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
167 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, | 168 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, |
168 | pos); | 169 | pos); |
169 | else | 170 | else if (rate) |
170 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, | 171 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, |
171 | pos); | 172 | pos); |
173 | else | ||
174 | put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos); | ||
172 | pos += 2; | 175 | pos += 2; |
173 | 176 | ||
174 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ | 177 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index a9da6ee69803..46222ce0e5b1 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -260,7 +260,7 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | |||
260 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 260 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
261 | struct ieee80211_radiotap_header *rthdr; | 261 | struct ieee80211_radiotap_header *rthdr; |
262 | unsigned char *pos; | 262 | unsigned char *pos; |
263 | __le16 txflags; | 263 | u16 txflags; |
264 | 264 | ||
265 | rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len); | 265 | rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len); |
266 | 266 | ||
@@ -290,13 +290,13 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | |||
290 | txflags = 0; | 290 | txflags = 0; |
291 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | 291 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && |
292 | !is_multicast_ether_addr(hdr->addr1)) | 292 | !is_multicast_ether_addr(hdr->addr1)) |
293 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | 293 | txflags |= IEEE80211_RADIOTAP_F_TX_FAIL; |
294 | 294 | ||
295 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | 295 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || |
296 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | 296 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) |
297 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | 297 | txflags |= IEEE80211_RADIOTAP_F_TX_CTS; |
298 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | 298 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) |
299 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | 299 | txflags |= IEEE80211_RADIOTAP_F_TX_RTS; |
300 | 300 | ||
301 | put_unaligned_le16(txflags, pos); | 301 | put_unaligned_le16(txflags, pos); |
302 | pos += 2; | 302 | pos += 2; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 5f7c1c601dc5..5243c2cadeef 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1034,6 +1034,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1034 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1034 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1035 | ssid, ssid_len, | 1035 | ssid, ssid_len, |
1036 | buf, buf_len); | 1036 | buf, buf_len); |
1037 | if (!skb) | ||
1038 | goto out; | ||
1037 | 1039 | ||
1038 | if (dst) { | 1040 | if (dst) { |
1039 | mgmt = (struct ieee80211_mgmt *) skb->data; | 1041 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -1042,6 +1044,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1042 | } | 1044 | } |
1043 | 1045 | ||
1044 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1046 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1047 | |||
1048 | out: | ||
1045 | kfree(buf); | 1049 | kfree(buf); |
1046 | 1050 | ||
1047 | return skb; | 1051 | return skb; |
@@ -1188,7 +1192,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1188 | struct ieee80211_sub_if_data, | 1192 | struct ieee80211_sub_if_data, |
1189 | u.ap); | 1193 | u.ap); |
1190 | 1194 | ||
1191 | memset(&sta->sta.drv_priv, 0, hw->sta_data_size); | ||
1192 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); | 1195 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); |
1193 | } | 1196 | } |
1194 | } | 1197 | } |