aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c165
1 files changed, 74 insertions, 91 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 5ca62ea15079..b80bc80e46cf 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -26,6 +26,7 @@
26#include <net/cfg80211.h> 26#include <net/cfg80211.h>
27 27
28#include "ieee80211_i.h" 28#include "ieee80211_i.h"
29#include "driver-ops.h"
29#include "rate.h" 30#include "rate.h"
30#include "mesh.h" 31#include "mesh.h"
31#include "wep.h" 32#include "wep.h"
@@ -81,10 +82,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
81 /* be a bit nasty */ 82 /* be a bit nasty */
82 new_flags |= (1<<31); 83 new_flags |= (1<<31);
83 84
84 local->ops->configure_filter(local_to_hw(local), 85 drv_configure_filter(local, changed_flags, &new_flags,
85 changed_flags, &new_flags, 86 local->mdev->mc_count,
86 local->mdev->mc_count, 87 local->mdev->mc_list);
87 local->mdev->mc_list);
88 88
89 WARN_ON(new_flags & (1<<31)); 89 WARN_ON(new_flags & (1<<31));
90 90
@@ -152,82 +152,6 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev)
152 ieee80211_configure_filter(local); 152 ieee80211_configure_filter(local);
153} 153}
154 154
155/* everything else */
156
157int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
158{
159 struct ieee80211_local *local = sdata->local;
160 struct ieee80211_if_conf conf;
161
162 if (WARN_ON(!netif_running(sdata->dev)))
163 return 0;
164
165 memset(&conf, 0, sizeof(conf));
166
167 if (sdata->vif.type == NL80211_IFTYPE_STATION)
168 conf.bssid = sdata->u.mgd.bssid;
169 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
170 conf.bssid = sdata->u.ibss.bssid;
171 else if (sdata->vif.type == NL80211_IFTYPE_AP)
172 conf.bssid = sdata->dev->dev_addr;
173 else if (ieee80211_vif_is_mesh(&sdata->vif)) {
174 static const u8 zero[ETH_ALEN] = { 0 };
175 conf.bssid = zero;
176 } else {
177 WARN_ON(1);
178 return -EINVAL;
179 }
180
181 if (!local->ops->config_interface)
182 return 0;
183
184 switch (sdata->vif.type) {
185 case NL80211_IFTYPE_AP:
186 case NL80211_IFTYPE_ADHOC:
187 case NL80211_IFTYPE_MESH_POINT:
188 break;
189 default:
190 /* do not warn to simplify caller in scan.c */
191 changed &= ~IEEE80211_IFCC_BEACON_ENABLED;
192 if (WARN_ON(changed & IEEE80211_IFCC_BEACON))
193 return -EINVAL;
194 changed &= ~IEEE80211_IFCC_BEACON;
195 break;
196 }
197
198 if (changed & IEEE80211_IFCC_BEACON_ENABLED) {
199 if (local->sw_scanning) {
200 conf.enable_beacon = false;
201 } else {
202 /*
203 * Beacon should be enabled, but AP mode must
204 * check whether there is a beacon configured.
205 */
206 switch (sdata->vif.type) {
207 case NL80211_IFTYPE_AP:
208 conf.enable_beacon =
209 !!rcu_dereference(sdata->u.ap.beacon);
210 break;
211 case NL80211_IFTYPE_ADHOC:
212 conf.enable_beacon = !!sdata->u.ibss.presp;
213 break;
214 case NL80211_IFTYPE_MESH_POINT:
215 conf.enable_beacon = true;
216 break;
217 default:
218 /* not reached */
219 WARN_ON(1);
220 break;
221 }
222 }
223 }
224
225 conf.changed = changed;
226
227 return local->ops->config_interface(local_to_hw(local),
228 &sdata->vif, &conf);
229}
230
231int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) 155int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
232{ 156{
233 struct ieee80211_channel *chan; 157 struct ieee80211_channel *chan;
@@ -268,7 +192,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
268 } 192 }
269 193
270 if (changed && local->open_count) { 194 if (changed && local->open_count) {
271 ret = local->ops->config(local_to_hw(local), changed); 195 ret = drv_config(local, changed);
272 /* 196 /*
273 * Goal: 197 * Goal:
274 * HW reconfiguration should never fail, the driver has told 198 * HW reconfiguration should never fail, the driver has told
@@ -294,17 +218,77 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
294{ 218{
295 struct ieee80211_local *local = sdata->local; 219 struct ieee80211_local *local = sdata->local;
296 220
297 if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) 221 if (!changed)
298 return; 222 return;
299 223
300 if (!changed) 224 if (sdata->vif.type == NL80211_IFTYPE_STATION)
225 sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
226 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
227 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
228 else if (sdata->vif.type == NL80211_IFTYPE_AP)
229 sdata->vif.bss_conf.bssid = sdata->dev->dev_addr;
230 else if (ieee80211_vif_is_mesh(&sdata->vif)) {
231 static const u8 zero[ETH_ALEN] = { 0 };
232 sdata->vif.bss_conf.bssid = zero;
233 } else {
234 WARN_ON(1);
301 return; 235 return;
236 }
237
238 switch (sdata->vif.type) {
239 case NL80211_IFTYPE_AP:
240 case NL80211_IFTYPE_ADHOC:
241 case NL80211_IFTYPE_MESH_POINT:
242 break;
243 default:
244 /* do not warn to simplify caller in scan.c */
245 changed &= ~BSS_CHANGED_BEACON_ENABLED;
246 if (WARN_ON(changed & BSS_CHANGED_BEACON))
247 return;
248 break;
249 }
250
251 if (changed & BSS_CHANGED_BEACON_ENABLED) {
252 if (local->sw_scanning) {
253 sdata->vif.bss_conf.enable_beacon = false;
254 } else {
255 /*
256 * Beacon should be enabled, but AP mode must
257 * check whether there is a beacon configured.
258 */
259 switch (sdata->vif.type) {
260 case NL80211_IFTYPE_AP:
261 sdata->vif.bss_conf.enable_beacon =
262 !!rcu_dereference(sdata->u.ap.beacon);
263 break;
264 case NL80211_IFTYPE_ADHOC:
265 sdata->vif.bss_conf.enable_beacon =
266 !!rcu_dereference(sdata->u.ibss.presp);
267 break;
268 case NL80211_IFTYPE_MESH_POINT:
269 sdata->vif.bss_conf.enable_beacon = true;
270 break;
271 default:
272 /* not reached */
273 WARN_ON(1);
274 break;
275 }
276 }
277 }
302 278
303 if (local->ops->bss_info_changed) 279 drv_bss_info_changed(local, &sdata->vif,
304 local->ops->bss_info_changed(local_to_hw(local), 280 &sdata->vif.bss_conf, changed);
305 &sdata->vif, 281
306 &sdata->vif.bss_conf, 282 /*
307 changed); 283 * DEPRECATED
284 *
285 * ~changed is just there to not do this at resume time
286 */
287 if (changed & BSS_CHANGED_BEACON_INT && ~changed) {
288 local->hw.conf.beacon_int = sdata->vif.bss_conf.beacon_int;
289 ieee80211_hw_config(local,
290 _IEEE80211_CONF_CHANGE_BEACON_INTERVAL);
291 }
308} 292}
309 293
310u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) 294u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
@@ -783,6 +767,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
783 767
784 INIT_LIST_HEAD(&local->interfaces); 768 INIT_LIST_HEAD(&local->interfaces);
785 mutex_init(&local->iflist_mtx); 769 mutex_init(&local->iflist_mtx);
770 mutex_init(&local->scan_mtx);
786 771
787 spin_lock_init(&local->key_lock); 772 spin_lock_init(&local->key_lock);
788 773
@@ -970,9 +955,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
970 955
971 debugfs_hw_add(local); 956 debugfs_hw_add(local);
972 957
973 if (local->hw.conf.beacon_int < 10)
974 local->hw.conf.beacon_int = 100;
975
976 if (local->hw.max_listen_interval == 0) 958 if (local->hw.max_listen_interval == 0)
977 local->hw.max_listen_interval = 1; 959 local->hw.max_listen_interval = 1;
978 960
@@ -1126,6 +1108,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
1126 struct ieee80211_local *local = hw_to_local(hw); 1108 struct ieee80211_local *local = hw_to_local(hw);
1127 1109
1128 mutex_destroy(&local->iflist_mtx); 1110 mutex_destroy(&local->iflist_mtx);
1111 mutex_destroy(&local->scan_mtx);
1129 1112
1130 wiphy_free(local->hw.wiphy); 1113 wiphy_free(local->hw.wiphy);
1131} 1114}