Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * BSS client mode implementation | 2 * BSS client mode implementation |
| 3 * Copyright 2003-2008, Jouni Malinen <j@w1.fi> | 3 * Copyright 2003-2008, Jouni Malinen <j@w1.fi> |
| 4 * Copyright 2004, Instant802 Networks, Inc. | 4 * Copyright 2004, Instant802 Networks, Inc. |
| 5 * Copyright 2005, Devicescape Software, Inc. | 5 * Copyright 2005, Devicescape Software, Inc. |
| 6 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 6 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
| 7 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | 7 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> |
| 8 * | 8 * |
| 9 * This program is free software; you can redistribute it and/or modify | 9 * This program is free software; you can redistribute it and/or modify |
| 10 * it under the terms of the GNU General Public License version 2 as | 10 * it under the terms of the GNU General Public License version 2 as |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 #include <linux/crc32.h> | 21 #include <linux/crc32.h> |
| 22 #include <linux/slab.h> | 22 #include <linux/slab.h> |
| 23 #include <net/mac80211.h> | 23 #include <net/mac80211.h> |
| 24 #include <asm/unaligned.h> | 24 #include <asm/unaligned.h> |
| 25 | 25 |
| 26 #include "ieee80211_i.h" | 26 #include "ieee80211_i.h" |
| 27 #include "driver-ops.h" | 27 #include "driver-ops.h" |
| 28 #include "rate.h" | 28 #include "rate.h" |
| 29 #include "led.h" | 29 #include "led.h" |
| 30 | 30 |
| 31 #define IEEE80211_MAX_PROBE_TRIES 1 | 31 #define IEEE80211_MAX_NULLFUNC_TRIES 2 |
|
Sam Leffler
2010/12/08 18:37:56
until we can override upstream defaults w/o modify
| |
| 32 #define IEEE80211_MAX_PROBE_TRIES 5 | |
| 32 | 33 |
| 33 /* | 34 /* |
| 34 * beacon loss timeout is calculated as N frames times the | 35 * Beacon loss timeout is calculated as N frames times the |
| 35 * advertised beacon interval. This may need to be somewhat | 36 * advertised beacon interval. This may need to be somewhat |
| 36 * higher than what hardware might detect to account for | 37 * higher than what hardware might detect to account for |
| 37 * delays in the host processing frames. But since we also | 38 * delays in the host processing frames. But since we also |
| 38 * probe on bmiss before declaring the connection lost default | 39 * probe on beacon miss before declaring the connection lost |
| 39 * to what we want. | 40 * default to what we want. |
| 40 */ | 41 */ |
| 41 #define»IEEE80211_BEACON_LOSS_COUNT» 7 | 42 #define IEEE80211_BEACON_LOSS_COUNT» 7 |
| 43 | |
| 42 /* | 44 /* |
| 43 * Time the connection can be idle before we probe | 45 * Time the connection can be idle before we probe |
| 44 * it to see if we can still talk to the AP. | 46 * it to see if we can still talk to the AP. |
| 45 */ | 47 */ |
| 46 #define IEEE80211_CONNECTION_IDLE_TIME (30 * HZ) | 48 #define IEEE80211_CONNECTION_IDLE_TIME (30 * HZ) |
| 47 /* | 49 /* |
| 48 * Time we wait for a probe response after sending | 50 * Time we wait for a probe response after sending |
| 49 * a probe request because of beacon loss or for | 51 * a probe request because of beacon loss or for |
| 50 * checking the connection still works. | 52 * checking the connection still works. |
| 51 */ | 53 */ |
| 52 #define IEEE80211_PROBE_WAIT» » (HZ / 5) | 54 #define IEEE80211_PROBE_WAIT» » (HZ / 2) |
| 53 | 55 |
| 54 /* | 56 /* |
| 55 * Weight given to the latest Beacon frame when calculating average signal | 57 * Weight given to the latest Beacon frame when calculating average signal |
| 56 * strength for Beacon frames received in the current BSS. This must be | 58 * strength for Beacon frames received in the current BSS. This must be |
| 57 * between 1 and 15. | 59 * between 1 and 15. |
| 58 */ | 60 */ |
| 59 #define IEEE80211_SIGNAL_AVE_WEIGHT 3 | 61 #define IEEE80211_SIGNAL_AVE_WEIGHT 3 |
| 60 | 62 |
| 61 /* | |
| 62 * How many Beacon frames need to have been used in average signal strength | |
| 63 * before starting to indicate signal change events. | |
| 64 */ | |
| 65 #define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 | |
| 66 | |
| 67 #define TMR_RUNNING_TIMER 0 | 63 #define TMR_RUNNING_TIMER 0 |
| 68 #define TMR_RUNNING_CHANSW 1 | 64 #define TMR_RUNNING_CHANSW 1 |
| 69 | 65 |
| 70 /* | 66 /* |
| 71 * All cfg80211 functions have to be called outside a locked | 67 * All cfg80211 functions have to be called outside a locked |
| 72 * section so that they can acquire a lock themselves... This | 68 * section so that they can acquire a lock themselves... This |
| 73 * is much simpler than queuing up things in cfg80211, but we | 69 * is much simpler than queuing up things in cfg80211, but we |
| 74 * do need some indirection for that here. | 70 * do need some indirection for that here. |
| 75 */ | 71 */ |
| 76 enum rx_mgmt_action { | 72 enum rx_mgmt_action { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 time_before(timeout, ifmgd->timer.expires)) | 114 time_before(timeout, ifmgd->timer.expires)) |
| 119 mod_timer(&ifmgd->timer, timeout); | 115 mod_timer(&ifmgd->timer, timeout); |
| 120 } | 116 } |
| 121 | 117 |
| 122 void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) | 118 void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) |
| 123 { | 119 { |
| 124 if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) | 120 if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER) |
| 125 return; | 121 return; |
| 126 | 122 |
| 127 mod_timer(&sdata->u.mgd.bcn_mon_timer, | 123 mod_timer(&sdata->u.mgd.bcn_mon_timer, |
| 128 » » round_jiffies_up(jiffies + sdata->u.mgd.bloss_timeout)); | 124 » » round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); |
| 129 } | 125 } |
| 130 | 126 |
| 131 void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) | 127 void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) |
| 132 { | 128 { |
| 133 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 129 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 134 | 130 |
| 135 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 131 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
| 136 return; | 132 return; |
| 137 | 133 |
| 138 mod_timer(&sdata->u.mgd.conn_mon_timer, | 134 mod_timer(&sdata->u.mgd.conn_mon_timer, |
| (...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 865 struct cfg80211_bss *cbss, | 861 struct cfg80211_bss *cbss, |
| 866 u32 bss_info_changed) | 862 u32 bss_info_changed) |
| 867 { | 863 { |
| 868 struct ieee80211_bss *bss = (void *)cbss->priv; | 864 struct ieee80211_bss *bss = (void *)cbss->priv; |
| 869 struct ieee80211_local *local = sdata->local; | 865 struct ieee80211_local *local = sdata->local; |
| 870 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 866 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
| 871 | 867 |
| 872 bss_info_changed |= BSS_CHANGED_ASSOC; | 868 bss_info_changed |= BSS_CHANGED_ASSOC; |
| 873 /* set timing information */ | 869 /* set timing information */ |
| 874 bss_conf->beacon_int = cbss->beacon_interval; | 870 bss_conf->beacon_int = cbss->beacon_interval; |
| 875 /* beacon_int is in TU, convert to jiffies for timer handling */ | |
| 876 sdata->u.mgd.bloss_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( | |
| 877 IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); | |
| 878 bss_conf->timestamp = cbss->tsf; | 871 bss_conf->timestamp = cbss->tsf; |
| 879 | 872 |
| 880 bss_info_changed |= BSS_CHANGED_BEACON_INT; | 873 bss_info_changed |= BSS_CHANGED_BEACON_INT; |
| 881 bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 874 bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
| 882 cbss->capability, bss->has_erp_value, bss->erp_value); | 875 cbss->capability, bss->has_erp_value, bss->erp_value); |
| 883 | 876 |
| 877 sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( | |
| 878 IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); | |
| 879 | |
| 884 sdata->u.mgd.associated = cbss; | 880 sdata->u.mgd.associated = cbss; |
| 885 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); | 881 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
| 886 | 882 |
| 887 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | 883 sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; |
| 888 | 884 |
| 889 /* just to be sure */ | 885 /* just to be sure */ |
| 890 sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 886 sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
| 891 IEEE80211_STA_BEACON_POLL); | 887 IEEE80211_STA_BEACON_POLL); |
| 892 | 888 |
| 893 /* | 889 /* |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1032 * be ignored here, because we need to trigger the timer during | 1028 * be ignored here, because we need to trigger the timer during |
| 1033 * data idle periods for sending the periodic probe request to the | 1029 * data idle periods for sending the periodic probe request to the |
| 1034 * AP we're connected to. | 1030 * AP we're connected to. |
| 1035 */ | 1031 */ |
| 1036 if (is_multicast_ether_addr(hdr->addr1)) | 1032 if (is_multicast_ether_addr(hdr->addr1)) |
| 1037 return; | 1033 return; |
| 1038 | 1034 |
| 1039 ieee80211_sta_reset_conn_monitor(sdata); | 1035 ieee80211_sta_reset_conn_monitor(sdata); |
| 1040 } | 1036 } |
| 1041 | 1037 |
| 1038 static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) | |
| 1039 { | |
| 1040 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | |
| 1041 | |
| 1042 if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | |
| 1043 IEEE80211_STA_CONNECTION_POLL))) | |
| 1044 return; | |
| 1045 | |
| 1046 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | |
| 1047 IEEE80211_STA_BEACON_POLL); | |
| 1048 mutex_lock(&sdata->local->iflist_mtx); | |
| 1049 ieee80211_recalc_ps(sdata->local, -1); | |
| 1050 mutex_unlock(&sdata->local->iflist_mtx); | |
| 1051 | |
| 1052 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | |
| 1053 return; | |
| 1054 | |
| 1055 /* | |
| 1056 * We've received a probe response, but are not sure whether | |
| 1057 * we have or will be receiving any beacons or data, so let's | |
| 1058 * schedule the timers again, just in case. | |
| 1059 */ | |
| 1060 ieee80211_sta_reset_beacon_monitor(sdata); | |
| 1061 | |
| 1062 mod_timer(&ifmgd->conn_mon_timer, | |
| 1063 round_jiffies_up(jiffies + | |
| 1064 IEEE80211_CONNECTION_IDLE_TIME)); | |
| 1065 } | |
| 1066 | |
| 1067 void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | |
| 1068 struct ieee80211_hdr *hdr, bool ack) | |
| 1069 { | |
| 1070 if (!ieee80211_is_data(hdr->frame_control)) | |
|
Sam Leffler
2010/12/08 18:37:56
this should check is_nullfunc instead and remove t
| |
| 1071 return; | |
| 1072 | |
| 1073 if (ack) | |
| 1074 ieee80211_sta_reset_conn_monitor(sdata); | |
| 1075 | |
| 1076 if (ieee80211_is_nullfunc(hdr->frame_control) && | |
| 1077 sdata->u.mgd.probe_send_count > 0) { | |
| 1078 if (ack) | |
| 1079 sdata->u.mgd.probe_send_count = 0; | |
| 1080 else | |
| 1081 sdata->u.mgd.nullfunc_failed = true; | |
| 1082 ieee80211_queue_work(&sdata->local->hw, &sdata->work); | |
|
Sam Leffler
2010/12/08 18:37:56
this code is confusing because there are no commen
| |
| 1083 } | |
| 1084 } | |
| 1085 | |
| 1042 static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | 1086 static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) |
| 1043 { | 1087 { |
| 1044 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1088 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 1045 const u8 *ssid; | 1089 const u8 *ssid; |
| 1046 u8 *dst = ifmgd->associated->bssid; | 1090 u8 *dst = ifmgd->associated->bssid; |
| 1091 u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); | |
| 1047 | 1092 |
| 1093 /* | |
| 1094 * Try sending broadcast probe requests for the last three | |
| 1095 * probe requests after the first ones failed since some | |
| 1096 * buggy APs only support broadcast probe requests. | |
| 1097 */ | |
| 1098 if (ifmgd->probe_send_count >= unicast_limit) | |
| 1099 dst = NULL; | |
| 1048 | 1100 |
| 1049 » if ((sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { | 1101 » /* |
| 1102 » * When the hardware reports an accurate Tx ACK status, it's | |
| 1103 » * better to send a nullfunc frame instead of a probe request, | |
| 1104 » * as it will kick us off the AP quickly if we aren't associated | |
| 1105 » * anymore. The timeout will be reset if the frame is ACKed by | |
| 1106 » * the AP. | |
| 1107 » */ | |
| 1108 » if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | |
| 1109 » » ifmgd->nullfunc_failed = false; | |
|
Sam Leffler
2010/12/08 18:37:56
it appears you are setting this here because the w
| |
| 1050 ieee80211_send_nullfunc(sdata->local, sdata, 0); | 1110 ieee80211_send_nullfunc(sdata->local, sdata, 0); |
| 1051 } else { | 1111 } else { |
| 1052 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1112 ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
| 1053 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0) ; | 1113 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0) ; |
| 1054 } | 1114 } |
| 1055 | 1115 |
| 1056 ifmgd->probe_send_count++; | 1116 ifmgd->probe_send_count++; |
| 1117 ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | |
| 1118 run_again(ifmgd, ifmgd->probe_timeout); | |
| 1057 } | 1119 } |
| 1058 | 1120 |
| 1059 static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | 1121 static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
| 1060 bool beacon) | 1122 bool beacon) |
| 1061 { | 1123 { |
| 1062 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1124 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 1063 bool already = false; | 1125 bool already = false; |
| 1064 | 1126 |
| 1065 if (!ieee80211_sdata_running(sdata)) | 1127 if (!ieee80211_sdata_running(sdata)) |
| 1066 return; | 1128 return; |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1478 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 1540 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
| 1479 if (baselen > len) | 1541 if (baselen > len) |
| 1480 return; | 1542 return; |
| 1481 | 1543 |
| 1482 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | 1544 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
| 1483 &elems); | 1545 &elems); |
| 1484 | 1546 |
| 1485 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 1547 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
| 1486 | 1548 |
| 1487 if (ifmgd->associated && | 1549 if (ifmgd->associated && |
| 1488 » memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && | 1550 » memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) |
| 1489 » ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 1551 » » ieee80211_reset_ap_probe(sdata); |
| 1490 » » » IEEE80211_STA_CONNECTION_POLL)) { | |
| 1491 » » ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | |
| 1492 » » » » IEEE80211_STA_BEACON_POLL); | |
| 1493 » » mutex_lock(&sdata->local->iflist_mtx); | |
| 1494 » » ieee80211_recalc_ps(sdata->local, -1); | |
| 1495 » » mutex_unlock(&sdata->local->iflist_mtx); | |
| 1496 | |
| 1497 » » if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | |
| 1498 » » » return; | |
| 1499 | |
| 1500 » » /* | |
| 1501 » » * We've received a probe response, but are not sure whether | |
| 1502 » » * we have or will be receiving any beacons or data, so let's | |
| 1503 » » * schedule the timers again, just in case. | |
| 1504 » » */ | |
| 1505 » » ieee80211_sta_reset_beacon_monitor(sdata); | |
| 1506 | |
| 1507 » » mod_timer(&ifmgd->conn_mon_timer, | |
| 1508 » » » round_jiffies_up(jiffies + | |
| 1509 » » » » » IEEE80211_CONNECTION_IDLE_TIME)); | |
| 1510 » } | |
| 1511 } | 1552 } |
| 1512 | 1553 |
| 1513 /* | 1554 /* |
| 1514 * This is the canonical list of information elements we care about, | 1555 * This is the canonical list of information elements we care about, |
| 1515 * the filter code also gives us all changes to the Microsoft OUI | 1556 * the filter code also gives us all changes to the Microsoft OUI |
| 1516 * (00:50:F2) vendor IE which is used for WMM which we need to track. | 1557 * (00:50:F2) vendor IE which is used for WMM which we need to track. |
| 1517 * | 1558 * |
| 1518 * We implement beacon filtering in software since that means we can | 1559 * We implement beacon filtering in software since that means we can |
| 1519 * avoid processing the frame here and in cfg80211, and userspace | 1560 * avoid processing the frame here and in cfg80211, and userspace |
| 1520 * will not be able to tell whether the hardware supports it or not. | 1561 * will not be able to tell whether the hardware supports it or not. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1572 */ | 1613 */ |
| 1573 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) | 1614 if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) |
| 1574 return; | 1615 return; |
| 1575 | 1616 |
| 1576 /* Track average RSSI from the Beacon frames of the current AP */ | 1617 /* Track average RSSI from the Beacon frames of the current AP */ |
| 1577 ifmgd->last_beacon_signal = rx_status->signal; | 1618 ifmgd->last_beacon_signal = rx_status->signal; |
| 1578 if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | 1619 if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { |
| 1579 ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | 1620 ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; |
| 1580 ifmgd->ave_beacon_signal = rx_status->signal * 16; | 1621 ifmgd->ave_beacon_signal = rx_status->signal * 16; |
| 1581 ifmgd->last_cqm_event_signal = 0; | 1622 ifmgd->last_cqm_event_signal = 0; |
| 1582 ifmgd->count_beacon_signal = 1; | |
| 1583 } else { | 1623 } else { |
| 1584 ifmgd->ave_beacon_signal = | 1624 ifmgd->ave_beacon_signal = |
| 1585 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | 1625 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + |
| 1586 (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * | 1626 (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * |
| 1587 ifmgd->ave_beacon_signal) / 16; | 1627 ifmgd->ave_beacon_signal) / 16; |
| 1588 ifmgd->count_beacon_signal++; | |
| 1589 } | 1628 } |
| 1590 if (bss_conf->cqm_rssi_thold && | 1629 if (bss_conf->cqm_rssi_thold && |
| 1591 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && | |
| 1592 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | 1630 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { |
| 1593 int sig = ifmgd->ave_beacon_signal / 16; | 1631 int sig = ifmgd->ave_beacon_signal / 16; |
| 1594 int last_event = ifmgd->last_cqm_event_signal; | 1632 int last_event = ifmgd->last_cqm_event_signal; |
| 1595 int thold = bss_conf->cqm_rssi_thold; | 1633 int thold = bss_conf->cqm_rssi_thold; |
| 1596 int hyst = bss_conf->cqm_rssi_hyst; | 1634 int hyst = bss_conf->cqm_rssi_hyst; |
| 1597 if (sig < thold && | 1635 if (sig < thold && |
| 1598 (last_event == 0 || sig < last_event - hyst)) { | 1636 (last_event == 0 || sig < last_event - hyst)) { |
| 1599 ifmgd->last_cqm_event_signal = sig; | 1637 ifmgd->last_cqm_event_signal = sig; |
| 1600 ieee80211_cqm_rssi_notify( | 1638 ieee80211_cqm_rssi_notify( |
| 1601 &sdata->vif, | 1639 &sdata->vif, |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1837 struct ieee80211_local *local = sdata->local; | 1875 struct ieee80211_local *local = sdata->local; |
| 1838 | 1876 |
| 1839 if (local->quiescing) { | 1877 if (local->quiescing) { |
| 1840 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1878 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
| 1841 return; | 1879 return; |
| 1842 } | 1880 } |
| 1843 | 1881 |
| 1844 ieee80211_queue_work(&local->hw, &sdata->work); | 1882 ieee80211_queue_work(&local->hw, &sdata->work); |
| 1845 } | 1883 } |
| 1846 | 1884 |
| 1885 static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |
| 1886 u8 *bssid) | |
| 1887 { | |
| 1888 struct ieee80211_local *local = sdata->local; | |
| 1889 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | |
| 1890 | |
| 1891 ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | |
| 1892 IEEE80211_STA_BEACON_POLL); | |
| 1893 | |
| 1894 ieee80211_set_disassoc(sdata, true, true); | |
| 1895 ieee80211_recalc_idle(local); | |
| 1896 mutex_unlock(&ifmgd->mtx); | |
| 1897 /* | |
| 1898 * must be outside lock due to cfg80211, | |
| 1899 * but that's not a problem. | |
| 1900 */ | |
| 1901 ieee80211_send_deauth_disassoc(sdata, bssid, | |
| 1902 IEEE80211_STYPE_DEAUTH, | |
| 1903 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | |
| 1904 NULL, true); | |
| 1905 mutex_lock(&ifmgd->mtx); | |
| 1906 } | |
| 1907 | |
| 1847 void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | 1908 void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
| 1848 { | 1909 { |
| 1849 » /* nothing right now */ | 1910 » struct ieee80211_local *local = sdata->local; |
| 1850 } | 1911 » struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 1851 | 1912 |
| 1852 static void ieee80211_sta_process_probe_status(struct ieee80211_sub_if_data *sda ta) | 1913 » /* then process the rest of the work */ |
| 1853 { | |
| 1854 » struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | |
| 1855 » struct ieee80211_local *local = sdata->local; | |
| 1856 » u8 bssid[ETH_ALEN]; | |
| 1857 | |
| 1858 mutex_lock(&ifmgd->mtx); | 1914 mutex_lock(&ifmgd->mtx); |
| 1859 | 1915 |
| 1860 » if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 1916 » if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
| 1861 » » » IEEE80211_STA_CONNECTION_POLL))) | 1917 » » » IEEE80211_STA_CONNECTION_POLL) && |
| 1862 » » goto done; | 1918 » ifmgd->associated) { |
| 1863 » if (!ifmgd->associated)»/* XXX can this fail if flags are set? */ | 1919 » » u8 bssid[ETH_ALEN]; |
| 1864 » » goto done; | 1920 » » int max_tries; |
| 1865 » memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | |
| 1866 » if (ifmgd->probe_acked) { | |
| 1867 » » /* | |
| 1868 » » * Probe frame was ACK'd, just clear polling state. | |
| 1869 » » */ | |
| 1870 » » ifmgd->flags &= ~(IEEE80211_STA_BEACON_POLL | | |
| 1871 » » » » IEEE80211_STA_CONNECTION_POLL); | |
| 1872 » » ifmgd->probe_send_count = 0; | |
| 1873 | 1921 |
| 1874 » » /* | 1922 » » memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
| 1875 » » * Re-enable power save | 1923 |
| 1876 » » */ | 1924 » » if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
| 1877 » » mutex_lock(&local->iflist_mtx); | 1925 » » » max_tries = IEEE80211_MAX_NULLFUNC_TRIES; |
| 1878 » » ieee80211_recalc_ps(local, -1); | 1926 » » else |
| 1879 » » mutex_unlock(&local->iflist_mtx); | 1927 » » » max_tries = IEEE80211_MAX_PROBE_TRIES; |
|
Sam Leffler
2010/12/08 18:37:56
I find this combined code too complicated; I think
| |
| 1880 » } else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { | 1928 |
| 1929 » » /* ACK received for nullfunc probing frame */ | |
| 1930 » » if (!ifmgd->probe_send_count) | |
| 1931 » » » ieee80211_reset_ap_probe(sdata); | |
| 1932 » » else if (ifmgd->nullfunc_failed) { | |
| 1933 » » » if (ifmgd->probe_send_count < max_tries) { | |
| 1881 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1934 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
| 1882 » » printk(KERN_DEBUG "No ACK of probe to AP %pM, try again (%d)\n", | 1935 » » » » wiphy_debug(local->hw.wiphy, |
| 1883 » » » bssid, ifmgd->probe_send_count); | 1936 » » » » » "%s: No ack for nullfunc frame to" |
| 1937 » » » » » " AP %pM, try %d\n", | |
| 1938 » » » » » sdata->name, bssid, | |
| 1939 » » » » » ifmgd->probe_send_count); | |
| 1884 #endif | 1940 #endif |
| 1885 » » ieee80211_mgd_probe_ap_send(sdata); | 1941 » » » » ieee80211_mgd_probe_ap_send(sdata); |
| 1886 » } else { | 1942 » » » } else { |
| 1887 » » /* | 1943 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
| 1888 » » * We actually lost the connection. | 1944 » » » » wiphy_debug(local->hw.wiphy, |
| 1889 » » */ | 1945 » » » » » "%s: No ack for nullfunc frame to" |
| 1890 » » ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 1946 » » » » » " AP %pM, disconnecting.\n", |
| 1891 » » » » IEEE80211_STA_BEACON_POLL); | 1947 » » » » » sdata->name, bssid, |
| 1948 » » » » » ifmgd->probe_send_count); | |
| 1949 #endif | |
| 1950 » » » » ieee80211_sta_connection_lost(sdata, bssid); | |
| 1951 » » » } | |
| 1952 » » } else if (time_is_after_jiffies(ifmgd->probe_timeout)) | |
| 1953 » » » run_again(ifmgd, ifmgd->probe_timeout); | |
| 1954 » » else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | |
|
Sam Leffler
2010/12/08 18:37:56
how do we get to this case? If we have TX status
| |
| 1955 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | |
| 1956 » » » wiphy_debug(local->hw.wiphy, | |
| 1957 » » » » "%s: Failed to send nullfunc to AP %pM" | |
| 1958 » » » » " after %dms, disconnecting.\n", | |
| 1959 » » » » sdata->name, | |
| 1960 » » » » bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | |
| 1961 #endif | |
| 1962 » » » ieee80211_sta_connection_lost(sdata, bssid); | |
| 1963 » » } else if (ifmgd->probe_send_count < max_tries) { | |
| 1964 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | |
| 1965 » » » printk(KERN_DEBUG "No probe response from AP %pM" | |
| 1966 » » » » " after %dms, try %d\n", bssid, | |
| 1967 » » » » (1000 * IEEE80211_PROBE_WAIT)/HZ, | |
| 1968 » » » » ifmgd->probe_send_count); | |
| 1969 #endif | |
| 1970 » » » ieee80211_mgd_probe_ap_send(sdata); | |
| 1971 » » } else { | |
| 1972 » » » /* | |
| 1973 » » » * We actually lost the connection ... or did we? | |
| 1974 » » » * Let's make sure! | |
| 1975 » » » */ | |
| 1976 » » » printk(KERN_DEBUG "No probe response from AP %pM" | |
| 1977 » » » » " after %dms, disconnecting.\n", | |
| 1978 » » » » bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | |
| 1892 | 1979 |
| 1893 » » /* XXX juggle __ieee80211_connection_loss to suit */ | 1980 » » » ieee80211_sta_connection_lost(sdata, bssid); |
| 1894 » » printk(KERN_DEBUG "No response from AP %pM, disconnecting.\n", | 1981 » » } |
| 1895 » » bssid); | 1982 » } |
| 1896 | 1983 |
| 1897 ieee80211_set_disassoc(sdata, true, true); | |
| 1898 ieee80211_recalc_idle(local); | |
| 1899 | |
| 1900 /* | |
| 1901 * NB: must be outside lock due to cfg80211. | |
| 1902 */ | |
| 1903 mutex_unlock(&ifmgd->mtx); | |
| 1904 ieee80211_send_deauth_disassoc(sdata, bssid, | |
| 1905 IEEE80211_STYPE_DEAUTH, | |
| 1906 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | |
| 1907 NULL, true); | |
| 1908 return; | |
| 1909 } | |
| 1910 done: | |
| 1911 mutex_unlock(&ifmgd->mtx); | 1984 mutex_unlock(&ifmgd->mtx); |
| 1912 } | 1985 } |
| 1913 | 1986 |
| 1914 /* | |
| 1915 * Process TX status for probe frame sent to the associated | |
| 1916 * AP on beacon or connection loss. | |
| 1917 */ | |
| 1918 static void ieee80211_probe_status_work(struct work_struct *work) | |
| 1919 { | |
| 1920 struct ieee80211_sub_if_data *sdata = container_of(work, | |
| 1921 struct ieee80211_sub_if_data, u.mgd.probe_status_work); | |
| 1922 | |
| 1923 WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION); | |
| 1924 | |
| 1925 if (ieee80211_sdata_running(sdata)) | |
| 1926 ieee80211_sta_process_probe_status(sdata); | |
| 1927 } | |
| 1928 | |
| 1929 static void ieee80211_sta_bcn_mon_timer(unsigned long data) | 1987 static void ieee80211_sta_bcn_mon_timer(unsigned long data) |
| 1930 { | 1988 { |
| 1931 struct ieee80211_sub_if_data *sdata = | 1989 struct ieee80211_sub_if_data *sdata = |
| 1932 (struct ieee80211_sub_if_data *) data; | 1990 (struct ieee80211_sub_if_data *) data; |
| 1933 struct ieee80211_local *local = sdata->local; | 1991 struct ieee80211_local *local = sdata->local; |
| 1934 | 1992 |
| 1935 if (local->quiescing) | 1993 if (local->quiescing) |
| 1936 return; | 1994 return; |
| 1937 | 1995 |
| 1938 ieee80211_queue_work(&sdata->local->hw, | 1996 ieee80211_queue_work(&sdata->local->hw, |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1960 | 2018 |
| 1961 ieee80211_mgd_probe_ap(sdata, false); | 2019 ieee80211_mgd_probe_ap(sdata, false); |
| 1962 } | 2020 } |
| 1963 | 2021 |
| 1964 static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | 2022 static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) |
| 1965 { | 2023 { |
| 1966 if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 2024 if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
| 1967 sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | | 2025 sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | |
| 1968 IEEE80211_STA_CONNECTION_POLL); | 2026 IEEE80211_STA_CONNECTION_POLL); |
| 1969 | 2027 |
| 2028 /* let's probe the connection once */ | |
| 2029 ieee80211_queue_work(&sdata->local->hw, | |
| 2030 &sdata->u.mgd.monitor_work); | |
| 1970 /* and do all the other regular work too */ | 2031 /* and do all the other regular work too */ |
| 1971 ieee80211_queue_work(&sdata->local->hw, &sdata->work); | 2032 ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
| 1972 } | 2033 } |
| 1973 } | 2034 } |
| 1974 | 2035 |
| 1975 #ifdef CONFIG_PM | 2036 #ifdef CONFIG_PM |
| 1976 void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | 2037 void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) |
| 1977 { | 2038 { |
| 1978 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2039 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 1979 | 2040 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1998 } | 2059 } |
| 1999 | 2060 |
| 2000 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | 2061 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) |
| 2001 { | 2062 { |
| 2002 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2063 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 2003 | 2064 |
| 2004 if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) | 2065 if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running)) |
| 2005 add_timer(&ifmgd->timer); | 2066 add_timer(&ifmgd->timer); |
| 2006 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) | 2067 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) |
| 2007 add_timer(&ifmgd->chswitch_timer); | 2068 add_timer(&ifmgd->chswitch_timer); |
| 2008 | |
| 2009 ieee80211_sta_reset_beacon_monitor(sdata); | 2069 ieee80211_sta_reset_beacon_monitor(sdata); |
| 2010 » ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work); | 2070 » ieee80211_restart_sta_timer(sdata); |
| 2011 } | 2071 } |
| 2012 #endif | 2072 #endif |
| 2013 | 2073 |
| 2014 /* interface setup */ | 2074 /* interface setup */ |
| 2015 void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | 2075 void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) |
| 2016 { | 2076 { |
| 2017 struct ieee80211_if_managed *ifmgd; | 2077 struct ieee80211_if_managed *ifmgd; |
| 2018 | 2078 |
| 2019 ifmgd = &sdata->u.mgd; | 2079 ifmgd = &sdata->u.mgd; |
| 2020 INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); | 2080 INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); |
| 2021 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 2081 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
| 2022 INIT_WORK(&ifmgd->beacon_connection_loss_work, | 2082 INIT_WORK(&ifmgd->beacon_connection_loss_work, |
| 2023 ieee80211_beacon_connection_loss_work); | 2083 ieee80211_beacon_connection_loss_work); |
| 2024 INIT_WORK(&ifmgd->probe_status_work, ieee80211_probe_status_work); | |
| 2025 INIT_WORK(&ifmgd->bitrate_notify_work, ieee80211_rate_notify_work); | 2084 INIT_WORK(&ifmgd->bitrate_notify_work, ieee80211_rate_notify_work); |
| 2026 setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 2085 setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
| 2027 (unsigned long) sdata); | 2086 (unsigned long) sdata); |
| 2028 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 2087 setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
| 2029 (unsigned long) sdata); | 2088 (unsigned long) sdata); |
| 2030 setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, | 2089 setup_timer(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, |
| 2031 (unsigned long) sdata); | 2090 (unsigned long) sdata); |
| 2032 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, | 2091 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, |
| 2033 (unsigned long) sdata); | 2092 (unsigned long) sdata); |
| 2034 | 2093 |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2437 enum nl80211_cqm_rssi_threshold_event rssi_event, | 2496 enum nl80211_cqm_rssi_threshold_event rssi_event, |
| 2438 gfp_t gfp) | 2497 gfp_t gfp) |
| 2439 { | 2498 { |
| 2440 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 2499 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
| 2441 | 2500 |
| 2442 trace_api_cqm_rssi_notify(sdata, rssi_event); | 2501 trace_api_cqm_rssi_notify(sdata, rssi_event); |
| 2443 | 2502 |
| 2444 cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | 2503 cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); |
| 2445 } | 2504 } |
| 2446 EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | 2505 EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); |
| OLD | NEW |