diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 2da58c9..8fced7a 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -56,6 +56,8 @@ extern "C" {
 #define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
 /** A BSS entry was removed (followed by BSS entry id and BSSID) */
 #define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
+/** Notify the Userspace about the freq conflict */
+#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT "
 
 /** WPS overlap detected in PBC mode */
 #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index d5c862c..53c3e9e 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -267,6 +267,9 @@ static void wpas_p2p_group_delete(struct wpa_supplicant *wpa_s)
 	case P2P_GROUP_REMOVAL_GO_ENDING_SESSION:
 		reason = " reason=GO_ENDING_SESSION";
 		break;
+	case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
+		reason = " reason=FREQ_CONFLICT";
+		break;
 	default:
 		reason = "";
 		break;
@@ -4713,3 +4716,49 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
 		return;
 	wpas_p2p_add_persistent_group_client(wpa_s, addr);
 }
+
+int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq)
+{
+	struct wpa_supplicant *iface = NULL;
+
+	for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+		if(!iface->p2p_group_interface || !iface->current_ssid ||
+			iface->current_ssid->frequency == freq)
+			continue;
+
+		if (iface->p2p_group_interface == P2P_GROUP_INTERFACE_GO) {
+			/*
+			 * Try to see whether we can move the GO. If it
+			 * is not possible, remove the GO interface
+			 */
+			if(wpa_drv_switch_channel(iface, freq) == 0) {
+					wpa_printf(MSG_INFO, "P2P: GO Moved to freq"
+					"(%d) MHz", freq);
+					iface->current_ssid->frequency = freq;
+					continue;
+			}
+		}
+
+		/* If GO cannot be moved or if the conflicting interface is a
+		 * P2P Client, remove the interface depending up on the connection
+		 * priority
+		 */
+		if(!wpas_is_p2p_prioritized(wpa_s)) {
+			/*
+			 * STA connection has priority over existing
+			 * P2P connection. So remove the interface
+			 */
+			wpa_printf(MSG_DEBUG, "P2P: Removing P2P connection due to "
+				"Single channel concurrent mode frequency conflict");
+			iface->removal_reason = P2P_GROUP_REMOVAL_FREQ_CONFLICT;
+			wpas_p2p_group_delete(iface);
+		} else {
+			/*
+			 * Existing connection has the priority. Disable the newly
+			 * selected network and let the application know about it.
+			 */
+			return -1;
+		}
+	}
+	return 0;
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index c15e42a..9b49b01 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -25,6 +25,8 @@ void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 				   unsigned int freq, unsigned int duration);
 void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
 					  unsigned int freq);
+int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
+                                          int freq);
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
 		       int freq);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index c5a7115..2c7ec09 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1100,6 +1100,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 	ibss_rsn_deinit(wpa_s->ibss_rsn);
 	wpa_s->ibss_rsn = NULL;
 #endif /* CONFIG_IBSS_RSN */
+	int freq = 0;
 
 	if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
 	    ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
@@ -1404,6 +1405,33 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 	wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
 #endif /* CONFIG_HT_OVERRIDES */
 
+	/*
+	 * If multichannel concurrency is not supported, check for any frequency
+	 * conflict and take appropriate action.
+	 */
+	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
+		((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) {
+		wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency"
+			"found (%d != %d)", freq, params.freq);
+#ifdef CONFIG_P2P
+		if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq) <
+			0) {
+			/*
+			 * Handling conflicts failed. Disable the current
+			 * connect req and notify the userspace to take
+			 * appropriate action.
+			 */
+			wpa_printf(MSG_DEBUG, "proiritize is not set."
+				"Notifying user space to handle the case");
+			wpa_supplicant_disable_network(wpa_s, ssid);
+			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_FREQ_CONFLICT
+				" id=%d", ssid->id);
+			os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+			return;
+		}
+#endif /* CONFIG_P2P */
+	}
+
 	ret = wpa_drv_associate(wpa_s, &params);
 	if (ret < 0) {
 		wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index b25116e..a28fa5a 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -504,7 +504,8 @@ struct wpa_supplicant {
 		P2P_GROUP_REMOVAL_REQUESTED,
 		P2P_GROUP_REMOVAL_IDLE_TIMEOUT,
 		P2P_GROUP_REMOVAL_UNAVAILABLE,
-		P2P_GROUP_REMOVAL_GO_ENDING_SESSION
+		P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
+		P2P_GROUP_REMOVAL_FREQ_CONFLICT
 	} removal_reason;
 
 	unsigned int p2p_cb_on_scan_complete:1;
-- 
1.7.4.1






- Jithu Jance

________________________________________
From: hostap-bounces@lists.shmoo.com [hostap-bounces@lists.shmoo.com] on behalf of Jouni Malinen [j@w1.fi]
Sent: Monday, April 09, 2012 12:08 AM
To: hostap@lists.shmoo.com
Subject: Re: [RFC 4/4] P2P: Handling single channel concurrency

On Tue, Mar 06, 2012 at 10:34:38AM +0530, Jithu Jance wrote:
> This patch handles cases where a STA connection is attempted after a P2P
> connection and the new sta connection detects a freq
> conflict with the existing P2P connection. Now based on the priority of the
> connection (either sta or p2p), either one of the connection
> will be terminated.

I applied the driver_nl80211.c part and below is a cleaned up version of
the rest. Though, I did not go through all the details yet.


[PATCH 3/3] P2P: Handle single channel concurrency

This patch handles cases where a STA connection is attempted after a P2P
connection and the new sta connection detects a freq conflict with the
existing P2P connection. Now based on the priority of the connection
(either sta or p2p), either one of the connection will be terminated.

Signed-hostap: Jithu Jance <jithu@broadcom.com>
---
 src/common/wpa_ctrl.h             |    2 +
 wpa_supplicant/p2p_supplicant.c   |   50 +++++++++++++++++++++++++++++++++++++
 wpa_supplicant/p2p_supplicant.h   |    2 +
 wpa_supplicant/wpa_supplicant.c   |   27 ++++++++++++++++++++
 wpa_supplicant/wpa_supplicant_i.h |    3 +-
 5 files changed, 83 insertions(+), 1 deletions(-)

diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 35012e8..2e35e9c 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -56,6 +56,8 @@ extern "C" {
 #define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
 /** A BSS entry was removed (followed by BSS entry id and BSSID) */
 #define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
+/** Notify the Userspace about the freq conflict */
+#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT "

 /** WPS overlap detected in PBC mode */
 #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 9d31fdb..3abcee7 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -4609,3 +4609,53 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
                return;
        wpas_p2p_add_persistent_group_client(wpa_s, addr);
 }
+
+
+int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq)
+{
+       struct wpa_supplicant *iface;
+
+       for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+               if (!iface->p2p_group_interface || !iface->current_ssid ||
+                   iface->current_ssid->frequency == freq)
+                       continue;
+
+               if (iface->p2p_group_interface == P2P_GROUP_INTERFACE_GO) {
+                       /*
+                        * Try to see whether we can move the GO. If it is not
+                        * possible, remove the GO interface.
+                        */
+                       if (wpa_drv_switch_channel(iface, freq) == 0) {
+                               wpa_printf(MSG_INFO, "P2P: GO Moved to freq "
+                                          "%d MHz", freq);
+                               iface->current_ssid->frequency = freq;
+                               continue;
+                       }
+               }
+
+               /*
+                * If GO cannot be moved or if the conflicting interface is a
+                * P2P Client, remove the interface depending up on the
+                * connection priority.
+                */
+               if (!wpas_is_p2p_prioritized(iface)) {
+                       /*
+                        * STA connection has priority over existing P2P
+                        * connection, so remove the interface.
+                        */
+                       wpas_p2p_disconnect(iface);
+                       iface->removal_reason =
+                               P2P_GROUP_REMOVAL_FREQ_CONFLICT;
+                       wpas_p2p_group_delete(iface);
+               } else {
+                       /*
+                        * Existing connection has the priority. Disable the
+                        * newly selected network and let the application know
+                        * about it.
+                        */
+                       return -1;
+               }
+       }
+
+       return 0;
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 8f8e635..fb0522b 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -25,6 +25,8 @@ void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
                                   unsigned int freq, unsigned int duration);
 void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
                                          unsigned int freq);
+int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
+                                       int freq);
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
 int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
                       int freq);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 1c88949..7b4e178 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1091,6 +1091,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        struct wpa_driver_capa capa;
        int assoc_failed = 0;
        struct wpa_ssid *old_ssid;
+       int freq;
 #ifdef CONFIG_HT_OVERRIDES
        struct ieee80211_ht_capabilities htcaps;
        struct ieee80211_ht_capabilities htcaps_mask;
@@ -1404,6 +1405,32 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
 #endif /* CONFIG_HT_OVERRIDES */

+       /*
+        * If multichannel concurrency is not supported, check for any
+        * frequency conflict and take appropriate action.
+        */
+       if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
+           ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && freq != params.freq) {
+               wpa_printf(MSG_DEBUG, "Shared interface with conflicting "
+                          "frequency found (%d != %d)", freq, params.freq);
+#ifdef CONFIG_P2P
+               if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq) <
+                   0) {
+                       /*
+                        * Handling conflicts failed. Disable the current
+                        * connect req and notify the userspace to take
+                        * appropriate action.
+                        */
+                       wpa_printf(MSG_DEBUG, "prioritize is not set. "
+                                  "Notifying user space to handle the case.");
+                       wpa_supplicant_disable_network(wpa_s, ssid);
+                       wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_FREQ_CONFLICT
+                               " id=%d", ssid->id);
+                       os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+               }
+#endif /* CONFIG_P2P */
+       }
+
        ret = wpa_drv_associate(wpa_s, &params);
        if (ret < 0) {
                wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 3f1f589..3c86857 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -509,7 +509,8 @@ struct wpa_supplicant {
                P2P_GROUP_REMOVAL_REQUESTED,
                P2P_GROUP_REMOVAL_IDLE_TIMEOUT,
                P2P_GROUP_REMOVAL_UNAVAILABLE,
-               P2P_GROUP_REMOVAL_GO_ENDING_SESSION
+               P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
+               P2P_GROUP_REMOVAL_FREQ_CONFLICT
        } removal_reason;

        unsigned int p2p_cb_on_scan_complete:1;
