Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Unified Diff: chromeos/compat-wireless/net/mac80211/mlme.c

Issue 5326002: Update compat-wireless to 2.6.36-5-spn (Closed) Base URL: http://git.chromium.org/git/kernel.git@master
Patch Set: Fixes for !ACK handling, missing local changes, log message fixes Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromeos/compat-wireless/net/mac80211/mesh_plink.c ('k') | chromeos/compat-wireless/net/mac80211/rate.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..a566a5c382270dd477d60fc0b26206064341712f 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/08 18:37:56 until we can override upstream defaults w/o modify
+#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)
/*
* 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);
@@ -1039,14 +1035,78 @@ 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, bool ack)
+{
+ if (!ieee80211_is_data(hdr->frame_control))
Sam Leffler 2010/12/08 18:37:56 this should check is_nullfunc instead and remove t
+ return;
+
+ if (ack)
+ ieee80211_sta_reset_conn_monitor(sdata);
+
+ if (ieee80211_is_nullfunc(hdr->frame_control) &&
+ sdata->u.mgd.probe_send_count > 0) {
+ if (ack)
+ sdata->u.mgd.probe_send_count = 0;
+ else
+ sdata->u.mgd.nullfunc_failed = true;
+ 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
+ }
+}
+
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) {
+ ifmgd->nullfunc_failed = false;
Sam Leffler 2010/12/08 18:37:56 it appears you are setting this here because the w
ieee80211_send_nullfunc(sdata->local, sdata, 0);
} else {
ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
@@ -1054,6 +1114,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
}
ifmgd->probe_send_count++;
+ ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
+ run_again(ifmgd, ifmgd->probe_timeout);
}
static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
@@ -1485,29 +1547,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 +1620,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;
@@ -1844,86 +1882,106 @@ static void ieee80211_sta_timer(unsigned long data)
ieee80211_queue_work(&local->hw, &sdata->work);
}
-void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
+ u8 *bssid)
{
- /* nothing right now */
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+ ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
+ IEEE80211_STA_BEACON_POLL);
+
+ ieee80211_set_disassoc(sdata, true, 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);
}
-static void ieee80211_sta_process_probe_status(struct ieee80211_sub_if_data *sdata)
+void ieee80211_sta_work(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;
Sam Leffler 2010/12/08 18:37:56 I find this combined code too complicated; I think
- 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);
+ else if (ifmgd->nullfunc_failed) {
+ if (ifmgd->probe_send_count < max_tries) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ wiphy_debug(local->hw.wiphy,
+ "%s: No ack for nullfunc frame to"
+ " AP %pM, try %d\n",
+ sdata->name, bssid,
+ ifmgd->probe_send_count);
+#endif
+ ieee80211_mgd_probe_ap_send(sdata);
+ } else {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ wiphy_debug(local->hw.wiphy,
+ "%s: No ack for nullfunc frame to"
+ " AP %pM, disconnecting.\n",
+ sdata->name, bssid,
+ ifmgd->probe_send_count);
+#endif
+ ieee80211_sta_connection_lost(sdata, bssid);
+ }
+ } else if (time_is_after_jiffies(ifmgd->probe_timeout))
+ run_again(ifmgd, ifmgd->probe_timeout);
+ 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
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+ wiphy_debug(local->hw.wiphy,
+ "%s: Failed to send nullfunc to AP %pM"
+ " after %dms, disconnecting.\n",
+ sdata->name,
+ bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
+#endif
+ ieee80211_sta_connection_lost(sdata, bssid);
+ } 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!
+ */
+ printk(KERN_DEBUG "No probe response from AP %pM"
+ " after %dms, disconnecting.\n",
+ bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
- /*
- * 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;
+ ieee80211_sta_connection_lost(sdata, bssid);
+ }
}
-done:
- mutex_unlock(&ifmgd->mtx);
-}
-/*
- * 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);
-
- 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 +2025,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 +2066,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);
}
#endif
@@ -2021,7 +2081,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);
« no previous file with comments | « chromeos/compat-wireless/net/mac80211/mesh_plink.c ('k') | chromeos/compat-wireless/net/mac80211/rate.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698