@@ -66,6 +66,8 @@ extern "C" {
/** RSN IBSS 4-way handshakes completed with specified peer */
#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
+/** 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 "
/** Available WPS AP with active PBC found in scan results */
@@ -92,7 +92,8 @@ enum p2p_group_removal_reason {
P2P_GROUP_REMOVAL_IDLE_TIMEOUT,
P2P_GROUP_REMOVAL_UNAVAILABLE,
P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
- P2P_GROUP_REMOVAL_PSK_FAILURE
+ P2P_GROUP_REMOVAL_PSK_FAILURE,
+ P2P_GROUP_REMOVAL_FREQ_CONFLICT
};
@@ -112,6 +113,7 @@ static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
void *timeout_ctx);
+static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
int group_added);
static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
@@ -426,6 +428,9 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
case P2P_GROUP_REMOVAL_PSK_FAILURE:
reason = " reason=PSK_FAILURE";
break;
+ case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
+ reason = " reason=FREQ_CONFLICT";
+ break;
default:
reason = "";
break;
@@ -436,6 +441,8 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
wpa_s->ifname, gtype, reason);
}
+ if (eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL) > 0)
+ wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group freq_conflict timeout");
if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
@@ -6535,6 +6542,56 @@ static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx)
wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_PSK_FAILURE);
}
+static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "P2P: Frequency conflict - terminate group");
+ wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FREQ_CONFLICT);
+}
+
+int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq,
+ struct wpa_ssid *ssid)
+{
+ struct wpa_supplicant *iface = NULL;
+
+ for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+ if ((iface->current_ssid) &&
+ (iface->current_ssid->frequency != freq) &&
+ ((iface->p2p_group_interface) ||
+ (iface->current_ssid->p2p_group))) {
+
+ /* Remove the connection with least priority */
+ if(!wpas_is_p2p_prioritized(iface)) {
+ /* 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");
+ eloop_register_timeout(0, 0, wpas_p2p_group_freq_conflict,
+ iface, NULL);
+ /* If connection in progress is p2p connection, do not
+ * proceed for the connection
+ */
+ if (wpa_s == iface)
+ return -1;
+ else
+ return 0;
+ } else {
+ /* P2p connection has priority, disable the STA network*/
+ wpa_supplicant_disable_network(wpa_s->global->ifaces, ssid);
+ wpa_msg(wpa_s->global->ifaces, MSG_INFO, WPA_EVENT_FREQ_CONFLICT
+ " id=%d", ssid->id);
+ os_memset(wpa_s->global->ifaces->pending_bssid, 0, ETH_ALEN);
+ /* If p2p connection is in progress, continue connecting...*/
+ if (wpa_s == iface)
+ return 0;
+ else
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
{
@@ -29,6 +29,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, struct wpa_ssid *ssid);
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, int ht40, int vht);
@@ -1294,6 +1294,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
struct ieee80211_ht_capabilities htcaps;
struct ieee80211_ht_capabilities htcaps_mask;
#endif /* CONFIG_HT_OVERRIDES */
+ int freq;
#ifdef CONFIG_IBSS_RSN
ibss_rsn_deinit(wpa_s->ibss_rsn);
@@ -1647,6 +1648,18 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms);
#endif /* CONFIG_HT_OVERRIDES */
+ /* If multi-channel concurrency is not supported, check for any
+ * frequency conflict. In case of any frequency conflict remove the
+ * least prioritized connection
+ */
+ if ((wpa_s->num_multichan_concurrent < 2) &&
+ ((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);
+ if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0)
+ return;
+ }
+
ret = wpa_drv_associate(wpa_s, ¶ms);
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "