[RFC] libertas: automatically scan and re-associate when loosing MAC association

Dan Williams dcbw at redhat.com
Fri Jul 6 10:10:38 EDT 2007


On Fri, 2007-07-06 at 09:41 +0200, Holger Schurig wrote:
> Don't free pending_assoc_req in the association worker, keep it
> as is. Free pending_assoc_req at adapter removal time. That way
> we always have an already filled-in assoc_req for reassociation.
> 
> When we get a MAC level event saying that we've been
> de-associated, use the alredy filled in association record to
> make a new scan and re-associate.

Looks good in principle.  However, let's rate-limit the reconnection
rate.  That means, basically, that if the we've hit this
reconnect-on-disconnect more than, say, 3 times in the past 5 seconds,
we stop retrying.

Dan

> Also moved wlan_postpone_association_work() and
> wlan_cancel_association_work() from a *.h file to the sole user,
> into wext.h. Renamed them to libertas_XXX as well.
> 
> Signed-off-by: Holger Schurig <hs4233 at mail.mn-solutions.de>
> ---
> 
> I've marked this patch as RFC so that I can get comments on it.
> 
> * I'm not sure when to totally clear the assoc req, maybe at
>   "ifconfig eth0 down" time?  Maybe it's not needed at all, e.g.
>   if "iwconfig eth1 key XXX" sets the key and and
>   "ethconfig eth1 key off" completely removes the key in the
>   assoc-req, but I haven't checked this yet.
> 
> * maybe I should rename "pending_assoc_req" into
>   "current_assoc_req" as well?
> 
>  drivers/net/wireless/libertas/assoc.c   |    2 -
>  drivers/net/wireless/libertas/assoc.h   |   20 +-------------
>  drivers/net/wireless/libertas/cmdresp.c |    6 ++++
>  drivers/net/wireless/libertas/main.c    |   15 +++++-----
>  drivers/net/wireless/libertas/wext.c    |   46 ++++++++++++++++++++-----------
>  5 files changed, 45 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
> index ffeec2f..f785b79 100644
> --- a/drivers/net/wireless/libertas/assoc.c
> +++ b/drivers/net/wireless/libertas/assoc.c
> @@ -486,7 +486,6 @@ void libertas_association_worker(struct work_struct *work)
>  
>  	mutex_lock(&adapter->lock);
>  	assoc_req = adapter->pending_assoc_req;
> -	adapter->pending_assoc_req = NULL;
>  	adapter->in_progress_assoc_req = assoc_req;
>  	mutex_unlock(&adapter->lock);
>  
> @@ -654,7 +653,6 @@ out:
>  	mutex_lock(&adapter->lock);
>  	adapter->in_progress_assoc_req = NULL;
>  	mutex_unlock(&adapter->lock);
> -	kfree(assoc_req);
>  
>  done:
>  	lbs_deb_leave(LBS_DEB_ASSOC);
> diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
> index 5e9c31f..929c9af 100644
> --- a/drivers/net/wireless/libertas/assoc.h
> +++ b/drivers/net/wireless/libertas/assoc.h
> @@ -11,22 +11,4 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter);
>  
>  void libertas_sync_channel(struct work_struct *work);
>  
> -#define ASSOC_DELAY (HZ / 2)
> -static inline void wlan_postpone_association_work(wlan_private *priv)
> -{
> -	if (priv->adapter->surpriseremoved)
> -		return;
> -	cancel_delayed_work(&priv->assoc_work);
> -	queue_delayed_work(priv->assoc_thread, &priv->assoc_work, ASSOC_DELAY);
> -}
> -
> -static inline void wlan_cancel_association_work(wlan_private *priv)
> -{
> -	cancel_delayed_work(&priv->assoc_work);
> -	if (priv->adapter->pending_assoc_req) {
> -		kfree(priv->adapter->pending_assoc_req);
> -		priv->adapter->pending_assoc_req = NULL;
> -	}
> -}
> -
> -#endif /* _WLAN_ASSOC_H */
> +#endif
> diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
> index 93bf63b..e29c46a 100644
> --- a/drivers/net/wireless/libertas/cmdresp.c
> +++ b/drivers/net/wireless/libertas/cmdresp.c
> @@ -79,6 +79,12 @@ void libertas_mac_event_disconnected(wlan_private * priv)
>  		lbs_deb_cmd("disconnected, so exit PS mode\n");
>  		libertas_ps_wakeup(priv, 0);
>  	}
> +
> +	if (adapter->pending_assoc_req) {
> +		cancel_delayed_work(&priv->assoc_work);
> +		queue_delayed_work(priv->assoc_thread, &priv->assoc_work, HZ / 4);
> +	}
> +
>  	lbs_deb_leave(LBS_DEB_CMD);
>  }
>  
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index 9ccc952..3002d26 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -394,11 +394,17 @@ static int libertas_open(struct net_device *dev)
>  static int libertas_dev_close(struct net_device *dev)
>  {
>  	wlan_private *priv = dev->priv;
> +	wlan_adapter *adapter = priv->adapter;
>  
>  	lbs_deb_enter(LBS_DEB_NET);
>  
> -	netif_carrier_off(priv->dev);
> +	mutex_lock(&adapter->lock);
>  	priv->open = 0;
> +	adapter->connect_status = LIBERTAS_DISCONNECTED;
> +	kfree(adapter->pending_assoc_req);
> +	adapter->pending_assoc_req = NULL;
> +	mutex_unlock(&adapter->lock);
> +	netif_carrier_off(priv->dev);
>  
>  	lbs_deb_leave(LBS_DEB_NET);
>  	return 0;
> @@ -947,15 +953,10 @@ static void libertas_free_adapter(wlan_private * priv)
>  		return;
>  	}
>  
> -	lbs_deb_fw("free command buffer\n");
>  	libertas_free_cmd_buffer(priv);
> -
> -	lbs_deb_fw("free command_timer\n");
>  	del_timer(&adapter->command_timer);
> -
> -	lbs_deb_fw("free scan results table\n");
>  	kfree(adapter->networks);
> -	adapter->networks = NULL;
> +	kfree(adapter->pending_assoc_req);
>  
>  	/* Free the adapter object itself */
>  	lbs_deb_fw("free adapter\n");
> diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
> index 5922321..fe88b8a 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -21,6 +21,20 @@
>  #include "assoc.h"
>  
> 
> +static inline void libertas_postpone_association_work(wlan_private *priv)
> +{
> +	if (priv->adapter->surpriseremoved)
> +		return;
> +	cancel_delayed_work(&priv->assoc_work);
> +	queue_delayed_work(priv->assoc_thread, &priv->assoc_work, HZ / 2);
> +}
> +
> +static inline void libertas_cancel_association_work(wlan_private *priv)
> +{
> +	cancel_delayed_work(&priv->assoc_work);
> +}
> +
> +
>  /**
>   *  @brief Convert mw value to dbm value
>   *
> @@ -1024,9 +1038,9 @@ static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
>  out:
>  	if (ret == 0) {
>  		set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
> -		wlan_postpone_association_work(priv);
> +		libertas_postpone_association_work(priv);
>  	} else {
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  	}
>  	mutex_unlock(&adapter->lock);
>  
> @@ -1125,11 +1139,11 @@ static int wlan_set_mode(struct net_device *dev,
>  	assoc_req = wlan_get_association_request(adapter);
>  	if (!assoc_req) {
>  		ret = -ENOMEM;
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  	} else {
>  		assoc_req->mode = *uwrq;
>  		set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
> -		wlan_postpone_association_work(priv);
> +		libertas_postpone_association_work(priv);
>  		lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
>  	}
>  	mutex_unlock(&adapter->lock);
> @@ -1410,9 +1424,9 @@ static int wlan_set_encode(struct net_device *dev,
>  out:
>  	if (ret == 0) {
>  		set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
> -		wlan_postpone_association_work(priv);
> +		libertas_postpone_association_work(priv);
>  	} else {
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  	}
>  	mutex_unlock(&adapter->lock);
>  
> @@ -1654,9 +1668,9 @@ static int wlan_set_encodeext(struct net_device *dev,
>  
>  out:
>  	if (ret == 0) {
> -		wlan_postpone_association_work(priv);
> +		libertas_postpone_association_work(priv);
>  	} else {
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  	}
>  	mutex_unlock(&adapter->lock);
>  
> @@ -1701,9 +1715,9 @@ static int wlan_set_genie(struct net_device *dev,
>  out:
>  	if (ret == 0) {
>  		set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
> -		wlan_postpone_association_work(priv);
> +		libertas_postpone_association_work(priv);
>  	} else {
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  	}
>  	mutex_unlock(&adapter->lock);
>  
> @@ -1830,9 +1844,9 @@ out:
>  	if (ret == 0) {
>  		if (updated)
>  			set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
> -		wlan_postpone_association_work(priv);
> +		libertas_postpone_association_work(priv);
>  	} else if (ret != -EOPNOTSUPP) {
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  	}
>  	mutex_unlock(&adapter->lock);
>  
> @@ -2018,13 +2032,13 @@ out:
>  			memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
>  			assoc_req->ssid_len = ssid_len;
>  			set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
> -			wlan_postpone_association_work(priv);
> +			libertas_postpone_association_work(priv);
>  		}
>  	}
>  
>  	/* Cancel the association request if there was an error */
>  	if (ret != 0) {
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  	}
>  
>  	mutex_unlock(&adapter->lock);
> @@ -2062,13 +2076,13 @@ static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
>  	/* Get or create the current association request */
>  	assoc_req = wlan_get_association_request(adapter);
>  	if (!assoc_req) {
> -		wlan_cancel_association_work(priv);
> +		libertas_cancel_association_work(priv);
>  		ret = -ENOMEM;
>  	} else {
>  		/* Copy the BSSID to the association request */
>  		memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
>  		set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
> -		wlan_postpone_association_work(priv);
> +		libertas_postpone_association_work(priv);
>  	}
>  
>  	mutex_unlock(&adapter->lock);




More information about the libertas-dev mailing list