diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-06-15 07:42:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-06-15 15:05:58 -0400 |
commit | 7e9debe9789456426ec8574ead879e33da19ee57 (patch) | |
tree | d1158594e3b9ea1b54e6e24f7bf370a68e6105eb /net | |
parent | db2e6bd4e966a36c6b2f1921feb3537e8254415c (diff) |
mac80211: disconnect when user changes channel
If we do not disconnect when a channel switch is requested,
we end up eventually detection beacon loss from the AP and
then disconnecting, without ever really telling the AP, so
we might just as well disconnect right away.
Additionally, this fixes a problem with iwlwifi where the
driver will clear some internal state on channel changes
like this and then get confused when we actually go clear
that state from mac80211.
It may look like this patch drops the no-IBSS check, but
that is already handled by cfg80211 in the wext handler it
provides for IBSS (cfg80211_ibss_wext_siwfreq).
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 5 | ||||
-rw-r--r-- | net/mac80211/util.c | 25 | ||||
-rw-r--r-- | net/mac80211/wext.c | 31 |
4 files changed, 31 insertions, 31 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f41fe1f1430c..68eb5052179a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1101,7 +1101,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
1101 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | 1101 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
1102 | struct ieee802_11_elems *elems, | 1102 | struct ieee802_11_elems *elems, |
1103 | u64 filter, u32 crc); | 1103 | u64 filter, u32 crc); |
1104 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); | ||
1105 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 1104 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
1106 | enum ieee80211_band band); | 1105 | enum ieee80211_band band); |
1107 | 1106 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e5de9cea0034..84e59b9b493a 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2223,7 +2223,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) | |||
2223 | capa_mask, capa_val); | 2223 | capa_mask, capa_val); |
2224 | 2224 | ||
2225 | if (bss) { | 2225 | if (bss) { |
2226 | ieee80211_set_freq(sdata, bss->cbss.channel->center_freq); | 2226 | local->oper_channel = bss->cbss.channel; |
2227 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
2228 | ieee80211_hw_config(local, 0); | ||
2229 | |||
2227 | if (!(ifmgd->flags & IEEE80211_STA_SSID_SET)) | 2230 | if (!(ifmgd->flags & IEEE80211_STA_SSID_SET)) |
2228 | ieee80211_sta_set_ssid(sdata, bss->ssid, | 2231 | ieee80211_sta_set_ssid(sdata, bss->ssid, |
2229 | bss->ssid_len); | 2232 | bss->ssid_len); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 66ce96a69f31..915e77769312 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -774,31 +774,6 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
774 | dev_queue_xmit(skb); | 774 | dev_queue_xmit(skb); |
775 | } | 775 | } |
776 | 776 | ||
777 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | ||
778 | { | ||
779 | int ret = -EINVAL; | ||
780 | struct ieee80211_channel *chan; | ||
781 | struct ieee80211_local *local = sdata->local; | ||
782 | |||
783 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | ||
784 | |||
785 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
786 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
787 | chan->flags & IEEE80211_CHAN_NO_IBSS) | ||
788 | return ret; | ||
789 | local->oper_channel = chan; | ||
790 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
791 | |||
792 | if (local->sw_scanning || local->hw_scanning) | ||
793 | ret = 0; | ||
794 | else | ||
795 | ret = ieee80211_hw_config( | ||
796 | local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
797 | } | ||
798 | |||
799 | return ret; | ||
800 | } | ||
801 | |||
802 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 777 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
803 | enum ieee80211_band band) | 778 | enum ieee80211_band band) |
804 | { | 779 | { |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index d2d81b103341..1da81f456744 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -55,6 +55,8 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
55 | struct iw_freq *freq, char *extra) | 55 | struct iw_freq *freq, char *extra) |
56 | { | 56 | { |
57 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 57 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
58 | struct ieee80211_local *local = sdata->local; | ||
59 | struct ieee80211_channel *chan; | ||
58 | 60 | ||
59 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 61 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
60 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | 62 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); |
@@ -69,17 +71,38 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
69 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 71 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
70 | return 0; | 72 | return 0; |
71 | } else | 73 | } else |
72 | return ieee80211_set_freq(sdata, | 74 | chan = ieee80211_get_channel(local->hw.wiphy, |
73 | ieee80211_channel_to_frequency(freq->m)); | 75 | ieee80211_channel_to_frequency(freq->m)); |
74 | } else { | 76 | } else { |
75 | int i, div = 1000000; | 77 | int i, div = 1000000; |
76 | for (i = 0; i < freq->e; i++) | 78 | for (i = 0; i < freq->e; i++) |
77 | div /= 10; | 79 | div /= 10; |
78 | if (div > 0) | 80 | if (div <= 0) |
79 | return ieee80211_set_freq(sdata, freq->m / div); | ||
80 | else | ||
81 | return -EINVAL; | 81 | return -EINVAL; |
82 | chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div); | ||
82 | } | 83 | } |
84 | |||
85 | if (!chan) | ||
86 | return -EINVAL; | ||
87 | |||
88 | if (chan->flags & IEEE80211_CHAN_DISABLED) | ||
89 | return -EINVAL; | ||
90 | |||
91 | /* | ||
92 | * no change except maybe auto -> fixed, ignore the HT | ||
93 | * setting so you can fix a channel you're on already | ||
94 | */ | ||
95 | if (local->oper_channel == chan) | ||
96 | return 0; | ||
97 | |||
98 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
99 | ieee80211_sta_req_auth(sdata); | ||
100 | |||
101 | local->oper_channel = chan; | ||
102 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
103 | ieee80211_hw_config(local, 0); | ||
104 | |||
105 | return 0; | ||
83 | } | 106 | } |
84 | 107 | ||
85 | 108 | ||