aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2010-04-15 16:21:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-04-15 16:21:34 -0400
commit5c01d5669356e13f0fb468944c1dd4c6a7e978ad (patch)
treefa43345288d7b25fac92b3b35360a177c4947313 /net/mac80211/mlme.c
parentfea069152614cdeefba4b2bf80afcddb9c217fc8 (diff)
parenta5e944f1d955f3819503348426763e21e0413ba6 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: Documentation/feature-removal-schedule.txt drivers/net/wireless/ath/ath5k/phy.c drivers/net/wireless/wl12xx/wl1271_main.c
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c106
1 files changed, 88 insertions, 18 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 71ff42a0465b..35d850223a75 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -47,6 +47,13 @@
47 */ 47 */
48#define IEEE80211_PROBE_WAIT (HZ / 2) 48#define IEEE80211_PROBE_WAIT (HZ / 2)
49 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
50#define TMR_RUNNING_TIMER 0 57#define TMR_RUNNING_TIMER 0
51#define TMR_RUNNING_CHANSW 1 58#define TMR_RUNNING_CHANSW 1
52 59
@@ -204,7 +211,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
204 211
205static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, 212static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
206 const u8 *bssid, u16 stype, u16 reason, 213 const u8 *bssid, u16 stype, u16 reason,
207 void *cookie) 214 void *cookie, bool send_frame)
208{ 215{
209 struct ieee80211_local *local = sdata->local; 216 struct ieee80211_local *local = sdata->local;
210 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 217 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -241,7 +248,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
241 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); 248 cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
242 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) 249 if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
243 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 250 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
244 ieee80211_tx_skb(sdata, skb); 251
252 if (send_frame)
253 ieee80211_tx_skb(sdata, skb);
254 else
255 kfree_skb(skb);
245} 256}
246 257
247void ieee80211_send_pspoll(struct ieee80211_local *local, 258void ieee80211_send_pspoll(struct ieee80211_local *local,
@@ -590,6 +601,9 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
590 int count; 601 int count;
591 u8 *pos, uapsd_queues = 0; 602 u8 *pos, uapsd_queues = 0;
592 603
604 if (!local->ops->conf_tx)
605 return;
606
593 if (local->hw.queues < 4) 607 if (local->hw.queues < 4)
594 return; 608 return;
595 609
@@ -664,11 +678,15 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
664 params.aifs, params.cw_min, params.cw_max, params.txop, 678 params.aifs, params.cw_min, params.cw_max, params.txop,
665 params.uapsd); 679 params.uapsd);
666#endif 680#endif
667 if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx) 681 if (drv_conf_tx(local, queue, &params))
668 printk(KERN_DEBUG "%s: failed to set TX queue " 682 printk(KERN_DEBUG "%s: failed to set TX queue "
669 "parameters for queue %d\n", 683 "parameters for queue %d\n",
670 wiphy_name(local->hw.wiphy), queue); 684 wiphy_name(local->hw.wiphy), queue);
671 } 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);
672} 690}
673 691
674static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, 692static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
@@ -729,6 +747,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
729 sdata->u.mgd.associated = cbss; 747 sdata->u.mgd.associated = cbss;
730 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); 748 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
731 749
750 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;
751
732 /* just to be sure */ 752 /* just to be sure */
733 sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | 753 sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
734 IEEE80211_STA_BEACON_POLL); 754 IEEE80211_STA_BEACON_POLL);
@@ -770,7 +790,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
770 netif_carrier_on(sdata->dev); 790 netif_carrier_on(sdata->dev);
771} 791}
772 792
773static 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)
774{ 795{
775 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 796 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
776 struct ieee80211_local *local = sdata->local; 797 struct ieee80211_local *local = sdata->local;
@@ -843,7 +864,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
843 changed |= BSS_CHANGED_BSSID; 864 changed |= BSS_CHANGED_BSSID;
844 ieee80211_bss_info_change_notify(sdata, changed); 865 ieee80211_bss_info_change_notify(sdata, changed);
845 866
846 sta_info_destroy_addr(sdata, bssid); 867 if (remove_sta)
868 sta_info_destroy_addr(sdata, bssid);
847} 869}
848 870
849void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 871void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -956,7 +978,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
956 978
957 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); 979 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
958 980
959 ieee80211_set_disassoc(sdata); 981 ieee80211_set_disassoc(sdata, true);
960 ieee80211_recalc_idle(local); 982 ieee80211_recalc_idle(local);
961 mutex_unlock(&ifmgd->mtx); 983 mutex_unlock(&ifmgd->mtx);
962 /* 984 /*
@@ -966,7 +988,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
966 ieee80211_send_deauth_disassoc(sdata, bssid, 988 ieee80211_send_deauth_disassoc(sdata, bssid,
967 IEEE80211_STYPE_DEAUTH, 989 IEEE80211_STYPE_DEAUTH,
968 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 990 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
969 NULL); 991 NULL, true);
970} 992}
971 993
972void ieee80211_beacon_connection_loss_work(struct work_struct *work) 994void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -986,6 +1008,8 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif)
986 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1008 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
987 struct ieee80211_hw *hw = &sdata->local->hw; 1009 struct ieee80211_hw *hw = &sdata->local->hw;
988 1010
1011 trace_api_beacon_loss(sdata);
1012
989 WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); 1013 WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
990 ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); 1014 ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
991} 1015}
@@ -996,6 +1020,8 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif)
996 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 1020 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
997 struct ieee80211_hw *hw = &sdata->local->hw; 1021 struct ieee80211_hw *hw = &sdata->local->hw;
998 1022
1023 trace_api_connection_loss(sdata);
1024
999 WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); 1025 WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR));
1000 ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); 1026 ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
1001} 1027}
@@ -1022,7 +1048,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1022 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", 1048 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
1023 sdata->name, bssid, reason_code); 1049 sdata->name, bssid, reason_code);
1024 1050
1025 ieee80211_set_disassoc(sdata); 1051 ieee80211_set_disassoc(sdata, true);
1026 ieee80211_recalc_idle(sdata->local); 1052 ieee80211_recalc_idle(sdata->local);
1027 1053
1028 return RX_MGMT_CFG80211_DEAUTH; 1054 return RX_MGMT_CFG80211_DEAUTH;
@@ -1052,7 +1078,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1052 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", 1078 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
1053 sdata->name, mgmt->sa, reason_code); 1079 sdata->name, mgmt->sa, reason_code);
1054 1080
1055 ieee80211_set_disassoc(sdata); 1081 ieee80211_set_disassoc(sdata, true);
1056 ieee80211_recalc_idle(sdata->local); 1082 ieee80211_recalc_idle(sdata->local);
1057 return RX_MGMT_CFG80211_DISASSOC; 1083 return RX_MGMT_CFG80211_DISASSOC;
1058} 1084}
@@ -1344,6 +1370,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1344 struct ieee80211_rx_status *rx_status) 1370 struct ieee80211_rx_status *rx_status)
1345{ 1371{
1346 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;
1347 size_t baselen; 1374 size_t baselen;
1348 struct ieee802_11_elems elems; 1375 struct ieee802_11_elems elems;
1349 struct ieee80211_local *local = sdata->local; 1376 struct ieee80211_local *local = sdata->local;
@@ -1379,6 +1406,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1379 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) 1406 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0)
1380 return; 1407 return;
1381 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
1382 if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { 1444 if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) {
1383#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 1445#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1384 if (net_ratelimit()) { 1446 if (net_ratelimit()) {
@@ -1664,7 +1726,7 @@ static void ieee80211_sta_work(struct work_struct *work)
1664 printk(KERN_DEBUG "No probe response from AP %pM" 1726 printk(KERN_DEBUG "No probe response from AP %pM"
1665 " after %dms, disconnecting.\n", 1727 " after %dms, disconnecting.\n",
1666 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 1728 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
1667 ieee80211_set_disassoc(sdata); 1729 ieee80211_set_disassoc(sdata, true);
1668 ieee80211_recalc_idle(local); 1730 ieee80211_recalc_idle(local);
1669 mutex_unlock(&ifmgd->mtx); 1731 mutex_unlock(&ifmgd->mtx);
1670 /* 1732 /*
@@ -1674,7 +1736,7 @@ static void ieee80211_sta_work(struct work_struct *work)
1674 ieee80211_send_deauth_disassoc(sdata, bssid, 1736 ieee80211_send_deauth_disassoc(sdata, bssid,
1675 IEEE80211_STYPE_DEAUTH, 1737 IEEE80211_STYPE_DEAUTH,
1676 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1738 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1677 NULL); 1739 NULL, true);
1678 mutex_lock(&ifmgd->mtx); 1740 mutex_lock(&ifmgd->mtx);
1679 } 1741 }
1680 } 1742 }
@@ -1858,6 +1920,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
1858 struct ieee80211_work *wk; 1920 struct ieee80211_work *wk;
1859 u16 auth_alg; 1921 u16 auth_alg;
1860 1922
1923 if (req->local_state_change)
1924 return 0; /* no need to update mac80211 state */
1925
1861 switch (req->auth_type) { 1926 switch (req->auth_type) {
1862 case NL80211_AUTHTYPE_OPEN_SYSTEM: 1927 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1863 auth_alg = WLAN_AUTH_OPEN; 1928 auth_alg = WLAN_AUTH_OPEN;
@@ -1966,7 +2031,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
1966 } 2031 }
1967 2032
1968 /* Trying to reassociate - clear previous association state */ 2033 /* Trying to reassociate - clear previous association state */
1969 ieee80211_set_disassoc(sdata); 2034 ieee80211_set_disassoc(sdata, true);
1970 } 2035 }
1971 mutex_unlock(&ifmgd->mtx); 2036 mutex_unlock(&ifmgd->mtx);
1972 2037
@@ -2070,7 +2135,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2070 2135
2071 if (ifmgd->associated == req->bss) { 2136 if (ifmgd->associated == req->bss) {
2072 bssid = req->bss->bssid; 2137 bssid = req->bss->bssid;
2073 ieee80211_set_disassoc(sdata); 2138 ieee80211_set_disassoc(sdata, true);
2074 mutex_unlock(&ifmgd->mtx); 2139 mutex_unlock(&ifmgd->mtx);
2075 } else { 2140 } else {
2076 bool not_auth_yet = false; 2141 bool not_auth_yet = false;
@@ -2113,9 +2178,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2113 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",
2114 sdata->name, bssid, req->reason_code); 2179 sdata->name, bssid, req->reason_code);
2115 2180
2116 ieee80211_send_deauth_disassoc(sdata, bssid, 2181 ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH,
2117 IEEE80211_STYPE_DEAUTH, req->reason_code, 2182 req->reason_code, cookie,
2118 cookie); 2183 !req->local_state_change);
2119 2184
2120 ieee80211_recalc_idle(sdata->local); 2185 ieee80211_recalc_idle(sdata->local);
2121 2186
@@ -2127,6 +2192,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2127 void *cookie) 2192 void *cookie)
2128{ 2193{
2129 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2194 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2195 u8 bssid[ETH_ALEN];
2130 2196
2131 mutex_lock(&ifmgd->mtx); 2197 mutex_lock(&ifmgd->mtx);
2132 2198
@@ -2144,13 +2210,15 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2144 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",
2145 sdata->name, req->bss->bssid, req->reason_code); 2211 sdata->name, req->bss->bssid, req->reason_code);
2146 2212
2147 ieee80211_set_disassoc(sdata); 2213 memcpy(bssid, req->bss->bssid, ETH_ALEN);
2214 ieee80211_set_disassoc(sdata, false);
2148 2215
2149 mutex_unlock(&ifmgd->mtx); 2216 mutex_unlock(&ifmgd->mtx);
2150 2217
2151 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, 2218 ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
2152 IEEE80211_STYPE_DISASSOC, req->reason_code, 2219 IEEE80211_STYPE_DISASSOC, req->reason_code,
2153 cookie); 2220 cookie, !req->local_state_change);
2221 sta_info_destroy_addr(sdata, bssid);
2154 2222
2155 ieee80211_recalc_idle(sdata->local); 2223 ieee80211_recalc_idle(sdata->local);
2156 2224
@@ -2198,6 +2266,8 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
2198{ 2266{
2199 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 2267 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
2200 2268
2269 trace_api_cqm_rssi_notify(sdata, rssi_event);
2270
2201 cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); 2271 cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
2202} 2272}
2203EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); 2273EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);