Chromium Code Reviews| Index: chromeos/compat-wireless/net/mac80211/mlme.c |
| diff --git a/chromeos/compat-wireless/net/mac80211/mlme.c b/chromeos/compat-wireless/net/mac80211/mlme.c |
| index 0c8510c49215263ed061a9e811311d0496fa4b20..873af1d691076661ea06f0da1c2e7a9c26344a59 100644 |
| --- a/chromeos/compat-wireless/net/mac80211/mlme.c |
| +++ b/chromeos/compat-wireless/net/mac80211/mlme.c |
| @@ -28,17 +28,19 @@ |
| #include "rate.h" |
| #include "led.h" |
| -#define IEEE80211_MAX_PROBE_TRIES 1 |
| +#define IEEE80211_MAX_NULLFUNC_TRIES 2 |
|
Sam Leffler
2010/12/01 00:23:44
lost local change
|
| +#define IEEE80211_MAX_PROBE_TRIES 5 |
| /* |
| - * beacon loss timeout is calculated as N frames times the |
| + * Beacon loss timeout is calculated as N frames times the |
| * advertised beacon interval. This may need to be somewhat |
| * higher than what hardware might detect to account for |
| * delays in the host processing frames. But since we also |
| - * probe on bmiss before declaring the connection lost default |
| - * to what we want. |
| + * probe on beacon miss before declaring the connection lost |
| + * default to what we want. |
| */ |
| -#define IEEE80211_BEACON_LOSS_COUNT 7 |
| +#define IEEE80211_BEACON_LOSS_COUNT 7 |
| + |
| /* |
| * Time the connection can be idle before we probe |
| * it to see if we can still talk to the AP. |
| @@ -49,7 +51,7 @@ |
| * a probe request because of beacon loss or for |
| * checking the connection still works. |
| */ |
| -#define IEEE80211_PROBE_WAIT (HZ / 5) |
| +#define IEEE80211_PROBE_WAIT (HZ / 2) |
|
Sam Leffler
2010/12/01 00:23:44
lost local change
nbd
2010/12/02 23:06:54
Intentionally dropped. Should be unnecessary with
Sam Leffler
2010/12/08 18:37:56
But you upped the max tries to 2 so there is now a
|
| /* |
| * Weight given to the latest Beacon frame when calculating average signal |
| @@ -58,12 +60,6 @@ |
| */ |
| #define IEEE80211_SIGNAL_AVE_WEIGHT 3 |
| -/* |
| - * How many Beacon frames need to have been used in average signal strength |
| - * before starting to indicate signal change events. |
| - */ |
| -#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4 |
| - |
| #define TMR_RUNNING_TIMER 0 |
| #define TMR_RUNNING_CHANSW 1 |
| @@ -125,7 +121,7 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) |
| return; |
| mod_timer(&sdata->u.mgd.bcn_mon_timer, |
| - round_jiffies_up(jiffies + sdata->u.mgd.bloss_timeout)); |
| + round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); |
| } |
| void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) |
| @@ -872,15 +868,15 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
| bss_info_changed |= BSS_CHANGED_ASSOC; |
| /* set timing information */ |
| bss_conf->beacon_int = cbss->beacon_interval; |
| - /* beacon_int is in TU, convert to jiffies for timer handling */ |
| - sdata->u.mgd.bloss_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( |
| - IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); |
| bss_conf->timestamp = cbss->tsf; |
| bss_info_changed |= BSS_CHANGED_BEACON_INT; |
| bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
| cbss->capability, bss->has_erp_value, bss->erp_value); |
| + sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( |
| + IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); |
| + |
| sdata->u.mgd.associated = cbss; |
| memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
| @@ -939,7 +935,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
| } |
| static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
| - bool remove_sta, bool tx) |
| + bool remove_sta) |
| { |
| struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| struct ieee80211_local *local = sdata->local; |
| @@ -978,7 +974,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
| sta = sta_info_get(sdata, bssid); |
| if (sta) { |
| set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
| - ieee80211_sta_tear_down_BA_sessions(sta, tx); |
| + ieee80211_sta_tear_down_BA_sessions(sta); |
| } |
| mutex_unlock(&local->sta_mtx); |
| @@ -1039,21 +1035,83 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
| ieee80211_sta_reset_conn_monitor(sdata); |
| } |
| +static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) |
| +{ |
| + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| + |
| + if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
| + IEEE80211_STA_CONNECTION_POLL))) |
| + return; |
| + |
| + ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
| + IEEE80211_STA_BEACON_POLL); |
| + mutex_lock(&sdata->local->iflist_mtx); |
| + ieee80211_recalc_ps(sdata->local, -1); |
| + mutex_unlock(&sdata->local->iflist_mtx); |
| + |
| + if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
| + return; |
| + |
| + /* |
| + * We've received a probe response, but are not sure whether |
| + * we have or will be receiving any beacons or data, so let's |
| + * schedule the timers again, just in case. |
| + */ |
| + ieee80211_sta_reset_beacon_monitor(sdata); |
| + |
| + mod_timer(&ifmgd->conn_mon_timer, |
| + round_jiffies_up(jiffies + |
| + IEEE80211_CONNECTION_IDLE_TIME)); |
| +} |
| + |
| +void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
| + struct ieee80211_hdr *hdr) |
| +{ |
| + if (!ieee80211_is_data(hdr->frame_control) && |
| + !ieee80211_is_nullfunc(hdr->frame_control)) |
|
Sam Leffler
2010/12/01 00:23:44
should be able to recognize NullData frame w/ one
|
| + return; |
| + |
| + ieee80211_sta_reset_conn_monitor(sdata); |
| + |
| + if (ieee80211_is_nullfunc(hdr->frame_control) && |
| + sdata->u.mgd.probe_send_count > 0) { |
| + sdata->u.mgd.probe_send_count = 0; |
| + ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
| + } |
| +} |
| + |
| static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) |
| { |
| struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| const u8 *ssid; |
| u8 *dst = ifmgd->associated->bssid; |
| + u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); |
| + /* |
| + * Try sending broadcast probe requests for the last three |
| + * probe requests after the first ones failed since some |
| + * buggy APs only support broadcast probe requests. |
| + */ |
| + if (ifmgd->probe_send_count >= unicast_limit) |
| + dst = NULL; |
| - if ((sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { |
| + /* |
| + * When the hardware reports an accurate Tx ACK status, it's |
| + * better to send a nullfunc frame instead of a probe request, |
| + * as it will kick us off the AP quickly if we aren't associated |
| + * anymore. The timeout will be reset if the frame is ACKed by |
| + * the AP. |
| + */ |
| + if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
| ieee80211_send_nullfunc(sdata->local, sdata, 0); |
| - } else { |
| + else { |
| ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
| ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0); |
| } |
| ifmgd->probe_send_count++; |
| + ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; |
| + run_again(ifmgd, ifmgd->probe_timeout); |
|
Sam Leffler
2010/12/01 00:23:44
this should not run for the send_nullfunc case as
nbd
2010/12/02 23:06:54
I think we should run this one even for the nullfu
Sam Leffler
2010/12/08 18:37:56
I don't understand how interference relates to sta
|
| } |
| static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
| @@ -1131,7 +1189,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) |
| printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); |
| - ieee80211_set_disassoc(sdata, true, true); |
| + ieee80211_set_disassoc(sdata, true); |
|
Sam Leffler
2010/12/01 00:23:44
missing local changes
|
| ieee80211_recalc_idle(local); |
| mutex_unlock(&ifmgd->mtx); |
| /* |
| @@ -1209,7 +1267,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
| printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
| sdata->name, bssid, reason_code); |
| - ieee80211_set_disassoc(sdata, true, false); |
| + ieee80211_set_disassoc(sdata, true); |
| ieee80211_recalc_idle(sdata->local); |
| return RX_MGMT_CFG80211_DEAUTH; |
| @@ -1239,7 +1297,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, |
| printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
| sdata->name, mgmt->sa, reason_code); |
| - ieee80211_set_disassoc(sdata, true, false); |
| + ieee80211_set_disassoc(sdata, true); |
| ieee80211_recalc_idle(sdata->local); |
| return RX_MGMT_CFG80211_DISASSOC; |
| } |
| @@ -1485,29 +1543,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, |
| ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
| if (ifmgd->associated && |
| - memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && |
| - ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
| - IEEE80211_STA_CONNECTION_POLL)) { |
| - ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
| - IEEE80211_STA_BEACON_POLL); |
| - mutex_lock(&sdata->local->iflist_mtx); |
| - ieee80211_recalc_ps(sdata->local, -1); |
| - mutex_unlock(&sdata->local->iflist_mtx); |
| - |
| - if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
| - return; |
| - |
| - /* |
| - * We've received a probe response, but are not sure whether |
| - * we have or will be receiving any beacons or data, so let's |
| - * schedule the timers again, just in case. |
| - */ |
| - ieee80211_sta_reset_beacon_monitor(sdata); |
| - |
| - mod_timer(&ifmgd->conn_mon_timer, |
| - round_jiffies_up(jiffies + |
| - IEEE80211_CONNECTION_IDLE_TIME)); |
| - } |
| + memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0) |
| + ieee80211_reset_ap_probe(sdata); |
| } |
| /* |
| @@ -1579,16 +1616,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, |
| ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; |
| ifmgd->ave_beacon_signal = rx_status->signal * 16; |
| ifmgd->last_cqm_event_signal = 0; |
| - ifmgd->count_beacon_signal = 1; |
| } else { |
| ifmgd->ave_beacon_signal = |
| (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + |
| (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * |
| ifmgd->ave_beacon_signal) / 16; |
| - ifmgd->count_beacon_signal++; |
| } |
| if (bss_conf->cqm_rssi_thold && |
| - ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && |
| !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { |
| int sig = ifmgd->ave_beacon_signal / 16; |
| int last_event = ifmgd->last_cqm_event_signal; |
| @@ -1846,84 +1880,66 @@ static void ieee80211_sta_timer(unsigned long data) |
| void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
| { |
| - /* nothing right now */ |
| -} |
| - |
| -static void ieee80211_sta_process_probe_status(struct ieee80211_sub_if_data *sdata) |
| -{ |
| - struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| struct ieee80211_local *local = sdata->local; |
| - u8 bssid[ETH_ALEN]; |
| + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| + /* then process the rest of the work */ |
| mutex_lock(&ifmgd->mtx); |
| - if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
| - IEEE80211_STA_CONNECTION_POLL))) |
| - goto done; |
| - if (!ifmgd->associated) /* XXX can this fail if flags are set? */ |
| - goto done; |
| - memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
| - if (ifmgd->probe_acked) { |
| - /* |
| - * Probe frame was ACK'd, just clear polling state. |
| - */ |
| - ifmgd->flags &= ~(IEEE80211_STA_BEACON_POLL | |
| - IEEE80211_STA_CONNECTION_POLL); |
| - ifmgd->probe_send_count = 0; |
| + if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
| + IEEE80211_STA_CONNECTION_POLL) && |
| + ifmgd->associated) { |
| + u8 bssid[ETH_ALEN]; |
| + int max_tries; |
| - /* |
| - * Re-enable power save |
| - */ |
| - mutex_lock(&local->iflist_mtx); |
| - ieee80211_recalc_ps(local, -1); |
| - mutex_unlock(&local->iflist_mtx); |
| - } else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { |
| -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
| - printk(KERN_DEBUG "No ACK of probe to AP %pM, try again (%d)\n", |
| - bssid, ifmgd->probe_send_count); |
| -#endif |
| - ieee80211_mgd_probe_ap_send(sdata); |
| - } else { |
| - /* |
| - * We actually lost the connection. |
| - */ |
| - ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
| - IEEE80211_STA_BEACON_POLL); |
| + memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
| - /* XXX juggle __ieee80211_connection_loss to suit */ |
| - printk(KERN_DEBUG "No response from AP %pM, disconnecting.\n", |
| - bssid); |
| + if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
| + max_tries = IEEE80211_MAX_NULLFUNC_TRIES; |
| + else |
| + max_tries = IEEE80211_MAX_PROBE_TRIES; |
| - ieee80211_set_disassoc(sdata, true, true); |
| - ieee80211_recalc_idle(local); |
| + /* ACK received for nullfunc probing frame */ |
| + if (!ifmgd->probe_send_count) |
| + ieee80211_reset_ap_probe(sdata); |
| - /* |
| - * NB: must be outside lock due to cfg80211. |
| - */ |
| - mutex_unlock(&ifmgd->mtx); |
| - ieee80211_send_deauth_disassoc(sdata, bssid, |
| - IEEE80211_STYPE_DEAUTH, |
| - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
| - NULL, true); |
| - return; |
| - } |
| -done: |
| - mutex_unlock(&ifmgd->mtx); |
| -} |
| + else if (time_is_after_jiffies(ifmgd->probe_timeout)) |
| + run_again(ifmgd, ifmgd->probe_timeout); |
| -/* |
| - * Process TX status for probe frame sent to the associated |
| - * AP on beacon or connection loss. |
| - */ |
| -static void ieee80211_probe_status_work(struct work_struct *work) |
| -{ |
| - struct ieee80211_sub_if_data *sdata = container_of(work, |
| - struct ieee80211_sub_if_data, u.mgd.probe_status_work); |
| - |
| - WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION); |
| + else if (ifmgd->probe_send_count < max_tries) { |
| +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
| + printk(KERN_DEBUG "No probe response from AP %pM" |
| + " after %dms, try %d\n", bssid, |
| + (1000 * IEEE80211_PROBE_WAIT)/HZ, |
| + ifmgd->probe_send_count); |
| +#endif |
| + ieee80211_mgd_probe_ap_send(sdata); |
| + } else { |
| + /* |
| + * We actually lost the connection ... or did we? |
| + * Let's make sure! |
|
Sam Leffler
2010/12/01 00:23:44
comment is wrong
|
| + */ |
| + ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
| + IEEE80211_STA_BEACON_POLL); |
| + printk(KERN_DEBUG "No probe response from AP %pM" |
| + " after %dms, disconnecting.\n", |
| + bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
|
Sam Leffler
2010/12/01 00:23:44
this msg is wrong for the nulldata case which is w
|
| + ieee80211_set_disassoc(sdata, true); |
| + ieee80211_recalc_idle(local); |
| + mutex_unlock(&ifmgd->mtx); |
| + /* |
| + * must be outside lock due to cfg80211, |
| + * but that's not a problem. |
| + */ |
| + ieee80211_send_deauth_disassoc(sdata, bssid, |
| + IEEE80211_STYPE_DEAUTH, |
| + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
| + NULL, true); |
| + mutex_lock(&ifmgd->mtx); |
| + } |
| + } |
| - if (ieee80211_sdata_running(sdata)) |
| - ieee80211_sta_process_probe_status(sdata); |
| + mutex_unlock(&ifmgd->mtx); |
| } |
| static void ieee80211_sta_bcn_mon_timer(unsigned long data) |
| @@ -1967,6 +1983,9 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) |
| sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | |
| IEEE80211_STA_CONNECTION_POLL); |
| + /* let's probe the connection once */ |
| + ieee80211_queue_work(&sdata->local->hw, |
| + &sdata->u.mgd.monitor_work); |
| /* and do all the other regular work too */ |
| ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
| } |
| @@ -2005,9 +2024,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) |
| add_timer(&ifmgd->timer); |
| if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) |
| add_timer(&ifmgd->chswitch_timer); |
| - |
| ieee80211_sta_reset_beacon_monitor(sdata); |
| - ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work); |
| + ieee80211_restart_sta_timer(sdata); |
|
Sam Leffler
2010/12/01 00:23:44
this restarts more than just the connection monito
nbd
2010/12/02 23:06:54
The interface may have collected some unprocessed
|
| } |
| #endif |
| @@ -2021,7 +2039,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) |
| INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
| INIT_WORK(&ifmgd->beacon_connection_loss_work, |
| ieee80211_beacon_connection_loss_work); |
| - INIT_WORK(&ifmgd->probe_status_work, ieee80211_probe_status_work); |
| INIT_WORK(&ifmgd->bitrate_notify_work, ieee80211_rate_notify_work); |
| setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
| (unsigned long) sdata); |
| @@ -2229,7 +2246,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
| } |
| /* Trying to reassociate - clear previous association state */ |
| - ieee80211_set_disassoc(sdata, true, false); |
| + ieee80211_set_disassoc(sdata, true); |
| } |
| mutex_unlock(&ifmgd->mtx); |
| @@ -2338,7 +2355,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, |
| memcpy(bssid, req->bss->bssid, ETH_ALEN); |
| if (ifmgd->associated == req->bss) { |
| - ieee80211_set_disassoc(sdata, false, true); |
| + ieee80211_set_disassoc(sdata, false); |
| mutex_unlock(&ifmgd->mtx); |
| assoc_bss = true; |
| } else { |
| @@ -2419,7 +2436,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, |
| sdata->name, req->bss->bssid, req->reason_code); |
| memcpy(bssid, req->bss->bssid, ETH_ALEN); |
| - ieee80211_set_disassoc(sdata, false, true); |
| + ieee80211_set_disassoc(sdata, false); |
| mutex_unlock(&ifmgd->mtx); |