aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-04-10 14:09:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-10 14:09:54 -0400
commit655d8e2328a6ef6b6b514609a4c1e33508d3a1da (patch)
tree144b686bf3fd6512a55987da2d911f739646ce02 /net/mac80211/mlme.c
parent6fe5468f452c0c40348ebd4e737758a842286ca8 (diff)
parentddc4db2e3d5393ede7a9222bb3b7522a603a4678 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Conflicts: drivers/net/wireless/ath/carl9170/debug.c drivers/net/wireless/ath/carl9170/main.c net/mac80211/ieee80211_i.h
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c128
1 files changed, 66 insertions, 62 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e06dbbf8cb4c..9c4968938472 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -56,7 +56,10 @@ MODULE_PARM_DESC(max_probe_tries,
56 * probe on beacon miss before declaring the connection lost 56 * probe on beacon miss before declaring the connection lost
57 * default to what we want. 57 * default to what we want.
58 */ 58 */
59#define IEEE80211_BEACON_LOSS_COUNT 7 59static int beacon_loss_count = 7;
60module_param(beacon_loss_count, int, 0644);
61MODULE_PARM_DESC(beacon_loss_count,
62 "Number of beacon intervals before we decide beacon was lost.");
60 63
61/* 64/*
62 * Time the connection can be idle before we probe 65 * Time the connection can be idle before we probe
@@ -985,6 +988,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
985{ 988{
986 struct ieee80211_sub_if_data *sdata = 989 struct ieee80211_sub_if_data *sdata =
987 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); 990 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
991 struct ieee80211_local *local = sdata->local;
988 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 992 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
989 993
990 if (!ieee80211_sdata_running(sdata)) 994 if (!ieee80211_sdata_running(sdata))
@@ -994,21 +998,30 @@ static void ieee80211_chswitch_work(struct work_struct *work)
994 if (!ifmgd->associated) 998 if (!ifmgd->associated)
995 goto out; 999 goto out;
996 1000
997 sdata->local->_oper_channel = sdata->local->csa_channel; 1001 /*
998 if (!sdata->local->ops->channel_switch) { 1002 * FIXME: Here we are downgrading to NL80211_CHAN_WIDTH_20_NOHT
1003 * and don't adjust our ht/vht settings
1004 * This is wrong - we should behave according to the CSA params
1005 */
1006 local->_oper_chandef.chan = local->csa_channel;
1007 local->_oper_chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
1008 local->_oper_chandef.center_freq1 =
1009 local->_oper_chandef.chan->center_freq;
1010 local->_oper_chandef.center_freq2 = 0;
1011
1012 if (!local->ops->channel_switch) {
999 /* call "hw_config" only if doing sw channel switch */ 1013 /* call "hw_config" only if doing sw channel switch */
1000 ieee80211_hw_config(sdata->local, 1014 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
1001 IEEE80211_CONF_CHANGE_CHANNEL);
1002 } else { 1015 } else {
1003 /* update the device channel directly */ 1016 /* update the device channel directly */
1004 sdata->local->hw.conf.channel = sdata->local->_oper_channel; 1017 local->hw.conf.chandef = local->_oper_chandef;
1005 } 1018 }
1006 1019
1007 /* XXX: shouldn't really modify cfg80211-owned data! */ 1020 /* XXX: shouldn't really modify cfg80211-owned data! */
1008 ifmgd->associated->channel = sdata->local->_oper_channel; 1021 ifmgd->associated->channel = local->_oper_chandef.chan;
1009 1022
1010 /* XXX: wait for a beacon first? */ 1023 /* XXX: wait for a beacon first? */
1011 ieee80211_wake_queues_by_reason(&sdata->local->hw, 1024 ieee80211_wake_queues_by_reason(&local->hw,
1012 IEEE80211_MAX_QUEUE_MAP, 1025 IEEE80211_MAX_QUEUE_MAP,
1013 IEEE80211_QUEUE_STOP_REASON_CSA); 1026 IEEE80211_QUEUE_STOP_REASON_CSA);
1014 out: 1027 out:
@@ -1430,13 +1443,11 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
1430 1443
1431 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && 1444 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
1432 !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { 1445 !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
1433 netif_tx_stop_all_queues(sdata->dev); 1446 if (drv_tx_frames_pending(local)) {
1434
1435 if (drv_tx_frames_pending(local))
1436 mod_timer(&local->dynamic_ps_timer, jiffies + 1447 mod_timer(&local->dynamic_ps_timer, jiffies +
1437 msecs_to_jiffies( 1448 msecs_to_jiffies(
1438 local->hw.conf.dynamic_ps_timeout)); 1449 local->hw.conf.dynamic_ps_timeout));
1439 else { 1450 } else {
1440 ieee80211_send_nullfunc(local, sdata, 1); 1451 ieee80211_send_nullfunc(local, sdata, 1);
1441 /* Flush to get the tx status of nullfunc frame */ 1452 /* Flush to get the tx status of nullfunc frame */
1442 ieee80211_flush_queues(local, sdata); 1453 ieee80211_flush_queues(local, sdata);
@@ -1450,9 +1461,6 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
1450 local->hw.conf.flags |= IEEE80211_CONF_PS; 1461 local->hw.conf.flags |= IEEE80211_CONF_PS;
1451 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); 1462 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
1452 } 1463 }
1453
1454 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
1455 netif_tx_wake_all_queues(sdata->dev);
1456} 1464}
1457 1465
1458void ieee80211_dynamic_ps_timer(unsigned long data) 1466void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -1645,7 +1653,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1645 bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value); 1653 bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value);
1646 1654
1647 sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( 1655 sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec(
1648 IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); 1656 beacon_loss_count * bss_conf->beacon_int));
1649 1657
1650 sdata->u.mgd.associated = cbss; 1658 sdata->u.mgd.associated = cbss;
1651 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); 1659 memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN);
@@ -1658,18 +1666,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1658 rcu_read_lock(); 1666 rcu_read_lock();
1659 ies = rcu_dereference(cbss->ies); 1667 ies = rcu_dereference(cbss->ies);
1660 if (ies) { 1668 if (ies) {
1661 u8 noa[2];
1662 int ret; 1669 int ret;
1663 1670
1664 ret = cfg80211_get_p2p_attr( 1671 ret = cfg80211_get_p2p_attr(
1665 ies->data, ies->len, 1672 ies->data, ies->len,
1666 IEEE80211_P2P_ATTR_ABSENCE_NOTICE, 1673 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
1667 noa, sizeof(noa)); 1674 (u8 *) &bss_conf->p2p_noa_attr,
1675 sizeof(bss_conf->p2p_noa_attr));
1668 if (ret >= 2) { 1676 if (ret >= 2) {
1669 bss_conf->p2p_oppps = noa[1] & 0x80; 1677 sdata->u.mgd.p2p_noa_index =
1670 bss_conf->p2p_ctwindow = noa[1] & 0x7f; 1678 bss_conf->p2p_noa_attr.index;
1671 bss_info_changed |= BSS_CHANGED_P2P_PS; 1679 bss_info_changed |= BSS_CHANGED_P2P_PS;
1672 sdata->u.mgd.p2p_noa_index = noa[0];
1673 } 1680 }
1674 } 1681 }
1675 rcu_read_unlock(); 1682 rcu_read_unlock();
@@ -1713,7 +1720,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
1713 ieee80211_recalc_smps(sdata); 1720 ieee80211_recalc_smps(sdata);
1714 ieee80211_recalc_ps_vif(sdata); 1721 ieee80211_recalc_ps_vif(sdata);
1715 1722
1716 netif_tx_start_all_queues(sdata->dev);
1717 netif_carrier_on(sdata->dev); 1723 netif_carrier_on(sdata->dev);
1718} 1724}
1719 1725
@@ -1736,22 +1742,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1736 ieee80211_stop_poll(sdata); 1742 ieee80211_stop_poll(sdata);
1737 1743
1738 ifmgd->associated = NULL; 1744 ifmgd->associated = NULL;
1739
1740 /*
1741 * we need to commit the associated = NULL change because the
1742 * scan code uses that to determine whether this iface should
1743 * go to/wake up from powersave or not -- and could otherwise
1744 * wake the queues erroneously.
1745 */
1746 smp_mb();
1747
1748 /*
1749 * Thus, we can only afterwards stop the queues -- to account
1750 * for the case where another CPU is finishing a scan at this
1751 * time -- we don't want the scan code to enable queues.
1752 */
1753
1754 netif_tx_stop_all_queues(sdata->dev);
1755 netif_carrier_off(sdata->dev); 1745 netif_carrier_off(sdata->dev);
1756 1746
1757 /* 1747 /*
@@ -1794,8 +1784,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1794 changed |= BSS_CHANGED_ASSOC; 1784 changed |= BSS_CHANGED_ASSOC;
1795 sdata->vif.bss_conf.assoc = false; 1785 sdata->vif.bss_conf.assoc = false;
1796 1786
1797 sdata->vif.bss_conf.p2p_ctwindow = 0; 1787 ifmgd->p2p_noa_index = -1;
1798 sdata->vif.bss_conf.p2p_oppps = false; 1788 memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
1789 sizeof(sdata->vif.bss_conf.p2p_noa_attr));
1799 1790
1800 /* on the next assoc, re-program HT/VHT parameters */ 1791 /* on the next assoc, re-program HT/VHT parameters */
1801 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); 1792 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
@@ -1975,12 +1966,15 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
1975 goto out; 1966 goto out;
1976 } 1967 }
1977 1968
1978 if (beacon) 1969 if (beacon) {
1979 mlme_dbg_ratelimited(sdata, 1970 mlme_dbg_ratelimited(sdata,
1980 "detected beacon loss from AP - probing\n"); 1971 "detected beacon loss from AP (missed %d beacons) - probing\n",
1972 beacon_loss_count);
1981 1973
1982 ieee80211_cqm_rssi_notify(&sdata->vif, 1974 ieee80211_cqm_rssi_notify(&sdata->vif,
1983 NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); 1975 NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
1976 GFP_KERNEL);
1977 }
1984 1978
1985 /* 1979 /*
1986 * The driver/our work has already reported this event or the 1980 * The driver/our work has already reported this event or the
@@ -2613,10 +2607,10 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
2613 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); 2607 ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
2614 2608
2615 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && 2609 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
2616 elems.timeout_int && elems.timeout_int_len == 5 && 2610 elems.timeout_int &&
2617 elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { 2611 elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) {
2618 u32 tu, ms; 2612 u32 tu, ms;
2619 tu = get_unaligned_le32(elems.timeout_int + 1); 2613 tu = le32_to_cpu(elems.timeout_int->value);
2620 ms = tu * 1024 / 1000; 2614 ms = tu * 1024 / 1000;
2621 sdata_info(sdata, 2615 sdata_info(sdata,
2622 "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n", 2616 "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n",
@@ -2679,7 +2673,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2679 } 2673 }
2680 } 2674 }
2681 2675
2682 if (elems->ds_params && elems->ds_params_len == 1) 2676 if (elems->ds_params)
2683 freq = ieee80211_channel_to_frequency(elems->ds_params[0], 2677 freq = ieee80211_channel_to_frequency(elems->ds_params[0],
2684 rx_status->band); 2678 rx_status->band);
2685 else 2679 else
@@ -2957,22 +2951,30 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
2957 } 2951 }
2958 2952
2959 if (sdata->vif.p2p) { 2953 if (sdata->vif.p2p) {
2960 u8 noa[2]; 2954 struct ieee80211_p2p_noa_attr noa = {};
2961 int ret; 2955 int ret;
2962 2956
2963 ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable, 2957 ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
2964 len - baselen, 2958 len - baselen,
2965 IEEE80211_P2P_ATTR_ABSENCE_NOTICE, 2959 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
2966 noa, sizeof(noa)); 2960 (u8 *) &noa, sizeof(noa));
2967 if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa[0]) { 2961 if (ret >= 2) {
2968 bss_conf->p2p_oppps = noa[1] & 0x80; 2962 if (sdata->u.mgd.p2p_noa_index != noa.index) {
2969 bss_conf->p2p_ctwindow = noa[1] & 0x7f; 2963 /* valid noa_attr and index changed */
2964 sdata->u.mgd.p2p_noa_index = noa.index;
2965 memcpy(&bss_conf->p2p_noa_attr, &noa, sizeof(noa));
2966 changed |= BSS_CHANGED_P2P_PS;
2967 /*
2968 * make sure we update all information, the CRC
2969 * mechanism doesn't look at P2P attributes.
2970 */
2971 ifmgd->beacon_crc_valid = false;
2972 }
2973 } else if (sdata->u.mgd.p2p_noa_index != -1) {
2974 /* noa_attr not found and we had valid noa_attr before */
2975 sdata->u.mgd.p2p_noa_index = -1;
2976 memset(&bss_conf->p2p_noa_attr, 0, sizeof(bss_conf->p2p_noa_attr));
2970 changed |= BSS_CHANGED_P2P_PS; 2977 changed |= BSS_CHANGED_P2P_PS;
2971 sdata->u.mgd.p2p_noa_index = noa[0];
2972 /*
2973 * make sure we update all information, the CRC
2974 * mechanism doesn't look at P2P attributes.
2975 */
2976 ifmgd->beacon_crc_valid = false; 2978 ifmgd->beacon_crc_valid = false;
2977 } 2979 }
2978 } 2980 }
@@ -3014,7 +3016,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
3014 changed |= BSS_CHANGED_DTIM_PERIOD; 3016 changed |= BSS_CHANGED_DTIM_PERIOD;
3015 } 3017 }
3016 3018
3017 if (elems.erp_info && elems.erp_info_len >= 1) { 3019 if (elems.erp_info) {
3018 erp_valid = true; 3020 erp_valid = true;
3019 erp_value = elems.erp_info[0]; 3021 erp_value = elems.erp_info[0];
3020 } else { 3022 } else {
@@ -3513,8 +3515,9 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
3513 3515
3514 ifmgd->flags = 0; 3516 ifmgd->flags = 0;
3515 ifmgd->powersave = sdata->wdev.ps; 3517 ifmgd->powersave = sdata->wdev.ps;
3516 ifmgd->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; 3518 ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues;
3517 ifmgd->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; 3519 ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
3520 ifmgd->p2p_noa_index = -1;
3518 3521
3519 mutex_init(&ifmgd->mtx); 3522 mutex_init(&ifmgd->mtx);
3520 3523
@@ -4063,7 +4066,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
4063 rcu_read_unlock(); 4066 rcu_read_unlock();
4064 4067
4065 if (bss->wmm_used && bss->uapsd_supported && 4068 if (bss->wmm_used && bss->uapsd_supported &&
4066 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { 4069 (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) &&
4070 sdata->wmm_acm != 0xff) {
4067 assoc_data->uapsd = true; 4071 assoc_data->uapsd = true;
4068 ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; 4072 ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
4069 } else { 4073 } else {