diff options
author | Kalle Valo <kalle.valo@nokia.com> | 2009-03-22 15:57:35 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:13:13 -0400 |
commit | 04de83815993714a7ba2618f637fa1092a5f664b (patch) | |
tree | 7e491e890a66a3be3e4eae9636914858a6f3bba8 /net/mac80211 | |
parent | a08c1c1ac0c26229ca1ca45d554b209a56edc8be (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.h | 2 | ||||
-rw-r--r-- | net/mac80211/iface.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 49 |
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); |
1087 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1088 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1088 | struct ieee80211_hdr *hdr); | 1089 | struct ieee80211_hdr *hdr); |
1090 | void ieee80211_beacon_loss_work(struct work_struct *work); | ||
1089 | 1091 | ||
1090 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1092 | void 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 | ||
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 | static void ieee80211_associated(struct ieee80211_sub_if_data *sdata) | 968 | static 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, |