aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKalle Valo <kalle.valo@nokia.com>2009-03-22 15:57:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:13:13 -0400
commit04de83815993714a7ba2618f637fa1092a5f664b (patch)
tree7e491e890a66a3be3e4eae9636914858a6f3bba8
parenta08c1c1ac0c26229ca1ca45d554b209a56edc8be (diff)
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>
-rw-r--r--Documentation/DocBook/mac80211.tmpl6
-rw-r--r--include/net/mac80211.h33
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/mlme.c49
5 files changed, 92 insertions, 1 deletions
diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
index 8af6d9626878..fbeaffc1dcc3 100644
--- a/Documentation/DocBook/mac80211.tmpl
+++ b/Documentation/DocBook/mac80211.tmpl
@@ -227,6 +227,12 @@ usage should require reading the full document.
227!Pinclude/net/mac80211.h Powersave support 227!Pinclude/net/mac80211.h Powersave support
228 </chapter> 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 <chapter id="qos"> 236 <chapter id="qos">
231 <title>Multiple queues and QoS support</title> 237 <title>Multiple queues and QoS support</title>
232 <para>TBD</para> 238 <para>TBD</para>
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 174dc1d7526b..d881ed8ad2c1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -882,6 +882,10 @@ enum ieee80211_tkip_key_type {
882 * 882 *
883 * @IEEE80211_HW_MFP_CAPABLE: 883 * @IEEE80211_HW_MFP_CAPABLE:
884 * Hardware supports management frame protection (MFP, IEEE 802.11w). 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 */
886enum ieee80211_hw_flags { 890enum ieee80211_hw_flags {
887 IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, 891 IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
@@ -897,6 +901,7 @@ enum ieee80211_hw_flags {
897 IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11, 901 IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11,
898 IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, 902 IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12,
899 IEEE80211_HW_MFP_CAPABLE = 1<<13, 903 IEEE80211_HW_MFP_CAPABLE = 1<<13,
904 IEEE80211_HW_BEACON_FILTER = 1<<14,
900}; 905};
901 906
902/** 907/**
@@ -1121,6 +1126,24 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
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 * DOC: Frame filtering 1147 * DOC: Frame filtering
1125 * 1148 *
1126 * mac80211 requires to see many management frames for proper 1149 * mac80211 requires to see many management frames for proper
@@ -1970,6 +1993,16 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
1970struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, 1993struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
1971 const u8 *addr); 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 */
2005void ieee80211_beacon_loss(struct ieee80211_vif *vif);
1973 2006
1974/* Rate control API */ 2007/* Rate control API */
1975 2008
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8a617a7fc090..acba78e1a5ca 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -275,6 +275,7 @@ struct ieee80211_if_managed {
275 struct timer_list chswitch_timer; 275 struct timer_list chswitch_timer;
276 struct work_struct work; 276 struct work_struct work;
277 struct work_struct chswitch_work; 277 struct work_struct chswitch_work;
278 struct work_struct beacon_loss_work;
278 279
279 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; 280 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
280 281
@@ -1086,6 +1087,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
1086 int powersave); 1087 int powersave);
1087void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, 1088void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1088 struct ieee80211_hdr *hdr); 1089 struct ieee80211_hdr *hdr);
1090void ieee80211_beacon_loss_work(struct work_struct *work);
1089 1091
1090void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, 1092void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
1091 enum queue_stop_reason reason); 1093 enum queue_stop_reason reason);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index dd2a276fa8ca..91e8e1bacaaa 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -477,6 +477,9 @@ static int ieee80211_stop(struct net_device *dev)
477 */ 477 */
478 cancel_work_sync(&sdata->u.mgd.work); 478 cancel_work_sync(&sdata->u.mgd.work);
479 cancel_work_sync(&sdata->u.mgd.chswitch_work); 479 cancel_work_sync(&sdata->u.mgd.chswitch_work);
480
481 cancel_work_sync(&sdata->u.mgd.beacon_loss_work);
482
480 /* 483 /*
481 * When we get here, the interface is marked down. 484 * When we get here, the interface is marked down.
482 * Call synchronize_rcu() to wait for the RX path 485 * Call synchronize_rcu() to wait for the RX path
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 8f30f4d19da0..7ecda9d59d8a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -610,6 +610,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
610 bss_info_changed |= ieee80211_handle_bss_capability(sdata, 610 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
611 bss->cbss.capability, bss->has_erp_value, bss->erp_value); 611 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
612 612
613 cfg80211_hold_bss(&bss->cbss);
614
613 ieee80211_rx_bss_put(local, bss); 615 ieee80211_rx_bss_put(local, bss);
614 } 616 }
615 617
@@ -751,6 +753,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
751{ 753{
752 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 754 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
753 struct ieee80211_local *local = sdata->local; 755 struct ieee80211_local *local = sdata->local;
756 struct ieee80211_conf *conf = &local_to_hw(local)->conf;
757 struct ieee80211_bss *bss;
754 struct sta_info *sta; 758 struct sta_info *sta;
755 u32 changed = 0, config_changed = 0; 759 u32 changed = 0, config_changed = 0;
756 760
@@ -774,6 +778,15 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
774 778
775 ieee80211_sta_tear_down_BA_sessions(sta); 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 if (self_disconnected) { 790 if (self_disconnected) {
778 if (deauth) 791 if (deauth)
779 ieee80211_send_deauth_disassoc(sdata, 792 ieee80211_send_deauth_disassoc(sdata,
@@ -925,6 +938,33 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
925 jiffies + IEEE80211_MONITORING_INTERVAL); 938 jiffies + IEEE80211_MONITORING_INTERVAL);
926} 939}
927 940
941void 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
959void 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}
966EXPORT_SYMBOL(ieee80211_beacon_loss);
967
928static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) 968static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
929{ 969{
930 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 970 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -959,7 +999,13 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
959 goto unlock; 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 ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) { 1009 ifmgd->last_beacon + IEEE80211_MONITORING_INTERVAL)) {
964 printk(KERN_DEBUG "%s: beacon loss from AP %pM " 1010 printk(KERN_DEBUG "%s: beacon loss from AP %pM "
965 "- sending probe request\n", 1011 "- sending probe request\n",
@@ -1869,6 +1915,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
1869 ifmgd = &sdata->u.mgd; 1915 ifmgd = &sdata->u.mgd;
1870 INIT_WORK(&ifmgd->work, ieee80211_sta_work); 1916 INIT_WORK(&ifmgd->work, ieee80211_sta_work);
1871 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); 1917 INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
1918 INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work);
1872 setup_timer(&ifmgd->timer, ieee80211_sta_timer, 1919 setup_timer(&ifmgd->timer, ieee80211_sta_timer,
1873 (unsigned long) sdata); 1920 (unsigned long) sdata);
1874 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer, 1921 setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,