diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 182 |
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 | ||
204 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 212 | static 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 | ||
246 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 258 | void 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, ¶ms) && local->ops->conf_tx) | 681 | if (drv_conf_tx(local, queue, ¶ms)) |
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 | ||
673 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 692 | static 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 | ||
767 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | 793 | static 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 | ||
843 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 871 | void 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 | ||
934 | void ieee80211_beacon_loss_work(struct work_struct *work) | 965 | static 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 | |||
994 | void 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 | ||
943 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 1006 | void 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 | } |
949 | EXPORT_SYMBOL(ieee80211_beacon_loss); | 1016 | EXPORT_SYMBOL(ieee80211_beacon_loss); |
950 | 1017 | ||
1018 | void 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 | } | ||
1028 | EXPORT_SYMBOL(ieee80211_connection_loss); | ||
1029 | |||
1030 | |||
951 | static enum rx_mgmt_action __must_check | 1031 | static enum rx_mgmt_action __must_check |
952 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 1032 | ieee80211_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 | ||
1643 | static void ieee80211_sta_conn_mon_timer(unsigned long data) | 1760 | static 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 | |||
2263 | void 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 | } | ||
2273 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | ||