diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-04-10 14:09:54 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-10 14:09:54 -0400 |
commit | 655d8e2328a6ef6b6b514609a4c1e33508d3a1da (patch) | |
tree | 144b686bf3fd6512a55987da2d911f739646ce02 /net/mac80211/mlme.c | |
parent | 6fe5468f452c0c40348ebd4e737758a842286ca8 (diff) | |
parent | ddc4db2e3d5393ede7a9222bb3b7522a603a4678 (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.c | 128 |
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 | 59 | static int beacon_loss_count = 7; |
60 | module_param(beacon_loss_count, int, 0644); | ||
61 | MODULE_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 | ||
1458 | void ieee80211_dynamic_ps_timer(unsigned long data) | 1466 | void 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 { |