diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 4bbd1bcca..157bf891c 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1076,7 +1076,7 @@ static int p2p_run_after_scan(struct p2p_data *p2p) p2p->after_scan_tx->bssid, (u8 *) (p2p->after_scan_tx + 1), p2p->after_scan_tx->len, - p2p->after_scan_tx->wait_time); + p2p->after_scan_tx->wait_time, NULL); os_free(p2p->after_scan_tx); p2p->after_scan_tx = NULL; return 1; @@ -4973,6 +4973,8 @@ int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, size_t len, unsigned int wait_time) { + int res, scheduled; + if (p2p->p2p_scan_running) { p2p_dbg(p2p, "Delay Action frame TX until p2p_scan completes"); if (p2p->after_scan_tx) { @@ -4993,8 +4995,16 @@ int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst, return 0; } - return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid, - buf, len, wait_time); + res = p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid, + buf, len, wait_time, &scheduled); + if (res == 0 && scheduled && p2p->in_listen && freq > 0 && + (unsigned int) p2p->drv_in_listen != freq) { + p2p_dbg(p2p, + "Stop listen on %d MHz to allow a frame to be sent immediately on %d MHz", + p2p->drv_in_listen, freq); + p2p_stop_listen_for_freq(p2p, freq); + } + return res; } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index f2969ee13..425b037be 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -665,6 +665,8 @@ struct p2p_config { * @buf: Frame body (starting from Category field) * @len: Length of buf in octets * @wait_time: How many msec to wait for a response frame + * @scheduled: Return value indicating whether the transmissions was + * scheduled to happen once the radio is available * Returns: 0 on success, -1 on failure * * The Action frame may not be transmitted immediately and the status @@ -675,7 +677,7 @@ struct p2p_config { */ int (*send_action)(void *ctx, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time); + size_t len, unsigned int wait_time, int *scheduled); /** * send_action_done - Notify that Action frame sequence was completed diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index 16c28a0d9..aa18af6c1 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -941,7 +941,8 @@ int p2p_group_go_discover(struct p2p_group *group, const u8 *dev_id, if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, m->addr, group->cfg->interface_addr, group->cfg->interface_addr, - wpabuf_head(req), wpabuf_len(req), 200) < 0) + wpabuf_head(req), wpabuf_len(req), 200, NULL) + < 0) { p2p_dbg(p2p, "Failed to send Action frame"); } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index e265128b7..18fd02c3e 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1584,20 +1584,27 @@ static int wpas_send_action_work(struct wpa_supplicant *wpa_s, static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time) + size_t len, unsigned int wait_time, int *scheduled) { struct wpa_supplicant *wpa_s = ctx; int listen_freq = -1, send_freq = -1; + if (scheduled) + *scheduled = 0; if (wpa_s->p2p_listen_work) listen_freq = wpa_s->p2p_listen_work->freq; if (wpa_s->p2p_send_action_work) send_freq = wpa_s->p2p_send_action_work->freq; if (listen_freq != (int) freq && send_freq != (int) freq) { - wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d)", - listen_freq, send_freq); - return wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf, - len, wait_time); + int res; + + wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d freq=%u)", + listen_freq, send_freq, freq); + res = wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf, + len, wait_time); + if (res == 0 && scheduled) + *scheduled = 1; + return res; } wpa_printf(MSG_DEBUG, "P2P: Use ongoing radio work for Action frame TX");