diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2008-12-12 01:27:43 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-12-19 15:22:54 -0500 |
commit | 094d05dc32fc2930e381189a942016e5561775d9 (patch) | |
tree | 4deedbcbe196f88cb8d9fe0cd0755775a7ff0939 /net | |
parent | 420e7fabd9c6d907280ed6b3e40eef425c5d8d8d (diff) |
mac80211: Fix HT channel selection
HT management is done differently for AP and STA modes, unify
to just the ->config() callback since HT is fundamentally a
PHY property and cannot be per-BSS.
Rename enum nl80211_sec_chan_offset as nl80211_channel_type to denote
the channel type ( NO_HT, HT20, HT40+, HT40- ).
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 4 | ||||
-rw-r--r-- | net/mac80211/ht.c | 35 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/main.c | 27 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 1 | ||||
-rw-r--r-- | net/mac80211/util.c | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 27 |
7 files changed, 52 insertions, 46 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 23b5eeaf7bc5..3ea0884c9432 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1122,12 +1122,12 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1122 | 1122 | ||
1123 | static int ieee80211_set_channel(struct wiphy *wiphy, | 1123 | static int ieee80211_set_channel(struct wiphy *wiphy, |
1124 | struct ieee80211_channel *chan, | 1124 | struct ieee80211_channel *chan, |
1125 | enum nl80211_sec_chan_offset sec_chan_offset) | 1125 | enum nl80211_channel_type channel_type) |
1126 | { | 1126 | { |
1127 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1127 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1128 | 1128 | ||
1129 | local->oper_channel = chan; | 1129 | local->oper_channel = chan; |
1130 | local->oper_sec_chan_offset = sec_chan_offset; | 1130 | local->oper_channel_type = channel_type; |
1131 | 1131 | ||
1132 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1132 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1133 | } | 1133 | } |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index a1eed7032c9b..5f510a13b9f0 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -98,6 +98,7 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
98 | struct ieee80211_bss_ht_conf ht; | 98 | struct ieee80211_bss_ht_conf ht; |
99 | u32 changed = 0; | 99 | u32 changed = 0; |
100 | bool enable_ht = true, ht_changed; | 100 | bool enable_ht = true, ht_changed; |
101 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
101 | 102 | ||
102 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 103 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
103 | 104 | ||
@@ -112,24 +113,36 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
112 | ieee80211_channel_to_frequency(hti->control_chan)) | 113 | ieee80211_channel_to_frequency(hti->control_chan)) |
113 | enable_ht = false; | 114 | enable_ht = false; |
114 | 115 | ||
115 | /* | 116 | if (enable_ht) { |
116 | * XXX: This is totally incorrect when there are multiple virtual | 117 | channel_type = NL80211_CHAN_HT20; |
117 | * interfaces, needs to be fixed later. | 118 | |
118 | */ | 119 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && |
119 | ht_changed = local->hw.conf.ht.enabled != enable_ht; | 120 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && |
121 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | ||
122 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
123 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
124 | channel_type = NL80211_CHAN_HT40PLUS; | ||
125 | break; | ||
126 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
127 | channel_type = NL80211_CHAN_HT40MINUS; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
133 | ht_changed = local->hw.conf.ht.enabled != enable_ht || | ||
134 | channel_type != local->hw.conf.ht.channel_type; | ||
135 | |||
136 | local->oper_channel_type = channel_type; | ||
120 | local->hw.conf.ht.enabled = enable_ht; | 137 | local->hw.conf.ht.enabled = enable_ht; |
138 | |||
121 | if (ht_changed) | 139 | if (ht_changed) |
122 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | 140 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); |
123 | 141 | ||
124 | /* disable HT */ | 142 | /* disable HT */ |
125 | if (!enable_ht) | 143 | if (!enable_ht) |
126 | return 0; | 144 | return 0; |
127 | ht.secondary_channel_offset = | 145 | |
128 | hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
129 | ht.width_40_ok = | ||
130 | !(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
131 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && | ||
132 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY); | ||
133 | ht.operation_mode = le16_to_cpu(hti->operation_mode); | 146 | ht.operation_mode = le16_to_cpu(hti->operation_mode); |
134 | 147 | ||
135 | /* if bss configuration changed store the new one */ | 148 | /* if bss configuration changed store the new one */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f59e11d7b33..a7dabaecfc72 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -625,7 +625,7 @@ struct ieee80211_local { | |||
625 | struct delayed_work scan_work; | 625 | struct delayed_work scan_work; |
626 | struct ieee80211_sub_if_data *scan_sdata; | 626 | struct ieee80211_sub_if_data *scan_sdata; |
627 | struct ieee80211_channel *oper_channel, *scan_channel; | 627 | struct ieee80211_channel *oper_channel, *scan_channel; |
628 | enum nl80211_sec_chan_offset oper_sec_chan_offset; | 628 | enum nl80211_channel_type oper_channel_type; |
629 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 629 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
630 | size_t scan_ssid_len; | 630 | size_t scan_ssid_len; |
631 | struct list_head bss_list; | 631 | struct list_head bss_list; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6d8710327d14..a0371caf01ce 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -195,37 +195,30 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
195 | struct ieee80211_channel *chan; | 195 | struct ieee80211_channel *chan; |
196 | int ret = 0; | 196 | int ret = 0; |
197 | int power; | 197 | int power; |
198 | enum nl80211_sec_chan_offset sec_chan_offset; | 198 | enum nl80211_channel_type channel_type; |
199 | 199 | ||
200 | might_sleep(); | 200 | might_sleep(); |
201 | 201 | ||
202 | if (local->sw_scanning) { | 202 | if (local->sw_scanning) { |
203 | chan = local->scan_channel; | 203 | chan = local->scan_channel; |
204 | sec_chan_offset = NL80211_SEC_CHAN_NO_HT; | 204 | channel_type = NL80211_CHAN_NO_HT; |
205 | } else { | 205 | } else { |
206 | chan = local->oper_channel; | 206 | chan = local->oper_channel; |
207 | sec_chan_offset = local->oper_sec_chan_offset; | 207 | channel_type = local->oper_channel_type; |
208 | } | 208 | } |
209 | 209 | ||
210 | if (chan != local->hw.conf.channel || | 210 | if (chan != local->hw.conf.channel || |
211 | sec_chan_offset != local->hw.conf.ht.sec_chan_offset) { | 211 | channel_type != local->hw.conf.ht.channel_type) { |
212 | local->hw.conf.channel = chan; | 212 | local->hw.conf.channel = chan; |
213 | switch (sec_chan_offset) { | 213 | local->hw.conf.ht.channel_type = channel_type; |
214 | case NL80211_SEC_CHAN_NO_HT: | 214 | switch (channel_type) { |
215 | case NL80211_CHAN_NO_HT: | ||
215 | local->hw.conf.ht.enabled = false; | 216 | local->hw.conf.ht.enabled = false; |
216 | local->hw.conf.ht.sec_chan_offset = 0; | ||
217 | break; | 217 | break; |
218 | case NL80211_SEC_CHAN_DISABLED: | 218 | case NL80211_CHAN_HT20: |
219 | case NL80211_CHAN_HT40MINUS: | ||
220 | case NL80211_CHAN_HT40PLUS: | ||
219 | local->hw.conf.ht.enabled = true; | 221 | local->hw.conf.ht.enabled = true; |
220 | local->hw.conf.ht.sec_chan_offset = 0; | ||
221 | break; | ||
222 | case NL80211_SEC_CHAN_BELOW: | ||
223 | local->hw.conf.ht.enabled = true; | ||
224 | local->hw.conf.ht.sec_chan_offset = -1; | ||
225 | break; | ||
226 | case NL80211_SEC_CHAN_ABOVE: | ||
227 | local->hw.conf.ht.enabled = true; | ||
228 | local->hw.conf.ht.sec_chan_offset = 1; | ||
229 | break; | 222 | break; |
230 | } | 223 | } |
231 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 224 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 290b0017ef2e..e4d1fca5c72d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -858,6 +858,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
858 | rcu_read_unlock(); | 858 | rcu_read_unlock(); |
859 | 859 | ||
860 | local->hw.conf.ht.enabled = false; | 860 | local->hw.conf.ht.enabled = false; |
861 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
861 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | 862 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); |
862 | 863 | ||
863 | ieee80211_bss_info_change_notify(sdata, changed); | 864 | ieee80211_bss_info_change_notify(sdata, changed); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 505d68f344ce..71a8391c54f6 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -641,7 +641,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | |||
641 | chan->flags & IEEE80211_CHAN_NO_IBSS) | 641 | chan->flags & IEEE80211_CHAN_NO_IBSS) |
642 | return ret; | 642 | return ret; |
643 | local->oper_channel = chan; | 643 | local->oper_channel = chan; |
644 | local->oper_sec_chan_offset = NL80211_SEC_CHAN_NO_HT; | 644 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
645 | 645 | ||
646 | if (local->sw_scanning || local->hw_scanning) | 646 | if (local->sw_scanning || local->hw_scanning) |
647 | ret = 0; | 647 | ret = 0; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 93c9b983ce08..1e728fff474e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -60,7 +60,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
60 | .len = BUS_ID_SIZE-1 }, | 60 | .len = BUS_ID_SIZE-1 }, |
61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | 61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | 62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, |
63 | [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 }, | 63 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, |
64 | 64 | ||
65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
@@ -362,8 +362,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
362 | } | 362 | } |
363 | 363 | ||
364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
365 | enum nl80211_sec_chan_offset sec_chan_offset = | 365 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
366 | NL80211_SEC_CHAN_NO_HT; | ||
367 | struct ieee80211_channel *chan; | 366 | struct ieee80211_channel *chan; |
368 | struct ieee80211_sta_ht_cap *ht_cap; | 367 | struct ieee80211_sta_ht_cap *ht_cap; |
369 | u32 freq, sec_freq; | 368 | u32 freq, sec_freq; |
@@ -375,13 +374,13 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
375 | 374 | ||
376 | result = -EINVAL; | 375 | result = -EINVAL; |
377 | 376 | ||
378 | if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { | 377 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
379 | sec_chan_offset = nla_get_u32(info->attrs[ | 378 | channel_type = nla_get_u32(info->attrs[ |
380 | NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); | 379 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); |
381 | if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && | 380 | if (channel_type != NL80211_CHAN_NO_HT && |
382 | sec_chan_offset != NL80211_SEC_CHAN_DISABLED && | 381 | channel_type != NL80211_CHAN_HT20 && |
383 | sec_chan_offset != NL80211_SEC_CHAN_BELOW && | 382 | channel_type != NL80211_CHAN_HT40PLUS && |
384 | sec_chan_offset != NL80211_SEC_CHAN_ABOVE) | 383 | channel_type != NL80211_CHAN_HT40MINUS) |
385 | goto bad_res; | 384 | goto bad_res; |
386 | } | 385 | } |
387 | 386 | ||
@@ -392,9 +391,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
392 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | 391 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) |
393 | goto bad_res; | 392 | goto bad_res; |
394 | 393 | ||
395 | if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) | 394 | if (channel_type == NL80211_CHAN_HT40MINUS) |
396 | sec_freq = freq - 20; | 395 | sec_freq = freq - 20; |
397 | else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) | 396 | else if (channel_type == NL80211_CHAN_HT40PLUS) |
398 | sec_freq = freq + 20; | 397 | sec_freq = freq + 20; |
399 | else | 398 | else |
400 | sec_freq = 0; | 399 | sec_freq = 0; |
@@ -402,7 +401,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
402 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | 401 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; |
403 | 402 | ||
404 | /* no HT capabilities */ | 403 | /* no HT capabilities */ |
405 | if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && | 404 | if (channel_type != NL80211_CHAN_NO_HT && |
406 | !ht_cap->ht_supported) | 405 | !ht_cap->ht_supported) |
407 | goto bad_res; | 406 | goto bad_res; |
408 | 407 | ||
@@ -422,7 +421,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
422 | } | 421 | } |
423 | 422 | ||
424 | result = rdev->ops->set_channel(&rdev->wiphy, chan, | 423 | result = rdev->ops->set_channel(&rdev->wiphy, chan, |
425 | sec_chan_offset); | 424 | channel_type); |
426 | if (result) | 425 | if (result) |
427 | goto bad_res; | 426 | goto bad_res; |
428 | } | 427 | } |