summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2018-08-31 04:31:18 -0400
committerJohannes Berg <johannes.berg@intel.com>2018-09-05 04:03:14 -0400
commit7eb26df2972504ffe37da77612c0e5f714f0d6df (patch)
tree4c3044951104f8765a40e55ae651072f90a10473
parent09b4a4faf9d037990ac4f8110dd944b27b42d5df (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.c4
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/mesh.c5
-rw-r--r--net/mac80211/mlme.c6
-rw-r--r--net/mac80211/spectmgmt.c5
-rw-r--r--net/mac80211/util.c48
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 */
2113bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper, 2113bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
2114 struct cfg80211_chan_def *chandef); 2114 struct cfg80211_chan_def *chandef);
2115bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper, 2115bool 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);
2117u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c); 2119u32 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
2760bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper, 2760bool 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;