]> Pileus Git - ~andy/linux/blobdiff - net/mac80211/mlme.c
mac80211: probe the AP when resuming
[~andy/linux] / net / mac80211 / mlme.c
index a3a9421555af30201e13d8ea24c36f4bb759680f..849d9c639add2d7f0656c094d05a0cd29b374d1a 100644 (file)
 #define IEEE80211_MAX_PROBE_TRIES 5
 
 /*
- * beacon loss detection timeout
- * XXX: should depend on beacon interval
+ * 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 beacon miss before declaring the connection lost
+ * default to what we want.
  */
-#define IEEE80211_BEACON_LOSS_TIME     (2 * HZ)
+#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.
@@ -121,7 +126,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 + IEEE80211_BEACON_LOSS_TIME));
+                 round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout));
 }
 
 void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
@@ -871,6 +876,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        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);
 
@@ -1108,6 +1116,30 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        mutex_unlock(&ifmgd->mtx);
 }
 
+struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
+                                         struct ieee80211_vif *vif)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct sk_buff *skb;
+       const u8 *ssid;
+
+       if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+               return NULL;
+
+       ASSERT_MGD_MTX(ifmgd);
+
+       if (!ifmgd->associated)
+               return NULL;
+
+       ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
+       skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
+                                       ssid + 2, ssid[1], NULL, 0);
+
+       return skb;
+}
+EXPORT_SYMBOL(ieee80211_ap_probereq_get);
+
 static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -1988,6 +2020,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_restart_sta_timer(sdata);
 }
 #endif