diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 1dbdf6d1c..d38e9c59d 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -4202,6 +4202,14 @@ void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5, } +void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq) +{ + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own frequency preference: " + "%d MHz", freq); + p2p->own_freq_preference = freq; +} + + const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p) { if (p2p == NULL || p2p->go_neg_peer == NULL) diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index ae96b6e51..eb57a3a51 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1641,6 +1641,17 @@ void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan); void p2p_set_best_channels(struct p2p_data *p2p, int freq_24, int freq_5, int freq_overall); +/** + * p2p_set_own_freq_preference - Set own preference for channel + * @p2p: P2P module context from p2p_init() + * @freq: Frequency (MHz) of the preferred channel or 0 if no preference + * + * This function can be used to set a preference on the operating channel based + * on frequencies used on the other virtual interfaces that share the same + * radio. If non-zero, this is used to try to avoid multi-channel concurrency. + */ +void p2p_set_own_freq_preference(struct p2p_data *p2p, int freq); + const u8 * p2p_get_go_neg_peer(struct p2p_data *p2p); /** diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index 8a86c5442..805bf6934 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -350,6 +350,18 @@ void p2p_reselect_channel(struct p2p_data *p2p, u8 op_reg_class, op_channel; unsigned int i; + if (p2p->own_freq_preference > 0 && + p2p_freq_to_channel(p2p->cfg->country, p2p->own_freq_preference, + &op_reg_class, &op_channel) == 0 && + p2p_channels_includes(intersection, op_reg_class, op_channel)) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Pick own channel " + "preference (reg_class %u channel %u) from " + "intersection", op_reg_class, op_channel); + p2p->op_reg_class = op_reg_class; + p2p->op_channel = op_channel; + return; + } + if (p2p->best_freq_overall > 0 && p2p_freq_to_channel(p2p->cfg->country, p2p->best_freq_overall, &op_reg_class, &op_channel) == 0 && diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index c753d4939..dff226ada 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -417,6 +417,7 @@ struct p2p_data { int best_freq_24; int best_freq_5; int best_freq_overall; + int own_freq_preference; /** * wps_vendor_ext - WPS Vendor Extensions to add diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index e016f8202..3a06406e9 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -93,6 +93,15 @@ static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s, static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s); +static void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s, + int freq) +{ + if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) + return; + p2p_set_own_freq_preference(wpa_s->global->p2p, freq); +} + + static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res) { @@ -2410,11 +2419,14 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid, } accept_inv: + wpas_p2p_set_own_freq_preference(wpa_s, 0); + if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, cur_bssid) == 0 && wpa_s->assoc_freq) { wpa_printf(MSG_DEBUG, "P2P: Trying to force channel to match " "the channel we are already using"); *force_freq = wpa_s->assoc_freq; + wpas_p2p_set_own_freq_preference(wpa_s, wpa_s->assoc_freq); } res = wpa_drv_shared_freq(wpa_s); @@ -2423,6 +2435,7 @@ accept_inv: "with the channel we are already using on a " "shared interface"); *force_freq = res; + wpas_p2p_set_own_freq_preference(wpa_s, res); } return P2P_SC_SUCCESS; @@ -3736,6 +3749,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, &oper_freq); if (res) return res; + wpas_p2p_set_own_freq_preference(wpa_s, oper_freq); wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s); @@ -4807,6 +4821,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, &oper_freq); if (res) return res; + wpas_p2p_set_own_freq_preference(wpa_s, oper_freq); return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid, ssid->ssid, ssid->ssid_len, force_freq,