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.c106
1 files changed, 79 insertions, 27 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b6c163ac22da..8b733cf6f3ea 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -54,6 +54,12 @@
54 */ 54 */
55#define IEEE80211_SIGNAL_AVE_WEIGHT 3 55#define IEEE80211_SIGNAL_AVE_WEIGHT 3
56 56
57/*
58 * How many Beacon frames need to have been used in average signal strength
59 * before starting to indicate signal change events.
60 */
61#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
62
57#define TMR_RUNNING_TIMER 0 63#define TMR_RUNNING_TIMER 0
58#define TMR_RUNNING_CHANSW 1 64#define TMR_RUNNING_CHANSW 1
59 65
@@ -86,7 +92,7 @@ enum rx_mgmt_action {
86/* utils */ 92/* utils */
87static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) 93static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
88{ 94{
89 WARN_ON(!mutex_is_locked(&ifmgd->mtx)); 95 lockdep_assert_held(&ifmgd->mtx);
90} 96}
91 97
92/* 98/*
@@ -109,7 +115,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd,
109 mod_timer(&ifmgd->timer, timeout); 115 mod_timer(&ifmgd->timer, timeout);
110} 116}
111 117
112static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata) 118void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
113{ 119{
114 if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) 120 if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
115 return; 121 return;
@@ -118,6 +124,19 @@ static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
118 round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME)); 124 round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME));
119} 125}
120 126
127void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
128{
129 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
130
131 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
132 return;
133
134 mod_timer(&sdata->u.mgd.conn_mon_timer,
135 round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
136
137 ifmgd->probe_send_count = 0;
138}
139
121static int ecw2cw(int ecw) 140static int ecw2cw(int ecw)
122{ 141{
123 return (1 << ecw) - 1; 142 return (1 << ecw) - 1;
@@ -778,16 +797,17 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
778 params.uapsd = uapsd; 797 params.uapsd = uapsd;
779 798
780#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 799#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
781 printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " 800 wiphy_debug(local->hw.wiphy,
782 "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", 801 "WMM queue=%d aci=%d acm=%d aifs=%d "
783 wiphy_name(local->hw.wiphy), queue, aci, acm, 802 "cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
784 params.aifs, params.cw_min, params.cw_max, params.txop, 803 queue, aci, acm,
785 params.uapsd); 804 params.aifs, params.cw_min, params.cw_max,
805 params.txop, params.uapsd);
786#endif 806#endif
787 if (drv_conf_tx(local, queue, &params)) 807 if (drv_conf_tx(local, queue, &params))
788 printk(KERN_DEBUG "%s: failed to set TX queue " 808 wiphy_debug(local->hw.wiphy,
789 "parameters for queue %d\n", 809 "failed to set TX queue parameters for queue %d\n",
790 wiphy_name(local->hw.wiphy), queue); 810 queue);
791 } 811 }
792 812
793 /* enable WMM or activate new settings */ 813 /* enable WMM or activate new settings */
@@ -990,6 +1010,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
990 1010
991 if (remove_sta) 1011 if (remove_sta)
992 sta_info_destroy_addr(sdata, bssid); 1012 sta_info_destroy_addr(sdata, bssid);
1013
1014 del_timer_sync(&sdata->u.mgd.conn_mon_timer);
1015 del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
1016 del_timer_sync(&sdata->u.mgd.timer);
1017 del_timer_sync(&sdata->u.mgd.chswitch_timer);
993} 1018}
994 1019
995void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1020void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1006,21 +1031,26 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1006 if (is_multicast_ether_addr(hdr->addr1)) 1031 if (is_multicast_ether_addr(hdr->addr1))
1007 return; 1032 return;
1008 1033
1009 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) 1034 ieee80211_sta_reset_conn_monitor(sdata);
1010 return;
1011
1012 mod_timer(&sdata->u.mgd.conn_mon_timer,
1013 round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
1014} 1035}
1015 1036
1016static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) 1037static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
1017{ 1038{
1018 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1039 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1019 const u8 *ssid; 1040 const u8 *ssid;
1041 u8 *dst = ifmgd->associated->bssid;
1042 u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3);
1043
1044 /*
1045 * Try sending broadcast probe requests for the last three
1046 * probe requests after the first ones failed since some
1047 * buggy APs only support broadcast probe requests.
1048 */
1049 if (ifmgd->probe_send_count >= unicast_limit)
1050 dst = NULL;
1020 1051
1021 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); 1052 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
1022 ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, 1053 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0);
1023 ssid + 2, ssid[1], NULL, 0);
1024 1054
1025 ifmgd->probe_send_count++; 1055 ifmgd->probe_send_count++;
1026 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; 1056 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
@@ -1103,8 +1133,11 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1103 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); 1133 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
1104 1134
1105 ieee80211_set_disassoc(sdata, true); 1135 ieee80211_set_disassoc(sdata, true);
1106 ieee80211_recalc_idle(local);
1107 mutex_unlock(&ifmgd->mtx); 1136 mutex_unlock(&ifmgd->mtx);
1137
1138 mutex_lock(&local->mtx);
1139 ieee80211_recalc_idle(local);
1140 mutex_unlock(&local->mtx);
1108 /* 1141 /*
1109 * must be outside lock due to cfg80211, 1142 * must be outside lock due to cfg80211,
1110 * but that's not a problem. 1143 * but that's not a problem.
@@ -1173,7 +1206,9 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1173 sdata->name, bssid, reason_code); 1206 sdata->name, bssid, reason_code);
1174 1207
1175 ieee80211_set_disassoc(sdata, true); 1208 ieee80211_set_disassoc(sdata, true);
1209 mutex_lock(&sdata->local->mtx);
1176 ieee80211_recalc_idle(sdata->local); 1210 ieee80211_recalc_idle(sdata->local);
1211 mutex_unlock(&sdata->local->mtx);
1177 1212
1178 return RX_MGMT_CFG80211_DEAUTH; 1213 return RX_MGMT_CFG80211_DEAUTH;
1179} 1214}
@@ -1203,7 +1238,9 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1203 sdata->name, mgmt->sa, reason_code); 1238 sdata->name, mgmt->sa, reason_code);
1204 1239
1205 ieee80211_set_disassoc(sdata, true); 1240 ieee80211_set_disassoc(sdata, true);
1241 mutex_lock(&sdata->local->mtx);
1206 ieee80211_recalc_idle(sdata->local); 1242 ieee80211_recalc_idle(sdata->local);
1243 mutex_unlock(&sdata->local->mtx);
1207 return RX_MGMT_CFG80211_DISASSOC; 1244 return RX_MGMT_CFG80211_DISASSOC;
1208} 1245}
1209 1246
@@ -1362,7 +1399,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1362 * Also start the timer that will detect beacon loss. 1399 * Also start the timer that will detect beacon loss.
1363 */ 1400 */
1364 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); 1401 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
1365 mod_beacon_timer(sdata); 1402 ieee80211_sta_reset_beacon_monitor(sdata);
1366 1403
1367 return true; 1404 return true;
1368} 1405}
@@ -1465,7 +1502,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
1465 * we have or will be receiving any beacons or data, so let's 1502 * we have or will be receiving any beacons or data, so let's
1466 * schedule the timers again, just in case. 1503 * schedule the timers again, just in case.
1467 */ 1504 */
1468 mod_beacon_timer(sdata); 1505 ieee80211_sta_reset_beacon_monitor(sdata);
1469 1506
1470 mod_timer(&ifmgd->conn_mon_timer, 1507 mod_timer(&ifmgd->conn_mon_timer,
1471 round_jiffies_up(jiffies + 1508 round_jiffies_up(jiffies +
@@ -1540,15 +1577,18 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1540 ifmgd->last_beacon_signal = rx_status->signal; 1577 ifmgd->last_beacon_signal = rx_status->signal;
1541 if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { 1578 if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
1542 ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; 1579 ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
1543 ifmgd->ave_beacon_signal = rx_status->signal; 1580 ifmgd->ave_beacon_signal = rx_status->signal * 16;
1544 ifmgd->last_cqm_event_signal = 0; 1581 ifmgd->last_cqm_event_signal = 0;
1582 ifmgd->count_beacon_signal = 1;
1545 } else { 1583 } else {
1546 ifmgd->ave_beacon_signal = 1584 ifmgd->ave_beacon_signal =
1547 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + 1585 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
1548 (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * 1586 (16 - IEEE80211_SIGNAL_AVE_WEIGHT) *
1549 ifmgd->ave_beacon_signal) / 16; 1587 ifmgd->ave_beacon_signal) / 16;
1588 ifmgd->count_beacon_signal++;
1550 } 1589 }
1551 if (bss_conf->cqm_rssi_thold && 1590 if (bss_conf->cqm_rssi_thold &&
1591 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
1552 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { 1592 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
1553 int sig = ifmgd->ave_beacon_signal / 16; 1593 int sig = ifmgd->ave_beacon_signal / 16;
1554 int last_event = ifmgd->last_cqm_event_signal; 1594 int last_event = ifmgd->last_cqm_event_signal;
@@ -1588,7 +1628,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1588 * Push the beacon loss detection into the future since 1628 * Push the beacon loss detection into the future since
1589 * we are processing a beacon from the AP just now. 1629 * we are processing a beacon from the AP just now.
1590 */ 1630 */
1591 mod_beacon_timer(sdata); 1631 ieee80211_sta_reset_beacon_monitor(sdata);
1592 1632
1593 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); 1633 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
1594 ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, 1634 ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
@@ -1751,7 +1791,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1751 struct ieee80211_local *local = sdata->local; 1791 struct ieee80211_local *local = sdata->local;
1752 struct ieee80211_work *wk; 1792 struct ieee80211_work *wk;
1753 1793
1754 mutex_lock(&local->work_mtx); 1794 mutex_lock(&local->mtx);
1755 list_for_each_entry(wk, &local->work_list, list) { 1795 list_for_each_entry(wk, &local->work_list, list) {
1756 if (wk->sdata != sdata) 1796 if (wk->sdata != sdata)
1757 continue; 1797 continue;
@@ -1783,7 +1823,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1783 free_work(wk); 1823 free_work(wk);
1784 break; 1824 break;
1785 } 1825 }
1786 mutex_unlock(&local->work_mtx); 1826 mutex_unlock(&local->mtx);
1787 1827
1788 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); 1828 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
1789 } 1829 }
@@ -1840,8 +1880,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1840 " after %dms, disconnecting.\n", 1880 " after %dms, disconnecting.\n",
1841 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 1881 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
1842 ieee80211_set_disassoc(sdata, true); 1882 ieee80211_set_disassoc(sdata, true);
1843 ieee80211_recalc_idle(local);
1844 mutex_unlock(&ifmgd->mtx); 1883 mutex_unlock(&ifmgd->mtx);
1884 mutex_lock(&local->mtx);
1885 ieee80211_recalc_idle(local);
1886 mutex_unlock(&local->mtx);
1845 /* 1887 /*
1846 * must be outside lock due to cfg80211, 1888 * must be outside lock due to cfg80211,
1847 * but that's not a problem. 1889 * but that's not a problem.
@@ -1917,6 +1959,8 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
1917 * time -- the code here is properly synchronised. 1959 * time -- the code here is properly synchronised.
1918 */ 1960 */
1919 1961
1962 cancel_work_sync(&ifmgd->request_smps_work);
1963
1920 cancel_work_sync(&ifmgd->beacon_connection_loss_work); 1964 cancel_work_sync(&ifmgd->beacon_connection_loss_work);
1921 if (del_timer_sync(&ifmgd->timer)) 1965 if (del_timer_sync(&ifmgd->timer))
1922 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); 1966 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -1952,6 +1996,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1952 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 1996 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
1953 INIT_WORK(&ifmgd->beacon_connection_loss_work, 1997 INIT_WORK(&ifmgd->beacon_connection_loss_work,
1954 ieee80211_beacon_connection_loss_work); 1998 ieee80211_beacon_connection_loss_work);
1999 INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work);
1955 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 2000 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
1956 (unsigned long) sdata); 2001 (unsigned long) sdata);
1957 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, 2002 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
@@ -2249,6 +2294,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2249 else 2294 else
2250 ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; 2295 ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
2251 2296
2297 sdata->control_port_protocol = req->crypto.control_port_ethertype;
2298 sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
2299
2252 ieee80211_add_work(wk); 2300 ieee80211_add_work(wk);
2253 return 0; 2301 return 0;
2254} 2302}
@@ -2275,7 +2323,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2275 2323
2276 mutex_unlock(&ifmgd->mtx); 2324 mutex_unlock(&ifmgd->mtx);
2277 2325
2278 mutex_lock(&local->work_mtx); 2326 mutex_lock(&local->mtx);
2279 list_for_each_entry(wk, &local->work_list, list) { 2327 list_for_each_entry(wk, &local->work_list, list) {
2280 if (wk->sdata != sdata) 2328 if (wk->sdata != sdata)
2281 continue; 2329 continue;
@@ -2294,7 +2342,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2294 free_work(wk); 2342 free_work(wk);
2295 break; 2343 break;
2296 } 2344 }
2297 mutex_unlock(&local->work_mtx); 2345 mutex_unlock(&local->mtx);
2298 2346
2299 /* 2347 /*
2300 * If somebody requests authentication and we haven't 2348 * If somebody requests authentication and we haven't
@@ -2319,7 +2367,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2319 if (assoc_bss) 2367 if (assoc_bss)
2320 sta_info_destroy_addr(sdata, bssid); 2368 sta_info_destroy_addr(sdata, bssid);
2321 2369
2370 mutex_lock(&sdata->local->mtx);
2322 ieee80211_recalc_idle(sdata->local); 2371 ieee80211_recalc_idle(sdata->local);
2372 mutex_unlock(&sdata->local->mtx);
2323 2373
2324 return 0; 2374 return 0;
2325} 2375}
@@ -2357,7 +2407,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2357 cookie, !req->local_state_change); 2407 cookie, !req->local_state_change);
2358 sta_info_destroy_addr(sdata, bssid); 2408 sta_info_destroy_addr(sdata, bssid);
2359 2409
2410 mutex_lock(&sdata->local->mtx);
2360 ieee80211_recalc_idle(sdata->local); 2411 ieee80211_recalc_idle(sdata->local);
2412 mutex_unlock(&sdata->local->mtx);
2361 2413
2362 return 0; 2414 return 0;
2363} 2415}