mac80211: make the beacon monitor available externally
[cascardo/linux.git] / net / mac80211 / mlme.c
index 5282ac1..07d03e7 100644 (file)
  */
 #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
 
@@ -86,7 +92,7 @@ enum rx_mgmt_action {
 /* utils */
 static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
 {
-       WARN_ON(!mutex_is_locked(&ifmgd->mtx));
+       lockdep_assert_held(&ifmgd->mtx);
 }
 
 /*
@@ -109,7 +115,7 @@ static void run_again(struct ieee80211_if_managed *ifmgd,
                mod_timer(&ifmgd->timer, timeout);
 }
 
-static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
+void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
 {
        if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
                return;
@@ -118,6 +124,19 @@ static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
                  round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME));
 }
 
+void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+       if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
+               return;
+
+       mod_timer(&sdata->u.mgd.conn_mon_timer,
+                 round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
+
+       ifmgd->probe_send_count = 0;
+}
+
 static int ecw2cw(int ecw)
 {
        return (1 << ecw) - 1;
@@ -991,6 +1010,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
        if (remove_sta)
                sta_info_destroy_addr(sdata, bssid);
+
+       del_timer_sync(&sdata->u.mgd.conn_mon_timer);
+       del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
+       del_timer_sync(&sdata->u.mgd.timer);
+       del_timer_sync(&sdata->u.mgd.chswitch_timer);
 }
 
 void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1007,11 +1031,7 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
        if (is_multicast_ether_addr(hdr->addr1))
                return;
 
-       if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
-               return;
-
-       mod_timer(&sdata->u.mgd.conn_mon_timer,
-                 round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
+       ieee80211_sta_reset_conn_monitor(sdata);
 }
 
 static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
@@ -1370,7 +1390,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
         * Also start the timer that will detect beacon loss.
         */
        ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
-       mod_beacon_timer(sdata);
+       ieee80211_sta_reset_beacon_monitor(sdata);
 
        return true;
 }
@@ -1473,7 +1493,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
                 * we have or will be receiving any beacons or data, so let's
                 * schedule the timers again, just in case.
                 */
-               mod_beacon_timer(sdata);
+               ieee80211_sta_reset_beacon_monitor(sdata);
 
                mod_timer(&ifmgd->conn_mon_timer,
                          round_jiffies_up(jiffies +
@@ -1548,15 +1568,18 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        ifmgd->last_beacon_signal = rx_status->signal;
        if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) {
                ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE;
-               ifmgd->ave_beacon_signal = rx_status->signal;
+               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;
@@ -1596,7 +1619,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
         * Push the beacon loss detection into the future since
         * we are processing a beacon from the AP just now.
         */
-       mod_beacon_timer(sdata);
+       ieee80211_sta_reset_beacon_monitor(sdata);
 
        ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
        ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
@@ -2262,6 +2285,9 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        else
                ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT;
 
+       sdata->control_port_protocol = req->crypto.control_port_ethertype;
+       sdata->control_port_no_encrypt = req->crypto.control_port_no_encrypt;
+
        ieee80211_add_work(wk);
        return 0;
 }