P2P: Fix radio work issue with wait-for-peer GO Negotiation

If a TX status event and RX event for a GO Negotiation frame gets
delayed long enough to miss the initial wait, it was possible for
reception of a GO Negotiation Response frame with status 1 to try to
initiate a new p2p-listen work item to wait for the peer to become ready
while a previous p2p-listen was already in progress due to that earlier
timeout while waiting for peer. This would result in the new
start_listen request getting rejected ("P2P: Reject start_listen since
p2p_listen_work already exists") and the negotiation not proceeding.

Work around this by using P2P_WAIT_PEER_CONNECT state instead of
P2P_WAIT_PEER_IDLE if P2P_CONNECT_LISTEN state has already been entered
when processing this special GO Negotiation Response status=1 case. This
can avoid double-scheduling of p2p-listen and as such, completion of the
GO negotiation even if the driver event or peer response are not
received in time (the response is supposed to be there within 100 ms per
spec, but there are number of deployed devices that do not really meet
this requirement).

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2014-09-09 17:20:23 +03:00 committed by Jouni Malinen
parent 76db5b6b12
commit 17e2091279
1 changed files with 4 additions and 1 deletions

View File

@ -958,7 +958,10 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
p2p_dbg(p2p, "Wait for the peer to become ready for GO Negotiation");
dev->flags |= P2P_DEV_NOT_YET_READY;
os_get_reltime(&dev->go_neg_wait_started);
p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
if (p2p->state == P2P_CONNECT_LISTEN)
p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
else
p2p_set_state(p2p, P2P_WAIT_PEER_IDLE);
p2p_set_timeout(p2p, 0, 0);
} else {
p2p_dbg(p2p, "Stop GO Negotiation attempt");