diff options
author | David S. Miller <davem@davemloft.net> | 2010-03-29 16:50:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-03-29 16:50:10 -0400 |
commit | 7905e357ebe67a26d9dc8caa1a0b8346431b5f0d (patch) | |
tree | 134442df2f062caa6cebda1b352948b8209efcec /net/mac80211 | |
parent | 083ba279d52bcad20f1dfa3cefd4255cbe82d521 (diff) | |
parent | 76232ebf898c4d5e657f2b663fbf7108bca80ded (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 27 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 79 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 |
5 files changed, 102 insertions, 12 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index b7116ef84a3b..c8f520529eec 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1402,6 +1402,32 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
1402 | return 0; | 1402 | return 0; |
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, | ||
1406 | struct net_device *dev, | ||
1407 | s32 rssi_thold, u32 rssi_hyst) | ||
1408 | { | ||
1409 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1410 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1411 | struct ieee80211_vif *vif = &sdata->vif; | ||
1412 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
1413 | |||
1414 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) | ||
1415 | return -EOPNOTSUPP; | ||
1416 | |||
1417 | if (rssi_thold == bss_conf->cqm_rssi_thold && | ||
1418 | rssi_hyst == bss_conf->cqm_rssi_hyst) | ||
1419 | return 0; | ||
1420 | |||
1421 | bss_conf->cqm_rssi_thold = rssi_thold; | ||
1422 | bss_conf->cqm_rssi_hyst = rssi_hyst; | ||
1423 | |||
1424 | /* tell the driver upon association, unless already associated */ | ||
1425 | if (sdata->u.mgd.associated) | ||
1426 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); | ||
1427 | |||
1428 | return 0; | ||
1429 | } | ||
1430 | |||
1405 | static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | 1431 | static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, |
1406 | struct net_device *dev, | 1432 | struct net_device *dev, |
1407 | const u8 *addr, | 1433 | const u8 *addr, |
@@ -1506,4 +1532,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1506 | .remain_on_channel = ieee80211_remain_on_channel, | 1532 | .remain_on_channel = ieee80211_remain_on_channel, |
1507 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1533 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1508 | .action = ieee80211_action, | 1534 | .action = ieee80211_action, |
1535 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | ||
1509 | }; | 1536 | }; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b84126491ab1..ab369e2a5282 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -327,7 +327,7 @@ struct ieee80211_if_managed { | |||
327 | struct work_struct work; | 327 | struct work_struct work; |
328 | struct work_struct monitor_work; | 328 | struct work_struct monitor_work; |
329 | struct work_struct chswitch_work; | 329 | struct work_struct chswitch_work; |
330 | struct work_struct beacon_loss_work; | 330 | struct work_struct beacon_connection_loss_work; |
331 | 331 | ||
332 | unsigned long probe_timeout; | 332 | unsigned long probe_timeout; |
333 | int probe_send_count; | 333 | int probe_send_count; |
@@ -1156,7 +1156,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
1156 | int powersave); | 1156 | int powersave); |
1157 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1157 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1158 | struct ieee80211_hdr *hdr); | 1158 | struct ieee80211_hdr *hdr); |
1159 | void ieee80211_beacon_loss_work(struct work_struct *work); | 1159 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); |
1160 | 1160 | ||
1161 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1161 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1162 | enum queue_stop_reason reason); | 1162 | enum queue_stop_reason reason); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d5571b9420cd..b4ec59a8dc03 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -486,7 +486,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
486 | cancel_work_sync(&sdata->u.mgd.work); | 486 | cancel_work_sync(&sdata->u.mgd.work); |
487 | cancel_work_sync(&sdata->u.mgd.chswitch_work); | 487 | cancel_work_sync(&sdata->u.mgd.chswitch_work); |
488 | cancel_work_sync(&sdata->u.mgd.monitor_work); | 488 | cancel_work_sync(&sdata->u.mgd.monitor_work); |
489 | cancel_work_sync(&sdata->u.mgd.beacon_loss_work); | 489 | cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work); |
490 | 490 | ||
491 | /* | 491 | /* |
492 | * When we get here, the interface is marked down. | 492 | * When we get here, the interface is marked down. |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index be5f723d643a..34e0650e9ef8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -753,6 +753,11 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
753 | /* And the BSSID changed - we're associated now */ | 753 | /* And the BSSID changed - we're associated now */ |
754 | bss_info_changed |= BSS_CHANGED_BSSID; | 754 | bss_info_changed |= BSS_CHANGED_BSSID; |
755 | 755 | ||
756 | /* Tell the driver to monitor connection quality (if supported) */ | ||
757 | if ((local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI) && | ||
758 | sdata->vif.bss_conf.cqm_rssi_thold) | ||
759 | bss_info_changed |= BSS_CHANGED_CQM; | ||
760 | |||
756 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 761 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
757 | 762 | ||
758 | mutex_lock(&local->iflist_mtx); | 763 | mutex_lock(&local->iflist_mtx); |
@@ -854,6 +859,9 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
854 | if (is_multicast_ether_addr(hdr->addr1)) | 859 | if (is_multicast_ether_addr(hdr->addr1)) |
855 | return; | 860 | return; |
856 | 861 | ||
862 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
863 | return; | ||
864 | |||
857 | mod_timer(&sdata->u.mgd.conn_mon_timer, | 865 | mod_timer(&sdata->u.mgd.conn_mon_timer, |
858 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | 866 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); |
859 | } | 867 | } |
@@ -931,23 +939,68 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
931 | mutex_unlock(&ifmgd->mtx); | 939 | mutex_unlock(&ifmgd->mtx); |
932 | } | 940 | } |
933 | 941 | ||
934 | void ieee80211_beacon_loss_work(struct work_struct *work) | 942 | static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) |
943 | { | ||
944 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
945 | struct ieee80211_local *local = sdata->local; | ||
946 | u8 bssid[ETH_ALEN]; | ||
947 | |||
948 | mutex_lock(&ifmgd->mtx); | ||
949 | if (!ifmgd->associated) { | ||
950 | mutex_unlock(&ifmgd->mtx); | ||
951 | return; | ||
952 | } | ||
953 | |||
954 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | ||
955 | |||
956 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | ||
957 | |||
958 | ieee80211_set_disassoc(sdata); | ||
959 | ieee80211_recalc_idle(local); | ||
960 | mutex_unlock(&ifmgd->mtx); | ||
961 | /* | ||
962 | * must be outside lock due to cfg80211, | ||
963 | * but that's not a problem. | ||
964 | */ | ||
965 | ieee80211_send_deauth_disassoc(sdata, bssid, | ||
966 | IEEE80211_STYPE_DEAUTH, | ||
967 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | ||
968 | NULL); | ||
969 | } | ||
970 | |||
971 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) | ||
935 | { | 972 | { |
936 | struct ieee80211_sub_if_data *sdata = | 973 | struct ieee80211_sub_if_data *sdata = |
937 | container_of(work, struct ieee80211_sub_if_data, | 974 | container_of(work, struct ieee80211_sub_if_data, |
938 | u.mgd.beacon_loss_work); | 975 | u.mgd.beacon_connection_loss_work); |
939 | 976 | ||
940 | ieee80211_mgd_probe_ap(sdata, true); | 977 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
978 | __ieee80211_connection_loss(sdata); | ||
979 | else | ||
980 | ieee80211_mgd_probe_ap(sdata, true); | ||
941 | } | 981 | } |
942 | 982 | ||
943 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) | 983 | void ieee80211_beacon_loss(struct ieee80211_vif *vif) |
944 | { | 984 | { |
945 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 985 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
986 | struct ieee80211_hw *hw = &sdata->local->hw; | ||
946 | 987 | ||
947 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); | 988 | WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); |
989 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | ||
948 | } | 990 | } |
949 | EXPORT_SYMBOL(ieee80211_beacon_loss); | 991 | EXPORT_SYMBOL(ieee80211_beacon_loss); |
950 | 992 | ||
993 | void ieee80211_connection_loss(struct ieee80211_vif *vif) | ||
994 | { | ||
995 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
996 | struct ieee80211_hw *hw = &sdata->local->hw; | ||
997 | |||
998 | WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); | ||
999 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | ||
1000 | } | ||
1001 | EXPORT_SYMBOL(ieee80211_connection_loss); | ||
1002 | |||
1003 | |||
951 | static enum rx_mgmt_action __must_check | 1004 | static enum rx_mgmt_action __must_check |
952 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 1005 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
953 | struct ieee80211_mgmt *mgmt, size_t len) | 1006 | struct ieee80211_mgmt *mgmt, size_t len) |
@@ -1637,7 +1690,8 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data) | |||
1637 | if (local->quiescing) | 1690 | if (local->quiescing) |
1638 | return; | 1691 | return; |
1639 | 1692 | ||
1640 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_loss_work); | 1693 | ieee80211_queue_work(&sdata->local->hw, |
1694 | &sdata->u.mgd.beacon_connection_loss_work); | ||
1641 | } | 1695 | } |
1642 | 1696 | ||
1643 | static void ieee80211_sta_conn_mon_timer(unsigned long data) | 1697 | static void ieee80211_sta_conn_mon_timer(unsigned long data) |
@@ -1689,7 +1743,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata) | |||
1689 | */ | 1743 | */ |
1690 | 1744 | ||
1691 | cancel_work_sync(&ifmgd->work); | 1745 | cancel_work_sync(&ifmgd->work); |
1692 | cancel_work_sync(&ifmgd->beacon_loss_work); | 1746 | cancel_work_sync(&ifmgd->beacon_connection_loss_work); |
1693 | if (del_timer_sync(&ifmgd->timer)) | 1747 | if (del_timer_sync(&ifmgd->timer)) |
1694 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); | 1748 | set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); |
1695 | 1749 | ||
@@ -1723,7 +1777,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
1723 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); | 1777 | INIT_WORK(&ifmgd->work, ieee80211_sta_work); |
1724 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); | 1778 | INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work); |
1725 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); | 1779 | INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work); |
1726 | INIT_WORK(&ifmgd->beacon_loss_work, ieee80211_beacon_loss_work); | 1780 | INIT_WORK(&ifmgd->beacon_connection_loss_work, |
1781 | ieee80211_beacon_connection_loss_work); | ||
1727 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 1782 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
1728 | (unsigned long) sdata); | 1783 | (unsigned long) sdata); |
1729 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 1784 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -2135,3 +2190,13 @@ int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | |||
2135 | *cookie = (unsigned long) skb; | 2190 | *cookie = (unsigned long) skb; |
2136 | return 0; | 2191 | return 0; |
2137 | } | 2192 | } |
2193 | |||
2194 | void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | ||
2195 | enum nl80211_cqm_rssi_threshold_event rssi_event, | ||
2196 | gfp_t gfp) | ||
2197 | { | ||
2198 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
2199 | |||
2200 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | ||
2201 | } | ||
2202 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cbe53ed4fb0b..08e1f17a4226 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -2010,14 +2010,12 @@ void ieee80211_tx_pending(unsigned long data) | |||
2010 | while (!skb_queue_empty(&local->pending[i])) { | 2010 | while (!skb_queue_empty(&local->pending[i])) { |
2011 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); | 2011 | struct sk_buff *skb = __skb_dequeue(&local->pending[i]); |
2012 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2012 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2013 | struct ieee80211_sub_if_data *sdata; | ||
2014 | 2013 | ||
2015 | if (WARN_ON(!info->control.vif)) { | 2014 | if (WARN_ON(!info->control.vif)) { |
2016 | kfree_skb(skb); | 2015 | kfree_skb(skb); |
2017 | continue; | 2016 | continue; |
2018 | } | 2017 | } |
2019 | 2018 | ||
2020 | sdata = vif_to_sdata(info->control.vif); | ||
2021 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 2019 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
2022 | flags); | 2020 | flags); |
2023 | 2021 | ||