aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c182
1 files changed, 159 insertions, 23 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index be5f723d643a..35d850223a75 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -19,6 +19,7 @@
19#include <linux/rtnetlink.h> 19#include <linux/rtnetlink.h>
20#include <linux/pm_qos_params.h> 20#include <linux/pm_qos_params.h>
21#include <linux/crc32.h> 21#include <linux/crc32.h>
22#include <linux/slab.h>
22#include <net/mac80211.h> 23#include <net/mac80211.h>
23#include <asm/unaligned.h> 24#include <asm/unaligned.h>
24 25
@@ -46,6 +47,13 @@
46 */ 47 */
47#define IEEE80211_PROBE_WAIT (HZ / 2) 48#define IEEE80211_PROBE_WAIT (HZ / 2)
48 49
50/*
51 * Weight given to the latest Beacon frame when calculating average signal
52 * strength for Beacon frames received in the current BSS. This must be
53 * between 1 and 15.
54 */
55#define IEEE80211_SIGNAL_AVE_WEIGHT 3
56
49#define TMR_RUNNING_TIMER 0 57#define TMR_RUNNING_TIMER 0
50#define TMR_RUNNING_CHANSW 1 58#define TMR_RUNNING_CHANSW 1
51 59
@@ -203,7 +211,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
203 211
204static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, 212static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
205 const u8 *bssid, u16 stype, u16 reason, 213 const u8 *bssid, u16 stype, u16 reason,
206 void *cookie) 214 void *cookie, bool send_frame)
207{ 215{
208 struct ieee80211_local *local = sdata->local; 216 struct ieee80211_local *local = sdata->local;
209 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 217 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -240,7 +248,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
240 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); 248 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
241 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) 249 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
242 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 250 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
243 ieee80211_tx_skb(sdata, skb); 251
252 if (send_frame)
253 ieee80211_tx_skb(sdata, skb);
254 else
255 kfree_skb(skb);
244} 256}
245 257
246void ieee80211_send_pspoll(struct ieee80211_local *local, 258void ieee80211_send_pspoll(struct ieee80211_local *local,
@@ -589,6 +601,9 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
589 int count; 601 int count;
590 u8 *pos, uapsd_queues = 0; 602 u8 *pos, uapsd_queues = 0;
591 603
604 if (!local->ops->conf_tx)
605 return;
606
592 if (local->hw.queues < 4) 607 if (local->hw.queues < 4)
593 return; 608 return;
594 609
@@ -663,11 +678,15 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
663 params.aifs, params.cw_min, params.cw_max, params.txop, 678 params.aifs, params.cw_min, params.cw_max, params.txop,
664 params.uapsd); 679 params.uapsd);
665#endif 680#endif
666 if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx) 681 if (drv_conf_tx(local, queue, &params))
667 printk(KERN_DEBUG "%s: failed to set TX queue " 682 printk(KERN_DEBUG "%s: failed to set TX queue "
668 "parameters for queue %d\n", 683 "parameters for queue %d\n",
669 wiphy_name(local->hw.wiphy), queue); 684 wiphy_name(local->hw.wiphy), queue);
670 } 685 }
686
687 /* enable WMM or activate new settings */
688 local->hw.conf.flags |= IEEE80211_CONF_QOS;
689 drv_config(local, IEEE80211_CONF_CHANGE_QOS);
671} 690}
672 691
673static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, 692static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
@@ -728,6 +747,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
728 sdata->u.mgd.associated = cbss; 747 sdata->u.mgd.associated = cbss;
729 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); 748 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
730 749
750 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
751
731 /* just to be sure */ 752 /* just to be sure */
732 sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | 753 sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
733 IEEE80211_STA_BEACON_POLL); 754 IEEE80211_STA_BEACON_POLL);
@@ -753,6 +774,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
753 /* And the BSSID changed - we're associated now */ 774 /* And the BSSID changed - we're associated now */
754 bss_info_changed |= BSS_CHANGED_BSSID; 775 bss_info_changed |= BSS_CHANGED_BSSID;
755 776
777 /* Tell the driver to monitor connection quality (if supported) */
778 if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) &&
779 sdata->vif.bss_conf.cqm_rssi_thold)
780 bss_info_changed |= BSS_CHANGED_CQM;
781
756 ieee80211_bss_info_change_notify(sdata, bss_info_changed); 782 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
757 783
758 mutex_lock(&local->iflist_mtx); 784 mutex_lock(&local->iflist_mtx);
@@ -764,7 +790,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
764 netif_carrier_on(sdata->dev); 790 netif_carrier_on(sdata->dev);
765} 791}
766 792
767static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) 793static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
794 bool remove_sta)
768{ 795{
769 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 796 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
770 struct ieee80211_local *local = sdata->local; 797 struct ieee80211_local *local = sdata->local;
@@ -837,7 +864,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
837 changed |= BSS_CHANGED_BSSID; 864 changed |= BSS_CHANGED_BSSID;
838 ieee80211_bss_info_change_notify(sdata, changed); 865 ieee80211_bss_info_change_notify(sdata, changed);
839 866
840 sta_info_destroy_addr(sdata, bssid); 867 if (remove_sta)
868 sta_info_destroy_addr(sdata, bssid);
841} 869}
842 870
843void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 871void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -854,6 +882,9 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
854 if (is_multicast_ether_addr(hdr->addr1)) 882 if (is_multicast_ether_addr(hdr->addr1))
855 return; 883 return;
856 884
885 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
886 return;
887
857 mod_timer(&sdata->u.mgd.conn_mon_timer, 888 mod_timer(&sdata->u.mgd.conn_mon_timer,
858 round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); 889 round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
859} 890}
@@ -931,23 +962,72 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
931 mutex_unlock(&ifmgd->mtx); 962 mutex_unlock(&ifmgd->mtx);
932} 963}
933 964
934void ieee80211_beacon_loss_work(struct work_struct *work) 965static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
966{
967 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
968 struct ieee80211_local *local = sdata->local;
969 u8 bssid[ETH_ALEN];
970
971 mutex_lock(&ifmgd->mtx);
972 if (!ifmgd->associated) {
973 mutex_unlock(&ifmgd->mtx);
974 return;
975 }
976
977 memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
978
979 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
980
981 ieee80211_set_disassoc(sdata, true);
982 ieee80211_recalc_idle(local);
983 mutex_unlock(&ifmgd->mtx);
984 /*
985 * must be outside lock due to cfg80211,
986 * but that's not a problem.
987 */
988 ieee80211_send_deauth_disassoc(sdata, bssid,
989 IEEE80211_STYPE_DEAUTH,
990 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
991 NULL, true);
992}
993
994void ieee80211_beacon_connection_loss_work(struct work_struct *work)
935{ 995{
936 struct ieee80211_sub_if_data *sdata = 996 struct ieee80211_sub_if_data *sdata =
937 container_of(work, struct ieee80211_sub_if_data, 997 container_of(work, struct ieee80211_sub_if_data,
938 u.mgd.beacon_loss_work); 998 u.mgd.beacon_connection_loss_work);
939 999
940 ieee80211_mgd_probe_ap(sdata, true); 1000 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1001 __ieee80211_connection_loss(sdata);
1002 else
1003 ieee80211_mgd_probe_ap(sdata, true);
941} 1004}
942 1005
943void ieee80211_beacon_loss(struct ieee80211_vif *vif) 1006void ieee80211_beacon_loss(struct ieee80211_vif *vif)
944{ 1007{
945 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1008 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1009 struct ieee80211_hw *hw = &sdata->local->hw;
1010
1011 trace_api_beacon_loss(sdata);
946 1012
947 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); 1013 WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
1014 ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
948} 1015}
949EXPORT_SYMBOL(ieee80211_beacon_loss); 1016EXPORT_SYMBOL(ieee80211_beacon_loss);
950 1017
1018void ieee80211_connection_loss(struct ieee80211_vif *vif)
1019{
1020 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1021 struct ieee80211_hw *hw = &sdata->local->hw;
1022
1023 trace_api_connection_loss(sdata);
1024
1025 WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR));
1026 ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
1027}
1028EXPORT_SYMBOL(ieee80211_connection_loss);
1029
1030
951static enum rx_mgmt_action __must_check 1031static enum rx_mgmt_action __must_check
952ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, 1032ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
953 struct ieee80211_mgmt *mgmt, size_t len) 1033 struct ieee80211_mgmt *mgmt, size_t len)
@@ -968,7 +1048,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
968 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", 1048 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
969 sdata->name, bssid, reason_code); 1049 sdata->name, bssid, reason_code);
970 1050
971 ieee80211_set_disassoc(sdata); 1051 ieee80211_set_disassoc(sdata, true);
972 ieee80211_recalc_idle(sdata->local); 1052 ieee80211_recalc_idle(sdata->local);
973 1053
974 return RX_MGMT_CFG80211_DEAUTH; 1054 return RX_MGMT_CFG80211_DEAUTH;
@@ -998,7 +1078,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
998 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", 1078 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
999 sdata->name, mgmt->sa, reason_code); 1079 sdata->name, mgmt->sa, reason_code);
1000 1080
1001 ieee80211_set_disassoc(sdata); 1081 ieee80211_set_disassoc(sdata, true);
1002 ieee80211_recalc_idle(sdata->local); 1082 ieee80211_recalc_idle(sdata->local);
1003 return RX_MGMT_CFG80211_DISASSOC; 1083 return RX_MGMT_CFG80211_DISASSOC;
1004} 1084}
@@ -1290,6 +1370,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1290 struct ieee80211_rx_status *rx_status) 1370 struct ieee80211_rx_status *rx_status)
1291{ 1371{
1292 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1372 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1373 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1293 size_t baselen; 1374 size_t baselen;
1294 struct ieee802_11_elems elems; 1375 struct ieee802_11_elems elems;
1295 struct ieee80211_local *local = sdata->local; 1376 struct ieee80211_local *local = sdata->local;
@@ -1325,6 +1406,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1325 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) 1406 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
1326 return; 1407 return;
1327 1408
1409 /* Track average RSSI from the Beacon frames of the current AP */
1410 ifmgd->last_beacon_signal = rx_status->signal;
1411 if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
1412 ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
1413 ifmgd->ave_beacon_signal = rx_status->signal;
1414 ifmgd->last_cqm_event_signal = 0;
1415 } else {
1416 ifmgd->ave_beacon_signal =
1417 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
1418 (16 - IEEE80211_SIGNAL_AVE_WEIGHT) *
1419 ifmgd->ave_beacon_signal) / 16;
1420 }
1421 if (bss_conf->cqm_rssi_thold &&
1422 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
1423 int sig = ifmgd->ave_beacon_signal / 16;
1424 int last_event = ifmgd->last_cqm_event_signal;
1425 int thold = bss_conf->cqm_rssi_thold;
1426 int hyst = bss_conf->cqm_rssi_hyst;
1427 if (sig < thold &&
1428 (last_event == 0 || sig < last_event - hyst)) {
1429 ifmgd->last_cqm_event_signal = sig;
1430 ieee80211_cqm_rssi_notify(
1431 &sdata->vif,
1432 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
1433 GFP_KERNEL);
1434 } else if (sig > thold &&
1435 (last_event == 0 || sig > last_event + hyst)) {
1436 ifmgd->last_cqm_event_signal = sig;
1437 ieee80211_cqm_rssi_notify(
1438 &sdata->vif,
1439 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
1440 GFP_KERNEL);
1441 }
1442 }
1443
1328 if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { 1444 if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
1329#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1445#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1330 if (net_ratelimit()) { 1446 if (net_ratelimit()) {
@@ -1610,7 +1726,7 @@ static void ieee80211_sta_work(struct work_struct *work)
1610 printk(KERN_DEBUG "No probe response from AP %pM" 1726 printk(KERN_DEBUG "No probe response from AP %pM"
1611 " after %dms, disconnecting.\n", 1727 " after %dms, disconnecting.\n",
1612 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 1728 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
1613 ieee80211_set_disassoc(sdata); 1729 ieee80211_set_disassoc(sdata, true);
1614 ieee80211_recalc_idle(local); 1730 ieee80211_recalc_idle(local);
1615 mutex_unlock(&ifmgd->mtx); 1731 mutex_unlock(&ifmgd->mtx);
1616 /* 1732 /*
@@ -1620,7 +1736,7 @@ static void ieee80211_sta_work(struct work_struct *work)
1620 ieee80211_send_deauth_disassoc(sdata, bssid, 1736 ieee80211_send_deauth_disassoc(sdata, bssid,
1621 IEEE80211_STYPE_DEAUTH, 1737 IEEE80211_STYPE_DEAUTH,
1622 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1738 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1623 NULL); 1739 NULL, true);
1624 mutex_lock(&ifmgd->mtx); 1740 mutex_lock(&ifmgd->mtx);
1625 } 1741 }
1626 } 1742 }
@@ -1637,7 +1753,8 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
1637 if (local->quiescing) 1753 if (local->quiescing)
1638 return; 1754 return;
1639 1755
1640 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); 1756 ieee80211_queue_work(&sdata->local->hw,
1757 &sdata->u.mgd.beacon_connection_loss_work);
1641} 1758}
1642 1759
1643static void ieee80211_sta_conn_mon_timer(unsigned long data) 1760static void ieee80211_sta_conn_mon_timer(unsigned long data)
@@ -1689,7 +1806,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
1689 */ 1806 */
1690 1807
1691 cancel_work_sync(&ifmgd->work); 1808 cancel_work_sync(&ifmgd->work);
1692 cancel_work_sync(&ifmgd->beacon_loss_work); 1809 cancel_work_sync(&ifmgd->beacon_connection_loss_work);
1693 if (del_timer_sync(&ifmgd->timer)) 1810 if (del_timer_sync(&ifmgd->timer))
1694 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); 1811 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
1695 1812
@@ -1723,7 +1840,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1723 INIT_WORK(&ifmgd->work, ieee80211_sta_work); 1840 INIT_WORK(&ifmgd->work, ieee80211_sta_work);
1724 INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); 1841 INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
1725 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 1842 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
1726 INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); 1843 INIT_WORK(&ifmgd->beacon_connection_loss_work,
1844 ieee80211_beacon_connection_loss_work);
1727 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 1845 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
1728 (unsigned long) sdata); 1846 (unsigned long) sdata);
1729 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 1847 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
@@ -1802,6 +1920,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
1802 struct ieee80211_work *wk; 1920 struct ieee80211_work *wk;
1803 u16 auth_alg; 1921 u16 auth_alg;
1804 1922
1923 if (req->local_state_change)
1924 return 0; /* no need to update mac80211 state */
1925
1805 switch (req->auth_type) { 1926 switch (req->auth_type) {
1806 case NL80211_AUTHTYPE_OPEN_SYSTEM: 1927 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1807 auth_alg = WLAN_AUTH_OPEN; 1928 auth_alg = WLAN_AUTH_OPEN;
@@ -1910,7 +2031,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
1910 } 2031 }
1911 2032
1912 /* Trying to reassociate - clear previous association state */ 2033 /* Trying to reassociate - clear previous association state */
1913 ieee80211_set_disassoc(sdata); 2034 ieee80211_set_disassoc(sdata, true);
1914 } 2035 }
1915 mutex_unlock(&ifmgd->mtx); 2036 mutex_unlock(&ifmgd->mtx);
1916 2037
@@ -2014,7 +2135,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2014 2135
2015 if (ifmgd->associated == req->bss) { 2136 if (ifmgd->associated == req->bss) {
2016 bssid = req->bss->bssid; 2137 bssid = req->bss->bssid;
2017 ieee80211_set_disassoc(sdata); 2138 ieee80211_set_disassoc(sdata, true);
2018 mutex_unlock(&ifmgd->mtx); 2139 mutex_unlock(&ifmgd->mtx);
2019 } else { 2140 } else {
2020 bool not_auth_yet = false; 2141 bool not_auth_yet = false;
@@ -2057,9 +2178,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2057 printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", 2178 printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
2058 sdata->name, bssid, req->reason_code); 2179 sdata->name, bssid, req->reason_code);
2059 2180
2060 ieee80211_send_deauth_disassoc(sdata, bssid, 2181 ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH,
2061 IEEE80211_STYPE_DEAUTH, req->reason_code, 2182 req->reason_code, cookie,
2062 cookie); 2183 !req->local_state_change);
2063 2184
2064 ieee80211_recalc_idle(sdata->local); 2185 ieee80211_recalc_idle(sdata->local);
2065 2186
@@ -2071,6 +2192,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2071 void *cookie) 2192 void *cookie)
2072{ 2193{
2073 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2194 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2195 u8 bssid[ETH_ALEN];
2074 2196
2075 mutex_lock(&ifmgd->mtx); 2197 mutex_lock(&ifmgd->mtx);
2076 2198
@@ -2088,13 +2210,15 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2088 printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", 2210 printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
2089 sdata->name, req->bss->bssid, req->reason_code); 2211 sdata->name, req->bss->bssid, req->reason_code);
2090 2212
2091 ieee80211_set_disassoc(sdata); 2213 memcpy(bssid, req->bss->bssid, ETH_ALEN);
2214 ieee80211_set_disassoc(sdata, false);
2092 2215
2093 mutex_unlock(&ifmgd->mtx); 2216 mutex_unlock(&ifmgd->mtx);
2094 2217
2095 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, 2218 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
2096 IEEE80211_STYPE_DISASSOC, req->reason_code, 2219 IEEE80211_STYPE_DISASSOC, req->reason_code,
2097 cookie); 2220 cookie, !req->local_state_change);
2221 sta_info_destroy_addr(sdata, bssid);
2098 2222
2099 ieee80211_recalc_idle(sdata->local); 2223 ieee80211_recalc_idle(sdata->local);
2100 2224
@@ -2135,3 +2259,15 @@ int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
2135 *cookie = (unsigned long) skb; 2259 *cookie = (unsigned long) skb;
2136 return 0; 2260 return 0;
2137} 2261}
2262
2263void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
2264 enum nl80211_cqm_rssi_threshold_event rssi_event,
2265 gfp_t gfp)
2266{
2267 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2268
2269 trace_api_cqm_rssi_notify(sdata, rssi_event);
2270
2271 cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
2272}
2273EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);