Commit 04de83815993714a7ba2618f637fa1092a5f664b

Authored by Kalle Valo
Committed by John W. Linville
1 parent a08c1c1ac0

mac80211: add beacon filtering support

Add IEEE80211_HW_BEACON_FILTERING flag so that driver inform that it supports
beacon filtering. Drivers need to call the new function
ieee80211_beacon_loss() to notify about beacon loss.

Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 5 changed files with 92 additions and 1 deletions Side-by-side Diff

Documentation/DocBook/mac80211.tmpl
... ... @@ -227,6 +227,12 @@
227 227 !Pinclude/net/mac80211.h Powersave support
228 228 </chapter>
229 229  
  230 + <chapter id="beacon-filter">
  231 + <title>Beacon filter support</title>
  232 +!Pinclude/net/mac80211.h Beacon filter support
  233 +!Finclude/net/mac80211.h ieee80211_beacon_loss
  234 + </chapter>
  235 +
230 236 <chapter id="qos">
231 237 <title>Multiple queues and QoS support</title>
232 238 <para>TBD</para>
include/net/mac80211.h
... ... @@ -882,6 +882,10 @@
882 882 *
883 883 * @IEEE80211_HW_MFP_CAPABLE:
884 884 * Hardware supports management frame protection (MFP, IEEE 802.11w).
  885 + *
  886 + * @IEEE80211_HW_BEACON_FILTER:
  887 + * Hardware supports dropping of irrelevant beacon frames to
  888 + * avoid waking up cpu.
885 889 */
886 890 enum ieee80211_hw_flags {
887 891 IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
... ... @@ -897,6 +901,7 @@
897 901 IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11,
898 902 IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12,
899 903 IEEE80211_HW_MFP_CAPABLE = 1<<13,
  904 + IEEE80211_HW_BEACON_FILTER = 1<<14,
900 905 };
901 906  
902 907 /**
... ... @@ -1121,6 +1126,24 @@
1121 1126 */
1122 1127  
1123 1128 /**
  1129 + * DOC: Beacon filter support
  1130 + *
  1131 + * Some hardware have beacon filter support to reduce host cpu wakeups
  1132 + * which will reduce system power consumption. It usuallly works so that
  1133 + * the firmware creates a checksum of the beacon but omits all constantly
  1134 + * changing elements (TSF, TIM etc). Whenever the checksum changes the
  1135 + * beacon is forwarded to the host, otherwise it will be just dropped. That
  1136 + * way the host will only receive beacons where some relevant information
  1137 + * (for example ERP protection or WMM settings) have changed.
  1138 + *
  1139 + * Beacon filter support is informed with %IEEE80211_HW_BEACON_FILTER flag.
  1140 + * The driver needs to enable beacon filter support whenever power save is
  1141 + * enabled, that is %IEEE80211_CONF_PS is set. When power save is enabled,
  1142 + * the stack will not check for beacon miss at all and the driver needs to
  1143 + * notify about complete loss of beacons with ieee80211_beacon_loss().
  1144 + */
  1145 +
  1146 +/**
1124 1147 * DOC: Frame filtering
1125 1148 *
1126 1149 * mac80211 requires to see many management frames for proper
... ... @@ -1970,6 +1993,16 @@
1970 1993 struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
1971 1994 const u8 *addr);
1972 1995  
  1996 +/**
  1997 + * ieee80211_beacon_loss - inform hardware does not receive beacons
  1998 + *
  1999 + * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
  2000 + *
  2001 + * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and
  2002 + * IEEE80211_CONF_PS is set, the driver needs to inform whenever the
  2003 + * hardware is not receiving beacons with this function.
  2004 + */
  2005 +void ieee80211_beacon_loss(struct ieee80211_vif *vif);
1973 2006  
1974 2007 /* Rate control API */
1975 2008  
net/mac80211/ieee80211_i.h
... ... @@ -275,6 +275,7 @@
275 275 struct timer_list chswitch_timer;
276 276 struct work_struct work;
277 277 struct work_struct chswitch_work;
  278 + struct work_struct beacon_loss_work;
278 279  
279 280 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
280 281  
... ... @@ -1086,6 +1087,7 @@
1086 1087 int powersave);
1087 1088 void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1088 1089 struct ieee80211_hdr *hdr);
  1090 +void ieee80211_beacon_loss_work(struct work_struct *work);
1089 1091  
1090 1092 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
1091 1093 enum queue_stop_reason reason);
net/mac80211/iface.c
... ... @@ -477,6 +477,9 @@
477 477 */
478 478 cancel_work_sync(&sdata->u.mgd.work);
479 479 cancel_work_sync(&sdata->u.mgd.chswitch_work);
  480 +
  481 + cancel_work_sync(&sdata->u.mgd.beacon_loss_work);
  482 +
480 483 /*
481 484 * When we get here, the interface is marked down.
482 485 * Call synchronize_rcu() to wait for the RX path
... ... @@ -610,6 +610,8 @@
610 610 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
611 611 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
612 612  
  613 + cfg80211_hold_bss(&bss->cbss);
  614 +
613 615 ieee80211_rx_bss_put(local, bss);
614 616 }
615 617  
... ... @@ -751,6 +753,8 @@
751 753 {
752 754 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
753 755 struct ieee80211_local *local = sdata->local;
  756 + struct ieee80211_conf *conf = &local_to_hw(local)->conf;
  757 + struct ieee80211_bss *bss;
754 758 struct sta_info *sta;
755 759 u32 changed = 0, config_changed = 0;
756 760  
... ... @@ -774,6 +778,15 @@
774 778  
775 779 ieee80211_sta_tear_down_BA_sessions(sta);
776 780  
  781 + bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
  782 + conf->channel->center_freq,
  783 + ifmgd->ssid, ifmgd->ssid_len);
  784 +
  785 + if (bss) {
  786 + cfg80211_unhold_bss(&bss->cbss);
  787 + ieee80211_rx_bss_put(local, bss);
  788 + }
  789 +
777 790 if (self_disconnected) {
778 791 if (deauth)
779 792 ieee80211_send_deauth_disassoc(sdata,
... ... @@ -925,6 +938,33 @@
925 938 jiffies + IEEE80211_MONITORING_INTERVAL);
926 939 }
927 940  
  941 +void ieee80211_beacon_loss_work(struct work_struct *work)
  942 +{
  943 + struct ieee80211_sub_if_data *sdata =
  944 + container_of(work, struct ieee80211_sub_if_data,
  945 + u.mgd.beacon_loss_work);
  946 + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
  947 +
  948 + printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
  949 + "- sending probe request\n", sdata->dev->name,
  950 + sdata->u.mgd.bssid);
  951 +
  952 + ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
  953 + ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
  954 + ifmgd->ssid_len, NULL, 0);
  955 +
  956 + mod_timer(&ifmgd->timer, jiffies + IEEE80211_MONITORING_INTERVAL);
  957 +}
  958 +
  959 +void ieee80211_beacon_loss(struct ieee80211_vif *vif)
  960 +{
  961 + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
  962 +
  963 + queue_work(sdata->local->hw.workqueue,
  964 + &sdata->u.mgd.beacon_loss_work);
  965 +}
  966 +EXPORT_SYMBOL(ieee80211_beacon_loss);
  967 +
928 968 static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
929 969 {
930 970 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
... ... @@ -959,7 +999,13 @@
959 999 goto unlock;
960 1000 }
961 1001  
962   - if (time_after(jiffies,
  1002 + /*
  1003 + * Beacon filtering is only enabled with power save and then the
  1004 + * stack should not check for beacon loss.
  1005 + */
  1006 + if (!((local->hw.flags & IEEE80211_HW_BEACON_FILTER) &&
  1007 + (local->hw.conf.flags & IEEE80211_CONF_PS)) &&
  1008 + time_after(jiffies,
963 1009 ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
964 1010 printk(KERN_DEBUG "%s: beacon loss from AP %pM "
965 1011 "- sending probe request\n",
... ... @@ -1869,6 +1915,7 @@
1869 1915 ifmgd = &sdata->u.mgd;
1870 1916 INIT_WORK(&ifmgd->work, ieee80211_sta_work);
1871 1917 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
  1918 + INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
1872 1919 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
1873 1920 (unsigned long) sdata);
1874 1921 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,