aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
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 /net/mac80211
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/mlme.c49
3 files changed, 53 insertions, 1 deletions
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,