aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/agg-tx.c42
-rw-r--r--net/mac80211/debugfs_sta.c4
-rw-r--r--net/mac80211/main.c6
-rw-r--r--net/mac80211/mlme.c2
-rw-r--r--net/mac80211/rx.c9
-rw-r--r--net/mac80211/status.c8
-rw-r--r--net/mac80211/util.c5
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 }