P2P: Wait until ongoing scan completes before starting P2P find
The P2P_FIND command was failing if it was issued at the moment when a scan operation was in progress. Avoid returning failure in this case by scheduling the P2P find to start once the ongoing scan is completed. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
		
							parent
							
								
									545cfc4bf3
								
							
						
					
					
						commit
						39185dfa54
					
				
					 6 changed files with 61 additions and 1 deletions
				
			
		|  | @ -106,6 +106,8 @@ static const char * p2p_state_txt(int state) | ||||||
| 		return "INVITE"; | 		return "INVITE"; | ||||||
| 	case P2P_INVITE_LISTEN: | 	case P2P_INVITE_LISTEN: | ||||||
| 		return "INVITE_LISTEN"; | 		return "INVITE_LISTEN"; | ||||||
|  | 	case P2P_SEARCH_WHEN_READY: | ||||||
|  | 		return "SEARCH_WHEN_READY"; | ||||||
| 	default: | 	default: | ||||||
| 		return "?"; | 		return "?"; | ||||||
| 	} | 	} | ||||||
|  | @ -878,6 +880,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, | ||||||
| 	p2p_device_clear_reported(p2p); | 	p2p_device_clear_reported(p2p); | ||||||
| 	p2p_set_state(p2p, P2P_SEARCH); | 	p2p_set_state(p2p, P2P_SEARCH); | ||||||
| 	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); | 	eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); | ||||||
|  | 	p2p->last_p2p_find_timeout = timeout; | ||||||
| 	if (timeout) | 	if (timeout) | ||||||
| 		eloop_register_timeout(timeout, 0, p2p_find_timeout, | 		eloop_register_timeout(timeout, 0, p2p_find_timeout, | ||||||
| 				       p2p, NULL); | 				       p2p, NULL); | ||||||
|  | @ -903,6 +906,13 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, | ||||||
| 		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL); | 		eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL); | ||||||
| 		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout, | 		eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout, | ||||||
| 				       p2p, NULL); | 				       p2p, NULL); | ||||||
|  | 	} else if (res == 1) { | ||||||
|  | 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Could not start " | ||||||
|  | 			"p2p_scan at this point - will try again after " | ||||||
|  | 			"previous scan completes"); | ||||||
|  | 		res = 0; | ||||||
|  | 		p2p_set_state(p2p, P2P_SEARCH_WHEN_READY); | ||||||
|  | 		eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); | ||||||
| 	} else { | 	} else { | ||||||
| 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start " | 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start " | ||||||
| 			"p2p_scan"); | 			"p2p_scan"); | ||||||
|  | @ -914,6 +924,19 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | int p2p_other_scan_completed(struct p2p_data *p2p) | ||||||
|  | { | ||||||
|  | 	if (p2p->state != P2P_SEARCH_WHEN_READY) | ||||||
|  | 		return 0; | ||||||
|  | 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find " | ||||||
|  | 		"now that previous scan was completed"); | ||||||
|  | 	if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type, | ||||||
|  | 		     p2p->num_req_dev_types, p2p->req_dev_types) < 0) | ||||||
|  | 		return 0; | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) | void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) | ||||||
| { | { | ||||||
| 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find"); | 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find"); | ||||||
|  | @ -2947,6 +2970,8 @@ static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx) | ||||||
| 	case P2P_INVITE_LISTEN: | 	case P2P_INVITE_LISTEN: | ||||||
| 		p2p_timeout_invite_listen(p2p); | 		p2p_timeout_invite_listen(p2p); | ||||||
| 		break; | 		break; | ||||||
|  | 	case P2P_SEARCH_WHEN_READY: | ||||||
|  | 		break; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1542,4 +1542,11 @@ int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel, | ||||||
|  */ |  */ | ||||||
| int p2p_in_progress(struct p2p_data *p2p); | int p2p_in_progress(struct p2p_data *p2p); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * p2p_other_scan_completed - Notify completion of non-P2P scan | ||||||
|  |  * @p2p: P2P module context from p2p_init() | ||||||
|  |  * Returns: 0 if P2P module is idle or 1 if an operation was started | ||||||
|  |  */ | ||||||
|  | int p2p_other_scan_completed(struct p2p_data *p2p); | ||||||
|  | 
 | ||||||
| #endif /* P2P_H */ | #endif /* P2P_H */ | ||||||
|  |  | ||||||
|  | @ -201,6 +201,11 @@ struct p2p_data { | ||||||
| 		 * P2P_INVITE_LISTEN - Listen during Invite | 		 * P2P_INVITE_LISTEN - Listen during Invite | ||||||
| 		 */ | 		 */ | ||||||
| 		P2P_INVITE_LISTEN, | 		P2P_INVITE_LISTEN, | ||||||
|  | 
 | ||||||
|  | 		/**
 | ||||||
|  | 		 * P2P_SEARCH_WHEN_READY - Waiting to start Search | ||||||
|  | 		 */ | ||||||
|  | 		P2P_SEARCH_WHEN_READY, | ||||||
| 	} state; | 	} state; | ||||||
| 
 | 
 | ||||||
| 	/**
 | 	/**
 | ||||||
|  | @ -355,6 +360,7 @@ struct p2p_data { | ||||||
| 	int inv_persistent; | 	int inv_persistent; | ||||||
| 
 | 
 | ||||||
| 	enum p2p_discovery_type find_type; | 	enum p2p_discovery_type find_type; | ||||||
|  | 	unsigned int last_p2p_find_timeout; | ||||||
| 	u8 last_prog_scan_class; | 	u8 last_prog_scan_class; | ||||||
| 	u8 last_prog_scan_chan; | 	u8 last_prog_scan_chan; | ||||||
| 	int p2p_scan_running; | 	int p2p_scan_running; | ||||||
|  |  | ||||||
|  | @ -1009,6 +1009,18 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, | ||||||
| 
 | 
 | ||||||
| 	wpa_supplicant_notify_scanning(wpa_s, 0); | 	wpa_supplicant_notify_scanning(wpa_s, 0); | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_P2P | ||||||
|  | 	if (wpa_s->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled && | ||||||
|  | 	    wpa_s->global->p2p != NULL) { | ||||||
|  | 		wpa_s->p2p_cb_on_scan_complete = 0; | ||||||
|  | 		if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) { | ||||||
|  | 			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation " | ||||||
|  | 				"stopped scan processing"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | #endif /* CONFIG_P2P */ | ||||||
|  | 
 | ||||||
| 	scan_res = wpa_supplicant_get_scan_results(wpa_s, | 	scan_res = wpa_supplicant_get_scan_results(wpa_s, | ||||||
| 						   data ? &data->scan_info : | 						   data ? &data->scan_info : | ||||||
| 						   NULL, 1); | 						   NULL, 1); | ||||||
|  |  | ||||||
|  | @ -94,6 +94,7 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, | ||||||
| 	struct wpabuf *wps_ie, *ies; | 	struct wpabuf *wps_ie, *ies; | ||||||
| 	int social_channels[] = { 2412, 2437, 2462, 0, 0 }; | 	int social_channels[] = { 2412, 2437, 2462, 0, 0 }; | ||||||
| 	size_t ielen; | 	size_t ielen; | ||||||
|  | 	int was_in_p2p_scan; | ||||||
| 
 | 
 | ||||||
| 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) | 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) | ||||||
| 		return -1; | 		return -1; | ||||||
|  | @ -144,13 +145,19 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	was_in_p2p_scan = wpa_s->scan_res_handler == wpas_p2p_scan_res_handler; | ||||||
| 	wpa_s->scan_res_handler = wpas_p2p_scan_res_handler; | 	wpa_s->scan_res_handler = wpas_p2p_scan_res_handler; | ||||||
| 	ret = wpa_drv_scan(wpa_s, ¶ms); | 	ret = wpa_drv_scan(wpa_s, ¶ms); | ||||||
| 
 | 
 | ||||||
| 	wpabuf_free(ies); | 	wpabuf_free(ies); | ||||||
| 
 | 
 | ||||||
| 	if (ret < 0) | 	if (ret) { | ||||||
| 		wpa_s->scan_res_handler = NULL; | 		wpa_s->scan_res_handler = NULL; | ||||||
|  | 		if (wpa_s->scanning || was_in_p2p_scan) { | ||||||
|  | 			wpa_s->p2p_cb_on_scan_complete = 1; | ||||||
|  | 			ret = 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | @ -3351,6 +3358,7 @@ void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s) | ||||||
| 	wpa_s->p2p_long_listen = 0; | 	wpa_s->p2p_long_listen = 0; | ||||||
| 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); | 	eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); | ||||||
| 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); | 	eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); | ||||||
|  | 	wpa_s->p2p_cb_on_scan_complete = 0; | ||||||
| 
 | 
 | ||||||
| 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) { | 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) { | ||||||
| 		wpa_drv_p2p_stop_find(wpa_s); | 		wpa_drv_p2p_stop_find(wpa_s); | ||||||
|  |  | ||||||
|  | @ -476,6 +476,8 @@ struct wpa_supplicant { | ||||||
| 		P2P_GROUP_REMOVAL_IDLE_TIMEOUT, | 		P2P_GROUP_REMOVAL_IDLE_TIMEOUT, | ||||||
| 		P2P_GROUP_REMOVAL_UNAVAILABLE | 		P2P_GROUP_REMOVAL_UNAVAILABLE | ||||||
| 	} removal_reason; | 	} removal_reason; | ||||||
|  | 
 | ||||||
|  | 	unsigned int p2p_cb_on_scan_complete:1; | ||||||
| #endif /* CONFIG_P2P */ | #endif /* CONFIG_P2P */ | ||||||
| 
 | 
 | ||||||
| 	struct wpa_ssid *bgscan_ssid; | 	struct wpa_ssid *bgscan_ssid; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Jouni Malinen
						Jouni Malinen