These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / mac80211 / scan.c
index 7bb6a93..acbe182 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2005, Devicescape Software, Inc.
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
- * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright 2013-2015  Intel Mobile Communications 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
@@ -16,7 +16,6 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
-#include <linux/pm_qos.h>
 #include <net/sch_generic.h>
 #include <linux/slab.h>
 #include <linux/export.h>
@@ -67,25 +66,30 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
        struct cfg80211_bss *cbss;
        struct ieee80211_bss *bss;
        int clen, srlen;
-       enum nl80211_bss_scan_width scan_width;
-       s32 signal = 0;
+       struct cfg80211_inform_bss bss_meta = {};
+       bool signal_valid;
 
-       if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
-               signal = rx_status->signal * 100;
-       else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
-               signal = (rx_status->signal * 100) / local->hw.max_signal;
+       if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
+               bss_meta.signal = rx_status->signal * 100;
+       else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
+               bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
 
-       scan_width = NL80211_BSS_CHAN_WIDTH_20;
+       bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
        if (rx_status->flag & RX_FLAG_5MHZ)
-               scan_width = NL80211_BSS_CHAN_WIDTH_5;
+               bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
        if (rx_status->flag & RX_FLAG_10MHZ)
-               scan_width = NL80211_BSS_CHAN_WIDTH_10;
+               bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
 
-       cbss = cfg80211_inform_bss_width_frame(local->hw.wiphy, channel,
-                                              scan_width, mgmt, len, signal,
-                                              GFP_ATOMIC);
+       bss_meta.chan = channel;
+       cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
+                                             mgmt, len, GFP_ATOMIC);
        if (!cbss)
                return NULL;
+       /* In case the signal is invalid update the status */
+       signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
+               <= local->hw.wiphy->max_adj_channel_rssi_comp;
+       if (!signal_valid)
+               rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
        bss = (void *)cbss->priv;
 
@@ -257,7 +261,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
        if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
                return false;
 
-       if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) {
+       if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) {
                for (i = 0; i < req->n_channels; i++) {
                        local->hw_scan_req->req.channels[i] = req->channels[i];
                        bands_used |= BIT(req->channels[i]->band);
@@ -310,6 +314,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
        bool was_scanning = local->scanning;
        struct cfg80211_scan_request *scan_req;
        struct ieee80211_sub_if_data *scan_sdata;
+       struct ieee80211_sub_if_data *sdata;
 
        lockdep_assert_held(&local->mtx);
 
@@ -326,7 +331,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
                return;
 
        if (hw_scan && !aborted &&
-           !(local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) &&
+           !ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS) &&
            ieee80211_prep_hw_scan(local)) {
                int rc;
 
@@ -369,7 +374,16 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
 
        ieee80211_mlme_notify_scan_completed(local);
        ieee80211_ibss_notify_scan_completed(local);
-       ieee80211_mesh_notify_scan_completed(local);
+
+       /* Requeue all the work that might have been ignored while
+        * the scan was in progress; if there was none this will
+        * just be a no-op for the particular interface.
+        */
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               if (ieee80211_sdata_running(sdata))
+                       ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+       }
+
        if (was_scanning)
                ieee80211_start_next_roc(local);
 }
@@ -520,7 +534,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 
                local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len;
 
-               if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) {
+               if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) {
                        int i, n_bands = 0;
                        u8 bands_counted = 0;
 
@@ -593,8 +607,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
                /* We need to ensure power level is at max for scanning. */
                ieee80211_hw_config(local, 0);
 
-               if ((req->channels[0]->flags &
-                    IEEE80211_CHAN_NO_IR) ||
+               if ((req->channels[0]->flags & (IEEE80211_CHAN_NO_IR |
+                                               IEEE80211_CHAN_RADAR)) ||
                    !req->n_ssids) {
                        next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
                } else {
@@ -641,7 +655,7 @@ ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
         * TODO: channel switching also consumes quite some time,
         * add that delay as well to get a better estimation
         */
-       if (chan->flags & IEEE80211_CHAN_NO_IR)
+       if (chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
                return IEEE80211_PASSIVE_CHANNEL_TIME;
        return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
 }
@@ -773,7 +787,8 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
         *
         * In any case, it is not necessary for a passive scan.
         */
-       if (chan->flags & IEEE80211_CHAN_NO_IR || !scan_req->n_ssids) {
+       if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) ||
+           !scan_req->n_ssids) {
                *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
                local->next_scan_state = SCAN_DECISION;
                return;
@@ -1136,10 +1151,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
        return ret;
 }
 
-int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
+int ieee80211_request_sched_scan_stop(struct ieee80211_local *local)
 {
-       struct ieee80211_local *local = sdata->local;
-       int ret = 0;
+       struct ieee80211_sub_if_data *sched_scan_sdata;
+       int ret = -ENOENT;
 
        mutex_lock(&local->mtx);
 
@@ -1151,8 +1166,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
        /* We don't want to restart sched scan anymore. */
        RCU_INIT_POINTER(local->sched_scan_req, NULL);
 
-       if (rcu_access_pointer(local->sched_scan_sdata)) {
-               ret = drv_sched_scan_stop(local, sdata);
+       sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
+                                               lockdep_is_held(&local->mtx));
+       if (sched_scan_sdata) {
+               ret = drv_sched_scan_stop(local, sched_scan_sdata);
                if (!ret)
                        RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
        }