diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/chan.c | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f0f87e5a1d35..0bfc914ddd15 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -68,16 +68,14 @@ ieee80211_get_channel_mode(struct ieee80211_local *local, | |||
68 | return mode; | 68 | return mode; |
69 | } | 69 | } |
70 | 70 | ||
71 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | 71 | static enum nl80211_channel_type |
72 | struct ieee80211_sub_if_data *sdata, | 72 | ieee80211_get_superchan(struct ieee80211_local *local, |
73 | enum nl80211_channel_type chantype) | 73 | struct ieee80211_sub_if_data *sdata) |
74 | { | 74 | { |
75 | struct ieee80211_sub_if_data *tmp; | ||
76 | enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; | 75 | enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT; |
77 | bool result; | 76 | struct ieee80211_sub_if_data *tmp; |
78 | 77 | ||
79 | mutex_lock(&local->iflist_mtx); | 78 | mutex_lock(&local->iflist_mtx); |
80 | |||
81 | list_for_each_entry(tmp, &local->interfaces, list) { | 79 | list_for_each_entry(tmp, &local->interfaces, list) { |
82 | if (tmp == sdata) | 80 | if (tmp == sdata) |
83 | continue; | 81 | continue; |
@@ -103,39 +101,70 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
103 | break; | 101 | break; |
104 | } | 102 | } |
105 | } | 103 | } |
104 | mutex_unlock(&local->iflist_mtx); | ||
106 | 105 | ||
107 | switch (superchan) { | 106 | return superchan; |
107 | } | ||
108 | |||
109 | static bool | ||
110 | ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, | ||
111 | enum nl80211_channel_type chantype2, | ||
112 | enum nl80211_channel_type *compat) | ||
113 | { | ||
114 | /* | ||
115 | * start out with chantype1 being the result, | ||
116 | * overwriting later if needed | ||
117 | */ | ||
118 | if (compat) | ||
119 | *compat = chantype1; | ||
120 | |||
121 | switch (chantype1) { | ||
108 | case NL80211_CHAN_NO_HT: | 122 | case NL80211_CHAN_NO_HT: |
123 | if (compat) | ||
124 | *compat = chantype2; | ||
125 | break; | ||
109 | case NL80211_CHAN_HT20: | 126 | case NL80211_CHAN_HT20: |
110 | /* | 127 | /* |
111 | * allow any change that doesn't go to no-HT | 128 | * allow any change that doesn't go to no-HT |
112 | * (if it already is no-HT no change is needed) | 129 | * (if it already is no-HT no change is needed) |
113 | */ | 130 | */ |
114 | if (chantype == NL80211_CHAN_NO_HT) | 131 | if (chantype2 == NL80211_CHAN_NO_HT) |
115 | break; | 132 | break; |
116 | superchan = chantype; | 133 | if (compat) |
134 | *compat = chantype2; | ||
117 | break; | 135 | break; |
118 | case NL80211_CHAN_HT40PLUS: | 136 | case NL80211_CHAN_HT40PLUS: |
119 | case NL80211_CHAN_HT40MINUS: | 137 | case NL80211_CHAN_HT40MINUS: |
120 | /* allow smaller bandwidth and same */ | 138 | /* allow smaller bandwidth and same */ |
121 | if (chantype == NL80211_CHAN_NO_HT) | 139 | if (chantype2 == NL80211_CHAN_NO_HT) |
122 | break; | 140 | break; |
123 | if (chantype == NL80211_CHAN_HT20) | 141 | if (chantype2 == NL80211_CHAN_HT20) |
124 | break; | 142 | break; |
125 | if (superchan == chantype) | 143 | if (chantype2 == chantype1) |
126 | break; | 144 | break; |
127 | result = false; | 145 | return false; |
128 | goto out; | ||
129 | } | 146 | } |
130 | 147 | ||
131 | local->_oper_channel_type = superchan; | 148 | return true; |
149 | } | ||
150 | |||
151 | bool ieee80211_set_channel_type(struct ieee80211_local *local, | ||
152 | struct ieee80211_sub_if_data *sdata, | ||
153 | enum nl80211_channel_type chantype) | ||
154 | { | ||
155 | enum nl80211_channel_type superchan; | ||
156 | enum nl80211_channel_type compatchan; | ||
157 | |||
158 | superchan = ieee80211_get_superchan(local, sdata); | ||
159 | if (!ieee80211_channel_types_are_compatible(superchan, chantype, | ||
160 | &compatchan)) | ||
161 | return false; | ||
162 | |||
163 | local->_oper_channel_type = compatchan; | ||
132 | 164 | ||
133 | if (sdata) | 165 | if (sdata) |
134 | sdata->vif.bss_conf.channel_type = chantype; | 166 | sdata->vif.bss_conf.channel_type = chantype; |
135 | 167 | ||
136 | result = true; | 168 | return true; |
137 | out: | ||
138 | mutex_unlock(&local->iflist_mtx); | ||
139 | 169 | ||
140 | return result; | ||
141 | } | 170 | } |