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 | 21 | ||||
-rw-r--r-- | net/mac80211/rx.c | 9 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 8 | ||||
-rw-r--r-- | net/mac80211/status.c | 8 | ||||
-rw-r--r-- | net/mac80211/util.c | 5 |
8 files changed, 85 insertions, 18 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index b3f65520e7a..b064e4df12c 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -161,6 +161,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
161 | return -ENOENT; | 161 | return -ENOENT; |
162 | } | 162 | } |
163 | 163 | ||
164 | /* if we're already stopping ignore any new requests to stop */ | ||
165 | if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | ||
166 | spin_unlock_bh(&sta->lock); | ||
167 | return -EALREADY; | ||
168 | } | ||
169 | |||
164 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 170 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
165 | /* not even started yet! */ | 171 | /* not even started yet! */ |
166 | ieee80211_assign_tid_tx(sta, tid, NULL); | 172 | ieee80211_assign_tid_tx(sta, tid, NULL); |
@@ -169,6 +175,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
169 | return 0; | 175 | return 0; |
170 | } | 176 | } |
171 | 177 | ||
178 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | ||
179 | |||
172 | spin_unlock_bh(&sta->lock); | 180 | spin_unlock_bh(&sta->lock); |
173 | 181 | ||
174 | #ifdef CONFIG_MAC80211_HT_DEBUG | 182 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -176,8 +184,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
176 | sta->sta.addr, tid); | 184 | sta->sta.addr, tid); |
177 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 185 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
178 | 186 | ||
179 | set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state); | ||
180 | |||
181 | del_timer_sync(&tid_tx->addba_resp_timer); | 187 | del_timer_sync(&tid_tx->addba_resp_timer); |
182 | 188 | ||
183 | /* | 189 | /* |
@@ -187,6 +193,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
187 | */ | 193 | */ |
188 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | 194 | clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
189 | 195 | ||
196 | /* | ||
197 | * There might be a few packets being processed right now (on | ||
198 | * another CPU) that have already gotten past the aggregation | ||
199 | * check when it was still OPERATIONAL and consequently have | ||
200 | * IEEE80211_TX_CTL_AMPDU set. In that case, this code might | ||
201 | * call into the driver at the same time or even before the | ||
202 | * TX paths calls into it, which could confuse the driver. | ||
203 | * | ||
204 | * Wait for all currently running TX paths to finish before | ||
205 | * telling the driver. New packets will not go through since | ||
206 | * the aggregation session is no longer OPERATIONAL. | ||
207 | */ | ||
208 | synchronize_net(); | ||
209 | |||
190 | tid_tx->stop_initiator = initiator; | 210 | tid_tx->stop_initiator = initiator; |
191 | tid_tx->tx_stop = tx; | 211 | tid_tx->tx_stop = tx; |
192 | 212 | ||
@@ -757,11 +777,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
757 | goto out; | 777 | goto out; |
758 | } | 778 | } |
759 | 779 | ||
760 | del_timer(&tid_tx->addba_resp_timer); | 780 | del_timer_sync(&tid_tx->addba_resp_timer); |
761 | 781 | ||
762 | #ifdef CONFIG_MAC80211_HT_DEBUG | 782 | #ifdef CONFIG_MAC80211_HT_DEBUG |
763 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | 783 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
764 | #endif | 784 | #endif |
785 | |||
786 | /* | ||
787 | * addba_resp_timer may have fired before we got here, and | ||
788 | * caused WANT_STOP to be set. If the stop then was already | ||
789 | * processed further, STOPPING might be set. | ||
790 | */ | ||
791 | if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) || | ||
792 | test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | ||
793 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
794 | printk(KERN_DEBUG | ||
795 | "got addBA resp for tid %d but we already gave up\n", | ||
796 | tid); | ||
797 | #endif | ||
798 | goto out; | ||
799 | } | ||
800 | |||
765 | /* | 801 | /* |
766 | * IEEE 802.11-2007 7.3.1.14: | 802 | * IEEE 802.11-2007 7.3.1.14: |
767 | * In an ADDBA Response frame, when the Status Code field | 803 | * 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 c5f341798c1..3110cbdc501 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 d999bf3b84e..cae443563ec 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -757,6 +757,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
757 | if (!local->int_scan_req) | 757 | if (!local->int_scan_req) |
758 | return -ENOMEM; | 758 | return -ENOMEM; |
759 | 759 | ||
760 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
761 | if (!local->hw.wiphy->bands[band]) | ||
762 | continue; | ||
763 | local->int_scan_req->rates[band] = (u32) -1; | ||
764 | } | ||
765 | |||
760 | /* if low-level driver supports AP, we also support VLAN */ | 766 | /* if low-level driver supports AP, we also support VLAN */ |
761 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { | 767 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { |
762 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | 768 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 72c8bea81a6..b1b1bb368f7 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1487,6 +1487,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1487 | int i, j, err; | 1487 | int i, j, err; |
1488 | bool have_higher_than_11mbit = false; | 1488 | bool have_higher_than_11mbit = false; |
1489 | u16 ap_ht_cap_flags; | 1489 | u16 ap_ht_cap_flags; |
1490 | int min_rate = INT_MAX, min_rate_index = -1; | ||
1490 | 1491 | ||
1491 | /* AssocResp and ReassocResp have identical structure */ | 1492 | /* AssocResp and ReassocResp have identical structure */ |
1492 | 1493 | ||
@@ -1553,6 +1554,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1553 | rates |= BIT(j); | 1554 | rates |= BIT(j); |
1554 | if (is_basic) | 1555 | if (is_basic) |
1555 | basic_rates |= BIT(j); | 1556 | basic_rates |= BIT(j); |
1557 | if (rate < min_rate) { | ||
1558 | min_rate = rate; | ||
1559 | min_rate_index = j; | ||
1560 | } | ||
1556 | break; | 1561 | break; |
1557 | } | 1562 | } |
1558 | } | 1563 | } |
@@ -1570,11 +1575,25 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1570 | rates |= BIT(j); | 1575 | rates |= BIT(j); |
1571 | if (is_basic) | 1576 | if (is_basic) |
1572 | basic_rates |= BIT(j); | 1577 | basic_rates |= BIT(j); |
1578 | if (rate < min_rate) { | ||
1579 | min_rate = rate; | ||
1580 | min_rate_index = j; | ||
1581 | } | ||
1573 | break; | 1582 | break; |
1574 | } | 1583 | } |
1575 | } | 1584 | } |
1576 | } | 1585 | } |
1577 | 1586 | ||
1587 | /* | ||
1588 | * some buggy APs don't advertise basic_rates. use the lowest | ||
1589 | * supported rate instead. | ||
1590 | */ | ||
1591 | if (unlikely(!basic_rates) && min_rate_index >= 0) { | ||
1592 | printk(KERN_DEBUG "%s: No basic rates in AssocResp. " | ||
1593 | "Using min supported rate instead.\n", sdata->name); | ||
1594 | basic_rates = BIT(min_rate_index); | ||
1595 | } | ||
1596 | |||
1578 | sta->sta.supp_rates[wk->chan->band] = rates; | 1597 | sta->sta.supp_rates[wk->chan->band] = rates; |
1579 | sdata->vif.bss_conf.basic_rates = basic_rates; | 1598 | sdata->vif.bss_conf.basic_rates = basic_rates; |
1580 | 1599 | ||
@@ -2269,6 +2288,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
2269 | 2288 | ||
2270 | cancel_work_sync(&ifmgd->request_smps_work); | 2289 | cancel_work_sync(&ifmgd->request_smps_work); |
2271 | 2290 | ||
2291 | cancel_work_sync(&ifmgd->monitor_work); | ||
2272 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); | 2292 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
2273 | if (del_timer_sync(&ifmgd->timer)) | 2293 | if (del_timer_sync(&ifmgd->timer)) |
2274 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 2294 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
@@ -2277,7 +2297,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
2277 | if (del_timer_sync(&ifmgd->chswitch_timer)) | 2297 | if (del_timer_sync(&ifmgd->chswitch_timer)) |
2278 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); | 2298 | set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); |
2279 | 2299 | ||
2280 | cancel_work_sync(&ifmgd->monitor_work); | ||
2281 | /* these will just be re-established on connection */ | 2300 | /* these will just be re-established on connection */ |
2282 | del_timer_sync(&ifmgd->conn_mon_timer); | 2301 | del_timer_sync(&ifmgd->conn_mon_timer); |
2283 | del_timer_sync(&ifmgd->bcn_mon_timer); | 2302 | del_timer_sync(&ifmgd->bcn_mon_timer); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bb53726cb04..fb123e2e081 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/sta_info.c b/net/mac80211/sta_info.c index ce962d2c878..8eaa746ec7a 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1354,12 +1354,12 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1354 | * Use MoreData flag to indicate whether there are | 1354 | * Use MoreData flag to indicate whether there are |
1355 | * more buffered frames for this STA | 1355 | * more buffered frames for this STA |
1356 | */ | 1356 | */ |
1357 | if (!more_data) | 1357 | if (more_data || !skb_queue_empty(&frames)) |
1358 | hdr->frame_control &= | ||
1359 | cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | ||
1360 | else | ||
1361 | hdr->frame_control |= | 1358 | hdr->frame_control |= |
1362 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1359 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
1360 | else | ||
1361 | hdr->frame_control &= | ||
1362 | cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | ||
1363 | 1363 | ||
1364 | if (ieee80211_is_data_qos(hdr->frame_control) || | 1364 | if (ieee80211_is_data_qos(hdr->frame_control) || |
1365 | ieee80211_is_qos_nullfunc(hdr->frame_control)) | 1365 | ieee80211_is_qos_nullfunc(hdr->frame_control)) |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 80de436eae2..16518f38611 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 51e256c5fb7..d5230ecc784 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -881,6 +881,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
881 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 881 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
882 | ssid, ssid_len, | 882 | ssid, ssid_len, |
883 | buf, buf_len); | 883 | buf, buf_len); |
884 | if (!skb) | ||
885 | goto out; | ||
884 | 886 | ||
885 | if (dst) { | 887 | if (dst) { |
886 | mgmt = (struct ieee80211_mgmt *) skb->data; | 888 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -889,6 +891,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
889 | } | 891 | } |
890 | 892 | ||
891 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 893 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
894 | |||
895 | out: | ||
892 | kfree(buf); | 896 | kfree(buf); |
893 | 897 | ||
894 | return skb; | 898 | return skb; |
@@ -1035,7 +1039,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1035 | struct ieee80211_sub_if_data, | 1039 | struct ieee80211_sub_if_data, |
1036 | u.ap); | 1040 | u.ap); |
1037 | 1041 | ||
1038 | memset(&sta->sta.drv_priv, 0, hw->sta_data_size); | ||
1039 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); | 1042 | WARN_ON(drv_sta_add(local, sdata, &sta->sta)); |
1040 | } | 1043 | } |
1041 | } | 1044 | } |