Accumulative patch from commit 932659696e2755bb1ecd6a27e1968fd27eef4948

9326596 nl80211: Remove unused WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT
0d08efa P2P: Use the number of concurrent channels in P2P flows
a21816a Use wpa_drv_shared_freq() if get_radio_name() is not supported
53c5dfc Change share_vif_oper_freq() to handle multiple freqs
4752147 nl80211: Report the number of concurrent support channels
d7df0fa Clean up wpa_supplicant_event() with deauth/disassoc helper functions
fd9f170 Remove unnecessary nested ifdef CONFIG_AP
13adc57 IBSS RSN: Add peer restart detection
b21990b nl80211: Register for AUTH frames when joining an IBSS network
c91f796 nl80211: Support not specifying the frame frequency
ec384c5 IBSS RSN: Fix disconnect() with internal SME
ed07764 nl80211: Remove redundant assignment of ifindex
4ed8d95 TDLS: Tear down TDLS using wpas_drv_tlds_oper() if not external
831770b Cancel delayed scheduled scan when wpa_supplicant cleans up
69dd296 WDS: Fix WEP usage with nl80211 wds_sta=1
c8ebeda wpa_supplicant: Add support for VHT BSS membership selector
3f9a813 hostapd: Add a config option to control beaconing
182b2e5 Add missing host_to_le32() for big endian hosts
3f53c00 nl80211: Ignore disconnect event in case of locally generated request

Change-Id: Ia7368e71ae40966a92970ac82b002c09a7971d41
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 8cd0f1d..9b6cd46 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -488,44 +488,6 @@
 
 #endif /* CONFIG_P2P */
 
-/*
- * Find the operating frequency of any other virtual interface that is using
- * the same radio concurrently.
- */
-static int shared_vif_oper_freq(struct wpa_supplicant *wpa_s)
-{
-	const char *rn, *rn2;
-	struct wpa_supplicant *ifs;
-	u8 bssid[ETH_ALEN];
-
-	if (!wpa_s->driver->get_radio_name)
-		return -1;
-
-	rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
-	if (rn == NULL || rn[0] == '\0')
-		return -1;
-
-	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
-		if (ifs == wpa_s || !ifs->driver->get_radio_name)
-			continue;
-
-		rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
-		if (!rn2 || os_strcmp(rn, rn2) != 0)
-			continue;
-
-		if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
-			continue;
-
-		if (ifs->current_ssid->mode == WPAS_MODE_AP ||
-		    ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
-			return ifs->current_ssid->frequency;
-		if (wpa_drv_get_bssid(ifs, bssid) == 0)
-			return ifs->assoc_freq;
-	}
-
-	return 0;
-}
-
 
 static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
 					  u16 num_modes,
@@ -828,14 +790,19 @@
 
 	/* Use current associated channel? */
 	if (wpa_s->conf->scan_cur_freq && !params.freqs) {
-		int freq = shared_vif_oper_freq(wpa_s);
-		if (freq > 0) {
-			wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current "
-				"operating channel (%d MHz) since "
-				"scan_cur_freq is enabled", freq);
-			params.freqs = os_zalloc(sizeof(int) * 2);
-			if (params.freqs)
-				params.freqs[0] = freq;
+		unsigned int num = wpa_s->num_multichan_concurrent;
+
+		params.freqs = os_calloc(num + 1, sizeof(int));
+		if (params.freqs) {
+			num = get_shared_radio_freqs(wpa_s, params.freqs, num);
+			if (num > 0) {
+				wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
+					"current operating channels since "
+					"scan_cur_freq is enabled");
+			} else {
+				os_free(params.freqs);
+				params.freqs = NULL;
+			}
 		}
 	}
 
@@ -873,18 +840,19 @@
 	if (wpa_s->scan_for_connection && scan_req == NORMAL_SCAN_REQ &&
 	    !scan_params->freqs && !params.freqs &&
 	    wpas_is_p2p_prioritized(wpa_s) &&
-	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
 	    wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
 	    non_p2p_network_enabled(wpa_s)) {
-		int freq = shared_vif_oper_freq(wpa_s);
-		if (freq > 0) {
-			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only the current "
-				"operating channel (%d MHz) since driver does "
-				"not support multi-channel concurrency", freq);
-			params.freqs = os_zalloc(sizeof(int) * 2);
-			if (params.freqs)
-				params.freqs[0] = freq;
-			scan_params->freqs = params.freqs;
+		unsigned int num = wpa_s->num_multichan_concurrent;
+
+		params.freqs = os_calloc(num + 1, sizeof(int));
+		if (params.freqs) {
+			num = get_shared_radio_freqs(wpa_s, params.freqs, num);
+			if (num > 0 && num == wpa_s->num_multichan_concurrent) {
+				wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used");
+			} else {
+				os_free(params.freqs);
+				params.freqs = NULL;
+			}
 		}
 	}
 #endif /* CONFIG_P2P */
@@ -1249,6 +1217,23 @@
 
 
 /**
+ * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is used to stop a delayed scheduled scan.
+ */
+void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->sched_scan_supported)
+		return;
+
+	wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan");
+	eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout,
+			     wpa_s, NULL);
+}
+
+
+/**
  * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans
  * @wpa_s: Pointer to wpa_supplicant data
  *