[PATCH] P2P: Clear pending_listen_freq when radio work is cancelled or stale
Arowa Suliman
arowa at chromium.org
Mon Aug 24 15:02:41 PDT 2026
When a P2P listen radio work is deinitialized before starting (e.g.,
preempted by a scan or stopped during provision discovery),
pending_listen_freq was not cleared in wpa_supplicant and the P2P core.
This left the state machine with a phantom pending listen state, causing
subsequent listen operations to be rejected and stalling the event loop.
Fix this by:
1. Clearing pending_listen_freq and notifying the P2P core in
wpas_start_listen_cb() on deinit and in wpas_stop_listen().
2. Clearing stale pending_listen_freq in p2p_listen_in_find() and
p2p_listen() if the driver is not actively in listen mode, or
scheduling a fallback timeout/stopping ongoing listen if busy.
3. Adding p2p_cancel_pending_listen() helper to clear pending_listen_freq
in struct p2p_data.
Signed-off-by: Arowa Suliman <arowa at chromium.org>
---
src/p2p/p2p.c | 34 +++++++++++++++++++++++++++------
src/p2p/p2p.h | 1 +
wpa_supplicant/p2p_supplicant.c | 6 ++++++
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 09ed2fe0f..56b09b4b3 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -272,9 +272,16 @@ static void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
p2p_state_txt(p2p->state));
if (p2p->pending_listen_freq) {
- /* We have a pending p2p_listen request */
- p2p_dbg(p2p, "p2p_listen command pending already");
- return;
+ if (!p2p->drv_in_listen) {
+ p2p_dbg(p2p, "Clear stale pending_listen_freq (%u)",
+ p2p->pending_listen_freq);
+ p2p->pending_listen_freq = 0;
+ } else {
+ /* We have an active driver listen in flight - retry after short delay */
+ p2p_dbg(p2p, "p2p_listen command pending already - retry after short delay");
+ p2p_set_timeout(p2p, 0, 100000);
+ return;
+ }
}
freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
@@ -327,9 +334,14 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout)
p2p_dbg(p2p, "Going to listen(only) state");
if (p2p->pending_listen_freq) {
- /* We have a pending p2p_listen request */
- p2p_dbg(p2p, "p2p_listen command pending already");
- return -1;
+ if (!p2p->drv_in_listen) {
+ p2p_dbg(p2p, "Clear stale pending_listen_freq (%u) for p2p_listen",
+ p2p->pending_listen_freq);
+ p2p->pending_listen_freq = 0;
+ } else {
+ p2p_dbg(p2p, "p2p_listen command pending already - stop ongoing listen first");
+ p2p_stop_listen_for_freq(p2p, 0);
+ }
}
freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel);
@@ -1418,6 +1430,16 @@ void p2p_stop_listen(struct p2p_data *p2p)
}
+void p2p_cancel_pending_listen(struct p2p_data *p2p)
+{
+ if (p2p && p2p->pending_listen_freq) {
+ p2p_dbg(p2p, "Clear pending_listen_freq (%u) for p2p_cancel_pending_listen",
+ p2p->pending_listen_freq);
+ p2p->pending_listen_freq = 0;
+ }
+}
+
+
void p2p_stop_find(struct p2p_data *p2p)
{
p2p->pending_listen_freq = 0;
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 7c89c8c35..0d1b81a18 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1606,6 +1606,7 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout);
* @p2p: P2P module context from p2p_init()
*/
void p2p_stop_listen(struct p2p_data *p2p);
+void p2p_cancel_pending_listen(struct p2p_data *p2p);
/**
* p2p_connect - Start P2P group formation (GO negotiation)
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index e5d4afe3c..f9d893528 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -3235,6 +3235,9 @@ static void wpas_start_listen_cb(struct wpa_radio_work *work, int deinit)
unsigned int duration;
if (deinit) {
+ wpa_s->pending_listen_freq = 0;
+ if (wpa_s->global->p2p)
+ p2p_cancel_pending_listen(wpa_s->global->p2p);
if (work->started && !wpa_s->p2p_removing_listen_work)
wpas_stop_started_listen_work(work);
wpas_p2p_listen_work_free(lwork);
@@ -3341,6 +3344,9 @@ static void wpas_stop_listen(void *ctx)
radio_remove_works(wpa_s, "p2p-listen", 0);
wpa_s->p2p_removing_listen_work = false;
}
+ wpa_s->pending_listen_freq = 0;
+ if (wpa_s->global->p2p)
+ p2p_cancel_pending_listen(wpa_s->global->p2p);
}
--
2.55.0.860.g4b6b3295ed-goog
More information about the Hostap
mailing list