aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-10-15 11:20:54 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-10-15 11:20:54 -0400
commitdf9b42963f2d010ae3163a894ce22cf6b27cd344 (patch)
treef42f826d9bb975766c1a79986c39e64c9a900908 /net/mac80211/mlme.c
parent33766368f6532313571534f9112b1796d6651bbe (diff)
parentc3e7724b6bc2f25e46c38dbe68f09d71fafeafb8 (diff)
Merge remote-tracking branch 'wireless/master' into mac80211
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c443
1 files changed, 270 insertions, 173 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f76b83341cf9..e714ed8bb198 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -88,8 +88,6 @@ MODULE_PARM_DESC(probe_wait_ms,
88#define TMR_RUNNING_TIMER 0 88#define TMR_RUNNING_TIMER 0
89#define TMR_RUNNING_CHANSW 1 89#define TMR_RUNNING_CHANSW 1
90 90
91#define DEAUTH_DISASSOC_LEN (24 /* hdr */ + 2 /* reason */)
92
93/* 91/*
94 * All cfg80211 functions have to be called outside a locked 92 * All cfg80211 functions have to be called outside a locked
95 * section so that they can acquire a lock themselves... This 93 * section so that they can acquire a lock themselves... This
@@ -146,6 +144,9 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
146 if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) 144 if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
147 return; 145 return;
148 146
147 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
148 return;
149
149 mod_timer(&sdata->u.mgd.bcn_mon_timer, 150 mod_timer(&sdata->u.mgd.bcn_mon_timer,
150 round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); 151 round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout));
151} 152}
@@ -182,15 +183,15 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
182 u16 ht_opmode; 183 u16 ht_opmode;
183 bool disable_40 = false; 184 bool disable_40 = false;
184 185
185 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 186 sband = local->hw.wiphy->bands[local->oper_channel->band];
186 187
187 switch (sdata->vif.bss_conf.channel_type) { 188 switch (sdata->vif.bss_conf.channel_type) {
188 case NL80211_CHAN_HT40PLUS: 189 case NL80211_CHAN_HT40PLUS:
189 if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40PLUS) 190 if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
190 disable_40 = true; 191 disable_40 = true;
191 break; 192 break;
192 case NL80211_CHAN_HT40MINUS: 193 case NL80211_CHAN_HT40MINUS:
193 if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40MINUS) 194 if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
194 disable_40 = true; 195 disable_40 = true;
195 break; 196 break;
196 default: 197 default:
@@ -326,6 +327,26 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
326 ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); 327 ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
327} 328}
328 329
330static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
331 struct sk_buff *skb,
332 struct ieee80211_supported_band *sband)
333{
334 u8 *pos;
335 u32 cap;
336 struct ieee80211_sta_vht_cap vht_cap;
337
338 BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));
339
340 memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
341
342 /* determine capability flags */
343 cap = vht_cap.cap;
344
345 /* reserve and fill IE */
346 pos = skb_put(skb, sizeof(struct ieee80211_vht_capabilities) + 2);
347 ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
348}
349
329static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) 350static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
330{ 351{
331 struct ieee80211_local *local = sdata->local; 352 struct ieee80211_local *local = sdata->local;
@@ -371,6 +392,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
371 4 + /* power capability */ 392 4 + /* power capability */
372 2 + 2 * sband->n_channels + /* supported channels */ 393 2 + 2 * sband->n_channels + /* supported channels */
373 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ 394 2 + sizeof(struct ieee80211_ht_cap) + /* HT */
395 2 + sizeof(struct ieee80211_vht_capabilities) + /* VHT */
374 assoc_data->ie_len + /* extra IEs */ 396 assoc_data->ie_len + /* extra IEs */
375 9, /* WMM */ 397 9, /* WMM */
376 GFP_KERNEL); 398 GFP_KERNEL);
@@ -503,6 +525,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
503 ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, 525 ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
504 sband, local->oper_channel, ifmgd->ap_smps); 526 sband, local->oper_channel, ifmgd->ap_smps);
505 527
528 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
529 ieee80211_add_vht_ie(sdata, skb, sband);
530
506 /* if present, add any custom non-vendor IEs that go after HT */ 531 /* if present, add any custom non-vendor IEs that go after HT */
507 if (assoc_data->ie_len && assoc_data->ie) { 532 if (assoc_data->ie_len && assoc_data->ie) {
508 noffset = ieee80211_ie_split_vendor(assoc_data->ie, 533 noffset = ieee80211_ie_split_vendor(assoc_data->ie,
@@ -547,48 +572,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
547 ieee80211_tx_skb(sdata, skb); 572 ieee80211_tx_skb(sdata, skb);
548} 573}
549 574
550static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
551 const u8 *bssid, u16 stype,
552 u16 reason, bool send_frame,
553 u8 *frame_buf)
554{
555 struct ieee80211_local *local = sdata->local;
556 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
557 struct sk_buff *skb;
558 struct ieee80211_mgmt *mgmt = (void *)frame_buf;
559
560 /* build frame */
561 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
562 mgmt->duration = 0; /* initialize only */
563 mgmt->seq_ctrl = 0; /* initialize only */
564 memcpy(mgmt->da, bssid, ETH_ALEN);
565 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
566 memcpy(mgmt->bssid, bssid, ETH_ALEN);
567 /* u.deauth.reason_code == u.disassoc.reason_code */
568 mgmt->u.deauth.reason_code = cpu_to_le16(reason);
569
570 if (send_frame) {
571 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
572 DEAUTH_DISASSOC_LEN);
573 if (!skb)
574 return;
575
576 skb_reserve(skb, local->hw.extra_tx_headroom);
577
578 /* copy in frame */
579 memcpy(skb_put(skb, DEAUTH_DISASSOC_LEN),
580 mgmt, DEAUTH_DISASSOC_LEN);
581
582 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
583 IEEE80211_SKB_CB(skb)->flags |=
584 IEEE80211_TX_INTFL_DONT_ENCRYPT;
585
586 drv_mgd_prepare_tx(local, sdata);
587
588 ieee80211_tx_skb(sdata, skb);
589 }
590}
591
592void ieee80211_send_pspoll(struct ieee80211_local *local, 575void ieee80211_send_pspoll(struct ieee80211_local *local,
593 struct ieee80211_sub_if_data *sdata) 576 struct ieee80211_sub_if_data *sdata)
594{ 577{
@@ -687,6 +670,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
687 /* XXX: shouldn't really modify cfg80211-owned data! */ 670 /* XXX: shouldn't really modify cfg80211-owned data! */
688 ifmgd->associated->channel = sdata->local->oper_channel; 671 ifmgd->associated->channel = sdata->local->oper_channel;
689 672
673 /* XXX: wait for a beacon first? */
690 ieee80211_wake_queues_by_reason(&sdata->local->hw, 674 ieee80211_wake_queues_by_reason(&sdata->local->hw,
691 IEEE80211_QUEUE_STOP_REASON_CSA); 675 IEEE80211_QUEUE_STOP_REASON_CSA);
692 out: 676 out:
@@ -704,16 +688,13 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
704 688
705 trace_api_chswitch_done(sdata, success); 689 trace_api_chswitch_done(sdata, success);
706 if (!success) { 690 if (!success) {
707 /* 691 sdata_info(sdata,
708 * If the channel switch was not successful, stay 692 "driver channel switch failed, disconnecting\n");
709 * around on the old channel. We currently lack 693 ieee80211_queue_work(&sdata->local->hw,
710 * good handling of this situation, possibly we 694 &ifmgd->csa_connection_drop_work);
711 * should just drop the association. 695 } else {
712 */ 696 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
713 sdata->local->csa_channel = sdata->local->oper_channel;
714 } 697 }
715
716 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
717} 698}
718EXPORT_SYMBOL(ieee80211_chswitch_done); 699EXPORT_SYMBOL(ieee80211_chswitch_done);
719 700
@@ -758,61 +739,111 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
758 return; 739 return;
759 740
760 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); 741 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
761 if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) 742 if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) {
743 sdata_info(sdata,
744 "AP %pM switches to unsupported channel (%d MHz), disconnecting\n",
745 ifmgd->associated->bssid, new_freq);
746 ieee80211_queue_work(&sdata->local->hw,
747 &ifmgd->csa_connection_drop_work);
762 return; 748 return;
749 }
763 750
764 sdata->local->csa_channel = new_ch; 751 sdata->local->csa_channel = new_ch;
765 752
753 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
754
755 if (sw_elem->mode)
756 ieee80211_stop_queues_by_reason(&sdata->local->hw,
757 IEEE80211_QUEUE_STOP_REASON_CSA);
758
766 if (sdata->local->ops->channel_switch) { 759 if (sdata->local->ops->channel_switch) {
767 /* use driver's channel switch callback */ 760 /* use driver's channel switch callback */
768 struct ieee80211_channel_switch ch_switch; 761 struct ieee80211_channel_switch ch_switch = {
769 memset(&ch_switch, 0, sizeof(ch_switch)); 762 .timestamp = timestamp,
770 ch_switch.timestamp = timestamp; 763 .block_tx = sw_elem->mode,
771 if (sw_elem->mode) { 764 .channel = new_ch,
772 ch_switch.block_tx = true; 765 .count = sw_elem->count,
773 ieee80211_stop_queues_by_reason(&sdata->local->hw, 766 };
774 IEEE80211_QUEUE_STOP_REASON_CSA); 767
775 }
776 ch_switch.channel = new_ch;
777 ch_switch.count = sw_elem->count;
778 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
779 drv_channel_switch(sdata->local, &ch_switch); 768 drv_channel_switch(sdata->local, &ch_switch);
780 return; 769 return;
781 } 770 }
782 771
783 /* channel switch handled in software */ 772 /* channel switch handled in software */
784 if (sw_elem->count <= 1) { 773 if (sw_elem->count <= 1)
785 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); 774 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
786 } else { 775 else
787 if (sw_elem->mode)
788 ieee80211_stop_queues_by_reason(&sdata->local->hw,
789 IEEE80211_QUEUE_STOP_REASON_CSA);
790 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
791 mod_timer(&ifmgd->chswitch_timer, 776 mod_timer(&ifmgd->chswitch_timer,
792 jiffies + 777 TU_TO_EXP_TIME(sw_elem->count *
793 msecs_to_jiffies(sw_elem->count * 778 cbss->beacon_interval));
794 cbss->beacon_interval));
795 }
796} 779}
797 780
798static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 781static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
799 u16 capab_info, u8 *pwr_constr_elem, 782 struct ieee80211_channel *channel,
800 u8 pwr_constr_elem_len) 783 const u8 *country_ie, u8 country_ie_len,
784 const u8 *pwr_constr_elem)
801{ 785{
802 struct ieee80211_conf *conf = &sdata->local->hw.conf; 786 struct ieee80211_country_ie_triplet *triplet;
787 int chan = ieee80211_frequency_to_channel(channel->center_freq);
788 int i, chan_pwr, chan_increment, new_ap_level;
789 bool have_chan_pwr = false;
803 790
804 if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT)) 791 /* Invalid IE */
792 if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
805 return; 793 return;
806 794
807 /* Power constraint IE length should be 1 octet */ 795 triplet = (void *)(country_ie + 3);
808 if (pwr_constr_elem_len != 1) 796 country_ie_len -= 3;
809 return; 797
798 switch (channel->band) {
799 default:
800 WARN_ON_ONCE(1);
801 /* fall through */
802 case IEEE80211_BAND_2GHZ:
803 case IEEE80211_BAND_60GHZ:
804 chan_increment = 1;
805 break;
806 case IEEE80211_BAND_5GHZ:
807 chan_increment = 4;
808 break;
809 }
810
811 /* find channel */
812 while (country_ie_len >= 3) {
813 u8 first_channel = triplet->chans.first_channel;
810 814
811 if ((*pwr_constr_elem <= conf->channel->max_reg_power) && 815 if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID)
812 (*pwr_constr_elem != sdata->local->power_constr_level)) { 816 goto next;
813 sdata->local->power_constr_level = *pwr_constr_elem; 817
814 ieee80211_hw_config(sdata->local, 0); 818 for (i = 0; i < triplet->chans.num_channels; i++) {
819 if (first_channel + i * chan_increment == chan) {
820 have_chan_pwr = true;
821 chan_pwr = triplet->chans.max_power;
822 break;
823 }
824 }
825 if (have_chan_pwr)
826 break;
827
828 next:
829 triplet++;
830 country_ie_len -= 3;
815 } 831 }
832
833 if (!have_chan_pwr)
834 return;
835
836 new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);
837
838 if (sdata->local->ap_power_level == new_ap_level)
839 return;
840
841 sdata_info(sdata,
842 "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
843 new_ap_level, chan_pwr, *pwr_constr_elem,
844 sdata->u.mgd.bssid);
845 sdata->local->ap_power_level = new_ap_level;
846 ieee80211_hw_config(sdata->local, 0);
816} 847}
817 848
818void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) 849void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
@@ -1007,6 +1038,16 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
1007 ieee80211_change_ps(local); 1038 ieee80211_change_ps(local);
1008} 1039}
1009 1040
1041void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata)
1042{
1043 bool ps_allowed = ieee80211_powersave_allowed(sdata);
1044
1045 if (sdata->vif.bss_conf.ps != ps_allowed) {
1046 sdata->vif.bss_conf.ps = ps_allowed;
1047 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_PS);
1048 }
1049}
1050
1010void ieee80211_dynamic_ps_disable_work(struct work_struct *work) 1051void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
1011{ 1052{
1012 struct ieee80211_local *local = 1053 struct ieee80211_local *local =
@@ -1239,7 +1280,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
1239 } 1280 }
1240 1281
1241 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); 1282 use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
1242 if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) 1283 if (sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ)
1243 use_short_slot = true; 1284 use_short_slot = true;
1244 1285
1245 if (use_protection != bss_conf->use_cts_prot) { 1286 if (use_protection != bss_conf->use_cts_prot) {
@@ -1307,9 +1348,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1307 1348
1308 mutex_lock(&local->iflist_mtx); 1349 mutex_lock(&local->iflist_mtx);
1309 ieee80211_recalc_ps(local, -1); 1350 ieee80211_recalc_ps(local, -1);
1310 ieee80211_recalc_smps(local);
1311 mutex_unlock(&local->iflist_mtx); 1351 mutex_unlock(&local->iflist_mtx);
1312 1352
1353 ieee80211_recalc_smps(local);
1354 ieee80211_recalc_ps_vif(sdata);
1355
1313 netif_tx_start_all_queues(sdata->dev); 1356 netif_tx_start_all_queues(sdata->dev);
1314 netif_carrier_on(sdata->dev); 1357 netif_carrier_on(sdata->dev);
1315} 1358}
@@ -1356,7 +1399,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1356 sta = sta_info_get(sdata, ifmgd->bssid); 1399 sta = sta_info_get(sdata, ifmgd->bssid);
1357 if (sta) { 1400 if (sta) {
1358 set_sta_flag(sta, WLAN_STA_BLOCK_BA); 1401 set_sta_flag(sta, WLAN_STA_BLOCK_BA);
1359 ieee80211_sta_tear_down_BA_sessions(sta, tx); 1402 ieee80211_sta_tear_down_BA_sessions(sta, false);
1360 } 1403 }
1361 mutex_unlock(&local->sta_mtx); 1404 mutex_unlock(&local->sta_mtx);
1362 1405
@@ -1371,6 +1414,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1371 } 1414 }
1372 local->ps_sdata = NULL; 1415 local->ps_sdata = NULL;
1373 1416
1417 /* disable per-vif ps */
1418 ieee80211_recalc_ps_vif(sdata);
1419
1374 /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ 1420 /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */
1375 if (tx) 1421 if (tx)
1376 drv_flush(local, false); 1422 drv_flush(local, false);
@@ -1401,7 +1447,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1401 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); 1447 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
1402 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); 1448 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1403 1449
1404 local->power_constr_level = 0; 1450 local->ap_power_level = 0;
1405 1451
1406 del_timer_sync(&local->dynamic_ps_timer); 1452 del_timer_sync(&local->dynamic_ps_timer);
1407 cancel_work_sync(&local->dynamic_ps_enable_work); 1453 cancel_work_sync(&local->dynamic_ps_enable_work);
@@ -1542,7 +1588,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1542 ssid_len = ssid[1]; 1588 ssid_len = ssid[1];
1543 1589
1544 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, 1590 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
1545 0, (u32) -1, true, false); 1591 0, (u32) -1, true, false,
1592 ifmgd->associated->channel);
1546 } 1593 }
1547 1594
1548 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); 1595 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
@@ -1645,19 +1692,21 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
1645 ssid_len = ssid[1]; 1692 ssid_len = ssid[1];
1646 1693
1647 skb = ieee80211_build_probe_req(sdata, cbss->bssid, 1694 skb = ieee80211_build_probe_req(sdata, cbss->bssid,
1648 (u32) -1, ssid + 2, ssid_len, 1695 (u32) -1,
1696 sdata->local->oper_channel,
1697 ssid + 2, ssid_len,
1649 NULL, 0, true); 1698 NULL, 0, true);
1650 1699
1651 return skb; 1700 return skb;
1652} 1701}
1653EXPORT_SYMBOL(ieee80211_ap_probereq_get); 1702EXPORT_SYMBOL(ieee80211_ap_probereq_get);
1654 1703
1655static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) 1704static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata,
1705 bool transmit_frame)
1656{ 1706{
1657 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1707 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1658 struct ieee80211_local *local = sdata->local; 1708 struct ieee80211_local *local = sdata->local;
1659 u8 bssid[ETH_ALEN]; 1709 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
1660 u8 frame_buf[DEAUTH_DISASSOC_LEN];
1661 1710
1662 mutex_lock(&ifmgd->mtx); 1711 mutex_lock(&ifmgd->mtx);
1663 if (!ifmgd->associated) { 1712 if (!ifmgd->associated) {
@@ -1665,27 +1714,24 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1665 return; 1714 return;
1666 } 1715 }
1667 1716
1668 memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
1669
1670 sdata_info(sdata, "Connection to AP %pM lost\n", bssid);
1671
1672 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 1717 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
1673 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1718 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1674 false, frame_buf); 1719 transmit_frame, frame_buf);
1720 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
1675 mutex_unlock(&ifmgd->mtx); 1721 mutex_unlock(&ifmgd->mtx);
1676 1722
1677 /* 1723 /*
1678 * must be outside lock due to cfg80211, 1724 * must be outside lock due to cfg80211,
1679 * but that's not a problem. 1725 * but that's not a problem.
1680 */ 1726 */
1681 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 1727 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
1682 1728
1683 mutex_lock(&local->mtx); 1729 mutex_lock(&local->mtx);
1684 ieee80211_recalc_idle(local); 1730 ieee80211_recalc_idle(local);
1685 mutex_unlock(&local->mtx); 1731 mutex_unlock(&local->mtx);
1686} 1732}
1687 1733
1688void ieee80211_beacon_connection_loss_work(struct work_struct *work) 1734static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
1689{ 1735{
1690 struct ieee80211_sub_if_data *sdata = 1736 struct ieee80211_sub_if_data *sdata =
1691 container_of(work, struct ieee80211_sub_if_data, 1737 container_of(work, struct ieee80211_sub_if_data,
@@ -1701,10 +1747,24 @@ void ieee80211_beacon_connection_loss_work(struct work_struct *work)
1701 rcu_read_unlock(); 1747 rcu_read_unlock();
1702 } 1748 }
1703 1749
1704 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) 1750 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) {
1705 __ieee80211_connection_loss(sdata); 1751 sdata_info(sdata, "Connection to AP %pM lost\n",
1706 else 1752 ifmgd->bssid);
1753 __ieee80211_disconnect(sdata, false);
1754 } else {
1707 ieee80211_mgd_probe_ap(sdata, true); 1755 ieee80211_mgd_probe_ap(sdata, true);
1756 }
1757}
1758
1759static void ieee80211_csa_connection_drop_work(struct work_struct *work)
1760{
1761 struct ieee80211_sub_if_data *sdata =
1762 container_of(work, struct ieee80211_sub_if_data,
1763 u.mgd.csa_connection_drop_work);
1764
1765 ieee80211_wake_queues_by_reason(&sdata->local->hw,
1766 IEEE80211_QUEUE_STOP_REASON_CSA);
1767 __ieee80211_disconnect(sdata, true);
1708} 1768}
1709 1769
1710void ieee80211_beacon_loss(struct ieee80211_vif *vif) 1770void ieee80211_beacon_loss(struct ieee80211_vif *vif)
@@ -2232,14 +2292,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2232 mutex_unlock(&local->iflist_mtx); 2292 mutex_unlock(&local->iflist_mtx);
2233 } 2293 }
2234 2294
2235 if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && 2295 if (elems->ch_switch_ie &&
2236 (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, 2296 memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0)
2237 ETH_ALEN) == 0)) { 2297 ieee80211_sta_process_chanswitch(sdata, elems->ch_switch_ie,
2238 struct ieee80211_channel_sw_ie *sw_elem =
2239 (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
2240 ieee80211_sta_process_chanswitch(sdata, sw_elem,
2241 bss, rx_status->mactime); 2298 bss, rx_status->mactime);
2242 }
2243} 2299}
2244 2300
2245 2301
@@ -2326,7 +2382,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2326 if (baselen > len) 2382 if (baselen > len)
2327 return; 2383 return;
2328 2384
2329 if (rx_status->freq != local->hw.conf.channel->center_freq) 2385 if (rx_status->freq != local->oper_channel->center_freq)
2330 return; 2386 return;
2331 2387
2332 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && 2388 if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon &&
@@ -2490,21 +2546,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2490 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { 2546 !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) {
2491 struct ieee80211_supported_band *sband; 2547 struct ieee80211_supported_band *sband;
2492 2548
2493 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 2549 sband = local->hw.wiphy->bands[local->oper_channel->band];
2494 2550
2495 changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, 2551 changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
2496 bssid, true); 2552 bssid, true);
2497 } 2553 }
2498 2554
2499 /* Note: country IE parsing is done for us by cfg80211 */ 2555 if (elems.country_elem && elems.pwr_constr_elem &&
2500 if (elems.country_elem) { 2556 mgmt->u.probe_resp.capab_info &
2501 /* TODO: IBSS also needs this */ 2557 cpu_to_le16(WLAN_CAPABILITY_SPECTRUM_MGMT))
2502 if (elems.pwr_constr_elem) 2558 ieee80211_handle_pwr_constr(sdata, local->oper_channel,
2503 ieee80211_handle_pwr_constr(sdata, 2559 elems.country_elem,
2504 le16_to_cpu(mgmt->u.probe_resp.capab_info), 2560 elems.country_elem_len,
2505 elems.pwr_constr_elem, 2561 elems.pwr_constr_elem);
2506 elems.pwr_constr_elem_len);
2507 }
2508 2562
2509 ieee80211_bss_info_change_notify(sdata, changed); 2563 ieee80211_bss_info_change_notify(sdata, changed);
2510} 2564}
@@ -2601,7 +2655,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2601{ 2655{
2602 struct ieee80211_local *local = sdata->local; 2656 struct ieee80211_local *local = sdata->local;
2603 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2657 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2604 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 2658 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
2605 2659
2606 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, 2660 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
2607 false, frame_buf); 2661 false, frame_buf);
@@ -2611,7 +2665,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2611 * must be outside lock due to cfg80211, 2665 * must be outside lock due to cfg80211,
2612 * but that's not a problem. 2666 * but that's not a problem.
2613 */ 2667 */
2614 cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 2668 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
2615 2669
2616 mutex_lock(&local->mtx); 2670 mutex_lock(&local->mtx);
2617 ieee80211_recalc_idle(local); 2671 ieee80211_recalc_idle(local);
@@ -2673,7 +2727,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
2673 * will not answer to direct packet in unassociated state. 2727 * will not answer to direct packet in unassociated state.
2674 */ 2728 */
2675 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], 2729 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
2676 NULL, 0, (u32) -1, true, false); 2730 NULL, 0, (u32) -1, true, false,
2731 auth_data->bss->channel);
2677 } 2732 }
2678 2733
2679 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; 2734 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -2894,6 +2949,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
2894 2949
2895 cancel_work_sync(&ifmgd->monitor_work); 2950 cancel_work_sync(&ifmgd->monitor_work);
2896 cancel_work_sync(&ifmgd->beacon_connection_loss_work); 2951 cancel_work_sync(&ifmgd->beacon_connection_loss_work);
2952 cancel_work_sync(&ifmgd->csa_connection_drop_work);
2897 if (del_timer_sync(&ifmgd->timer)) 2953 if (del_timer_sync(&ifmgd->timer))
2898 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); 2954 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
2899 2955
@@ -2950,6 +3006,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2950 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 3006 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
2951 INIT_WORK(&ifmgd->beacon_connection_loss_work, 3007 INIT_WORK(&ifmgd->beacon_connection_loss_work,
2952 ieee80211_beacon_connection_loss_work); 3008 ieee80211_beacon_connection_loss_work);
3009 INIT_WORK(&ifmgd->csa_connection_drop_work,
3010 ieee80211_csa_connection_drop_work);
2953 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work); 3011 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work);
2954 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 3012 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
2955 (unsigned long) sdata); 3013 (unsigned long) sdata);
@@ -3000,41 +3058,17 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
3000 return 0; 3058 return 0;
3001} 3059}
3002 3060
3003static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, 3061static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
3004 struct cfg80211_bss *cbss, bool assoc) 3062 struct cfg80211_bss *cbss)
3005{ 3063{
3006 struct ieee80211_local *local = sdata->local; 3064 struct ieee80211_local *local = sdata->local;
3007 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3065 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3008 struct ieee80211_bss *bss = (void *)cbss->priv;
3009 struct sta_info *sta = NULL;
3010 bool have_sta = false;
3011 int err;
3012 int ht_cfreq; 3066 int ht_cfreq;
3013 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 3067 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
3014 const u8 *ht_oper_ie; 3068 const u8 *ht_oper_ie;
3015 const struct ieee80211_ht_operation *ht_oper = NULL; 3069 const struct ieee80211_ht_operation *ht_oper = NULL;
3016 struct ieee80211_supported_band *sband; 3070 struct ieee80211_supported_band *sband;
3017 3071
3018 if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
3019 return -EINVAL;
3020
3021 if (assoc) {
3022 rcu_read_lock();
3023 have_sta = sta_info_get(sdata, cbss->bssid);
3024 rcu_read_unlock();
3025 }
3026
3027 if (!have_sta) {
3028 sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
3029 if (!sta)
3030 return -ENOMEM;
3031 }
3032
3033 mutex_lock(&local->mtx);
3034 ieee80211_recalc_idle(sdata->local);
3035 mutex_unlock(&local->mtx);
3036
3037 /* switch to the right channel */
3038 sband = local->hw.wiphy->bands[cbss->channel->band]; 3072 sband = local->hw.wiphy->bands[cbss->channel->band];
3039 3073
3040 ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; 3074 ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ;
@@ -3097,10 +3131,51 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3097 local->oper_channel = cbss->channel; 3131 local->oper_channel = cbss->channel;
3098 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 3132 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
3099 3133
3100 if (sta) { 3134 return 0;
3135}
3136
3137static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3138 struct cfg80211_bss *cbss, bool assoc)
3139{
3140 struct ieee80211_local *local = sdata->local;
3141 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3142 struct ieee80211_bss *bss = (void *)cbss->priv;
3143 struct sta_info *new_sta = NULL;
3144 bool have_sta = false;
3145 int err;
3146
3147 if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
3148 return -EINVAL;
3149
3150 if (assoc) {
3151 rcu_read_lock();
3152 have_sta = sta_info_get(sdata, cbss->bssid);
3153 rcu_read_unlock();
3154 }
3155
3156 if (!have_sta) {
3157 new_sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL);
3158 if (!new_sta)
3159 return -ENOMEM;
3160 }
3161
3162 mutex_lock(&local->mtx);
3163 ieee80211_recalc_idle(sdata->local);
3164 mutex_unlock(&local->mtx);
3165
3166 if (new_sta) {
3101 u32 rates = 0, basic_rates = 0; 3167 u32 rates = 0, basic_rates = 0;
3102 bool have_higher_than_11mbit; 3168 bool have_higher_than_11mbit;
3103 int min_rate = INT_MAX, min_rate_index = -1; 3169 int min_rate = INT_MAX, min_rate_index = -1;
3170 struct ieee80211_supported_band *sband;
3171
3172 sband = local->hw.wiphy->bands[cbss->channel->band];
3173
3174 err = ieee80211_prep_channel(sdata, cbss);
3175 if (err) {
3176 sta_info_free(local, new_sta);
3177 return err;
3178 }
3104 3179
3105 ieee80211_get_rates(sband, bss->supp_rates, 3180 ieee80211_get_rates(sband, bss->supp_rates,
3106 bss->supp_rates_len, 3181 bss->supp_rates_len,
@@ -3122,7 +3197,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3122 basic_rates = BIT(min_rate_index); 3197 basic_rates = BIT(min_rate_index);
3123 } 3198 }
3124 3199
3125 sta->sta.supp_rates[cbss->channel->band] = rates; 3200 new_sta->sta.supp_rates[cbss->channel->band] = rates;
3126 sdata->vif.bss_conf.basic_rates = basic_rates; 3201 sdata->vif.bss_conf.basic_rates = basic_rates;
3127 3202
3128 /* cf. IEEE 802.11 9.2.12 */ 3203 /* cf. IEEE 802.11 9.2.12 */
@@ -3145,10 +3220,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3145 BSS_CHANGED_BEACON_INT); 3220 BSS_CHANGED_BEACON_INT);
3146 3221
3147 if (assoc) 3222 if (assoc)
3148 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); 3223 sta_info_pre_move_state(new_sta, IEEE80211_STA_AUTH);
3149 3224
3150 err = sta_info_insert(sta); 3225 err = sta_info_insert(new_sta);
3151 sta = NULL; 3226 new_sta = NULL;
3152 if (err) { 3227 if (err) {
3153 sdata_info(sdata, 3228 sdata_info(sdata,
3154 "failed to insert STA entry for the AP (error %d)\n", 3229 "failed to insert STA entry for the AP (error %d)\n",
@@ -3302,9 +3377,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3302 } 3377 }
3303 3378
3304 /* prepare assoc data */ 3379 /* prepare assoc data */
3305 3380
3306 ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; 3381 /*
3307 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; 3382 * keep only the 40 MHz disable bit set as it might have
3383 * been set during authentication already, all other bits
3384 * should be reset for a new connection
3385 */
3386 ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ;
3308 3387
3309 ifmgd->beacon_crc_valid = false; 3388 ifmgd->beacon_crc_valid = false;
3310 3389
@@ -3320,21 +3399,34 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3320 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || 3399 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
3321 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { 3400 req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
3322 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3401 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
3402 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
3323 netdev_info(sdata->dev, 3403 netdev_info(sdata->dev,
3324 "disabling HT due to WEP/TKIP use\n"); 3404 "disabling HT/VHT due to WEP/TKIP use\n");
3325 } 3405 }
3326 } 3406 }
3327 3407
3328 if (req->flags & ASSOC_REQ_DISABLE_HT) 3408 if (req->flags & ASSOC_REQ_DISABLE_HT) {
3329 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3409 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
3410 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
3411 }
3330 3412
3331 /* Also disable HT if we don't support it or the AP doesn't use WMM */ 3413 /* Also disable HT if we don't support it or the AP doesn't use WMM */
3332 sband = local->hw.wiphy->bands[req->bss->channel->band]; 3414 sband = local->hw.wiphy->bands[req->bss->channel->band];
3333 if (!sband->ht_cap.ht_supported || 3415 if (!sband->ht_cap.ht_supported ||
3334 local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { 3416 local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
3335 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 3417 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
3336 netdev_info(sdata->dev, 3418 if (!bss->wmm_used)
3337 "disabling HT as WMM/QoS is not supported\n"); 3419 netdev_info(sdata->dev,
3420 "disabling HT as WMM/QoS is not supported by the AP\n");
3421 }
3422
3423 /* disable VHT if we don't support it or the AP doesn't use WMM */
3424 if (!sband->vht_cap.vht_supported ||
3425 local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
3426 ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
3427 if (!bss->wmm_used)
3428 netdev_info(sdata->dev,
3429 "disabling VHT as WMM/QoS is not supported by the AP\n");
3338 } 3430 }
3339 3431
3340 memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); 3432 memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
@@ -3456,7 +3548,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3456 struct cfg80211_deauth_request *req) 3548 struct cfg80211_deauth_request *req)
3457{ 3549{
3458 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3550 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3459 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 3551 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3460 3552
3461 mutex_lock(&ifmgd->mtx); 3553 mutex_lock(&ifmgd->mtx);
3462 3554
@@ -3471,17 +3563,21 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
3471 req->bssid, req->reason_code); 3563 req->bssid, req->reason_code);
3472 3564
3473 if (ifmgd->associated && 3565 if (ifmgd->associated &&
3474 ether_addr_equal(ifmgd->associated->bssid, req->bssid)) 3566 ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
3475 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, 3567 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
3476 req->reason_code, true, frame_buf); 3568 req->reason_code, true, frame_buf);
3477 else 3569 } else {
3570 drv_mgd_prepare_tx(sdata->local, sdata);
3478 ieee80211_send_deauth_disassoc(sdata, req->bssid, 3571 ieee80211_send_deauth_disassoc(sdata, req->bssid,
3479 IEEE80211_STYPE_DEAUTH, 3572 IEEE80211_STYPE_DEAUTH,
3480 req->reason_code, true, 3573 req->reason_code, true,
3481 frame_buf); 3574 frame_buf);
3575 }
3576
3482 mutex_unlock(&ifmgd->mtx); 3577 mutex_unlock(&ifmgd->mtx);
3483 3578
3484 __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 3579 __cfg80211_send_deauth(sdata->dev, frame_buf,
3580 IEEE80211_DEAUTH_FRAME_LEN);
3485 3581
3486 mutex_lock(&sdata->local->mtx); 3582 mutex_lock(&sdata->local->mtx);
3487 ieee80211_recalc_idle(sdata->local); 3583 ieee80211_recalc_idle(sdata->local);
@@ -3495,7 +3591,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
3495{ 3591{
3496 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 3592 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
3497 u8 bssid[ETH_ALEN]; 3593 u8 bssid[ETH_ALEN];
3498 u8 frame_buf[DEAUTH_DISASSOC_LEN]; 3594 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
3499 3595
3500 mutex_lock(&ifmgd->mtx); 3596 mutex_lock(&ifmgd->mtx);
3501 3597
@@ -3520,7 +3616,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
3520 frame_buf); 3616 frame_buf);
3521 mutex_unlock(&ifmgd->mtx); 3617 mutex_unlock(&ifmgd->mtx);
3522 3618
3523 __cfg80211_send_disassoc(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); 3619 __cfg80211_send_disassoc(sdata->dev, frame_buf,
3620 IEEE80211_DEAUTH_FRAME_LEN);
3524 3621
3525 mutex_lock(&sdata->local->mtx); 3622 mutex_lock(&sdata->local->mtx);
3526 ieee80211_recalc_idle(sdata->local); 3623 ieee80211_recalc_idle(sdata->local);