diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2010-05-05 09:28:27 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-05-07 14:55:51 -0400 |
commit | 0aaffa9b9699894aab3266195a529baf9f96ac29 (patch) | |
tree | 26fe5f5277ac6d7061ea723f92d4038b0c28b0b8 /net/mac80211/cfg.c | |
parent | f444de05d20e27cdd960c13fcbcfca3099f03143 (diff) |
mac80211: improve HT channel handling
Currently, when one interface switches HT mode,
all others will follow along. This is clearly
undesirable, since the new one might switch to
no-HT while another one is operating in HT.
Address this issue by keeping track of the HT
mode per interface, and allowing only changes
that are compatible, i.e. switching into HT40+
is not possible when another interface is in
HT40-, in that case the second one needs to
fall back to HT20.
Also, to allow drivers to know what's going on,
store the per-interface HT mode (channel type)
in the virtual interface's bss_conf.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 414b7dd7d7fd..ab166c6d9399 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1166,23 +1166,34 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1166 | enum nl80211_channel_type channel_type) | 1166 | enum nl80211_channel_type channel_type) |
1167 | { | 1167 | { |
1168 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1168 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1169 | struct ieee80211_sub_if_data *sdata = NULL; | ||
1170 | |||
1171 | if (netdev) | ||
1172 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | ||
1169 | 1173 | ||
1170 | switch (ieee80211_get_channel_mode(local, NULL)) { | 1174 | switch (ieee80211_get_channel_mode(local, NULL)) { |
1171 | case CHAN_MODE_HOPPING: | 1175 | case CHAN_MODE_HOPPING: |
1172 | return -EBUSY; | 1176 | return -EBUSY; |
1173 | case CHAN_MODE_FIXED: | 1177 | case CHAN_MODE_FIXED: |
1174 | if (local->oper_channel == chan && | 1178 | if (local->oper_channel != chan) |
1175 | local->oper_channel_type == channel_type) | 1179 | return -EBUSY; |
1180 | if (!sdata && local->_oper_channel_type == channel_type) | ||
1176 | return 0; | 1181 | return 0; |
1177 | return -EBUSY; | 1182 | break; |
1178 | case CHAN_MODE_UNDEFINED: | 1183 | case CHAN_MODE_UNDEFINED: |
1179 | break; | 1184 | break; |
1180 | } | 1185 | } |
1181 | 1186 | ||
1182 | local->oper_channel = chan; | 1187 | local->oper_channel = chan; |
1183 | local->oper_channel_type = channel_type; | ||
1184 | 1188 | ||
1185 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1189 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) |
1190 | return -EBUSY; | ||
1191 | |||
1192 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
1193 | if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
1194 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | ||
1195 | |||
1196 | return 0; | ||
1186 | } | 1197 | } |
1187 | 1198 | ||
1188 | #ifdef CONFIG_PM | 1199 | #ifdef CONFIG_PM |
@@ -1406,7 +1417,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1406 | * association, there's no need to send an action frame. | 1417 | * association, there's no need to send an action frame. |
1407 | */ | 1418 | */ |
1408 | if (!sdata->u.mgd.associated || | 1419 | if (!sdata->u.mgd.associated || |
1409 | sdata->local->oper_channel_type == NL80211_CHAN_NO_HT) { | 1420 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
1410 | mutex_lock(&sdata->local->iflist_mtx); | 1421 | mutex_lock(&sdata->local->iflist_mtx); |
1411 | ieee80211_recalc_smps(sdata->local, sdata); | 1422 | ieee80211_recalc_smps(sdata->local, sdata); |
1412 | mutex_unlock(&sdata->local->iflist_mtx); | 1423 | mutex_unlock(&sdata->local->iflist_mtx); |