diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 3f533ce82..e802489ed 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5761,7 +5761,7 @@ static int p2p_ctrl_disallow_freq(struct wpa_supplicant *wpa_s, freq->min, freq->max); } - wpas_p2p_update_channel_list(wpa_s); + wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW); return 0; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 8b468101e..829cd3f33 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3015,7 +3015,7 @@ static void wpa_supplicant_update_channel_list( wpa_supplicant_req_scan(wpa_s, 0, 0); } - wpas_p2p_update_channel_list(wpa_s); + wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DRIVER); } @@ -3154,7 +3154,8 @@ static void wpa_supplicant_notify_avoid_freq(struct wpa_supplicant *wpa_s, * The update channel flow will also take care of moving a GO * from the unsafe frequency if needed. */ - wpas_p2p_update_channel_list(wpa_s); + wpas_p2p_update_channel_list(wpa_s, + WPAS_P2P_CHANNEL_UPDATE_AVOID); } #endif /* CONFIG_P2P */ diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 0ac7690e8..e849b91bf 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -146,9 +146,10 @@ static void wpas_p2p_optimize_listen_channel(struct wpa_supplicant *wpa_s, unsigned int num); static void wpas_p2p_move_go(void *eloop_ctx, void *timeout_ctx); static int wpas_p2p_go_is_peer_freq(struct wpa_supplicant *wpa_s, int freq); -static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s, - struct wpa_used_freq_data *freqs, - unsigned int num); +static void +wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s, + struct wpa_used_freq_data *freqs, unsigned int num, + enum wpas_p2p_channel_update_trig trig); static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx); @@ -7076,7 +7077,8 @@ void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx) } -void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s) +void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s, + enum wpas_p2p_channel_update_trig trig) { struct p2p_channels chan, cli_chan; struct wpa_used_freq_data *freqs = NULL; @@ -7109,7 +7111,7 @@ void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s) * possible that due to policy consideration, it would be preferable to * move it to a frequency already used by other station interfaces. */ - wpas_p2p_consider_moving_gos(wpa_s, freqs, num); + wpas_p2p_consider_moving_gos(wpa_s, freqs, num, trig); os_free(freqs); } @@ -8490,7 +8492,8 @@ static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx) num = get_shared_radio_freqs_data(wpa_s, freqs, num); /* Previous attempt to move a GO was not possible -- try again. */ - wpas_p2p_consider_moving_gos(wpa_s, freqs, num); + wpas_p2p_consider_moving_gos(wpa_s, freqs, num, + WPAS_P2P_CHANNEL_UPDATE_ANY); os_free(freqs); } @@ -8591,7 +8594,8 @@ static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s, static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s, struct wpa_used_freq_data *freqs, - unsigned int num) + unsigned int num, + enum wpas_p2p_channel_update_trig trig) { struct wpa_supplicant *ifs; @@ -8609,6 +8613,21 @@ static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s, ifs->current_ssid->mode != WPAS_MODE_P2P_GO) continue; + /* + * The GO was just started or completed channel switch, no need + * to move it. + */ + if (wpa_s == ifs && + (trig == WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE || + trig == WPAS_P2P_CHANNEL_UPDATE_CS)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: GO move - schedule re-consideration"); + eloop_register_timeout(P2P_RECONSIDER_GO_MOVE_DELAY, 0, + wpas_p2p_reconsider_moving_go, + wpa_s, NULL); + continue; + } + wpas_p2p_consider_moving_one_go(ifs, freqs, num); } } @@ -8619,7 +8638,8 @@ void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s) if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return; - wpas_p2p_update_channel_list(wpa_s); + wpas_p2p_update_channel_list(wpa_s, + WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE); } diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index b02f92421..f622c2849 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -17,6 +17,15 @@ struct p2p_channels; struct wps_event_fail; struct p2ps_provision; +enum wpas_p2p_channel_update_trig { + WPAS_P2P_CHANNEL_UPDATE_ANY, + WPAS_P2P_CHANNEL_UPDATE_DRIVER, + WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE, + WPAS_P2P_CHANNEL_UPDATE_AVOID, + WPAS_P2P_CHANNEL_UPDATE_DISALLOW, + WPAS_P2P_CHANNEL_UPDATE_CS, +}; + int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s, const char *conf_p2p_dev); struct wpa_supplicant * wpas_get_p2p_go_iface(struct wpa_supplicant *wpa_s, @@ -161,7 +170,10 @@ int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr, unsigned int rx_freq, int ssi_signal); void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int registrar); -void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s); + +void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s, + enum wpas_p2p_channel_update_trig trig); + void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s, int freq_24, int freq_5, int freq_overall); void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da, @@ -222,7 +234,9 @@ static inline void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, { } -static inline void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s) +static inline void +wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s, + enum wpas_p2p_channel_update_trig trig) { }