Merge commit 'f62167e88c0c1b9621f2984f1a59ae7d41cf4c88' into HEAD
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index d666c91..69f920d 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3172,6 +3172,7 @@
 	{ FUNC(freq_list), 0 },
 	{ INT(scan_cur_freq), 0 },
 	{ INT(sched_scan_interval), 0 },
+	{ INT(tdls_external_control), 0},
 };
 
 #undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 1748cf3..3fe46e3 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -876,6 +876,17 @@
 	 * sched_scan_interval -  schedule scan interval
 	 */
 	unsigned int sched_scan_interval;
+
+	/**
+	 * tdls_external_control - External control for TDLS setup requests
+	 *
+	 * Enable TDLS mode where external programs are given the control
+	 * to specify the TDLS link to get established to the driver. The
+	 * driver requests the TDLS setup to the supplicant only for the
+	 * specified TDLS peers.
+	 *
+	 */
+	int tdls_external_control;
 };
 
 
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index a2791eb..bb0e536 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1048,6 +1048,10 @@
 	if (config->sched_scan_interval)
 		fprintf(f, "sched_scan_interval=%u\n",
 			config->sched_scan_interval);
+
+	if (config->tdls_external_control)
+		fprintf(f, "tdls_external_control=%u\n",
+			config->tdls_external_control);
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index af57afa..6335605 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -58,6 +58,12 @@
 	if (wpa_s->pno)
 		return 0;
 
+	if ((wpa_s->wpa_state > WPA_SCANNING) &&
+	    (wpa_s->wpa_state <= WPA_COMPLETED)) {
+		wpa_printf(MSG_ERROR, "PNO: In assoc process");
+		return -EAGAIN;
+	}
+
 	if (wpa_s->wpa_state == WPA_SCANNING) {
 		wpa_supplicant_cancel_sched_scan(wpa_s);
 		wpa_supplicant_cancel_scan(wpa_s);
@@ -562,6 +568,11 @@
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
 		   MAC2STR(peer));
 
+	if ((wpa_s->conf->tdls_external_control) &&
+	     wpa_tdls_is_external_setup(wpa_s->wpa)) {
+		return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
+	}
+
 	wpa_tdls_remove(wpa_s->wpa, peer);
 
 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
@@ -588,6 +599,11 @@
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
 		   MAC2STR(peer));
 
+	if ((wpa_s->conf->tdls_external_control) &&
+	     wpa_tdls_is_external_setup(wpa_s->wpa)) {
+		return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
+	}
+
 	if (wpa_tdls_is_external_setup(wpa_s->wpa))
 		ret = wpa_tdls_teardown_link(
 			wpa_s->wpa, peer,
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 9ae898b..b431662 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1800,7 +1800,7 @@
 	 * Try to reassociate since there is no current configuration and a new
 	 * network was made available.
 	 */
-	if (!wpa_s->current_ssid)
+	if (!wpa_s->current_ssid && !wpa_s->disconnected)
 		wpa_s->reassociate = 1;
 }
 
@@ -1821,7 +1821,7 @@
 	} else
 		wpa_supplicant_enable_one_network(wpa_s, ssid);
 
-	if (wpa_s->reassociate) {
+	if (wpa_s->reassociate && !wpa_s->disconnected) {
 		if (wpa_s->sched_scanning) {
 			wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
 				   "new network to scan filters");