diff options
author | Jeremy Erickson <jerickso@cs.unc.edu> | 2014-04-18 17:06:00 -0400 |
---|---|---|
committer | Jeremy Erickson <jerickso@cs.unc.edu> | 2014-04-18 17:06:00 -0400 |
commit | a215aa7b9ab3759c047201199fba64d3042d7f13 (patch) | |
tree | bca37493d9b2233450e6d3ffced1261d0e4f71fe /net/mac80211 | |
parent | d31199a77ef606f1d06894385f1852181ba6136b (diff) |
Update 2.6.36 to 2.6.36.4wip-dissipation2-jerickso
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/agg-rx.c | 11 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 5 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 1 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/key.c | 6 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 17 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 48 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 7 | ||||
-rw-r--r-- | net/mac80211/rate.c | 3 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 7 | ||||
-rw-r--r-- | net/mac80211/rx.c | 3 | ||||
-rw-r--r-- | net/mac80211/status.c | 1 | ||||
-rw-r--r-- | net/mac80211/tx.c | 27 |
14 files changed, 104 insertions, 37 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 965b272499fd..2f6903e48dd9 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -172,8 +172,6 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
172 | struct ieee80211_mgmt *mgmt, | 172 | struct ieee80211_mgmt *mgmt, |
173 | size_t len) | 173 | size_t len) |
174 | { | 174 | { |
175 | struct ieee80211_hw *hw = &local->hw; | ||
176 | struct ieee80211_conf *conf = &hw->conf; | ||
177 | struct tid_ampdu_rx *tid_agg_rx; | 175 | struct tid_ampdu_rx *tid_agg_rx; |
178 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | 176 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; |
179 | u8 dialog_token; | 177 | u8 dialog_token; |
@@ -218,13 +216,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
218 | goto end_no_lock; | 216 | goto end_no_lock; |
219 | } | 217 | } |
220 | /* determine default buffer size */ | 218 | /* determine default buffer size */ |
221 | if (buf_size == 0) { | 219 | if (buf_size == 0) |
222 | struct ieee80211_supported_band *sband; | 220 | buf_size = IEEE80211_MAX_AMPDU_BUF; |
223 | |||
224 | sband = local->hw.wiphy->bands[conf->channel->band]; | ||
225 | buf_size = IEEE80211_MIN_AMPDU_BUF; | ||
226 | buf_size = buf_size << sband->ht_cap.ampdu_factor; | ||
227 | } | ||
228 | 221 | ||
229 | 222 | ||
230 | /* examine state machine */ | 223 | /* examine state machine */ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 29ac8e1a509e..2095602dcc3a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -634,6 +634,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
634 | struct sta_info *sta, | 634 | struct sta_info *sta, |
635 | struct station_parameters *params) | 635 | struct station_parameters *params) |
636 | { | 636 | { |
637 | unsigned long flags; | ||
637 | u32 rates; | 638 | u32 rates; |
638 | int i, j; | 639 | int i, j; |
639 | struct ieee80211_supported_band *sband; | 640 | struct ieee80211_supported_band *sband; |
@@ -642,7 +643,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
642 | 643 | ||
643 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 644 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
644 | 645 | ||
645 | spin_lock_bh(&sta->lock); | 646 | spin_lock_irqsave(&sta->flaglock, flags); |
646 | mask = params->sta_flags_mask; | 647 | mask = params->sta_flags_mask; |
647 | set = params->sta_flags_set; | 648 | set = params->sta_flags_set; |
648 | 649 | ||
@@ -669,7 +670,7 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
669 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 670 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
670 | sta->flags |= WLAN_STA_MFP; | 671 | sta->flags |= WLAN_STA_MFP; |
671 | } | 672 | } |
672 | spin_unlock_bh(&sta->lock); | 673 | spin_unlock_irqrestore(&sta->flaglock, flags); |
673 | 674 | ||
674 | /* | 675 | /* |
675 | * cfg80211 validates this (1-2007) and allows setting the AID | 676 | * cfg80211 validates this (1-2007) and allows setting the AID |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index c691780725a7..45c99f096c7b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -435,6 +435,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
435 | if (!sta) | 435 | if (!sta) |
436 | return NULL; | 436 | return NULL; |
437 | 437 | ||
438 | sta->last_rx = jiffies; | ||
438 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | 439 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); |
439 | 440 | ||
440 | /* make sure mandatory rates are always added */ | 441 | /* make sure mandatory rates are always added */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 65e0ed6c2975..3546054505ab 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1003,6 +1003,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | |||
1003 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); | 1003 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); |
1004 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1004 | void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
1005 | struct sk_buff *skb); | 1005 | struct sk_buff *skb); |
1006 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); | ||
1007 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | ||
1006 | 1008 | ||
1007 | /* IBSS code */ | 1009 | /* IBSS code */ |
1008 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1010 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 1b9d87ed143a..3f76484221a2 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -323,6 +323,12 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key) | |||
323 | if (!key) | 323 | if (!key) |
324 | return; | 324 | return; |
325 | 325 | ||
326 | /* | ||
327 | * Synchronize so the TX path can no longer be using | ||
328 | * this key before we free/remove it. | ||
329 | */ | ||
330 | synchronize_rcu(); | ||
331 | |||
326 | if (key->local) | 332 | if (key->local) |
327 | ieee80211_key_disable_hw_accel(key); | 333 | ieee80211_key_disable_hw_accel(key); |
328 | 334 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ded5c3843e06..e8acdb2fb2ca 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -108,7 +108,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
108 | chan = scan_chan; | 108 | chan = scan_chan; |
109 | channel_type = NL80211_CHAN_NO_HT; | 109 | channel_type = NL80211_CHAN_NO_HT; |
110 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 110 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; |
111 | } else if (local->tmp_channel) { | 111 | } else if (local->tmp_channel && |
112 | local->oper_channel != local->tmp_channel) { | ||
112 | chan = scan_chan = local->tmp_channel; | 113 | chan = scan_chan = local->tmp_channel; |
113 | channel_type = local->tmp_channel_type; | 114 | channel_type = local->tmp_channel_type; |
114 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 115 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index ea13a80a476c..1c91f0f3c307 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -412,7 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
412 | enum plink_event event; | 412 | enum plink_event event; |
413 | enum plink_frame_type ftype; | 413 | enum plink_frame_type ftype; |
414 | size_t baselen; | 414 | size_t baselen; |
415 | bool deactivated; | 415 | bool deactivated, matches_local = true; |
416 | u8 ie_len; | 416 | u8 ie_len; |
417 | u8 *baseaddr; | 417 | u8 *baseaddr; |
418 | __le16 plid, llid, reason; | 418 | __le16 plid, llid, reason; |
@@ -487,6 +487,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
487 | /* Now we will figure out the appropriate event... */ | 487 | /* Now we will figure out the appropriate event... */ |
488 | event = PLINK_UNDEFINED; | 488 | event = PLINK_UNDEFINED; |
489 | if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { | 489 | if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { |
490 | matches_local = false; | ||
490 | switch (ftype) { | 491 | switch (ftype) { |
491 | case PLINK_OPEN: | 492 | case PLINK_OPEN: |
492 | event = OPN_RJCT; | 493 | event = OPN_RJCT; |
@@ -498,7 +499,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
498 | /* avoid warning */ | 499 | /* avoid warning */ |
499 | break; | 500 | break; |
500 | } | 501 | } |
501 | spin_lock_bh(&sta->lock); | 502 | } |
503 | |||
504 | if (!sta && !matches_local) { | ||
505 | rcu_read_unlock(); | ||
506 | reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); | ||
507 | llid = 0; | ||
508 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, | ||
509 | plid, reason); | ||
510 | return; | ||
502 | } else if (!sta) { | 511 | } else if (!sta) { |
503 | /* ftype == PLINK_OPEN */ | 512 | /* ftype == PLINK_OPEN */ |
504 | u32 rates; | 513 | u32 rates; |
@@ -522,7 +531,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
522 | } | 531 | } |
523 | event = OPN_ACPT; | 532 | event = OPN_ACPT; |
524 | spin_lock_bh(&sta->lock); | 533 | spin_lock_bh(&sta->lock); |
525 | } else { | 534 | } else if (matches_local) { |
526 | spin_lock_bh(&sta->lock); | 535 | spin_lock_bh(&sta->lock); |
527 | switch (ftype) { | 536 | switch (ftype) { |
528 | case PLINK_OPEN: | 537 | case PLINK_OPEN: |
@@ -564,6 +573,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
564 | rcu_read_unlock(); | 573 | rcu_read_unlock(); |
565 | return; | 574 | return; |
566 | } | 575 | } |
576 | } else { | ||
577 | spin_lock_bh(&sta->lock); | ||
567 | } | 578 | } |
568 | 579 | ||
569 | mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", | 580 | mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index b6c163ac22da..4c5eed9446f4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -109,7 +109,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd, | |||
109 | mod_timer(&ifmgd->timer, timeout); | 109 | mod_timer(&ifmgd->timer, timeout); |
110 | } | 110 | } |
111 | 111 | ||
112 | static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | 112 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) |
113 | { | 113 | { |
114 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) | 114 | if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) |
115 | return; | 115 | return; |
@@ -118,6 +118,19 @@ static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) | |||
118 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); | 118 | round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); |
119 | } | 119 | } |
120 | 120 | ||
121 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) | ||
122 | { | ||
123 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
124 | |||
125 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
126 | return; | ||
127 | |||
128 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
129 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
130 | |||
131 | ifmgd->probe_send_count = 0; | ||
132 | } | ||
133 | |||
121 | static int ecw2cw(int ecw) | 134 | static int ecw2cw(int ecw) |
122 | { | 135 | { |
123 | return (1 << ecw) - 1; | 136 | return (1 << ecw) - 1; |
@@ -1006,21 +1019,26 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1006 | if (is_multicast_ether_addr(hdr->addr1)) | 1019 | if (is_multicast_ether_addr(hdr->addr1)) |
1007 | return; | 1020 | return; |
1008 | 1021 | ||
1009 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 1022 | ieee80211_sta_reset_conn_monitor(sdata); |
1010 | return; | ||
1011 | |||
1012 | mod_timer(&sdata->u.mgd.conn_mon_timer, | ||
1013 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | ||
1014 | } | 1023 | } |
1015 | 1024 | ||
1016 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | 1025 | static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) |
1017 | { | 1026 | { |
1018 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1027 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1019 | const u8 *ssid; | 1028 | const u8 *ssid; |
1029 | u8 *dst = ifmgd->associated->bssid; | ||
1030 | u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); | ||
1031 | |||
1032 | /* | ||
1033 | * Try sending broadcast probe requests for the last three | ||
1034 | * probe requests after the first ones failed since some | ||
1035 | * buggy APs only support broadcast probe requests. | ||
1036 | */ | ||
1037 | if (ifmgd->probe_send_count >= unicast_limit) | ||
1038 | dst = NULL; | ||
1020 | 1039 | ||
1021 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1040 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1022 | ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, | 1041 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); |
1023 | ssid + 2, ssid[1], NULL, 0); | ||
1024 | 1042 | ||
1025 | ifmgd->probe_send_count++; | 1043 | ifmgd->probe_send_count++; |
1026 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | 1044 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; |
@@ -1262,7 +1280,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1262 | 1280 | ||
1263 | rates = 0; | 1281 | rates = 0; |
1264 | basic_rates = 0; | 1282 | basic_rates = 0; |
1265 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1283 | sband = local->hw.wiphy->bands[wk->chan->band]; |
1266 | 1284 | ||
1267 | for (i = 0; i < elems.supp_rates_len; i++) { | 1285 | for (i = 0; i < elems.supp_rates_len; i++) { |
1268 | int rate = (elems.supp_rates[i] & 0x7f) * 5; | 1286 | int rate = (elems.supp_rates[i] & 0x7f) * 5; |
@@ -1298,11 +1316,11 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1298 | } | 1316 | } |
1299 | } | 1317 | } |
1300 | 1318 | ||
1301 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 1319 | sta->sta.supp_rates[wk->chan->band] = rates; |
1302 | sdata->vif.bss_conf.basic_rates = basic_rates; | 1320 | sdata->vif.bss_conf.basic_rates = basic_rates; |
1303 | 1321 | ||
1304 | /* cf. IEEE 802.11 9.2.12 */ | 1322 | /* cf. IEEE 802.11 9.2.12 */ |
1305 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 1323 | if (wk->chan->band == IEEE80211_BAND_2GHZ && |
1306 | have_higher_than_11mbit) | 1324 | have_higher_than_11mbit) |
1307 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 1325 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
1308 | else | 1326 | else |
@@ -1362,7 +1380,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk, | |||
1362 | * Also start the timer that will detect beacon loss. | 1380 | * Also start the timer that will detect beacon loss. |
1363 | */ | 1381 | */ |
1364 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 1382 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1365 | mod_beacon_timer(sdata); | 1383 | ieee80211_sta_reset_beacon_monitor(sdata); |
1366 | 1384 | ||
1367 | return true; | 1385 | return true; |
1368 | } | 1386 | } |
@@ -1465,7 +1483,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1465 | * we have or will be receiving any beacons or data, so let's | 1483 | * we have or will be receiving any beacons or data, so let's |
1466 | * schedule the timers again, just in case. | 1484 | * schedule the timers again, just in case. |
1467 | */ | 1485 | */ |
1468 | mod_beacon_timer(sdata); | 1486 | ieee80211_sta_reset_beacon_monitor(sdata); |
1469 | 1487 | ||
1470 | mod_timer(&ifmgd->conn_mon_timer, | 1488 | mod_timer(&ifmgd->conn_mon_timer, |
1471 | round_jiffies_up(jiffies + | 1489 | round_jiffies_up(jiffies + |
@@ -1540,7 +1558,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1540 | ifmgd->last_beacon_signal = rx_status->signal; | 1558 | ifmgd->last_beacon_signal = rx_status->signal; |
1541 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | 1559 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { |
1542 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | 1560 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; |
1543 | ifmgd->ave_beacon_signal = rx_status->signal; | 1561 | ifmgd->ave_beacon_signal = rx_status->signal * 16; |
1544 | ifmgd->last_cqm_event_signal = 0; | 1562 | ifmgd->last_cqm_event_signal = 0; |
1545 | } else { | 1563 | } else { |
1546 | ifmgd->ave_beacon_signal = | 1564 | ifmgd->ave_beacon_signal = |
@@ -1588,7 +1606,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1588 | * Push the beacon loss detection into the future since | 1606 | * Push the beacon loss detection into the future since |
1589 | * we are processing a beacon from the AP just now. | 1607 | * we are processing a beacon from the AP just now. |
1590 | */ | 1608 | */ |
1591 | mod_beacon_timer(sdata); | 1609 | ieee80211_sta_reset_beacon_monitor(sdata); |
1592 | 1610 | ||
1593 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); | 1611 | ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); |
1594 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, | 1612 | ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index c36b1911987a..cf5ee305785b 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -22,12 +22,16 @@ | |||
22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | 22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) |
23 | { | 23 | { |
24 | struct ieee80211_local *local = sdata->local; | 24 | struct ieee80211_local *local = sdata->local; |
25 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
25 | 26 | ||
26 | local->offchannel_ps_enabled = false; | 27 | local->offchannel_ps_enabled = false; |
27 | 28 | ||
28 | /* FIXME: what to do when local->pspolling is true? */ | 29 | /* FIXME: what to do when local->pspolling is true? */ |
29 | 30 | ||
30 | del_timer_sync(&local->dynamic_ps_timer); | 31 | del_timer_sync(&local->dynamic_ps_timer); |
32 | del_timer_sync(&ifmgd->bcn_mon_timer); | ||
33 | del_timer_sync(&ifmgd->conn_mon_timer); | ||
34 | |||
31 | cancel_work_sync(&local->dynamic_ps_enable_work); | 35 | cancel_work_sync(&local->dynamic_ps_enable_work); |
32 | 36 | ||
33 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 37 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
@@ -85,6 +89,9 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
85 | mod_timer(&local->dynamic_ps_timer, jiffies + | 89 | mod_timer(&local->dynamic_ps_timer, jiffies + |
86 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 90 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
87 | } | 91 | } |
92 | |||
93 | ieee80211_sta_reset_beacon_monitor(sdata); | ||
94 | ieee80211_sta_reset_conn_monitor(sdata); | ||
88 | } | 95 | } |
89 | 96 | ||
90 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | 97 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index be04d46110fe..82d5750a110a 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -328,6 +328,9 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, | |||
328 | * if needed. | 328 | * if needed. |
329 | */ | 329 | */ |
330 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 330 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
331 | /* Skip invalid rates */ | ||
332 | if (info->control.rates[i].idx < 0) | ||
333 | break; | ||
331 | /* Rate masking supports only legacy rates for now */ | 334 | /* Rate masking supports only legacy rates for now */ |
332 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) | 335 | if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) |
333 | continue; | 336 | continue; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c5b465904e3b..2a18d6602d4a 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -397,8 +397,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
397 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 397 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
398 | return; | 398 | return; |
399 | 399 | ||
400 | if (!info->status.ampdu_len) { | 400 | if (!(info->flags & IEEE80211_TX_STAT_AMPDU)) { |
401 | info->status.ampdu_ack_len = 1; | 401 | info->status.ampdu_ack_len = |
402 | (info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); | ||
402 | info->status.ampdu_len = 1; | 403 | info->status.ampdu_len = 1; |
403 | } | 404 | } |
404 | 405 | ||
@@ -426,7 +427,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
426 | group = minstrel_ht_get_group_idx(&ar[i]); | 427 | group = minstrel_ht_get_group_idx(&ar[i]); |
427 | rate = &mi->groups[group].rates[ar[i].idx % 8]; | 428 | rate = &mi->groups[group].rates[ar[i].idx % 8]; |
428 | 429 | ||
429 | if (last && (info->flags & IEEE80211_TX_STAT_ACK)) | 430 | if (last) |
430 | rate->success += info->status.ampdu_ack_len; | 431 | rate->success += info->status.ampdu_ack_len; |
431 | 432 | ||
432 | rate->attempts += ar[i].count * info->status.ampdu_len; | 433 | rate->attempts += ar[i].count * info->status.ampdu_len; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 28624282c5f3..2bec9b9dba09 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1715,6 +1715,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1715 | if (!fwd_skb && net_ratelimit()) | 1715 | if (!fwd_skb && net_ratelimit()) |
1716 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1716 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1717 | sdata->name); | 1717 | sdata->name); |
1718 | if (!fwd_skb) | ||
1719 | goto out; | ||
1718 | 1720 | ||
1719 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1721 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1720 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | 1722 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); |
@@ -1752,6 +1754,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1752 | } | 1754 | } |
1753 | } | 1755 | } |
1754 | 1756 | ||
1757 | out: | ||
1755 | if (is_multicast_ether_addr(hdr->addr1) || | 1758 | if (is_multicast_ether_addr(hdr->addr1) || |
1756 | sdata->dev->flags & IFF_PROMISC) | 1759 | sdata->dev->flags & IFF_PROMISC) |
1757 | return RX_CONTINUE; | 1760 | return RX_CONTINUE; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 34da67995d94..6ffa26a9de39 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -58,6 +58,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
58 | info->control.vif = &sta->sdata->vif; | 58 | info->control.vif = &sta->sdata->vif; |
59 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | | 59 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING | |
60 | IEEE80211_TX_INTFL_RETRANSMISSION; | 60 | IEEE80211_TX_INTFL_RETRANSMISSION; |
61 | info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS; | ||
61 | 62 | ||
62 | sta->tx_filtered_count++; | 63 | sta->tx_filtered_count++; |
63 | 64 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c54db966926b..9d5af5dd0d98 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1694,7 +1694,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1694 | { | 1694 | { |
1695 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1695 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1696 | struct ieee80211_local *local = sdata->local; | 1696 | struct ieee80211_local *local = sdata->local; |
1697 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1697 | struct ieee80211_tx_info *info; |
1698 | int ret = NETDEV_TX_BUSY, head_need; | 1698 | int ret = NETDEV_TX_BUSY, head_need; |
1699 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1699 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1700 | __le16 fc; | 1700 | __le16 fc; |
@@ -1705,15 +1705,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1705 | int nh_pos, h_pos; | 1705 | int nh_pos, h_pos; |
1706 | struct sta_info *sta = NULL; | 1706 | struct sta_info *sta = NULL; |
1707 | u32 sta_flags = 0; | 1707 | u32 sta_flags = 0; |
1708 | struct sk_buff *tmp_skb; | ||
1708 | 1709 | ||
1709 | if (unlikely(skb->len < ETH_HLEN)) { | 1710 | if (unlikely(skb->len < ETH_HLEN)) { |
1710 | ret = NETDEV_TX_OK; | 1711 | ret = NETDEV_TX_OK; |
1711 | goto fail; | 1712 | goto fail; |
1712 | } | 1713 | } |
1713 | 1714 | ||
1714 | nh_pos = skb_network_header(skb) - skb->data; | ||
1715 | h_pos = skb_transport_header(skb) - skb->data; | ||
1716 | |||
1717 | /* convert Ethernet header to proper 802.11 header (based on | 1715 | /* convert Ethernet header to proper 802.11 header (based on |
1718 | * operation mode) */ | 1716 | * operation mode) */ |
1719 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1717 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
@@ -1885,6 +1883,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1885 | goto fail; | 1883 | goto fail; |
1886 | } | 1884 | } |
1887 | 1885 | ||
1886 | /* | ||
1887 | * If the skb is shared we need to obtain our own copy. | ||
1888 | */ | ||
1889 | if (skb_shared(skb)) { | ||
1890 | tmp_skb = skb; | ||
1891 | skb = skb_copy(skb, GFP_ATOMIC); | ||
1892 | kfree_skb(tmp_skb); | ||
1893 | |||
1894 | if (!skb) { | ||
1895 | ret = NETDEV_TX_OK; | ||
1896 | goto fail; | ||
1897 | } | ||
1898 | } | ||
1899 | |||
1888 | hdr.frame_control = fc; | 1900 | hdr.frame_control = fc; |
1889 | hdr.duration_id = 0; | 1901 | hdr.duration_id = 0; |
1890 | hdr.seq_ctrl = 0; | 1902 | hdr.seq_ctrl = 0; |
@@ -1903,6 +1915,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1903 | encaps_len = 0; | 1915 | encaps_len = 0; |
1904 | } | 1916 | } |
1905 | 1917 | ||
1918 | nh_pos = skb_network_header(skb) - skb->data; | ||
1919 | h_pos = skb_transport_header(skb) - skb->data; | ||
1920 | |||
1906 | skb_pull(skb, skip_header_bytes); | 1921 | skb_pull(skb, skip_header_bytes); |
1907 | nh_pos -= skip_header_bytes; | 1922 | nh_pos -= skip_header_bytes; |
1908 | h_pos -= skip_header_bytes; | 1923 | h_pos -= skip_header_bytes; |
@@ -1969,6 +1984,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1969 | skb_set_network_header(skb, nh_pos); | 1984 | skb_set_network_header(skb, nh_pos); |
1970 | skb_set_transport_header(skb, h_pos); | 1985 | skb_set_transport_header(skb, h_pos); |
1971 | 1986 | ||
1987 | info = IEEE80211_SKB_CB(skb); | ||
1972 | memset(info, 0, sizeof(*info)); | 1988 | memset(info, 0, sizeof(*info)); |
1973 | 1989 | ||
1974 | dev->trans_start = jiffies; | 1990 | dev->trans_start = jiffies; |
@@ -2160,6 +2176,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2160 | 2176 | ||
2161 | sdata = vif_to_sdata(vif); | 2177 | sdata = vif_to_sdata(vif); |
2162 | 2178 | ||
2179 | if (!ieee80211_sdata_running(sdata)) | ||
2180 | goto out; | ||
2181 | |||
2163 | if (tim_offset) | 2182 | if (tim_offset) |
2164 | *tim_offset = 0; | 2183 | *tim_offset = 0; |
2165 | if (tim_length) | 2184 | if (tim_length) |