Browse Source

P2P: Fix remain-on-channel use with PD/Invitation Request while in Listen

If Listen state was in progress on another channel when a request to
send an Action frame (e.g., Provision Discovery Request or Invitation
Request to a peer on the peer's Listen channel that is different from
our Listenc hannel) is issued, wpa_supplicant tried to use concurrent
remain-on-channel operations. While some drivers can handle this
cleanly, there are drivers that don't and wpa_supplicant is not expected
to request concurrent remain-on-channel operations.

Fix this by cancelling the ongoing remain-on-channel with stop_listen
prior to sending the Action frame on another channel. If a P2P search
was in progress, it will be continued after the timeout on the new
operation.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 13 years ago
parent
commit
1a9c618d3f
4 changed files with 15 additions and 0 deletions
  1. 10 0
      src/p2p/p2p.c
  2. 1 0
      src/p2p/p2p_i.h
  3. 2 0
      src/p2p/p2p_invitation.c
  4. 2 0
      src/p2p/p2p_pd.c

+ 10 - 0
src/p2p/p2p.c

@@ -1024,11 +1024,21 @@ void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
 	p2p->go_neg_peer = NULL;
 	p2p->sd_peer = NULL;
 	p2p->invite_peer = NULL;
+	p2p_stop_listen_for_freq(p2p, freq);
+}
+
+
+void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq)
+{
 	if (freq > 0 && p2p->drv_in_listen == freq && p2p->in_listen) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip stop_listen "
 			"since we are on correct channel for response");
 		return;
 	}
+	if (p2p->in_listen) {
+		p2p->in_listen = 0;
+		p2p_clear_timeout(p2p);
+	}
 	if (p2p->drv_in_listen) {
 		/*
 		 * The driver may not deliver callback to p2p_listen_end()

+ 1 - 0
src/p2p/p2p_i.h

@@ -667,5 +667,6 @@ void p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len);
 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);
+void p2p_stop_listen_for_freq(struct p2p_data *p2p, int freq);
 
 #endif /* P2P_I_H */

+ 2 - 0
src/p2p/p2p_invitation.c

@@ -344,6 +344,8 @@ int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
 	req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
 	if (req == NULL)
 		return -1;
+	if (p2p->state != P2P_IDLE)
+		p2p_stop_listen_for_freq(p2p, freq);
 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 		"P2P: Sending Invitation Request");
 	p2p_set_state(p2p, P2P_INVITE);

+ 2 - 0
src/p2p/p2p_pd.c

@@ -316,6 +316,8 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
 	if (req == NULL)
 		return -1;
 
+	if (p2p->state != P2P_IDLE)
+		p2p_stop_listen_for_freq(p2p, freq);
 	p2p->pending_action_state = P2P_PENDING_PD;
 	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
 			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,