Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / scan.c
index 43e60b5a7546eba4fd6e5e18eb313b7526d4f5b1..8e9bb168b73bff0f1c50c44d5e835ffba4696ae1 100644 (file)
@@ -336,6 +336,10 @@ EXPORT_SYMBOL(ieee80211_scan_completed);
 
 static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 {
+       /* Software scan is not supported in multi-channel cases */
+       if (local->use_chanctx)
+               return -EOPNOTSUPP;
+
        /*
         * Hardware/driver doesn't support hw_scan, so use software
         * scanning instead. First send a nullfunc frame with power save
@@ -417,7 +421,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
                        local->scan_req->ie, local->scan_req->ie_len,
                        local->scan_req->rates[band], false,
                        local->scan_req->no_cck,
-                       local->hw.conf.channel);
+                       local->hw.conf.channel, true);
 
        /*
         * After sending probe requests, wait for probe responses
@@ -462,6 +466,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
                        sizeof(*local->hw_scan_req) +
                        req->n_channels * sizeof(req->channels[0]);
                local->hw_scan_req->ie = ies;
+               local->hw_scan_req->flags = req->flags;
 
                local->hw_scan_band = 0;
 
@@ -480,7 +485,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
        if (local->ops->hw_scan) {
                __set_bit(SCAN_HW_SCANNING, &local->scanning);
        } else if ((req->n_channels == 1) &&
-                  (req->channels[0] == local->oper_channel)) {
+                  (req->channels[0] == local->_oper_channel)) {
                /*
                 * If we are scanning only on the operating channel
                 * then we do not need to stop normal activities
@@ -562,6 +567,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
        unsigned long min_beacon_int = 0;
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_channel *next_chan;
+       enum mac80211_scan_state next_scan_state;
 
        /*
         * check if at least one STA interface is associated,
@@ -620,10 +626,18 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
                        usecs_to_jiffies(min_beacon_int * 1024) *
                        local->hw.conf.listen_interval);
 
-       if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
-               local->next_scan_state = SCAN_SUSPEND;
-       else
-               local->next_scan_state = SCAN_SET_CHANNEL;
+       if (associated && !tx_empty) {
+               if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+                       next_scan_state = SCAN_ABORT;
+               else
+                       next_scan_state = SCAN_SUSPEND;
+       } else if (associated && (bad_latency || listen_int_exceeded)) {
+               next_scan_state = SCAN_SUSPEND;
+       } else {
+               next_scan_state = SCAN_SET_CHANNEL;
+       }
+
+       local->next_scan_state = next_scan_state;
 
        *next_delay = 0;
 }
@@ -794,6 +808,9 @@ void ieee80211_scan_work(struct work_struct *work)
                case SCAN_RESUME:
                        ieee80211_scan_state_resume(local, &next_delay);
                        break;
+               case SCAN_ABORT:
+                       aborted = true;
+                       goto out_complete;
                }
        } while (next_delay == 0);