mac80211: reduce indentation by inlining a check
[cascardo/linux.git] / net / mac80211 / mlme.c
index 9b2cc27..88894d9 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright (C) 2015 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -80,13 +81,6 @@ MODULE_PARM_DESC(probe_wait_ms,
                 "Maximum time(ms) to wait for probe response"
                 " before disconnecting (reason 4).");
 
-/*
- * Weight given to the latest Beacon frame when calculating average signal
- * strength for Beacon frames received in the current BSS. This must be
- * between 1 and 15.
- */
-#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.
@@ -538,11 +532,16 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
        ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
 }
 
+/* This function determines vht capability flags for the association
+ * and builds the IE.
+ * Note - the function may set the owner of the MU-MIMO capability
+ */
 static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
                                 struct sk_buff *skb,
                                 struct ieee80211_supported_band *sband,
                                 struct ieee80211_vht_cap *ap_vht_cap)
 {
+       struct ieee80211_local *local = sdata->local;
        u8 *pos;
        u32 cap;
        struct ieee80211_sta_vht_cap vht_cap;
@@ -576,7 +575,34 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
         */
        if (!(ap_vht_cap->vht_cap_info &
                        cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)))
-               cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
+               cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+                        IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
+       else if (!(ap_vht_cap->vht_cap_info &
+                       cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)))
+               cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
+
+       /*
+        * If some other vif is using the MU-MIMO capablity we cannot associate
+        * using MU-MIMO - this will lead to contradictions in the group-id
+        * mechanism.
+        * Ownership is defined since association request, in order to avoid
+        * simultaneous associations with MU-MIMO.
+        */
+       if (cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) {
+               bool disable_mu_mimo = false;
+               struct ieee80211_sub_if_data *other;
+
+               list_for_each_entry_rcu(other, &local->interfaces, list) {
+                       if (other->flags & IEEE80211_SDATA_MU_MIMO_OWNER) {
+                               disable_mu_mimo = true;
+                               break;
+                       }
+               }
+               if (disable_mu_mimo)
+                       cap &= ~IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
+               else
+                       sdata->flags |= IEEE80211_SDATA_MU_MIMO_OWNER;
+       }
 
        mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
 
@@ -1096,24 +1122,6 @@ static void ieee80211_chswitch_timer(unsigned long data)
        ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
 }
 
-static void ieee80211_teardown_tdls_peers(struct ieee80211_sub_if_data *sdata)
-{
-       struct sta_info *sta;
-       u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
-               if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded ||
-                   !test_sta_flag(sta, WLAN_STA_AUTHORIZED))
-                       continue;
-
-               ieee80211_tdls_oper_request(&sdata->vif, sta->sta.addr,
-                                           NL80211_TDLS_TEARDOWN, reason,
-                                           GFP_ATOMIC);
-       }
-       rcu_read_unlock();
-}
-
 static void
 ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                                 u64 timestamp, u32 device_timestamp,
@@ -2076,6 +2084,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
        memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa));
        memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask));
+       sdata->flags &= ~IEEE80211_SDATA_MU_MIMO_OWNER;
 
        sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
 
@@ -2538,6 +2547,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
                eth_zero_addr(sdata->u.mgd.bssid);
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
                sdata->u.mgd.flags = 0;
+               sdata->flags &= ~IEEE80211_SDATA_MU_MIMO_OWNER;
                mutex_lock(&sdata->local->mtx);
                ieee80211_vif_release_channel(sdata);
                mutex_unlock(&sdata->local->mtx);
@@ -3034,12 +3044,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 
        rate_control_rate_init(sta);
 
-       if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED) {
+       if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
                set_sta_flag(sta, WLAN_STA_MFP);
-               sta->sta.mfp = true;
-       } else {
-               sta->sta.mfp = false;
-       }
 
        sta->sta.wme = elems.wmm_param && local->hw.queues >= IEEE80211_NUM_ACS;
 
@@ -3249,16 +3255,6 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->associated &&
            ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
                ieee80211_reset_ap_probe(sdata);
-
-       if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies &&
-           ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) {
-               /* got probe response, continue with auth */
-               sdata_info(sdata, "direct probe responded\n");
-               ifmgd->auth_data->tries = 0;
-               ifmgd->auth_data->timeout = jiffies;
-               ifmgd->auth_data->timeout_started = true;
-               run_again(sdata, ifmgd->auth_data->timeout);
-       }
 }
 
 /*
@@ -3361,24 +3357,21 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        bssid = ifmgd->associated->bssid;
 
        /* Track average RSSI from the Beacon frames of the current AP */
-       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 * 16;
+               ewma_beacon_signal_init(&ifmgd->ave_beacon_signal);
                ifmgd->last_cqm_event_signal = 0;
                ifmgd->count_beacon_signal = 1;
                ifmgd->last_ave_beacon_signal = 0;
        } 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++;
        }
 
+       ewma_beacon_signal_add(&ifmgd->ave_beacon_signal, -rx_status->signal);
+
        if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
            ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
-               int sig = ifmgd->ave_beacon_signal;
+               int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
                int last_sig = ifmgd->last_ave_beacon_signal;
                struct ieee80211_event event = {
                        .type = RSSI_EVENT,
@@ -3405,10 +3398,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        if (bss_conf->cqm_rssi_thold &&
            ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
            !(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)) {
-               int sig = ifmgd->ave_beacon_signal / 16;
+               int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
                int last_event = ifmgd->last_cqm_event_signal;
                int thold = bss_conf->cqm_rssi_thold;
                int hyst = bss_conf->cqm_rssi_hyst;
+
                if (sig < thold &&
                    (last_event == 0 || sig < last_event - hyst)) {
                        ifmgd->last_cqm_event_signal = sig;
@@ -3443,31 +3437,27 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                                          len - baselen, false, &elems,
                                          care_about_ies, ncrc);
 
-       if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK)) {
-               bool directed_tim = ieee80211_check_tim(elems.tim,
-                                                       elems.tim_len,
-                                                       ifmgd->aid);
-               if (directed_tim) {
-                       if (local->hw.conf.dynamic_ps_timeout > 0) {
-                               if (local->hw.conf.flags & IEEE80211_CONF_PS) {
-                                       local->hw.conf.flags &= ~IEEE80211_CONF_PS;
-                                       ieee80211_hw_config(local,
-                                                           IEEE80211_CONF_CHANGE_PS);
-                               }
-                               ieee80211_send_nullfunc(local, sdata, 0);
-                       } else if (!local->pspolling && sdata->u.mgd.powersave) {
-                               local->pspolling = true;
-
-                               /*
-                                * Here is assumed that the driver will be
-                                * able to send ps-poll frame and receive a
-                                * response even though power save mode is
-                                * enabled, but some drivers might require
-                                * to disable power save here. This needs
-                                * to be investigated.
-                                */
-                               ieee80211_send_pspoll(local, sdata);
+       if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
+           ieee80211_check_tim(elems.tim, elems.tim_len, ifmgd->aid)) {
+               if (local->hw.conf.dynamic_ps_timeout > 0) {
+                       if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+                               local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+                               ieee80211_hw_config(local,
+                                                   IEEE80211_CONF_CHANGE_PS);
                        }
+                       ieee80211_send_nullfunc(local, sdata, 0);
+               } else if (!local->pspolling && sdata->u.mgd.powersave) {
+                       local->pspolling = true;
+
+                       /*
+                        * Here is assumed that the driver will be
+                        * able to send ps-poll frame and receive a
+                        * response even though power save mode is
+                        * enabled, but some drivers might require
+                        * to disable power save here. This needs
+                        * to be investigated.
+                        */
+                       ieee80211_send_pspoll(local, sdata);
                }
        }
 
@@ -3704,12 +3694,14 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
                                    reason);
 }
 
-static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
+static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
        u32 tx_flags = 0;
+       u16 trans = 1;
+       u16 status = 0;
 
        sdata_assert_lock(sdata);
 
@@ -3733,54 +3725,27 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
 
        drv_mgd_prepare_tx(local, sdata);
 
-       if (auth_data->bss->proberesp_ies) {
-               u16 trans = 1;
-               u16 status = 0;
+       sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
+                  auth_data->bss->bssid, auth_data->tries,
+                  IEEE80211_AUTH_MAX_TRIES);
 
-               sdata_info(sdata, "send auth to %pM (try %d/%d)\n",
-                          auth_data->bss->bssid, auth_data->tries,
-                          IEEE80211_AUTH_MAX_TRIES);
-
-               auth_data->expected_transaction = 2;
-
-               if (auth_data->algorithm == WLAN_AUTH_SAE) {
-                       trans = auth_data->sae_trans;
-                       status = auth_data->sae_status;
-                       auth_data->expected_transaction = trans;
-               }
+       auth_data->expected_transaction = 2;
 
-               if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
-                       tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
-                                  IEEE80211_TX_INTFL_MLME_CONN_TX;
-
-               ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
-                                   auth_data->data, auth_data->data_len,
-                                   auth_data->bss->bssid,
-                                   auth_data->bss->bssid, NULL, 0, 0,
-                                   tx_flags);
-       } else {
-               const u8 *ssidie;
+       if (auth_data->algorithm == WLAN_AUTH_SAE) {
+               trans = auth_data->sae_trans;
+               status = auth_data->sae_status;
+               auth_data->expected_transaction = trans;
+       }
 
-               sdata_info(sdata, "direct probe to %pM (try %d/%i)\n",
-                          auth_data->bss->bssid, auth_data->tries,
-                          IEEE80211_AUTH_MAX_TRIES);
+       if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS))
+               tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
+                          IEEE80211_TX_INTFL_MLME_CONN_TX;
 
-               rcu_read_lock();
-               ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID);
-               if (!ssidie) {
-                       rcu_read_unlock();
-                       return -EINVAL;
-               }
-               /*
-                * Direct probe is sent to broadcast address as some APs
-                * will not answer to direct packet in unassociated state.
-                */
-               ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
-                                        ssidie + 2, ssidie[1],
-                                        NULL, 0, (u32) -1, true, 0,
-                                        auth_data->bss->channel, false);
-               rcu_read_unlock();
-       }
+       ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
+                           auth_data->data, auth_data->data_len,
+                           auth_data->bss->bssid,
+                           auth_data->bss->bssid, NULL, 0, 0,
+                           tx_flags);
 
        if (tx_flags == 0) {
                auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
@@ -3861,8 +3826,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                bool status_acked = ifmgd->status_acked;
 
                ifmgd->status_received = false;
-               if (ifmgd->auth_data &&
-                   (ieee80211_is_probe_req(fc) || ieee80211_is_auth(fc))) {
+               if (ifmgd->auth_data && ieee80211_is_auth(fc)) {
                        if (status_acked) {
                                ifmgd->auth_data->timeout =
                                        jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;
@@ -3893,7 +3857,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                         * so let's just kill the auth data
                         */
                        ieee80211_destroy_auth_data(sdata, false);
-               } else if (ieee80211_probe_auth(sdata)) {
+               } else if (ieee80211_auth(sdata)) {
                        u8 bssid[ETH_ALEN];
                        struct ieee80211_event event = {
                                .type = MLME_EVENT,
@@ -4584,7 +4548,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        if (err)
                goto err_clear;
 
-       err = ieee80211_probe_auth(sdata);
+       err = ieee80211_auth(sdata);
        if (err) {
                sta_info_destroy_addr(sdata, req->bss->bssid);
                goto err_clear;