diff options
author | Johannes Berg <johannes.berg@intel.com> | 2018-08-31 04:31:18 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2018-09-05 04:03:14 -0400 |
commit | 7eb26df2972504ffe37da77612c0e5f714f0d6df (patch) | |
tree | 4c3044951104f8765a40e55ae651072f90a10473 | |
parent | 09b4a4faf9d037990ac4f8110dd944b27b42d5df (diff) |
mac80211: add ability to parse CCFS2
With newer VHT implementations, it's necessary to look at the
HT operation's CCFS2 field to identify the actual bandwidth
used.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/mac80211/ibss.c | 4 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 4 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 5 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 6 | ||||
-rw-r--r-- | net/mac80211/spectmgmt.c | 5 | ||||
-rw-r--r-- | net/mac80211/util.c | 48 |
6 files changed, 50 insertions, 22 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f0f5fedb8caa..0d704e8d7078 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -1070,7 +1070,9 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, | |||
1070 | struct ieee80211_vht_cap cap_ie; | 1070 | struct ieee80211_vht_cap cap_ie; |
1071 | struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap; | 1071 | struct ieee80211_sta_vht_cap cap = sta->sta.vht_cap; |
1072 | 1072 | ||
1073 | ieee80211_chandef_vht_oper(elems->vht_operation, | 1073 | ieee80211_chandef_vht_oper(&local->hw, |
1074 | elems->vht_operation, | ||
1075 | elems->ht_operation, | ||
1074 | &chandef); | 1076 | &chandef); |
1075 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); | 1077 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); |
1076 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1078 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 08da90adeaea..f40a2167935f 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -2112,7 +2112,9 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo); | |||
2112 | /* channel management */ | 2112 | /* channel management */ |
2113 | bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper, | 2113 | bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper, |
2114 | struct cfg80211_chan_def *chandef); | 2114 | struct cfg80211_chan_def *chandef); |
2115 | bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper, | 2115 | bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, |
2116 | const struct ieee80211_vht_operation *oper, | ||
2117 | const struct ieee80211_ht_operation *htop, | ||
2116 | struct cfg80211_chan_def *chandef); | 2118 | struct cfg80211_chan_def *chandef); |
2117 | u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); | 2119 | u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); |
2118 | 2120 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index d51da26e9c18..8bad414c52ad 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008, 2009 open80211s Ltd. | 2 | * Copyright (c) 2008, 2009 open80211s Ltd. |
3 | * Copyright (C) 2018 Intel Corporation | ||
3 | * Authors: Luis Carlos Cobo <luisca@cozybit.com> | 4 | * Authors: Luis Carlos Cobo <luisca@cozybit.com> |
4 | * Javier Cardona <javier@cozybit.com> | 5 | * Javier Cardona <javier@cozybit.com> |
5 | * | 6 | * |
@@ -98,7 +99,9 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
98 | cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan, | 99 | cfg80211_chandef_create(&sta_chan_def, sdata->vif.bss_conf.chandef.chan, |
99 | NL80211_CHAN_NO_HT); | 100 | NL80211_CHAN_NO_HT); |
100 | ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def); | 101 | ieee80211_chandef_ht_oper(ie->ht_operation, &sta_chan_def); |
101 | ieee80211_chandef_vht_oper(ie->vht_operation, &sta_chan_def); | 102 | ieee80211_chandef_vht_oper(&sdata->local->hw, |
103 | ie->vht_operation, ie->ht_operation, | ||
104 | &sta_chan_def); | ||
102 | 105 | ||
103 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, | 106 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, |
104 | &sta_chan_def)) | 107 | &sta_chan_def)) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3dbecae4be73..764a0f8e1dd1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -220,7 +220,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
220 | memcpy(&he_oper_vht_cap, he_oper->optional, 3); | 220 | memcpy(&he_oper_vht_cap, he_oper->optional, 3); |
221 | he_oper_vht_cap.basic_mcs_set = cpu_to_le16(0); | 221 | he_oper_vht_cap.basic_mcs_set = cpu_to_le16(0); |
222 | 222 | ||
223 | if (!ieee80211_chandef_vht_oper(&he_oper_vht_cap, | 223 | if (!ieee80211_chandef_vht_oper(&sdata->local->hw, |
224 | &he_oper_vht_cap, ht_oper, | ||
224 | &vht_chandef)) { | 225 | &vht_chandef)) { |
225 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) | 226 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) |
226 | sdata_info(sdata, | 227 | sdata_info(sdata, |
@@ -228,7 +229,8 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, | |||
228 | ret = IEEE80211_STA_DISABLE_HE; | 229 | ret = IEEE80211_STA_DISABLE_HE; |
229 | goto out; | 230 | goto out; |
230 | } | 231 | } |
231 | } else if (!ieee80211_chandef_vht_oper(vht_oper, &vht_chandef)) { | 232 | } else if (!ieee80211_chandef_vht_oper(&sdata->local->hw, vht_oper, |
233 | ht_oper, &vht_chandef)) { | ||
232 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 234 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
233 | sdata_info(sdata, | 235 | sdata_info(sdata, |
234 | "AP VHT information is invalid, disable VHT\n"); | 236 | "AP VHT information is invalid, disable VHT\n"); |
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 029334835747..4e4902bdbef8 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -144,6 +144,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | |||
144 | wide_bw_chansw_ie->new_center_freq_seg1, | 144 | wide_bw_chansw_ie->new_center_freq_seg1, |
145 | /* .basic_mcs_set doesn't matter */ | 145 | /* .basic_mcs_set doesn't matter */ |
146 | }; | 146 | }; |
147 | struct ieee80211_ht_operation ht_oper = {}; | ||
147 | 148 | ||
148 | /* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT, | 149 | /* default, for the case of IEEE80211_VHT_CHANWIDTH_USE_HT, |
149 | * to the previously parsed chandef | 150 | * to the previously parsed chandef |
@@ -151,7 +152,9 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, | |||
151 | new_vht_chandef = csa_ie->chandef; | 152 | new_vht_chandef = csa_ie->chandef; |
152 | 153 | ||
153 | /* ignore if parsing fails */ | 154 | /* ignore if parsing fails */ |
154 | if (!ieee80211_chandef_vht_oper(&vht_oper, &new_vht_chandef)) | 155 | if (!ieee80211_chandef_vht_oper(&sdata->local->hw, |
156 | &vht_oper, &ht_oper, | ||
157 | &new_vht_chandef)) | ||
155 | new_vht_chandef.chan = NULL; | 158 | new_vht_chandef.chan = NULL; |
156 | 159 | ||
157 | if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ && | 160 | if (sta_flags & IEEE80211_STA_DISABLE_80P80MHZ && |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b51fdcb5adf9..36a3c2ada515 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -2757,49 +2757,65 @@ bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper, | |||
2757 | return true; | 2757 | return true; |
2758 | } | 2758 | } |
2759 | 2759 | ||
2760 | bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper, | 2760 | bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, |
2761 | const struct ieee80211_vht_operation *oper, | ||
2762 | const struct ieee80211_ht_operation *htop, | ||
2761 | struct cfg80211_chan_def *chandef) | 2763 | struct cfg80211_chan_def *chandef) |
2762 | { | 2764 | { |
2763 | struct cfg80211_chan_def new = *chandef; | 2765 | struct cfg80211_chan_def new = *chandef; |
2764 | int cf1, cf2; | 2766 | int cf0, cf1; |
2767 | int ccfs0, ccfs1, ccfs2; | ||
2768 | int ccf0, ccf1; | ||
2765 | 2769 | ||
2766 | if (!oper) | 2770 | if (!oper || !htop) |
2767 | return false; | 2771 | return false; |
2768 | 2772 | ||
2769 | cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg0_idx, | 2773 | ccfs0 = oper->center_freq_seg0_idx; |
2770 | chandef->chan->band); | 2774 | ccfs1 = oper->center_freq_seg1_idx; |
2771 | cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx, | 2775 | ccfs2 = (le16_to_cpu(htop->operation_mode) & |
2772 | chandef->chan->band); | 2776 | IEEE80211_HT_OP_MODE_CCFS2_MASK) |
2777 | >> IEEE80211_HT_OP_MODE_CCFS2_SHIFT; | ||
2778 | |||
2779 | /* when parsing (and we know how to) CCFS1 and CCFS2 are equivalent */ | ||
2780 | ccf0 = ccfs0; | ||
2781 | ccf1 = ccfs1; | ||
2782 | if (!ccfs1 && ieee80211_hw_check(hw, SUPPORTS_VHT_EXT_NSS_BW)) | ||
2783 | ccf1 = ccfs2; | ||
2784 | |||
2785 | cf0 = ieee80211_channel_to_frequency(ccf0, chandef->chan->band); | ||
2786 | cf1 = ieee80211_channel_to_frequency(ccf1, chandef->chan->band); | ||
2773 | 2787 | ||
2774 | switch (oper->chan_width) { | 2788 | switch (oper->chan_width) { |
2775 | case IEEE80211_VHT_CHANWIDTH_USE_HT: | 2789 | case IEEE80211_VHT_CHANWIDTH_USE_HT: |
2790 | /* just use HT information directly */ | ||
2776 | break; | 2791 | break; |
2777 | case IEEE80211_VHT_CHANWIDTH_80MHZ: | 2792 | case IEEE80211_VHT_CHANWIDTH_80MHZ: |
2778 | new.width = NL80211_CHAN_WIDTH_80; | 2793 | new.width = NL80211_CHAN_WIDTH_80; |
2779 | new.center_freq1 = cf1; | 2794 | new.center_freq1 = cf0; |
2780 | /* If needed, adjust based on the newer interop workaround. */ | 2795 | /* If needed, adjust based on the newer interop workaround. */ |
2781 | if (oper->center_freq_seg1_idx) { | 2796 | if (ccf1) { |
2782 | unsigned int diff; | 2797 | unsigned int diff; |
2783 | 2798 | ||
2784 | diff = abs(oper->center_freq_seg1_idx - | 2799 | diff = abs(ccf1 - ccf0); |
2785 | oper->center_freq_seg0_idx); | ||
2786 | if (diff == 8) { | 2800 | if (diff == 8) { |
2787 | new.width = NL80211_CHAN_WIDTH_160; | 2801 | new.width = NL80211_CHAN_WIDTH_160; |
2788 | new.center_freq1 = cf2; | 2802 | new.center_freq1 = cf1; |
2789 | } else if (diff > 8) { | 2803 | } else if (diff > 8) { |
2790 | new.width = NL80211_CHAN_WIDTH_80P80; | 2804 | new.width = NL80211_CHAN_WIDTH_80P80; |
2791 | new.center_freq2 = cf2; | 2805 | new.center_freq2 = cf1; |
2792 | } | 2806 | } |
2793 | } | 2807 | } |
2794 | break; | 2808 | break; |
2795 | case IEEE80211_VHT_CHANWIDTH_160MHZ: | 2809 | case IEEE80211_VHT_CHANWIDTH_160MHZ: |
2810 | /* deprecated encoding */ | ||
2796 | new.width = NL80211_CHAN_WIDTH_160; | 2811 | new.width = NL80211_CHAN_WIDTH_160; |
2797 | new.center_freq1 = cf1; | 2812 | new.center_freq1 = cf0; |
2798 | break; | 2813 | break; |
2799 | case IEEE80211_VHT_CHANWIDTH_80P80MHZ: | 2814 | case IEEE80211_VHT_CHANWIDTH_80P80MHZ: |
2815 | /* deprecated encoding */ | ||
2800 | new.width = NL80211_CHAN_WIDTH_80P80; | 2816 | new.width = NL80211_CHAN_WIDTH_80P80; |
2801 | new.center_freq1 = cf1; | 2817 | new.center_freq1 = cf0; |
2802 | new.center_freq2 = cf2; | 2818 | new.center_freq2 = cf1; |
2803 | break; | 2819 | break; |
2804 | default: | 2820 | default: |
2805 | return false; | 2821 | return false; |