diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/p2p.c')
| -rw-r--r-- | drivers/net/wireless/ath/wil6210/p2p.c | 160 | 
1 files changed, 118 insertions, 42 deletions
| diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index 4087785d3090..fbae99525e01 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -22,6 +22,43 @@  #define P2P_SEARCH_DURATION_MS 500  #define P2P_DEFAULT_BI 100 +static int wil_p2p_start_listen(struct wil6210_priv *wil) +{ +	struct wil_p2p_info *p2p = &wil->p2p; +	u8 channel = p2p->listen_chan.hw_value; +	int rc; + +	lockdep_assert_held(&wil->mutex); + +	rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI); +	if (rc) { +		wil_err(wil, "wmi_p2p_cfg failed\n"); +		goto out; +	} + +	rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); +	if (rc) { +		wil_err(wil, "wmi_set_ssid failed\n"); +		goto out_stop; +	} + +	rc = wmi_start_listen(wil); +	if (rc) { +		wil_err(wil, "wmi_start_listen failed\n"); +		goto out_stop; +	} + +	INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired); +	mod_timer(&p2p->discovery_timer, +		  jiffies + msecs_to_jiffies(p2p->listen_duration)); +out_stop: +	if (rc) +		wmi_stop_discovery(wil); + +out: +	return rc; +} +  bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request)  {  	return (request->n_channels == 1) && @@ -46,7 +83,7 @@ int wil_p2p_search(struct wil6210_priv *wil,  	wil_dbg_misc(wil, "%s: channel %d\n",  		     __func__, P2P_DMG_SOCIAL_CHANNEL); -	mutex_lock(&wil->mutex); +	lockdep_assert_held(&wil->mutex);  	if (p2p->discovery_started) {  		wil_err(wil, "%s: search failed. discovery already ongoing\n", @@ -103,22 +140,19 @@ out_stop:  		wmi_stop_discovery(wil);  out: -	mutex_unlock(&wil->mutex);  	return rc;  } -int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration, -		   struct ieee80211_channel *chan, u64 *cookie) +int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, +		   unsigned int duration, struct ieee80211_channel *chan, +		   u64 *cookie)  {  	struct wil_p2p_info *p2p = &wil->p2p; -	u8 channel = P2P_DMG_SOCIAL_CHANNEL;  	int rc;  	if (!chan)  		return -EINVAL; -	channel = chan->hw_value; -  	wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration);  	mutex_lock(&wil->mutex); @@ -129,35 +163,30 @@ int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration,  		goto out;  	} -	rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI); -	if (rc) { -		wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__); -		goto out; -	} - -	rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); -	if (rc) { -		wil_err(wil, "%s: wmi_set_ssid failed\n", __func__); -		goto out_stop; -	} +	memcpy(&p2p->listen_chan, chan, sizeof(*chan)); +	*cookie = ++p2p->cookie; +	p2p->listen_duration = duration; -	rc = wmi_start_listen(wil); -	if (rc) { -		wil_err(wil, "%s: wmi_start_listen failed\n", __func__); -		goto out_stop; +	mutex_lock(&wil->p2p_wdev_mutex); +	if (wil->scan_request) { +		wil_dbg_misc(wil, "Delaying p2p listen until scan done\n"); +		p2p->pending_listen_wdev = wdev; +		p2p->discovery_started = 1; +		rc = 0; +		mutex_unlock(&wil->p2p_wdev_mutex); +		goto out;  	} +	mutex_unlock(&wil->p2p_wdev_mutex); -	memcpy(&p2p->listen_chan, chan, sizeof(*chan)); -	*cookie = ++p2p->cookie; +	rc = wil_p2p_start_listen(wil); +	if (rc) +		goto out;  	p2p->discovery_started = 1; -	INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired); -	mod_timer(&p2p->discovery_timer, -		  jiffies + msecs_to_jiffies(duration)); +	wil->radio_wdev = wdev; -out_stop: -	if (rc) -		wmi_stop_discovery(wil); +	cfg80211_ready_on_channel(wdev, *cookie, chan, duration, +				  GFP_KERNEL);  out:  	mutex_unlock(&wil->mutex); @@ -170,9 +199,14 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)  	u8 started = p2p->discovery_started;  	if (p2p->discovery_started) { -		del_timer_sync(&p2p->discovery_timer); +		if (p2p->pending_listen_wdev) { +			/* discovery not really started, only pending */ +			p2p->pending_listen_wdev = NULL; +		} else { +			del_timer_sync(&p2p->discovery_timer); +			wmi_stop_discovery(wil); +		}  		p2p->discovery_started = 0; -		wmi_stop_discovery(wil);  	}  	return started; @@ -257,13 +291,59 @@ void wil_p2p_search_expired(struct work_struct *work)  		};  		mutex_lock(&wil->p2p_wdev_mutex); -		cfg80211_scan_done(wil->scan_request, &info); -		wil->scan_request = NULL; -		wil->radio_wdev = wil->wdev; +		if (wil->scan_request) { +			cfg80211_scan_done(wil->scan_request, &info); +			wil->scan_request = NULL; +			wil->radio_wdev = wil->wdev; +		}  		mutex_unlock(&wil->p2p_wdev_mutex);  	}  } +void wil_p2p_delayed_listen_work(struct work_struct *work) +{ +	struct wil_p2p_info *p2p = container_of(work, +			struct wil_p2p_info, delayed_listen_work); +	struct wil6210_priv *wil = container_of(p2p, +			struct wil6210_priv, p2p); +	int rc; + +	mutex_lock(&wil->mutex); + +	wil_dbg_misc(wil, "Checking delayed p2p listen\n"); +	if (!p2p->discovery_started || !p2p->pending_listen_wdev) +		goto out; + +	mutex_lock(&wil->p2p_wdev_mutex); +	if (wil->scan_request) { +		/* another scan started, wait again... */ +		mutex_unlock(&wil->p2p_wdev_mutex); +		goto out; +	} +	mutex_unlock(&wil->p2p_wdev_mutex); + +	rc = wil_p2p_start_listen(wil); + +	mutex_lock(&wil->p2p_wdev_mutex); +	if (rc) { +		cfg80211_remain_on_channel_expired(p2p->pending_listen_wdev, +						   p2p->cookie, +						   &p2p->listen_chan, +						   GFP_KERNEL); +		wil->radio_wdev = wil->wdev; +	} else { +		cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie, +					  &p2p->listen_chan, +					  p2p->listen_duration, GFP_KERNEL); +		wil->radio_wdev = p2p->pending_listen_wdev; +	} +	p2p->pending_listen_wdev = NULL; +	mutex_unlock(&wil->p2p_wdev_mutex); + +out: +	mutex_unlock(&wil->mutex); +} +  void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)  {  	struct wil_p2p_info *p2p = &wil->p2p; @@ -272,8 +352,7 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)  	};  	lockdep_assert_held(&wil->mutex); - -	mutex_lock(&wil->p2p_wdev_mutex); +	lockdep_assert_held(&wil->p2p_wdev_mutex);  	if (wil->radio_wdev != wil->p2p_wdev)  		goto out; @@ -281,10 +360,8 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)  	if (!p2p->discovery_started) {  		/* Regular scan on the p2p device */  		if (wil->scan_request && -		    wil->scan_request->wdev == wil->p2p_wdev) { -			cfg80211_scan_done(wil->scan_request, &info); -			wil->scan_request = NULL; -		} +		    wil->scan_request->wdev == wil->p2p_wdev) +			wil_abort_scan(wil, true);  		goto out;  	} @@ -307,5 +384,4 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)  out:  	wil->radio_wdev = wil->wdev; -	mutex_unlock(&wil->p2p_wdev_mutex);  } |