Search Linux Wireless

Re: [RFC PATCHv4 1/1] mac80211: Add support connection monitor in hardware

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2010-03-18 at 17:23 +0100, ext Johannes Berg wrote:
> On Thu, 2010-03-18 at 09:12 +0200, Juuso Oikarinen wrote:
> > This patch is based on a RFC patch by Kalle Valo.
> > 
> > The wl1271 has a feature which handles the connection monitor logic
> > in hardware, basically sending periodically nullfunc frames and reporting
> > to the host if AP is lost, after attempting to recover by sending
> > probe-requests to the AP.
> > 
> > Add support to mac80211 by adding a new flag IEEE80211_HW_CONNECTION_MONITOR
> > which prevents conn_mon_timer from triggering during idle periods, and
> > prevents sending probe-requests to the AP if beacon-loss is indicated by the
> > hardware.
> 
> Reviewed-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>
> 

Thank you!

-Juuso

> 
> > Cc: Kalle Valo <kalle.valo@xxxxxxxxx>
> > Signed-off-by: Juuso Oikarinen <juuso.oikarinen@xxxxxxxxx>
> > ---
> >  include/net/mac80211.h     |   24 +++++++++++++++-
> >  net/mac80211/ieee80211_i.h |    4 +-
> >  net/mac80211/iface.c       |    2 +-
> >  net/mac80211/mlme.c        |   64 +++++++++++++++++++++++++++++++++++++++-----
> >  4 files changed, 82 insertions(+), 12 deletions(-)
> > 
> > diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> > index 936bc41..d14226f 100644
> > --- a/include/net/mac80211.h
> > +++ b/include/net/mac80211.h
> > @@ -954,6 +954,11 @@ enum ieee80211_tkip_key_type {
> >   *	Hardware can provide ack status reports of Tx frames to
> >   *	the stack.
> >   *
> > + * @IEEE80211_HW_CONNECTION_MONITOR:
> > + *      The hardware performs its own connection monitoring, including
> > + *      periodic keep-alives to the AP and probing the AP on beacon loss.
> > + *      When this flag is set, signaling beacon-loss will cause an immediate
> > + *      change to disassociated state.
> >   */
> >  enum ieee80211_hw_flags {
> >  	IEEE80211_HW_HAS_RATE_CONTROL			= 1<<0,
> > @@ -975,6 +980,7 @@ enum ieee80211_hw_flags {
> >  	IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS		= 1<<16,
> >  	IEEE80211_HW_SUPPORTS_UAPSD			= 1<<17,
> >  	IEEE80211_HW_REPORTS_TX_ACK_STATUS		= 1<<18,
> > +	IEEE80211_HW_CONNECTION_MONITOR			= 1<<19,
> >  };
> >  
> >  /**
> > @@ -2364,12 +2370,26 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
> >   *
> >   * @vif: &struct ieee80211_vif pointer from the add_interface callback.
> >   *
> > - * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and
> > - * IEEE80211_CONF_PS is set, the driver needs to inform whenever the
> > + * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING and
> > + * %IEEE80211_CONF_PS is set, the driver needs to inform whenever the
> >   * hardware is not receiving beacons with this function.
> >   */
> >  void ieee80211_beacon_loss(struct ieee80211_vif *vif);
> >  
> > +/**
> > + * ieee80211_connection_loss - inform hardware has lost connection to the AP
> > + *
> > + * @vif: &struct ieee80211_vif pointer from the add_interface callback.
> > + *
> > + * When beacon filtering is enabled with %IEEE80211_HW_BEACON_FILTERING, and
> > + * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver
> > + * needs to inform if the connection to the AP has been lost.
> > + *
> > + * This function will cause immediate change to disassociated state,
> > + * without connection recovery attempts.
> > + */
> > +void ieee80211_connection_loss(struct ieee80211_vif *vif);
> > +
> >  /* Rate control API */
> >  
> >  /**
> > diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> > index b841264..ab369e2 100644
> > --- a/net/mac80211/ieee80211_i.h
> > +++ b/net/mac80211/ieee80211_i.h
> > @@ -327,7 +327,7 @@ struct ieee80211_if_managed {
> >  	struct work_struct work;
> >  	struct work_struct monitor_work;
> >  	struct work_struct chswitch_work;
> > -	struct work_struct beacon_loss_work;
> > +	struct work_struct beacon_connection_loss_work;
> >  
> >  	unsigned long probe_timeout;
> >  	int probe_send_count;
> > @@ -1156,7 +1156,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
> >  			     int powersave);
> >  void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
> >  			     struct ieee80211_hdr *hdr);
> > -void ieee80211_beacon_loss_work(struct work_struct *work);
> > +void ieee80211_beacon_connection_loss_work(struct work_struct *work);
> >  
> >  void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
> >  				     enum queue_stop_reason reason);
> > diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> > index d5571b9..b4ec59a 100644
> > --- a/net/mac80211/iface.c
> > +++ b/net/mac80211/iface.c
> > @@ -486,7 +486,7 @@ static int ieee80211_stop(struct net_device *dev)
> >  		cancel_work_sync(&sdata->u.mgd.work);
> >  		cancel_work_sync(&sdata->u.mgd.chswitch_work);
> >  		cancel_work_sync(&sdata->u.mgd.monitor_work);
> > -		cancel_work_sync(&sdata->u.mgd.beacon_loss_work);
> > +		cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work);
> >  
> >  		/*
> >  		 * When we get here, the interface is marked down.
> > diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> > index be5f723..6b43a0a 100644
> > --- a/net/mac80211/mlme.c
> > +++ b/net/mac80211/mlme.c
> > @@ -854,6 +854,9 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
> >  	if (is_multicast_ether_addr(hdr->addr1))
> >  		return;
> >  
> > +	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
> > +		return;
> > +
> >  	mod_timer(&sdata->u.mgd.conn_mon_timer,
> >  		  round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
> >  }
> > @@ -931,23 +934,68 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
> >  	mutex_unlock(&ifmgd->mtx);
> >  }
> >  
> > -void ieee80211_beacon_loss_work(struct work_struct *work)
> > +static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
> > +{
> > +	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
> > +	struct ieee80211_local *local = sdata->local;
> > +	u8 bssid[ETH_ALEN];
> > +
> > +	mutex_lock(&ifmgd->mtx);
> > +	if (!ifmgd->associated) {
> > +		mutex_unlock(&ifmgd->mtx);
> > +		return;
> > +	}
> > +
> > +	memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
> > +
> > +	printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
> > +
> > +	ieee80211_set_disassoc(sdata);
> > +	ieee80211_recalc_idle(local);
> > +	mutex_unlock(&ifmgd->mtx);
> > +	/*
> > +	 * must be outside lock due to cfg80211,
> > +	 * but that's not a problem.
> > +	 */
> > +	ieee80211_send_deauth_disassoc(sdata, bssid,
> > +				       IEEE80211_STYPE_DEAUTH,
> > +				       WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
> > +				       NULL);
> > +}
> > +
> > +void ieee80211_beacon_connection_loss_work(struct work_struct *work)
> >  {
> >  	struct ieee80211_sub_if_data *sdata =
> >  		container_of(work, struct ieee80211_sub_if_data,
> > -			     u.mgd.beacon_loss_work);
> > +			     u.mgd.beacon_connection_loss_work);
> >  
> > -	ieee80211_mgd_probe_ap(sdata, true);
> > +	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
> > +		__ieee80211_connection_loss(sdata);
> > +	else
> > +		ieee80211_mgd_probe_ap(sdata, true);
> >  }
> >  
> >  void ieee80211_beacon_loss(struct ieee80211_vif *vif)
> >  {
> >  	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> > +	struct ieee80211_hw *hw = &sdata->local->hw;
> >  
> > -	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
> > +	WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR);
> > +	ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
> >  }
> >  EXPORT_SYMBOL(ieee80211_beacon_loss);
> >  
> > +void ieee80211_connection_loss(struct ieee80211_vif *vif)
> > +{
> > +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> > +	struct ieee80211_hw *hw = &sdata->local->hw;
> > +
> > +	WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR));
> > +	ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work);
> > +}
> > +EXPORT_SYMBOL(ieee80211_connection_loss);
> > +
> > +
> >  static enum rx_mgmt_action __must_check
> >  ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
> >  			 struct ieee80211_mgmt *mgmt, size_t len)
> > @@ -1637,7 +1685,8 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data)
> >  	if (local->quiescing)
> >  		return;
> >  
> > -	ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work);
> > +	ieee80211_queue_work(&sdata->local->hw,
> > +			     &sdata->u.mgd.beacon_connection_loss_work);
> >  }
> >  
> >  static void ieee80211_sta_conn_mon_timer(unsigned long data)
> > @@ -1689,7 +1738,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
> >  	 */
> >  
> >  	cancel_work_sync(&ifmgd->work);
> > -	cancel_work_sync(&ifmgd->beacon_loss_work);
> > +	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
> >  	if (del_timer_sync(&ifmgd->timer))
> >  		set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
> >  
> > @@ -1723,7 +1772,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
> >  	INIT_WORK(&ifmgd->work, ieee80211_sta_work);
> >  	INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
> >  	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
> > -	INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
> > +	INIT_WORK(&ifmgd->beacon_connection_loss_work,
> > +		  ieee80211_beacon_connection_loss_work);
> >  	setup_timer(&ifmgd->timer, ieee80211_sta_timer,
> >  		    (unsigned long) sdata);
> >  	setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
> 
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux