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>
This commit is contained in:
Jouni Malinen 2012-02-27 17:23:41 +02:00 committed by Jouni Malinen
parent e62f4ed0df
commit 1a9c618d3f
4 changed files with 15 additions and 0 deletions

View file

@ -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()

View file

@ -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 */

View file

@ -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);

View file

@ -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,