diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/core/net-sysfs.c | 4 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 36 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 15 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 48 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.h | 5 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 67 | ||||
-rw-r--r-- | net/mac80211/iface.c | 392 | ||||
-rw-r--r-- | net/mac80211/main.c | 171 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 172 | ||||
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 8 | ||||
-rw-r--r-- | net/mac80211/rx.c | 38 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 29 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 1 | ||||
-rw-r--r-- | net/mac80211/tx.c | 126 | ||||
-rw-r--r-- | net/mac80211/util.c | 4 | ||||
-rw-r--r-- | net/mac80211/wext.c | 65 | ||||
-rw-r--r-- | net/wireless/Kconfig | 11 |
17 files changed, 547 insertions, 645 deletions
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 3f7941319217..c1f4e0d428c0 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -318,7 +318,7 @@ static struct attribute_group netstat_group = { | |||
318 | .attrs = netstat_attrs, | 318 | .attrs = netstat_attrs, |
319 | }; | 319 | }; |
320 | 320 | ||
321 | #ifdef CONFIG_WIRELESS_EXT | 321 | #ifdef CONFIG_WIRELESS_EXT_SYSFS |
322 | /* helper function that does all the locking etc for wireless stats */ | 322 | /* helper function that does all the locking etc for wireless stats */ |
323 | static ssize_t wireless_show(struct device *d, char *buf, | 323 | static ssize_t wireless_show(struct device *d, char *buf, |
324 | ssize_t (*format)(const struct iw_statistics *, | 324 | ssize_t (*format)(const struct iw_statistics *, |
@@ -459,7 +459,7 @@ int netdev_register_kobject(struct net_device *net) | |||
459 | #ifdef CONFIG_SYSFS | 459 | #ifdef CONFIG_SYSFS |
460 | *groups++ = &netstat_group; | 460 | *groups++ = &netstat_group; |
461 | 461 | ||
462 | #ifdef CONFIG_WIRELESS_EXT | 462 | #ifdef CONFIG_WIRELESS_EXT_SYSFS |
463 | if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats) | 463 | if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats) |
464 | *groups++ = &wireless_group; | 464 | *groups++ = &wireless_group; |
465 | #endif | 465 | #endif |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 81087281b031..8e7ba0e62cf5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -50,14 +50,11 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
50 | struct ieee80211_sub_if_data *sdata; | 50 | struct ieee80211_sub_if_data *sdata; |
51 | int err; | 51 | int err; |
52 | 52 | ||
53 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | ||
54 | return -ENODEV; | ||
55 | |||
56 | itype = nl80211_type_to_mac80211_type(type); | 53 | itype = nl80211_type_to_mac80211_type(type); |
57 | if (itype == IEEE80211_IF_TYPE_INVALID) | 54 | if (itype == IEEE80211_IF_TYPE_INVALID) |
58 | return -EINVAL; | 55 | return -EINVAL; |
59 | 56 | ||
60 | err = ieee80211_if_add(local->mdev, name, &dev, itype, params); | 57 | err = ieee80211_if_add(local, name, &dev, itype, params); |
61 | if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags) | 58 | if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags) |
62 | return err; | 59 | return err; |
63 | 60 | ||
@@ -68,54 +65,41 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
68 | 65 | ||
69 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | 66 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) |
70 | { | 67 | { |
71 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
72 | struct net_device *dev; | 68 | struct net_device *dev; |
73 | char *name; | ||
74 | |||
75 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | ||
76 | return -ENODEV; | ||
77 | 69 | ||
78 | /* we're under RTNL */ | 70 | /* we're under RTNL */ |
79 | dev = __dev_get_by_index(&init_net, ifindex); | 71 | dev = __dev_get_by_index(&init_net, ifindex); |
80 | if (!dev) | 72 | if (!dev) |
81 | return 0; | 73 | return -ENODEV; |
82 | 74 | ||
83 | name = dev->name; | 75 | ieee80211_if_remove(dev); |
84 | 76 | ||
85 | return ieee80211_if_remove(local->mdev, name, -1); | 77 | return 0; |
86 | } | 78 | } |
87 | 79 | ||
88 | static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | 80 | static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, |
89 | enum nl80211_iftype type, u32 *flags, | 81 | enum nl80211_iftype type, u32 *flags, |
90 | struct vif_params *params) | 82 | struct vif_params *params) |
91 | { | 83 | { |
92 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
93 | struct net_device *dev; | 84 | struct net_device *dev; |
94 | enum ieee80211_if_types itype; | 85 | enum ieee80211_if_types itype; |
95 | struct ieee80211_sub_if_data *sdata; | 86 | struct ieee80211_sub_if_data *sdata; |
96 | 87 | int ret; | |
97 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) | ||
98 | return -ENODEV; | ||
99 | 88 | ||
100 | /* we're under RTNL */ | 89 | /* we're under RTNL */ |
101 | dev = __dev_get_by_index(&init_net, ifindex); | 90 | dev = __dev_get_by_index(&init_net, ifindex); |
102 | if (!dev) | 91 | if (!dev) |
103 | return -ENODEV; | 92 | return -ENODEV; |
104 | 93 | ||
105 | if (netif_running(dev)) | ||
106 | return -EBUSY; | ||
107 | |||
108 | itype = nl80211_type_to_mac80211_type(type); | 94 | itype = nl80211_type_to_mac80211_type(type); |
109 | if (itype == IEEE80211_IF_TYPE_INVALID) | 95 | if (itype == IEEE80211_IF_TYPE_INVALID) |
110 | return -EINVAL; | 96 | return -EINVAL; |
111 | 97 | ||
112 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 98 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
113 | 99 | ||
114 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 100 | ret = ieee80211_if_change_type(sdata, itype); |
115 | return -EOPNOTSUPP; | 101 | if (ret) |
116 | 102 | return ret; | |
117 | ieee80211_if_reinit(dev); | ||
118 | ieee80211_if_set_type(dev, itype); | ||
119 | 103 | ||
120 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 104 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
121 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 105 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, |
@@ -485,7 +469,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
485 | 469 | ||
486 | kfree(old); | 470 | kfree(old); |
487 | 471 | ||
488 | return ieee80211_if_config_beacon(sdata->dev); | 472 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
489 | } | 473 | } |
490 | 474 | ||
491 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 475 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
@@ -539,7 +523,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
539 | synchronize_rcu(); | 523 | synchronize_rcu(); |
540 | kfree(old); | 524 | kfree(old); |
541 | 525 | ||
542 | return ieee80211_if_config_beacon(dev); | 526 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
543 | } | 527 | } |
544 | 528 | ||
545 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ | 529 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index d20d90eead1f..ee509f1109e2 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -70,16 +70,6 @@ DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", | |||
70 | 70 | ||
71 | /* statistics stuff */ | 71 | /* statistics stuff */ |
72 | 72 | ||
73 | static inline int rtnl_lock_local(struct ieee80211_local *local) | ||
74 | { | ||
75 | rtnl_lock(); | ||
76 | if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) { | ||
77 | rtnl_unlock(); | ||
78 | return -ENODEV; | ||
79 | } | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ | 73 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ |
84 | DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value) | 74 | DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value) |
85 | 75 | ||
@@ -96,10 +86,7 @@ static ssize_t format_devstat_counter(struct ieee80211_local *local, | |||
96 | if (!local->ops->get_stats) | 86 | if (!local->ops->get_stats) |
97 | return -EOPNOTSUPP; | 87 | return -EOPNOTSUPP; |
98 | 88 | ||
99 | res = rtnl_lock_local(local); | 89 | rtnl_lock(); |
100 | if (res) | ||
101 | return res; | ||
102 | |||
103 | res = local->ops->get_stats(local_to_hw(local), &stats); | 90 | res = local->ops->get_stats(local_to_hw(local), &stats); |
104 | rtnl_unlock(); | 91 | rtnl_unlock(); |
105 | if (!res) | 92 | if (!res) |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index b2089b2da48a..475f89a8aee1 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -156,6 +156,8 @@ static const struct file_operations name##_ops = { \ | |||
156 | 156 | ||
157 | /* common attributes */ | 157 | /* common attributes */ |
158 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 158 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
159 | IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); | ||
160 | IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | ||
159 | 161 | ||
160 | /* STA/IBSS attributes */ | 162 | /* STA/IBSS attributes */ |
161 | IEEE80211_IF_FILE(state, u.sta.state, DEC); | 163 | IEEE80211_IF_FILE(state, u.sta.state, DEC); |
@@ -191,8 +193,6 @@ __IEEE80211_IF_FILE(flags); | |||
191 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 193 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
192 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 194 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
193 | IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); | 195 | IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); |
194 | IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC); | ||
195 | IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC); | ||
196 | 196 | ||
197 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( | 197 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( |
198 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | 198 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) |
@@ -248,6 +248,9 @@ IEEE80211_IF_WFILE(min_discovery_timeout, | |||
248 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 248 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) |
249 | { | 249 | { |
250 | DEBUGFS_ADD(drop_unencrypted, sta); | 250 | DEBUGFS_ADD(drop_unencrypted, sta); |
251 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
252 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
253 | |||
251 | DEBUGFS_ADD(state, sta); | 254 | DEBUGFS_ADD(state, sta); |
252 | DEBUGFS_ADD(bssid, sta); | 255 | DEBUGFS_ADD(bssid, sta); |
253 | DEBUGFS_ADD(prev_bssid, sta); | 256 | DEBUGFS_ADD(prev_bssid, sta); |
@@ -268,23 +271,29 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
268 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 271 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
269 | { | 272 | { |
270 | DEBUGFS_ADD(drop_unencrypted, ap); | 273 | DEBUGFS_ADD(drop_unencrypted, ap); |
274 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
275 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
276 | |||
271 | DEBUGFS_ADD(num_sta_ps, ap); | 277 | DEBUGFS_ADD(num_sta_ps, ap); |
272 | DEBUGFS_ADD(dtim_count, ap); | 278 | DEBUGFS_ADD(dtim_count, ap); |
273 | DEBUGFS_ADD(num_beacons, ap); | 279 | DEBUGFS_ADD(num_beacons, ap); |
274 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
275 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
276 | DEBUGFS_ADD(num_buffered_multicast, ap); | 280 | DEBUGFS_ADD(num_buffered_multicast, ap); |
277 | } | 281 | } |
278 | 282 | ||
279 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 283 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
280 | { | 284 | { |
281 | DEBUGFS_ADD(drop_unencrypted, wds); | 285 | DEBUGFS_ADD(drop_unencrypted, wds); |
286 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
287 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
288 | |||
282 | DEBUGFS_ADD(peer, wds); | 289 | DEBUGFS_ADD(peer, wds); |
283 | } | 290 | } |
284 | 291 | ||
285 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | 292 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) |
286 | { | 293 | { |
287 | DEBUGFS_ADD(drop_unencrypted, vlan); | 294 | DEBUGFS_ADD(drop_unencrypted, vlan); |
295 | DEBUGFS_ADD(force_unicast_rateidx, ap); | ||
296 | DEBUGFS_ADD(max_ratectrl_rateidx, ap); | ||
288 | } | 297 | } |
289 | 298 | ||
290 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 299 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
@@ -372,6 +381,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
372 | static void del_sta_files(struct ieee80211_sub_if_data *sdata) | 381 | static void del_sta_files(struct ieee80211_sub_if_data *sdata) |
373 | { | 382 | { |
374 | DEBUGFS_DEL(drop_unencrypted, sta); | 383 | DEBUGFS_DEL(drop_unencrypted, sta); |
384 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
385 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
386 | |||
375 | DEBUGFS_DEL(state, sta); | 387 | DEBUGFS_DEL(state, sta); |
376 | DEBUGFS_DEL(bssid, sta); | 388 | DEBUGFS_DEL(bssid, sta); |
377 | DEBUGFS_DEL(prev_bssid, sta); | 389 | DEBUGFS_DEL(prev_bssid, sta); |
@@ -392,23 +404,29 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) | |||
392 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) | 404 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) |
393 | { | 405 | { |
394 | DEBUGFS_DEL(drop_unencrypted, ap); | 406 | DEBUGFS_DEL(drop_unencrypted, ap); |
407 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
408 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
409 | |||
395 | DEBUGFS_DEL(num_sta_ps, ap); | 410 | DEBUGFS_DEL(num_sta_ps, ap); |
396 | DEBUGFS_DEL(dtim_count, ap); | 411 | DEBUGFS_DEL(dtim_count, ap); |
397 | DEBUGFS_DEL(num_beacons, ap); | 412 | DEBUGFS_DEL(num_beacons, ap); |
398 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
399 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
400 | DEBUGFS_DEL(num_buffered_multicast, ap); | 413 | DEBUGFS_DEL(num_buffered_multicast, ap); |
401 | } | 414 | } |
402 | 415 | ||
403 | static void del_wds_files(struct ieee80211_sub_if_data *sdata) | 416 | static void del_wds_files(struct ieee80211_sub_if_data *sdata) |
404 | { | 417 | { |
405 | DEBUGFS_DEL(drop_unencrypted, wds); | 418 | DEBUGFS_DEL(drop_unencrypted, wds); |
419 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
420 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
421 | |||
406 | DEBUGFS_DEL(peer, wds); | 422 | DEBUGFS_DEL(peer, wds); |
407 | } | 423 | } |
408 | 424 | ||
409 | static void del_vlan_files(struct ieee80211_sub_if_data *sdata) | 425 | static void del_vlan_files(struct ieee80211_sub_if_data *sdata) |
410 | { | 426 | { |
411 | DEBUGFS_DEL(drop_unencrypted, vlan); | 427 | DEBUGFS_DEL(drop_unencrypted, vlan); |
428 | DEBUGFS_DEL(force_unicast_rateidx, ap); | ||
429 | DEBUGFS_DEL(max_ratectrl_rateidx, ap); | ||
412 | } | 430 | } |
413 | 431 | ||
414 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) | 432 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) |
@@ -458,12 +476,12 @@ static void del_mesh_config(struct ieee80211_sub_if_data *sdata) | |||
458 | } | 476 | } |
459 | #endif | 477 | #endif |
460 | 478 | ||
461 | static void del_files(struct ieee80211_sub_if_data *sdata, int type) | 479 | static void del_files(struct ieee80211_sub_if_data *sdata) |
462 | { | 480 | { |
463 | if (!sdata->debugfsdir) | 481 | if (!sdata->debugfsdir) |
464 | return; | 482 | return; |
465 | 483 | ||
466 | switch (type) { | 484 | switch (sdata->vif.type) { |
467 | case IEEE80211_IF_TYPE_MESH_POINT: | 485 | case IEEE80211_IF_TYPE_MESH_POINT: |
468 | #ifdef CONFIG_MAC80211_MESH | 486 | #ifdef CONFIG_MAC80211_MESH |
469 | del_mesh_stats(sdata); | 487 | del_mesh_stats(sdata); |
@@ -503,29 +521,23 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata) | |||
503 | sprintf(buf, "netdev:%s", sdata->dev->name); | 521 | sprintf(buf, "netdev:%s", sdata->dev->name); |
504 | sdata->debugfsdir = debugfs_create_dir(buf, | 522 | sdata->debugfsdir = debugfs_create_dir(buf, |
505 | sdata->local->hw.wiphy->debugfsdir); | 523 | sdata->local->hw.wiphy->debugfsdir); |
524 | add_files(sdata); | ||
506 | } | 525 | } |
507 | 526 | ||
508 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) | 527 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata) |
509 | { | 528 | { |
510 | del_files(sdata, sdata->vif.type); | 529 | del_files(sdata); |
511 | debugfs_remove(sdata->debugfsdir); | 530 | debugfs_remove(sdata->debugfsdir); |
512 | sdata->debugfsdir = NULL; | 531 | sdata->debugfsdir = NULL; |
513 | } | 532 | } |
514 | 533 | ||
515 | void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata, | ||
516 | int oldtype) | ||
517 | { | ||
518 | del_files(sdata, oldtype); | ||
519 | add_files(sdata); | ||
520 | } | ||
521 | |||
522 | static int netdev_notify(struct notifier_block *nb, | 534 | static int netdev_notify(struct notifier_block *nb, |
523 | unsigned long state, | 535 | unsigned long state, |
524 | void *ndev) | 536 | void *ndev) |
525 | { | 537 | { |
526 | struct net_device *dev = ndev; | 538 | struct net_device *dev = ndev; |
527 | struct dentry *dir; | 539 | struct dentry *dir; |
528 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 540 | struct ieee80211_sub_if_data *sdata; |
529 | char buf[10+IFNAMSIZ]; | 541 | char buf[10+IFNAMSIZ]; |
530 | 542 | ||
531 | if (state != NETDEV_CHANGENAME) | 543 | if (state != NETDEV_CHANGENAME) |
@@ -537,6 +549,8 @@ static int netdev_notify(struct notifier_block *nb, | |||
537 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) | 549 | if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) |
538 | return 0; | 550 | return 0; |
539 | 551 | ||
552 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
553 | |||
540 | sprintf(buf, "netdev:%s", dev->name); | 554 | sprintf(buf, "netdev:%s", dev->name); |
541 | dir = sdata->debugfsdir; | 555 | dir = sdata->debugfsdir; |
542 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) | 556 | if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) |
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h index a690071fde8a..7af731f0b731 100644 --- a/net/mac80211/debugfs_netdev.h +++ b/net/mac80211/debugfs_netdev.h | |||
@@ -6,8 +6,6 @@ | |||
6 | #ifdef CONFIG_MAC80211_DEBUGFS | 6 | #ifdef CONFIG_MAC80211_DEBUGFS |
7 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); | 7 | void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata); |
8 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); | 8 | void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata); |
9 | void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata, | ||
10 | int oldtype); | ||
11 | void ieee80211_debugfs_netdev_init(void); | 9 | void ieee80211_debugfs_netdev_init(void); |
12 | void ieee80211_debugfs_netdev_exit(void); | 10 | void ieee80211_debugfs_netdev_exit(void); |
13 | #else | 11 | #else |
@@ -17,9 +15,6 @@ static inline void ieee80211_debugfs_add_netdev( | |||
17 | static inline void ieee80211_debugfs_remove_netdev( | 15 | static inline void ieee80211_debugfs_remove_netdev( |
18 | struct ieee80211_sub_if_data *sdata) | 16 | struct ieee80211_sub_if_data *sdata) |
19 | {} | 17 | {} |
20 | static inline void ieee80211_debugfs_change_if_type( | ||
21 | struct ieee80211_sub_if_data *sdata, int oldtype) | ||
22 | {} | ||
23 | static inline void ieee80211_debugfs_netdev_init(void) | 18 | static inline void ieee80211_debugfs_netdev_init(void) |
24 | {} | 19 | {} |
25 | 20 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 02a8753a4eca..cbea0154ee3a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -237,8 +237,6 @@ struct ieee80211_if_ap { | |||
237 | struct sk_buff_head ps_bc_buf; | 237 | struct sk_buff_head ps_bc_buf; |
238 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 238 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
239 | int dtim_count; | 239 | int dtim_count; |
240 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | ||
241 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | ||
242 | int num_beacons; /* number of TXed beacon frames for this BSS */ | 240 | int num_beacons; /* number of TXed beacon frames for this BSS */ |
243 | }; | 241 | }; |
244 | 242 | ||
@@ -248,7 +246,6 @@ struct ieee80211_if_wds { | |||
248 | }; | 246 | }; |
249 | 247 | ||
250 | struct ieee80211_if_vlan { | 248 | struct ieee80211_if_vlan { |
251 | struct ieee80211_sub_if_data *ap; | ||
252 | struct list_head list; | 249 | struct list_head list; |
253 | }; | 250 | }; |
254 | 251 | ||
@@ -422,8 +419,6 @@ struct ieee80211_sub_if_data { | |||
422 | */ | 419 | */ |
423 | u64 basic_rates; | 420 | u64 basic_rates; |
424 | 421 | ||
425 | u16 sequence; | ||
426 | |||
427 | /* Fragment table for host-based reassembly */ | 422 | /* Fragment table for host-based reassembly */ |
428 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 423 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
429 | unsigned int fragment_next; | 424 | unsigned int fragment_next; |
@@ -432,16 +427,18 @@ struct ieee80211_sub_if_data { | |||
432 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; | 427 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; |
433 | struct ieee80211_key *default_key; | 428 | struct ieee80211_key *default_key; |
434 | 429 | ||
430 | /* BSS configuration for this interface. */ | ||
431 | struct ieee80211_bss_conf bss_conf; | ||
432 | |||
435 | /* | 433 | /* |
436 | * BSS configuration for this interface. | 434 | * AP this belongs to: self in AP mode and |
437 | * | 435 | * corresponding AP in VLAN mode, NULL for |
438 | * FIXME: I feel bad putting this here when we already have a | 436 | * all others (might be needed later in IBSS) |
439 | * bss pointer, but the bss pointer is just wrong when | ||
440 | * you have multiple virtual STA mode interfaces... | ||
441 | * This needs to be fixed. | ||
442 | */ | 437 | */ |
443 | struct ieee80211_bss_conf bss_conf; | 438 | struct ieee80211_if_ap *bss; |
444 | struct ieee80211_if_ap *bss; /* BSS that this device belongs to */ | 439 | |
440 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | ||
441 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | ||
445 | 442 | ||
446 | union { | 443 | union { |
447 | struct ieee80211_if_ap ap; | 444 | struct ieee80211_if_ap ap; |
@@ -533,8 +530,6 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
533 | return container_of(p, struct ieee80211_sub_if_data, vif); | 530 | return container_of(p, struct ieee80211_sub_if_data, vif); |
534 | } | 531 | } |
535 | 532 | ||
536 | #define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev) | ||
537 | |||
538 | enum { | 533 | enum { |
539 | IEEE80211_RX_MSG = 1, | 534 | IEEE80211_RX_MSG = 1, |
540 | IEEE80211_TX_STATUS_MSG = 2, | 535 | IEEE80211_TX_STATUS_MSG = 2, |
@@ -561,12 +556,6 @@ struct ieee80211_local { | |||
561 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ | 556 | bool tim_in_locked_section; /* see ieee80211_beacon_get() */ |
562 | int tx_headroom; /* required headroom for hardware/radiotap */ | 557 | int tx_headroom; /* required headroom for hardware/radiotap */ |
563 | 558 | ||
564 | enum { | ||
565 | IEEE80211_DEV_UNINITIALIZED = 0, | ||
566 | IEEE80211_DEV_REGISTERED, | ||
567 | IEEE80211_DEV_UNREGISTERED, | ||
568 | } reg_state; | ||
569 | |||
570 | /* Tasklet and skb queue to process calls from IRQ mode. All frames | 559 | /* Tasklet and skb queue to process calls from IRQ mode. All frames |
571 | * added to skb_queue will be processed, but frames in | 560 | * added to skb_queue will be processed, but frames in |
572 | * skb_queue_unreliable may be dropped if the total length of these | 561 | * skb_queue_unreliable may be dropped if the total length of these |
@@ -760,6 +749,16 @@ static inline int ieee80211_is_multiqueue(struct ieee80211_local *local) | |||
760 | #endif | 749 | #endif |
761 | } | 750 | } |
762 | 751 | ||
752 | static inline struct ieee80211_sub_if_data * | ||
753 | IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | ||
754 | { | ||
755 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
756 | |||
757 | BUG_ON(!local || local->mdev == dev); | ||
758 | |||
759 | return netdev_priv(dev); | ||
760 | } | ||
761 | |||
763 | /* this struct represents 802.11n's RA/TID combination */ | 762 | /* this struct represents 802.11n's RA/TID combination */ |
764 | struct ieee80211_ra_tid { | 763 | struct ieee80211_ra_tid { |
765 | u8 ra[ETH_ALEN]; | 764 | u8 ra[ETH_ALEN]; |
@@ -853,10 +852,8 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | |||
853 | 852 | ||
854 | /* ieee80211.c */ | 853 | /* ieee80211.c */ |
855 | int ieee80211_hw_config(struct ieee80211_local *local); | 854 | int ieee80211_hw_config(struct ieee80211_local *local); |
856 | int ieee80211_if_config(struct net_device *dev); | 855 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); |
857 | int ieee80211_if_config_beacon(struct net_device *dev); | ||
858 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 856 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
859 | void ieee80211_if_setup(struct net_device *dev); | ||
860 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | 857 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, |
861 | struct ieee80211_ht_info *req_ht_cap, | 858 | struct ieee80211_ht_info *req_ht_cap, |
862 | struct ieee80211_ht_bss_info *req_bss_cap); | 859 | struct ieee80211_ht_bss_info *req_bss_cap); |
@@ -883,8 +880,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, | |||
883 | ieee80211_rx_result ieee80211_sta_rx_scan( | 880 | ieee80211_rx_result ieee80211_sta_rx_scan( |
884 | struct net_device *dev, struct sk_buff *skb, | 881 | struct net_device *dev, struct sk_buff *skb, |
885 | struct ieee80211_rx_status *rx_status); | 882 | struct ieee80211_rx_status *rx_status); |
886 | void ieee80211_rx_bss_list_init(struct net_device *dev); | 883 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); |
887 | void ieee80211_rx_bss_list_deinit(struct net_device *dev); | 884 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); |
888 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); | 885 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); |
889 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | 886 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, |
890 | struct sk_buff *skb, u8 *bssid, | 887 | struct sk_buff *skb, u8 *bssid, |
@@ -925,17 +922,15 @@ static inline void ieee80211_start_mesh(struct net_device *dev) | |||
925 | {} | 922 | {} |
926 | #endif | 923 | #endif |
927 | 924 | ||
928 | /* ieee80211_iface.c */ | 925 | /* interface handling */ |
929 | int ieee80211_if_add(struct net_device *dev, const char *name, | 926 | void ieee80211_if_setup(struct net_device *dev); |
930 | struct net_device **new_dev, int type, | 927 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
928 | struct net_device **new_dev, enum ieee80211_if_types type, | ||
931 | struct vif_params *params); | 929 | struct vif_params *params); |
932 | void ieee80211_if_set_type(struct net_device *dev, int type); | 930 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
933 | void ieee80211_if_reinit(struct net_device *dev); | 931 | enum ieee80211_if_types type); |
934 | void __ieee80211_if_del(struct ieee80211_local *local, | 932 | void ieee80211_if_remove(struct net_device *dev); |
935 | struct ieee80211_sub_if_data *sdata); | 933 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
936 | int ieee80211_if_remove(struct net_device *dev, const char *name, int id); | ||
937 | void ieee80211_if_free(struct net_device *dev); | ||
938 | void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata); | ||
939 | 934 | ||
940 | /* tx handling */ | 935 | /* tx handling */ |
941 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 936 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index eeb16926aa7d..610ed1d9893a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -17,145 +18,91 @@ | |||
17 | #include "debugfs_netdev.h" | 18 | #include "debugfs_netdev.h" |
18 | #include "mesh.h" | 19 | #include "mesh.h" |
19 | 20 | ||
20 | void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata) | 21 | /* |
22 | * Called when the netdev is removed or, by the code below, before | ||
23 | * the interface type changes. | ||
24 | */ | ||
25 | static void ieee80211_teardown_sdata(struct net_device *dev) | ||
21 | { | 26 | { |
27 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
28 | struct ieee80211_local *local = sdata->local; | ||
29 | struct beacon_data *beacon; | ||
30 | struct sk_buff *skb; | ||
31 | int flushed; | ||
22 | int i; | 32 | int i; |
23 | 33 | ||
24 | /* Default values for sub-interface parameters */ | 34 | ieee80211_debugfs_remove_netdev(sdata); |
25 | sdata->drop_unencrypted = 0; | ||
26 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | ||
27 | skb_queue_head_init(&sdata->fragments[i].skb_list); | ||
28 | |||
29 | INIT_LIST_HEAD(&sdata->key_list); | ||
30 | } | ||
31 | 35 | ||
32 | static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata) | 36 | /* free extra data */ |
33 | { | 37 | ieee80211_free_keys(sdata); |
34 | int i; | ||
35 | 38 | ||
36 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 39 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
37 | __skb_queue_purge(&sdata->fragments[i].skb_list); | 40 | __skb_queue_purge(&sdata->fragments[i].skb_list); |
38 | } | 41 | sdata->fragment_next = 0; |
39 | |||
40 | /* Must be called with rtnl lock held. */ | ||
41 | int ieee80211_if_add(struct net_device *dev, const char *name, | ||
42 | struct net_device **new_dev, int type, | ||
43 | struct vif_params *params) | ||
44 | { | ||
45 | struct net_device *ndev; | ||
46 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
47 | struct ieee80211_sub_if_data *sdata = NULL; | ||
48 | int ret; | ||
49 | |||
50 | ASSERT_RTNL(); | ||
51 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, | ||
52 | name, ieee80211_if_setup); | ||
53 | if (!ndev) | ||
54 | return -ENOMEM; | ||
55 | 42 | ||
56 | ndev->needed_headroom = local->tx_headroom + | 43 | switch (sdata->vif.type) { |
57 | 4*6 /* four MAC addresses */ | 44 | case IEEE80211_IF_TYPE_AP: |
58 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | 45 | beacon = sdata->u.ap.beacon; |
59 | + 6 /* mesh */ | 46 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); |
60 | + 8 /* rfc1042/bridge tunnel */ | 47 | synchronize_rcu(); |
61 | - ETH_HLEN /* ethernet hard_header_len */ | 48 | kfree(beacon); |
62 | + IEEE80211_ENCRYPT_HEADROOM; | ||
63 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | ||
64 | |||
65 | ret = dev_alloc_name(ndev, ndev->name); | ||
66 | if (ret < 0) | ||
67 | goto fail; | ||
68 | |||
69 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | ||
70 | ndev->base_addr = dev->base_addr; | ||
71 | ndev->irq = dev->irq; | ||
72 | ndev->mem_start = dev->mem_start; | ||
73 | ndev->mem_end = dev->mem_end; | ||
74 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | ||
75 | |||
76 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | ||
77 | ndev->ieee80211_ptr = &sdata->wdev; | ||
78 | sdata->wdev.wiphy = local->hw.wiphy; | ||
79 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | ||
80 | sdata->dev = ndev; | ||
81 | sdata->local = local; | ||
82 | ieee80211_if_sdata_init(sdata); | ||
83 | |||
84 | ret = register_netdevice(ndev); | ||
85 | if (ret) | ||
86 | goto fail; | ||
87 | |||
88 | ieee80211_debugfs_add_netdev(sdata); | ||
89 | ieee80211_if_set_type(ndev, type); | ||
90 | 49 | ||
91 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 50 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { |
92 | params && params->mesh_id_len) | 51 | local->total_ps_buffered--; |
93 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 52 | dev_kfree_skb(skb); |
94 | params->mesh_id_len, | 53 | } |
95 | params->mesh_id); | ||
96 | 54 | ||
97 | /* we're under RTNL so all this is fine */ | 55 | break; |
98 | if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) { | 56 | case IEEE80211_IF_TYPE_MESH_POINT: |
99 | __ieee80211_if_del(local, sdata); | 57 | /* Allow compiler to elide mesh_rmc_free call. */ |
100 | return -ENODEV; | 58 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
59 | mesh_rmc_free(dev); | ||
60 | /* fall through */ | ||
61 | case IEEE80211_IF_TYPE_STA: | ||
62 | case IEEE80211_IF_TYPE_IBSS: | ||
63 | kfree(sdata->u.sta.extra_ie); | ||
64 | kfree(sdata->u.sta.assocreq_ies); | ||
65 | kfree(sdata->u.sta.assocresp_ies); | ||
66 | kfree_skb(sdata->u.sta.probe_resp); | ||
67 | break; | ||
68 | case IEEE80211_IF_TYPE_WDS: | ||
69 | case IEEE80211_IF_TYPE_VLAN: | ||
70 | case IEEE80211_IF_TYPE_MNTR: | ||
71 | break; | ||
72 | case IEEE80211_IF_TYPE_INVALID: | ||
73 | BUG(); | ||
74 | break; | ||
101 | } | 75 | } |
102 | list_add_tail_rcu(&sdata->list, &local->interfaces); | ||
103 | 76 | ||
104 | if (new_dev) | 77 | flushed = sta_info_flush(local, sdata); |
105 | *new_dev = ndev; | 78 | WARN_ON(flushed); |
106 | |||
107 | return 0; | ||
108 | |||
109 | fail: | ||
110 | free_netdev(ndev); | ||
111 | return ret; | ||
112 | } | 79 | } |
113 | 80 | ||
114 | void ieee80211_if_set_type(struct net_device *dev, int type) | 81 | /* |
82 | * Helper function to initialise an interface to a specific type. | ||
83 | */ | ||
84 | static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | ||
85 | enum ieee80211_if_types type) | ||
115 | { | 86 | { |
116 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 87 | struct ieee80211_if_sta *ifsta; |
117 | int oldtype = sdata->vif.type; | ||
118 | |||
119 | /* | ||
120 | * We need to call this function on the master interface | ||
121 | * which already has a hard_start_xmit routine assigned | ||
122 | * which must not be changed. | ||
123 | */ | ||
124 | if (dev != sdata->local->mdev) | ||
125 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
126 | 88 | ||
127 | /* | 89 | /* clear type-dependent union */ |
128 | * Called even when register_netdevice fails, it would | 90 | memset(&sdata->u, 0, sizeof(sdata->u)); |
129 | * oops if assigned before initialising the rest. | ||
130 | */ | ||
131 | dev->uninit = ieee80211_if_reinit; | ||
132 | 91 | ||
133 | /* most have no BSS pointer */ | 92 | /* and set some type-dependent values */ |
134 | sdata->bss = NULL; | ||
135 | sdata->vif.type = type; | 93 | sdata->vif.type = type; |
136 | 94 | ||
137 | sdata->basic_rates = 0; | 95 | /* only monitor differs */ |
96 | sdata->dev->type = ARPHRD_ETHER; | ||
138 | 97 | ||
139 | switch (type) { | 98 | switch (type) { |
140 | case IEEE80211_IF_TYPE_WDS: | ||
141 | /* nothing special */ | ||
142 | break; | ||
143 | case IEEE80211_IF_TYPE_VLAN: | ||
144 | sdata->u.vlan.ap = NULL; | ||
145 | break; | ||
146 | case IEEE80211_IF_TYPE_AP: | 99 | case IEEE80211_IF_TYPE_AP: |
147 | sdata->u.ap.force_unicast_rateidx = -1; | ||
148 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
149 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 100 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
150 | sdata->bss = &sdata->u.ap; | ||
151 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 101 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
152 | break; | 102 | break; |
153 | case IEEE80211_IF_TYPE_MESH_POINT: | 103 | case IEEE80211_IF_TYPE_MESH_POINT: |
154 | case IEEE80211_IF_TYPE_STA: | 104 | case IEEE80211_IF_TYPE_STA: |
155 | case IEEE80211_IF_TYPE_IBSS: { | 105 | case IEEE80211_IF_TYPE_IBSS: |
156 | struct ieee80211_sub_if_data *msdata; | ||
157 | struct ieee80211_if_sta *ifsta; | ||
158 | |||
159 | ifsta = &sdata->u.sta; | 106 | ifsta = &sdata->u.sta; |
160 | INIT_WORK(&ifsta->work, ieee80211_sta_work); | 107 | INIT_WORK(&ifsta->work, ieee80211_sta_work); |
161 | setup_timer(&ifsta->timer, ieee80211_sta_timer, | 108 | setup_timer(&ifsta->timer, ieee80211_sta_timer, |
@@ -171,153 +118,152 @@ void ieee80211_if_set_type(struct net_device *dev, int type) | |||
171 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | 118 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) |
172 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | 119 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; |
173 | 120 | ||
174 | msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev); | ||
175 | sdata->bss = &msdata->u.ap; | ||
176 | |||
177 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 121 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
178 | ieee80211_mesh_init_sdata(sdata); | 122 | ieee80211_mesh_init_sdata(sdata); |
179 | break; | 123 | break; |
180 | } | ||
181 | case IEEE80211_IF_TYPE_MNTR: | 124 | case IEEE80211_IF_TYPE_MNTR: |
182 | dev->type = ARPHRD_IEEE80211_RADIOTAP; | 125 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; |
183 | dev->hard_start_xmit = ieee80211_monitor_start_xmit; | 126 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; |
184 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | | 127 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | |
185 | MONITOR_FLAG_OTHER_BSS; | 128 | MONITOR_FLAG_OTHER_BSS; |
186 | break; | 129 | break; |
130 | case IEEE80211_IF_TYPE_WDS: | ||
131 | case IEEE80211_IF_TYPE_VLAN: | ||
132 | break; | ||
187 | case IEEE80211_IF_TYPE_INVALID: | 133 | case IEEE80211_IF_TYPE_INVALID: |
188 | BUG(); | 134 | BUG(); |
189 | break; | 135 | break; |
190 | } | 136 | } |
191 | ieee80211_debugfs_change_if_type(sdata, oldtype); | 137 | |
138 | ieee80211_debugfs_add_netdev(sdata); | ||
192 | } | 139 | } |
193 | 140 | ||
194 | /* Must be called with rtnl lock held. */ | 141 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
195 | void ieee80211_if_reinit(struct net_device *dev) | 142 | enum ieee80211_if_types type) |
196 | { | 143 | { |
197 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 144 | ASSERT_RTNL(); |
198 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 145 | |
199 | struct sk_buff *skb; | 146 | if (type == sdata->vif.type) |
200 | int flushed; | 147 | return 0; |
148 | |||
149 | /* | ||
150 | * We could, here, on changes between IBSS/STA/MESH modes, | ||
151 | * invoke an MLME function instead that disassociates etc. | ||
152 | * and goes into the requested mode. | ||
153 | */ | ||
154 | |||
155 | if (netif_running(sdata->dev)) | ||
156 | return -EBUSY; | ||
157 | |||
158 | /* Purge and reset type-dependent state. */ | ||
159 | ieee80211_teardown_sdata(sdata->dev); | ||
160 | ieee80211_setup_sdata(sdata, type); | ||
161 | |||
162 | /* reset some values that shouldn't be kept across type changes */ | ||
163 | sdata->basic_rates = 0; | ||
164 | sdata->drop_unencrypted = 0; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | ||
170 | struct net_device **new_dev, enum ieee80211_if_types type, | ||
171 | struct vif_params *params) | ||
172 | { | ||
173 | struct net_device *ndev; | ||
174 | struct ieee80211_sub_if_data *sdata = NULL; | ||
175 | int ret, i; | ||
201 | 176 | ||
202 | ASSERT_RTNL(); | 177 | ASSERT_RTNL(); |
203 | 178 | ||
204 | ieee80211_free_keys(sdata); | 179 | ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, |
180 | name, ieee80211_if_setup); | ||
181 | if (!ndev) | ||
182 | return -ENOMEM; | ||
205 | 183 | ||
206 | ieee80211_if_sdata_deinit(sdata); | 184 | ndev->needed_headroom = local->tx_headroom + |
185 | 4*6 /* four MAC addresses */ | ||
186 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | ||
187 | + 6 /* mesh */ | ||
188 | + 8 /* rfc1042/bridge tunnel */ | ||
189 | - ETH_HLEN /* ethernet hard_header_len */ | ||
190 | + IEEE80211_ENCRYPT_HEADROOM; | ||
191 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | ||
207 | 192 | ||
208 | /* Need to handle mesh specially to allow eliding the function call */ | 193 | ret = dev_alloc_name(ndev, ndev->name); |
209 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 194 | if (ret < 0) |
210 | mesh_rmc_free(dev); | 195 | goto fail; |
211 | 196 | ||
212 | switch (sdata->vif.type) { | 197 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
213 | case IEEE80211_IF_TYPE_INVALID: | 198 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
214 | /* cannot happen */ | ||
215 | WARN_ON(1); | ||
216 | break; | ||
217 | case IEEE80211_IF_TYPE_AP: { | ||
218 | /* Remove all virtual interfaces that use this BSS | ||
219 | * as their sdata->bss */ | ||
220 | struct ieee80211_sub_if_data *tsdata, *n; | ||
221 | struct beacon_data *beacon; | ||
222 | |||
223 | list_for_each_entry_safe(tsdata, n, &local->interfaces, list) { | ||
224 | if (tsdata != sdata && tsdata->bss == &sdata->u.ap) { | ||
225 | printk(KERN_DEBUG "%s: removing virtual " | ||
226 | "interface %s because its BSS interface" | ||
227 | " is being removed\n", | ||
228 | sdata->dev->name, tsdata->dev->name); | ||
229 | list_del_rcu(&tsdata->list); | ||
230 | /* | ||
231 | * We have lots of time and can afford | ||
232 | * to sync for each interface | ||
233 | */ | ||
234 | synchronize_rcu(); | ||
235 | __ieee80211_if_del(local, tsdata); | ||
236 | } | ||
237 | } | ||
238 | 199 | ||
239 | beacon = sdata->u.ap.beacon; | 200 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
240 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 201 | sdata = netdev_priv(ndev); |
241 | synchronize_rcu(); | 202 | ndev->ieee80211_ptr = &sdata->wdev; |
242 | kfree(beacon); | ||
243 | 203 | ||
244 | while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) { | 204 | /* initialise type-independent data */ |
245 | local->total_ps_buffered--; | 205 | sdata->wdev.wiphy = local->hw.wiphy; |
246 | dev_kfree_skb(skb); | 206 | sdata->local = local; |
247 | } | 207 | sdata->dev = ndev; |
248 | 208 | ||
249 | break; | 209 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
250 | } | 210 | skb_queue_head_init(&sdata->fragments[i].skb_list); |
251 | case IEEE80211_IF_TYPE_WDS: | ||
252 | /* nothing to do */ | ||
253 | break; | ||
254 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
255 | case IEEE80211_IF_TYPE_STA: | ||
256 | case IEEE80211_IF_TYPE_IBSS: | ||
257 | kfree(sdata->u.sta.extra_ie); | ||
258 | sdata->u.sta.extra_ie = NULL; | ||
259 | kfree(sdata->u.sta.assocreq_ies); | ||
260 | sdata->u.sta.assocreq_ies = NULL; | ||
261 | kfree(sdata->u.sta.assocresp_ies); | ||
262 | sdata->u.sta.assocresp_ies = NULL; | ||
263 | if (sdata->u.sta.probe_resp) { | ||
264 | dev_kfree_skb(sdata->u.sta.probe_resp); | ||
265 | sdata->u.sta.probe_resp = NULL; | ||
266 | } | ||
267 | 211 | ||
268 | break; | 212 | INIT_LIST_HEAD(&sdata->key_list); |
269 | case IEEE80211_IF_TYPE_MNTR: | ||
270 | dev->type = ARPHRD_ETHER; | ||
271 | break; | ||
272 | case IEEE80211_IF_TYPE_VLAN: | ||
273 | sdata->u.vlan.ap = NULL; | ||
274 | break; | ||
275 | } | ||
276 | 213 | ||
277 | flushed = sta_info_flush(local, sdata); | 214 | sdata->force_unicast_rateidx = -1; |
278 | WARN_ON(flushed); | 215 | sdata->max_ratectrl_rateidx = -1; |
279 | 216 | ||
280 | memset(&sdata->u, 0, sizeof(sdata->u)); | 217 | /* setup type-dependent data */ |
281 | ieee80211_if_sdata_init(sdata); | 218 | ieee80211_setup_sdata(sdata, type); |
282 | } | ||
283 | 219 | ||
284 | /* Must be called with rtnl lock held. */ | 220 | ret = register_netdevice(ndev); |
285 | void __ieee80211_if_del(struct ieee80211_local *local, | 221 | if (ret) |
286 | struct ieee80211_sub_if_data *sdata) | 222 | goto fail; |
287 | { | ||
288 | struct net_device *dev = sdata->dev; | ||
289 | 223 | ||
290 | ieee80211_debugfs_remove_netdev(sdata); | 224 | ndev->uninit = ieee80211_teardown_sdata; |
291 | unregister_netdevice(dev); | 225 | |
292 | /* Except master interface, the net_device will be freed by | 226 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
293 | * net_device->destructor (i. e. ieee80211_if_free). */ | 227 | params && params->mesh_id_len) |
228 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | ||
229 | params->mesh_id_len, | ||
230 | params->mesh_id); | ||
231 | |||
232 | list_add_tail_rcu(&sdata->list, &local->interfaces); | ||
233 | |||
234 | if (new_dev) | ||
235 | *new_dev = ndev; | ||
236 | |||
237 | return 0; | ||
238 | |||
239 | fail: | ||
240 | free_netdev(ndev); | ||
241 | return ret; | ||
294 | } | 242 | } |
295 | 243 | ||
296 | /* Must be called with rtnl lock held. */ | 244 | void ieee80211_if_remove(struct net_device *dev) |
297 | int ieee80211_if_remove(struct net_device *dev, const char *name, int id) | ||
298 | { | 245 | { |
299 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 246 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
300 | struct ieee80211_sub_if_data *sdata, *n; | ||
301 | 247 | ||
302 | ASSERT_RTNL(); | 248 | ASSERT_RTNL(); |
303 | 249 | ||
304 | list_for_each_entry_safe(sdata, n, &local->interfaces, list) { | 250 | list_del_rcu(&sdata->list); |
305 | if ((sdata->vif.type == id || id == -1) && | 251 | synchronize_rcu(); |
306 | strcmp(name, sdata->dev->name) == 0 && | 252 | unregister_netdevice(dev); |
307 | sdata->dev != local->mdev) { | ||
308 | list_del_rcu(&sdata->list); | ||
309 | synchronize_rcu(); | ||
310 | __ieee80211_if_del(local, sdata); | ||
311 | return 0; | ||
312 | } | ||
313 | } | ||
314 | return -ENODEV; | ||
315 | } | 253 | } |
316 | 254 | ||
317 | void ieee80211_if_free(struct net_device *dev) | 255 | /* |
256 | * Remove all interfaces, may only be called at hardware unregistration | ||
257 | * time because it doesn't do RCU-safe list removals. | ||
258 | */ | ||
259 | void ieee80211_remove_interfaces(struct ieee80211_local *local) | ||
318 | { | 260 | { |
319 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 261 | struct ieee80211_sub_if_data *sdata, *tmp; |
320 | 262 | ||
321 | ieee80211_if_sdata_deinit(sdata); | 263 | ASSERT_RTNL(); |
322 | free_netdev(dev); | 264 | |
265 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | ||
266 | list_del(&sdata->list); | ||
267 | unregister_netdevice(sdata->dev); | ||
268 | } | ||
323 | } | 269 | } |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 1c4d3ba6b878..36859e794928 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -105,7 +105,7 @@ static int ieee80211_master_open(struct net_device *dev) | |||
105 | 105 | ||
106 | /* we hold the RTNL here so can safely walk the list */ | 106 | /* we hold the RTNL here so can safely walk the list */ |
107 | list_for_each_entry(sdata, &local->interfaces, list) { | 107 | list_for_each_entry(sdata, &local->interfaces, list) { |
108 | if (sdata->dev != dev && netif_running(sdata->dev)) { | 108 | if (netif_running(sdata->dev)) { |
109 | res = 0; | 109 | res = 0; |
110 | break; | 110 | break; |
111 | } | 111 | } |
@@ -126,7 +126,7 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
126 | 126 | ||
127 | /* we hold the RTNL here so can safely walk the list */ | 127 | /* we hold the RTNL here so can safely walk the list */ |
128 | list_for_each_entry(sdata, &local->interfaces, list) | 128 | list_for_each_entry(sdata, &local->interfaces, list) |
129 | if (sdata->dev != dev && netif_running(sdata->dev)) | 129 | if (netif_running(sdata->dev)) |
130 | dev_close(sdata->dev); | 130 | dev_close(sdata->dev); |
131 | 131 | ||
132 | return 0; | 132 | return 0; |
@@ -194,7 +194,7 @@ static int ieee80211_open(struct net_device *dev) | |||
194 | list_for_each_entry(nsdata, &local->interfaces, list) { | 194 | list_for_each_entry(nsdata, &local->interfaces, list) { |
195 | struct net_device *ndev = nsdata->dev; | 195 | struct net_device *ndev = nsdata->dev; |
196 | 196 | ||
197 | if (ndev != dev && ndev != local->mdev && netif_running(ndev)) { | 197 | if (ndev != dev && netif_running(ndev)) { |
198 | /* | 198 | /* |
199 | * Allow only a single IBSS interface to be up at any | 199 | * Allow only a single IBSS interface to be up at any |
200 | * time. This is restricted because beacon distribution | 200 | * time. This is restricted because beacon distribution |
@@ -210,30 +210,6 @@ static int ieee80211_open(struct net_device *dev) | |||
210 | return -EBUSY; | 210 | return -EBUSY; |
211 | 211 | ||
212 | /* | 212 | /* |
213 | * Disallow multiple IBSS/STA mode interfaces. | ||
214 | * | ||
215 | * This is a technical restriction, it is possible although | ||
216 | * most likely not IEEE 802.11 compliant to have multiple | ||
217 | * STAs with just a single hardware (the TSF timer will not | ||
218 | * be adjusted properly.) | ||
219 | * | ||
220 | * However, because mac80211 uses the master device's BSS | ||
221 | * information for each STA/IBSS interface, doing this will | ||
222 | * currently corrupt that BSS information completely, unless, | ||
223 | * a not very useful case, both STAs are associated to the | ||
224 | * same BSS. | ||
225 | * | ||
226 | * To remove this restriction, the BSS information needs to | ||
227 | * be embedded in the STA/IBSS mode sdata instead of using | ||
228 | * the master device's BSS structure. | ||
229 | */ | ||
230 | if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
231 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) && | ||
232 | (nsdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
233 | nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)) | ||
234 | return -EBUSY; | ||
235 | |||
236 | /* | ||
237 | * The remaining checks are only performed for interfaces | 213 | * The remaining checks are only performed for interfaces |
238 | * with the same MAC address. | 214 | * with the same MAC address. |
239 | */ | 215 | */ |
@@ -252,7 +228,7 @@ static int ieee80211_open(struct net_device *dev) | |||
252 | */ | 228 | */ |
253 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && | 229 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && |
254 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) | 230 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) |
255 | sdata->u.vlan.ap = nsdata; | 231 | sdata->bss = &nsdata->u.ap; |
256 | } | 232 | } |
257 | } | 233 | } |
258 | 234 | ||
@@ -262,10 +238,13 @@ static int ieee80211_open(struct net_device *dev) | |||
262 | return -ENOLINK; | 238 | return -ENOLINK; |
263 | break; | 239 | break; |
264 | case IEEE80211_IF_TYPE_VLAN: | 240 | case IEEE80211_IF_TYPE_VLAN: |
265 | if (!sdata->u.vlan.ap) | 241 | if (!sdata->bss) |
266 | return -ENOLINK; | 242 | return -ENOLINK; |
243 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | ||
267 | break; | 244 | break; |
268 | case IEEE80211_IF_TYPE_AP: | 245 | case IEEE80211_IF_TYPE_AP: |
246 | sdata->bss = &sdata->u.ap; | ||
247 | break; | ||
269 | case IEEE80211_IF_TYPE_STA: | 248 | case IEEE80211_IF_TYPE_STA: |
270 | case IEEE80211_IF_TYPE_MNTR: | 249 | case IEEE80211_IF_TYPE_MNTR: |
271 | case IEEE80211_IF_TYPE_IBSS: | 250 | case IEEE80211_IF_TYPE_IBSS: |
@@ -283,14 +262,13 @@ static int ieee80211_open(struct net_device *dev) | |||
283 | if (local->ops->start) | 262 | if (local->ops->start) |
284 | res = local->ops->start(local_to_hw(local)); | 263 | res = local->ops->start(local_to_hw(local)); |
285 | if (res) | 264 | if (res) |
286 | return res; | 265 | goto err_del_bss; |
287 | need_hw_reconfig = 1; | 266 | need_hw_reconfig = 1; |
288 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | 267 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); |
289 | } | 268 | } |
290 | 269 | ||
291 | switch (sdata->vif.type) { | 270 | switch (sdata->vif.type) { |
292 | case IEEE80211_IF_TYPE_VLAN: | 271 | case IEEE80211_IF_TYPE_VLAN: |
293 | list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans); | ||
294 | /* no need to tell driver */ | 272 | /* no need to tell driver */ |
295 | break; | 273 | break; |
296 | case IEEE80211_IF_TYPE_MNTR: | 274 | case IEEE80211_IF_TYPE_MNTR: |
@@ -329,7 +307,8 @@ static int ieee80211_open(struct net_device *dev) | |||
329 | if (res) | 307 | if (res) |
330 | goto err_stop; | 308 | goto err_stop; |
331 | 309 | ||
332 | ieee80211_if_config(dev); | 310 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
311 | ieee80211_start_mesh(sdata->dev); | ||
333 | changed |= ieee80211_reset_erp_info(dev); | 312 | changed |= ieee80211_reset_erp_info(dev); |
334 | ieee80211_bss_info_change_notify(sdata, changed); | 313 | ieee80211_bss_info_change_notify(sdata, changed); |
335 | ieee80211_enable_keys(sdata); | 314 | ieee80211_enable_keys(sdata); |
@@ -404,6 +383,10 @@ static int ieee80211_open(struct net_device *dev) | |||
404 | err_stop: | 383 | err_stop: |
405 | if (!local->open_count && local->ops->stop) | 384 | if (!local->open_count && local->ops->stop) |
406 | local->ops->stop(local_to_hw(local)); | 385 | local->ops->stop(local_to_hw(local)); |
386 | err_del_bss: | ||
387 | sdata->bss = NULL; | ||
388 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | ||
389 | list_del(&sdata->u.vlan.list); | ||
407 | return res; | 390 | return res; |
408 | } | 391 | } |
409 | 392 | ||
@@ -486,7 +469,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
486 | switch (sdata->vif.type) { | 469 | switch (sdata->vif.type) { |
487 | case IEEE80211_IF_TYPE_VLAN: | 470 | case IEEE80211_IF_TYPE_VLAN: |
488 | list_del(&sdata->u.vlan.list); | 471 | list_del(&sdata->u.vlan.list); |
489 | sdata->u.vlan.ap = NULL; | ||
490 | /* no need to tell driver */ | 472 | /* no need to tell driver */ |
491 | break; | 473 | break; |
492 | case IEEE80211_IF_TYPE_MNTR: | 474 | case IEEE80211_IF_TYPE_MNTR: |
@@ -549,6 +531,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
549 | local->ops->remove_interface(local_to_hw(local), &conf); | 531 | local->ops->remove_interface(local_to_hw(local), &conf); |
550 | } | 532 | } |
551 | 533 | ||
534 | sdata->bss = NULL; | ||
535 | |||
552 | if (local->open_count == 0) { | 536 | if (local->open_count == 0) { |
553 | if (netif_running(local->mdev)) | 537 | if (netif_running(local->mdev)) |
554 | dev_close(local->mdev); | 538 | dev_close(local->mdev); |
@@ -988,7 +972,6 @@ static const struct header_ops ieee80211_header_ops = { | |||
988 | .cache_update = eth_header_cache_update, | 972 | .cache_update = eth_header_cache_update, |
989 | }; | 973 | }; |
990 | 974 | ||
991 | /* Must not be called for mdev */ | ||
992 | void ieee80211_if_setup(struct net_device *dev) | 975 | void ieee80211_if_setup(struct net_device *dev) |
993 | { | 976 | { |
994 | ether_setup(dev); | 977 | ether_setup(dev); |
@@ -998,62 +981,52 @@ void ieee80211_if_setup(struct net_device *dev) | |||
998 | dev->change_mtu = ieee80211_change_mtu; | 981 | dev->change_mtu = ieee80211_change_mtu; |
999 | dev->open = ieee80211_open; | 982 | dev->open = ieee80211_open; |
1000 | dev->stop = ieee80211_stop; | 983 | dev->stop = ieee80211_stop; |
1001 | dev->destructor = ieee80211_if_free; | 984 | dev->destructor = free_netdev; |
1002 | } | 985 | } |
1003 | 986 | ||
1004 | /* everything else */ | 987 | /* everything else */ |
1005 | 988 | ||
1006 | static int __ieee80211_if_config(struct net_device *dev, | 989 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) |
1007 | struct sk_buff *beacon) | ||
1008 | { | 990 | { |
1009 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 991 | struct ieee80211_local *local = sdata->local; |
1010 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1011 | struct ieee80211_if_conf conf; | 992 | struct ieee80211_if_conf conf; |
1012 | 993 | ||
1013 | if (!local->ops->config_interface || !netif_running(dev)) | 994 | if (WARN_ON(!netif_running(sdata->dev))) |
995 | return 0; | ||
996 | |||
997 | if (!local->ops->config_interface) | ||
1014 | return 0; | 998 | return 0; |
1015 | 999 | ||
1016 | memset(&conf, 0, sizeof(conf)); | 1000 | memset(&conf, 0, sizeof(conf)); |
1017 | conf.type = sdata->vif.type; | 1001 | conf.changed = changed; |
1002 | |||
1018 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1003 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || |
1019 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1004 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { |
1020 | conf.bssid = sdata->u.sta.bssid; | 1005 | conf.bssid = sdata->u.sta.bssid; |
1021 | conf.ssid = sdata->u.sta.ssid; | 1006 | conf.ssid = sdata->u.sta.ssid; |
1022 | conf.ssid_len = sdata->u.sta.ssid_len; | 1007 | conf.ssid_len = sdata->u.sta.ssid_len; |
1023 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1024 | conf.beacon = beacon; | ||
1025 | ieee80211_start_mesh(dev); | ||
1026 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 1008 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { |
1009 | conf.bssid = sdata->dev->dev_addr; | ||
1027 | conf.ssid = sdata->u.ap.ssid; | 1010 | conf.ssid = sdata->u.ap.ssid; |
1028 | conf.ssid_len = sdata->u.ap.ssid_len; | 1011 | conf.ssid_len = sdata->u.ap.ssid_len; |
1029 | conf.beacon = beacon; | 1012 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1013 | u8 zero[ETH_ALEN] = { 0 }; | ||
1014 | conf.bssid = zero; | ||
1015 | conf.ssid = zero; | ||
1016 | conf.ssid_len = 0; | ||
1017 | } else { | ||
1018 | WARN_ON(1); | ||
1019 | return -EINVAL; | ||
1030 | } | 1020 | } |
1031 | return local->ops->config_interface(local_to_hw(local), | ||
1032 | &sdata->vif, &conf); | ||
1033 | } | ||
1034 | 1021 | ||
1035 | int ieee80211_if_config(struct net_device *dev) | 1022 | if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) |
1036 | { | 1023 | return -EINVAL; |
1037 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1038 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1039 | if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT && | ||
1040 | (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | ||
1041 | return ieee80211_if_config_beacon(dev); | ||
1042 | return __ieee80211_if_config(dev, NULL); | ||
1043 | } | ||
1044 | 1024 | ||
1045 | int ieee80211_if_config_beacon(struct net_device *dev) | 1025 | if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID))) |
1046 | { | 1026 | return -EINVAL; |
1047 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1048 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1049 | struct sk_buff *skb; | ||
1050 | 1027 | ||
1051 | if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE)) | 1028 | return local->ops->config_interface(local_to_hw(local), |
1052 | return 0; | 1029 | &sdata->vif, &conf); |
1053 | skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif); | ||
1054 | if (!skb) | ||
1055 | return -ENOMEM; | ||
1056 | return __ieee80211_if_config(dev, skb); | ||
1057 | } | 1030 | } |
1058 | 1031 | ||
1059 | int ieee80211_hw_config(struct ieee80211_local *local) | 1032 | int ieee80211_hw_config(struct ieee80211_local *local) |
@@ -1659,7 +1632,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1659 | int result; | 1632 | int result; |
1660 | enum ieee80211_band band; | 1633 | enum ieee80211_band band; |
1661 | struct net_device *mdev; | 1634 | struct net_device *mdev; |
1662 | struct ieee80211_sub_if_data *sdata; | 1635 | struct wireless_dev *mwdev; |
1663 | 1636 | ||
1664 | /* | 1637 | /* |
1665 | * generic code guarantees at least one band, | 1638 | * generic code guarantees at least one band, |
@@ -1699,8 +1672,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1699 | hw->ampdu_queues = 0; | 1672 | hw->ampdu_queues = 0; |
1700 | #endif | 1673 | #endif |
1701 | 1674 | ||
1702 | /* for now, mdev needs sub_if_data :/ */ | 1675 | mdev = alloc_netdev_mq(sizeof(struct wireless_dev), |
1703 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data), | ||
1704 | "wmaster%d", ether_setup, | 1676 | "wmaster%d", ether_setup, |
1705 | ieee80211_num_queues(hw)); | 1677 | ieee80211_num_queues(hw)); |
1706 | if (!mdev) | 1678 | if (!mdev) |
@@ -1709,13 +1681,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1709 | if (ieee80211_num_queues(hw) > 1) | 1681 | if (ieee80211_num_queues(hw) > 1) |
1710 | mdev->features |= NETIF_F_MULTI_QUEUE; | 1682 | mdev->features |= NETIF_F_MULTI_QUEUE; |
1711 | 1683 | ||
1712 | sdata = IEEE80211_DEV_TO_SUB_IF(mdev); | 1684 | mwdev = netdev_priv(mdev); |
1713 | mdev->ieee80211_ptr = &sdata->wdev; | 1685 | mdev->ieee80211_ptr = mwdev; |
1714 | sdata->wdev.wiphy = local->hw.wiphy; | 1686 | mwdev->wiphy = local->hw.wiphy; |
1715 | 1687 | ||
1716 | local->mdev = mdev; | 1688 | local->mdev = mdev; |
1717 | 1689 | ||
1718 | ieee80211_rx_bss_list_init(mdev); | 1690 | ieee80211_rx_bss_list_init(local); |
1719 | 1691 | ||
1720 | mdev->hard_start_xmit = ieee80211_master_start_xmit; | 1692 | mdev->hard_start_xmit = ieee80211_master_start_xmit; |
1721 | mdev->open = ieee80211_master_open; | 1693 | mdev->open = ieee80211_master_open; |
@@ -1724,16 +1696,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1724 | mdev->header_ops = &ieee80211_header_ops; | 1696 | mdev->header_ops = &ieee80211_header_ops; |
1725 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | 1697 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; |
1726 | 1698 | ||
1727 | sdata->vif.type = IEEE80211_IF_TYPE_AP; | ||
1728 | sdata->dev = mdev; | ||
1729 | sdata->local = local; | ||
1730 | sdata->u.ap.force_unicast_rateidx = -1; | ||
1731 | sdata->u.ap.max_ratectrl_rateidx = -1; | ||
1732 | ieee80211_if_sdata_init(sdata); | ||
1733 | |||
1734 | /* no RCU needed since we're still during init phase */ | ||
1735 | list_add_tail(&sdata->list, &local->interfaces); | ||
1736 | |||
1737 | name = wiphy_dev(local->hw.wiphy)->driver->name; | 1699 | name = wiphy_dev(local->hw.wiphy)->driver->name; |
1738 | local->hw.workqueue = create_freezeable_workqueue(name); | 1700 | local->hw.workqueue = create_freezeable_workqueue(name); |
1739 | if (!local->hw.workqueue) { | 1701 | if (!local->hw.workqueue) { |
@@ -1779,9 +1741,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1779 | if (result < 0) | 1741 | if (result < 0) |
1780 | goto fail_dev; | 1742 | goto fail_dev; |
1781 | 1743 | ||
1782 | ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); | ||
1783 | ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP); | ||
1784 | |||
1785 | result = ieee80211_init_rate_ctrl_alg(local, | 1744 | result = ieee80211_init_rate_ctrl_alg(local, |
1786 | hw->rate_control_algorithm); | 1745 | hw->rate_control_algorithm); |
1787 | if (result < 0) { | 1746 | if (result < 0) { |
@@ -1801,13 +1760,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1801 | ieee80211_install_qdisc(local->mdev); | 1760 | ieee80211_install_qdisc(local->mdev); |
1802 | 1761 | ||
1803 | /* add one default STA interface */ | 1762 | /* add one default STA interface */ |
1804 | result = ieee80211_if_add(local->mdev, "wlan%d", NULL, | 1763 | result = ieee80211_if_add(local, "wlan%d", NULL, |
1805 | IEEE80211_IF_TYPE_STA, NULL); | 1764 | IEEE80211_IF_TYPE_STA, NULL); |
1806 | if (result) | 1765 | if (result) |
1807 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", | 1766 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", |
1808 | wiphy_name(local->hw.wiphy)); | 1767 | wiphy_name(local->hw.wiphy)); |
1809 | 1768 | ||
1810 | local->reg_state = IEEE80211_DEV_REGISTERED; | ||
1811 | rtnl_unlock(); | 1769 | rtnl_unlock(); |
1812 | 1770 | ||
1813 | ieee80211_led_init(local); | 1771 | ieee80211_led_init(local); |
@@ -1817,7 +1775,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1817 | fail_wep: | 1775 | fail_wep: |
1818 | rate_control_deinitialize(local); | 1776 | rate_control_deinitialize(local); |
1819 | fail_rate: | 1777 | fail_rate: |
1820 | ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); | ||
1821 | unregister_netdevice(local->mdev); | 1778 | unregister_netdevice(local->mdev); |
1822 | local->mdev = NULL; | 1779 | local->mdev = NULL; |
1823 | fail_dev: | 1780 | fail_dev: |
@@ -1827,10 +1784,8 @@ fail_sta_info: | |||
1827 | debugfs_hw_del(local); | 1784 | debugfs_hw_del(local); |
1828 | destroy_workqueue(local->hw.workqueue); | 1785 | destroy_workqueue(local->hw.workqueue); |
1829 | fail_workqueue: | 1786 | fail_workqueue: |
1830 | if (local->mdev != NULL) { | 1787 | if (local->mdev) |
1831 | ieee80211_if_free(local->mdev); | 1788 | free_netdev(local->mdev); |
1832 | local->mdev = NULL; | ||
1833 | } | ||
1834 | fail_mdev_alloc: | 1789 | fail_mdev_alloc: |
1835 | wiphy_unregister(local->hw.wiphy); | 1790 | wiphy_unregister(local->hw.wiphy); |
1836 | return result; | 1791 | return result; |
@@ -1840,42 +1795,27 @@ EXPORT_SYMBOL(ieee80211_register_hw); | |||
1840 | void ieee80211_unregister_hw(struct ieee80211_hw *hw) | 1795 | void ieee80211_unregister_hw(struct ieee80211_hw *hw) |
1841 | { | 1796 | { |
1842 | struct ieee80211_local *local = hw_to_local(hw); | 1797 | struct ieee80211_local *local = hw_to_local(hw); |
1843 | struct ieee80211_sub_if_data *sdata, *tmp; | ||
1844 | 1798 | ||
1845 | tasklet_kill(&local->tx_pending_tasklet); | 1799 | tasklet_kill(&local->tx_pending_tasklet); |
1846 | tasklet_kill(&local->tasklet); | 1800 | tasklet_kill(&local->tasklet); |
1847 | 1801 | ||
1848 | rtnl_lock(); | 1802 | rtnl_lock(); |
1849 | 1803 | ||
1850 | BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED); | ||
1851 | |||
1852 | local->reg_state = IEEE80211_DEV_UNREGISTERED; | ||
1853 | |||
1854 | /* | 1804 | /* |
1855 | * At this point, interface list manipulations are fine | 1805 | * At this point, interface list manipulations are fine |
1856 | * because the driver cannot be handing us frames any | 1806 | * because the driver cannot be handing us frames any |
1857 | * more and the tasklet is killed. | 1807 | * more and the tasklet is killed. |
1858 | */ | 1808 | */ |
1859 | 1809 | ||
1860 | /* | 1810 | /* First, we remove all virtual interfaces. */ |
1861 | * First, we remove all non-master interfaces. Do this because they | 1811 | ieee80211_remove_interfaces(local); |
1862 | * may have bss pointer dependency on the master, and when we free | ||
1863 | * the master these would be freed as well, breaking our list | ||
1864 | * iteration completely. | ||
1865 | */ | ||
1866 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | ||
1867 | if (sdata->dev == local->mdev) | ||
1868 | continue; | ||
1869 | list_del(&sdata->list); | ||
1870 | __ieee80211_if_del(local, sdata); | ||
1871 | } | ||
1872 | 1812 | ||
1873 | /* then, finally, remove the master interface */ | 1813 | /* then, finally, remove the master interface */ |
1874 | __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev)); | 1814 | unregister_netdevice(local->mdev); |
1875 | 1815 | ||
1876 | rtnl_unlock(); | 1816 | rtnl_unlock(); |
1877 | 1817 | ||
1878 | ieee80211_rx_bss_list_deinit(local->mdev); | 1818 | ieee80211_rx_bss_list_deinit(local); |
1879 | ieee80211_clear_tx_pending(local); | 1819 | ieee80211_clear_tx_pending(local); |
1880 | sta_info_stop(local); | 1820 | sta_info_stop(local); |
1881 | rate_control_deinitialize(local); | 1821 | rate_control_deinitialize(local); |
@@ -1892,8 +1832,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1892 | wiphy_unregister(local->hw.wiphy); | 1832 | wiphy_unregister(local->hw.wiphy); |
1893 | ieee80211_wep_free(local); | 1833 | ieee80211_wep_free(local); |
1894 | ieee80211_led_exit(local); | 1834 | ieee80211_led_exit(local); |
1895 | ieee80211_if_free(local->mdev); | 1835 | free_netdev(local->mdev); |
1896 | local->mdev = NULL; | ||
1897 | } | 1836 | } |
1898 | EXPORT_SYMBOL(ieee80211_unregister_hw); | 1837 | EXPORT_SYMBOL(ieee80211_unregister_hw); |
1899 | 1838 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index dbc8cf454bc0..8f51375317dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -78,7 +78,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | |||
78 | static struct ieee80211_sta_bss * | 78 | static struct ieee80211_sta_bss * |
79 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, | 79 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, |
80 | u8 *ssid, u8 ssid_len); | 80 | u8 *ssid, u8 ssid_len); |
81 | static void ieee80211_rx_bss_put(struct net_device *dev, | 81 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, |
82 | struct ieee80211_sta_bss *bss); | 82 | struct ieee80211_sta_bss *bss); |
83 | static int ieee80211_sta_find_ibss(struct net_device *dev, | 83 | static int ieee80211_sta_find_ibss(struct net_device *dev, |
84 | struct ieee80211_if_sta *ifsta); | 84 | struct ieee80211_if_sta *ifsta); |
@@ -345,7 +345,7 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, | |||
345 | params.aifs = pos[0] & 0x0f; | 345 | params.aifs = pos[0] & 0x0f; |
346 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); | 346 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); |
347 | params.cw_min = ecw2cw(pos[1] & 0x0f); | 347 | params.cw_min = ecw2cw(pos[1] & 0x0f); |
348 | params.txop = pos[2] | (pos[3] << 8); | 348 | params.txop = get_unaligned_le16(pos + 2); |
349 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 349 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
350 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | 350 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " |
351 | "cWmin=%d cWmax=%d txop=%d\n", | 351 | "cWmin=%d cWmax=%d txop=%d\n", |
@@ -554,7 +554,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
554 | 554 | ||
555 | changed |= ieee80211_handle_bss_capability(sdata, bss); | 555 | changed |= ieee80211_handle_bss_capability(sdata, bss); |
556 | 556 | ||
557 | ieee80211_rx_bss_put(dev, bss); | 557 | ieee80211_rx_bss_put(local, bss); |
558 | } | 558 | } |
559 | 559 | ||
560 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | 560 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { |
@@ -760,7 +760,7 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
760 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | 760 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) |
761 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | 761 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; |
762 | 762 | ||
763 | ieee80211_rx_bss_put(dev, bss); | 763 | ieee80211_rx_bss_put(local, bss); |
764 | } else { | 764 | } else { |
765 | rates = ~0; | 765 | rates = ~0; |
766 | rates_len = sband->n_bitrates; | 766 | rates_len = sband->n_bitrates; |
@@ -992,7 +992,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, | |||
992 | wep_privacy = !!ieee80211_sta_wep_configured(dev); | 992 | wep_privacy = !!ieee80211_sta_wep_configured(dev); |
993 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); | 993 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); |
994 | 994 | ||
995 | ieee80211_rx_bss_put(dev, bss); | 995 | ieee80211_rx_bss_put(local, bss); |
996 | 996 | ||
997 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) | 997 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) |
998 | return 0; | 998 | return 0; |
@@ -2094,7 +2094,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2094 | sta->last_signal = bss->signal; | 2094 | sta->last_signal = bss->signal; |
2095 | sta->last_qual = bss->qual; | 2095 | sta->last_qual = bss->qual; |
2096 | sta->last_noise = bss->noise; | 2096 | sta->last_noise = bss->noise; |
2097 | ieee80211_rx_bss_put(dev, bss); | 2097 | ieee80211_rx_bss_put(local, bss); |
2098 | } | 2098 | } |
2099 | 2099 | ||
2100 | err = sta_info_insert(sta); | 2100 | err = sta_info_insert(sta); |
@@ -2212,10 +2212,9 @@ static void __ieee80211_rx_bss_hash_add(struct net_device *dev, | |||
2212 | 2212 | ||
2213 | 2213 | ||
2214 | /* Caller must hold local->sta_bss_lock */ | 2214 | /* Caller must hold local->sta_bss_lock */ |
2215 | static void __ieee80211_rx_bss_hash_del(struct net_device *dev, | 2215 | static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, |
2216 | struct ieee80211_sta_bss *bss) | 2216 | struct ieee80211_sta_bss *bss) |
2217 | { | 2217 | { |
2218 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2219 | struct ieee80211_sta_bss *b, *prev = NULL; | 2218 | struct ieee80211_sta_bss *b, *prev = NULL; |
2220 | b = local->sta_bss_hash[STA_HASH(bss->bssid)]; | 2219 | b = local->sta_bss_hash[STA_HASH(bss->bssid)]; |
2221 | while (b) { | 2220 | while (b) { |
@@ -2367,39 +2366,35 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) | |||
2367 | } | 2366 | } |
2368 | 2367 | ||
2369 | 2368 | ||
2370 | static void ieee80211_rx_bss_put(struct net_device *dev, | 2369 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, |
2371 | struct ieee80211_sta_bss *bss) | 2370 | struct ieee80211_sta_bss *bss) |
2372 | { | 2371 | { |
2373 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2374 | |||
2375 | local_bh_disable(); | 2372 | local_bh_disable(); |
2376 | if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { | 2373 | if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { |
2377 | local_bh_enable(); | 2374 | local_bh_enable(); |
2378 | return; | 2375 | return; |
2379 | } | 2376 | } |
2380 | 2377 | ||
2381 | __ieee80211_rx_bss_hash_del(dev, bss); | 2378 | __ieee80211_rx_bss_hash_del(local, bss); |
2382 | list_del(&bss->list); | 2379 | list_del(&bss->list); |
2383 | spin_unlock_bh(&local->sta_bss_lock); | 2380 | spin_unlock_bh(&local->sta_bss_lock); |
2384 | ieee80211_rx_bss_free(bss); | 2381 | ieee80211_rx_bss_free(bss); |
2385 | } | 2382 | } |
2386 | 2383 | ||
2387 | 2384 | ||
2388 | void ieee80211_rx_bss_list_init(struct net_device *dev) | 2385 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local) |
2389 | { | 2386 | { |
2390 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2391 | spin_lock_init(&local->sta_bss_lock); | 2387 | spin_lock_init(&local->sta_bss_lock); |
2392 | INIT_LIST_HEAD(&local->sta_bss_list); | 2388 | INIT_LIST_HEAD(&local->sta_bss_list); |
2393 | } | 2389 | } |
2394 | 2390 | ||
2395 | 2391 | ||
2396 | void ieee80211_rx_bss_list_deinit(struct net_device *dev) | 2392 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) |
2397 | { | 2393 | { |
2398 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2399 | struct ieee80211_sta_bss *bss, *tmp; | 2394 | struct ieee80211_sta_bss *bss, *tmp; |
2400 | 2395 | ||
2401 | list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) | 2396 | list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) |
2402 | ieee80211_rx_bss_put(dev, bss); | 2397 | ieee80211_rx_bss_put(local, bss); |
2403 | } | 2398 | } |
2404 | 2399 | ||
2405 | 2400 | ||
@@ -2411,8 +2406,6 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2411 | int res, rates, i, j; | 2406 | int res, rates, i, j; |
2412 | struct sk_buff *skb; | 2407 | struct sk_buff *skb; |
2413 | struct ieee80211_mgmt *mgmt; | 2408 | struct ieee80211_mgmt *mgmt; |
2414 | struct ieee80211_tx_info *control; | ||
2415 | struct rate_selection ratesel; | ||
2416 | u8 *pos; | 2409 | u8 *pos; |
2417 | struct ieee80211_sub_if_data *sdata; | 2410 | struct ieee80211_sub_if_data *sdata; |
2418 | struct ieee80211_supported_band *sband; | 2411 | struct ieee80211_supported_band *sband; |
@@ -2430,7 +2423,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2430 | local->ops->reset_tsf(local_to_hw(local)); | 2423 | local->ops->reset_tsf(local_to_hw(local)); |
2431 | } | 2424 | } |
2432 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); | 2425 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); |
2433 | res = ieee80211_if_config(dev); | 2426 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
2434 | if (res) | 2427 | if (res) |
2435 | return res; | 2428 | return res; |
2436 | 2429 | ||
@@ -2444,19 +2437,16 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2444 | if (res) | 2437 | if (res) |
2445 | return res; | 2438 | return res; |
2446 | 2439 | ||
2447 | /* Set beacon template */ | 2440 | /* Build IBSS probe response */ |
2448 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 2441 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
2449 | do { | 2442 | if (skb) { |
2450 | if (!skb) | ||
2451 | break; | ||
2452 | |||
2453 | skb_reserve(skb, local->hw.extra_tx_headroom); | 2443 | skb_reserve(skb, local->hw.extra_tx_headroom); |
2454 | 2444 | ||
2455 | mgmt = (struct ieee80211_mgmt *) | 2445 | mgmt = (struct ieee80211_mgmt *) |
2456 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 2446 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
2457 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 2447 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
2458 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 2448 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, |
2459 | IEEE80211_STYPE_BEACON); | 2449 | IEEE80211_STYPE_PROBE_RESP); |
2460 | memset(mgmt->da, 0xff, ETH_ALEN); | 2450 | memset(mgmt->da, 0xff, ETH_ALEN); |
2461 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 2451 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); |
2462 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 2452 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
@@ -2500,61 +2490,22 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2500 | memcpy(pos, &bss->supp_rates[8], rates); | 2490 | memcpy(pos, &bss->supp_rates[8], rates); |
2501 | } | 2491 | } |
2502 | 2492 | ||
2503 | control = IEEE80211_SKB_CB(skb); | 2493 | ifsta->probe_resp = skb; |
2504 | |||
2505 | rate_control_get_rate(dev, sband, skb, &ratesel); | ||
2506 | if (ratesel.rate_idx < 0) { | ||
2507 | printk(KERN_DEBUG "%s: Failed to determine TX rate " | ||
2508 | "for IBSS beacon\n", dev->name); | ||
2509 | break; | ||
2510 | } | ||
2511 | control->control.vif = &sdata->vif; | ||
2512 | control->tx_rate_idx = ratesel.rate_idx; | ||
2513 | if (sdata->bss_conf.use_short_preamble && | ||
2514 | sband->bitrates[ratesel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) | ||
2515 | control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | ||
2516 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | ||
2517 | control->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
2518 | control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
2519 | control->control.retry_limit = 1; | ||
2520 | |||
2521 | ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); | ||
2522 | if (ifsta->probe_resp) { | ||
2523 | mgmt = (struct ieee80211_mgmt *) | ||
2524 | ifsta->probe_resp->data; | ||
2525 | mgmt->frame_control = | ||
2526 | IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
2527 | IEEE80211_STYPE_PROBE_RESP); | ||
2528 | } else { | ||
2529 | printk(KERN_DEBUG "%s: Could not allocate ProbeResp " | ||
2530 | "template for IBSS\n", dev->name); | ||
2531 | } | ||
2532 | 2494 | ||
2533 | if (local->ops->beacon_update && | 2495 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
2534 | local->ops->beacon_update(local_to_hw(local), skb) == 0) { | 2496 | } |
2535 | printk(KERN_DEBUG "%s: Configured IBSS beacon " | ||
2536 | "template\n", dev->name); | ||
2537 | skb = NULL; | ||
2538 | } | ||
2539 | |||
2540 | rates = 0; | ||
2541 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2542 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
2543 | int bitrate = (bss->supp_rates[i] & 0x7f) * 5; | ||
2544 | for (j = 0; j < sband->n_bitrates; j++) | ||
2545 | if (sband->bitrates[j].bitrate == bitrate) | ||
2546 | rates |= BIT(j); | ||
2547 | } | ||
2548 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | ||
2549 | |||
2550 | ieee80211_sta_def_wmm_params(dev, bss, 1); | ||
2551 | } while (0); | ||
2552 | 2497 | ||
2553 | if (skb) { | 2498 | rates = 0; |
2554 | printk(KERN_DEBUG "%s: Failed to configure IBSS beacon " | 2499 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2555 | "template\n", dev->name); | 2500 | for (i = 0; i < bss->supp_rates_len; i++) { |
2556 | dev_kfree_skb(skb); | 2501 | int bitrate = (bss->supp_rates[i] & 0x7f) * 5; |
2502 | for (j = 0; j < sband->n_bitrates; j++) | ||
2503 | if (sband->bitrates[j].bitrate == bitrate) | ||
2504 | rates |= BIT(j); | ||
2557 | } | 2505 | } |
2506 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | ||
2507 | |||
2508 | ieee80211_sta_def_wmm_params(dev, bss, 1); | ||
2558 | 2509 | ||
2559 | ifsta->state = IEEE80211_IBSS_JOINED; | 2510 | ifsta->state = IEEE80211_IBSS_JOINED; |
2560 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 2511 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
@@ -2775,7 +2726,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2775 | */ | 2726 | */ |
2776 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 2727 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && |
2777 | bss->probe_resp && beacon) { | 2728 | bss->probe_resp && beacon) { |
2778 | ieee80211_rx_bss_put(dev, bss); | 2729 | ieee80211_rx_bss_put(local, bss); |
2779 | return; | 2730 | return; |
2780 | } | 2731 | } |
2781 | 2732 | ||
@@ -2918,7 +2869,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2918 | } | 2869 | } |
2919 | } | 2870 | } |
2920 | 2871 | ||
2921 | ieee80211_rx_bss_put(dev, bss); | 2872 | ieee80211_rx_bss_put(local, bss); |
2922 | } | 2873 | } |
2923 | 2874 | ||
2924 | 2875 | ||
@@ -3338,7 +3289,7 @@ static void ieee80211_mesh_housekeeping(struct net_device *dev, | |||
3338 | 3289 | ||
3339 | free_plinks = mesh_plink_availables(sdata); | 3290 | free_plinks = mesh_plink_availables(sdata); |
3340 | if (free_plinks != sdata->u.sta.accepting_plinks) | 3291 | if (free_plinks != sdata->u.sta.accepting_plinks) |
3341 | ieee80211_if_config_beacon(dev); | 3292 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); |
3342 | 3293 | ||
3343 | mod_timer(&ifsta->timer, jiffies + | 3294 | mod_timer(&ifsta->timer, jiffies + |
3344 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); | 3295 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); |
@@ -3578,7 +3529,7 @@ static int ieee80211_sta_config_auth(struct net_device *dev, | |||
3578 | selected->ssid_len); | 3529 | selected->ssid_len); |
3579 | ieee80211_sta_set_bssid(dev, selected->bssid); | 3530 | ieee80211_sta_set_bssid(dev, selected->bssid); |
3580 | ieee80211_sta_def_wmm_params(dev, selected, 0); | 3531 | ieee80211_sta_def_wmm_params(dev, selected, 0); |
3581 | ieee80211_rx_bss_put(dev, selected); | 3532 | ieee80211_rx_bss_put(local, selected); |
3582 | ifsta->state = IEEE80211_AUTHENTICATE; | 3533 | ifsta->state = IEEE80211_AUTHENTICATE; |
3583 | ieee80211_sta_reset_auth(dev, ifsta); | 3534 | ieee80211_sta_reset_auth(dev, ifsta); |
3584 | return 0; | 3535 | return 0; |
@@ -3655,7 +3606,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
3655 | } | 3606 | } |
3656 | 3607 | ||
3657 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 3608 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); |
3658 | ieee80211_rx_bss_put(dev, bss); | 3609 | ieee80211_rx_bss_put(local, bss); |
3659 | return ret; | 3610 | return ret; |
3660 | } | 3611 | } |
3661 | 3612 | ||
@@ -3711,7 +3662,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3711 | " based on configured SSID\n", | 3662 | " based on configured SSID\n", |
3712 | dev->name, print_mac(mac, bssid)); | 3663 | dev->name, print_mac(mac, bssid)); |
3713 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 3664 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); |
3714 | ieee80211_rx_bss_put(dev, bss); | 3665 | ieee80211_rx_bss_put(local, bss); |
3715 | return ret; | 3666 | return ret; |
3716 | } | 3667 | } |
3717 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 3668 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
@@ -3762,28 +3713,45 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) | |||
3762 | { | 3713 | { |
3763 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3714 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3764 | struct ieee80211_if_sta *ifsta; | 3715 | struct ieee80211_if_sta *ifsta; |
3716 | int res; | ||
3765 | 3717 | ||
3766 | if (len > IEEE80211_MAX_SSID_LEN) | 3718 | if (len > IEEE80211_MAX_SSID_LEN) |
3767 | return -EINVAL; | 3719 | return -EINVAL; |
3768 | 3720 | ||
3769 | ifsta = &sdata->u.sta; | 3721 | ifsta = &sdata->u.sta; |
3770 | 3722 | ||
3771 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) | 3723 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { |
3724 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); | ||
3725 | memcpy(ifsta->ssid, ssid, len); | ||
3726 | ifsta->ssid_len = len; | ||
3772 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | 3727 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
3773 | memcpy(ifsta->ssid, ssid, len); | 3728 | |
3774 | memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len); | 3729 | res = 0; |
3775 | ifsta->ssid_len = len; | 3730 | /* |
3731 | * Hack! MLME code needs to be cleaned up to have different | ||
3732 | * entry points for configuration and internal selection change | ||
3733 | */ | ||
3734 | if (netif_running(sdata->dev)) | ||
3735 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); | ||
3736 | if (res) { | ||
3737 | printk(KERN_DEBUG "%s: Failed to config new SSID to " | ||
3738 | "the low-level driver\n", dev->name); | ||
3739 | return res; | ||
3740 | } | ||
3741 | } | ||
3776 | 3742 | ||
3777 | if (len) | 3743 | if (len) |
3778 | ifsta->flags |= IEEE80211_STA_SSID_SET; | 3744 | ifsta->flags |= IEEE80211_STA_SSID_SET; |
3779 | else | 3745 | else |
3780 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | 3746 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; |
3747 | |||
3781 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | 3748 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && |
3782 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { | 3749 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { |
3783 | ifsta->ibss_join_req = jiffies; | 3750 | ifsta->ibss_join_req = jiffies; |
3784 | ifsta->state = IEEE80211_IBSS_SEARCH; | 3751 | ifsta->state = IEEE80211_IBSS_SEARCH; |
3785 | return ieee80211_sta_find_ibss(dev, ifsta); | 3752 | return ieee80211_sta_find_ibss(dev, ifsta); |
3786 | } | 3753 | } |
3754 | |||
3787 | return 0; | 3755 | return 0; |
3788 | } | 3756 | } |
3789 | 3757 | ||
@@ -3809,7 +3777,12 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) | |||
3809 | 3777 | ||
3810 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 3778 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { |
3811 | memcpy(ifsta->bssid, bssid, ETH_ALEN); | 3779 | memcpy(ifsta->bssid, bssid, ETH_ALEN); |
3812 | res = ieee80211_if_config(dev); | 3780 | res = 0; |
3781 | /* | ||
3782 | * Hack! See also ieee80211_sta_set_ssid. | ||
3783 | */ | ||
3784 | if (netif_running(sdata->dev)) | ||
3785 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | ||
3813 | if (res) { | 3786 | if (res) { |
3814 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " | 3787 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " |
3815 | "the low-level driver\n", dev->name); | 3788 | "the low-level driver\n", dev->name); |
@@ -3907,11 +3880,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
3907 | 3880 | ||
3908 | rcu_read_lock(); | 3881 | rcu_read_lock(); |
3909 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 3882 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
3910 | |||
3911 | /* No need to wake the master device. */ | ||
3912 | if (sdata->dev == local->mdev) | ||
3913 | continue; | ||
3914 | |||
3915 | /* Tell AP we're back */ | 3883 | /* Tell AP we're back */ |
3916 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | 3884 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && |
3917 | sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) | 3885 | sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) |
@@ -4077,12 +4045,6 @@ static int ieee80211_sta_start_scan(struct net_device *dev, | |||
4077 | 4045 | ||
4078 | rcu_read_lock(); | 4046 | rcu_read_lock(); |
4079 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 4047 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
4080 | |||
4081 | /* Don't stop the master interface, otherwise we can't transmit | ||
4082 | * probes! */ | ||
4083 | if (sdata->dev == local->mdev) | ||
4084 | continue; | ||
4085 | |||
4086 | netif_stop_queue(sdata->dev); | 4048 | netif_stop_queue(sdata->dev); |
4087 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | 4049 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && |
4088 | (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) | 4050 | (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) |
@@ -4398,7 +4360,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | |||
4398 | return NULL; | 4360 | return NULL; |
4399 | } | 4361 | } |
4400 | 4362 | ||
4401 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) | 4363 | if (compare_ether_addr(bssid, sdata->u.sta.bssid)) |
4402 | return NULL; | 4364 | return NULL; |
4403 | 4365 | ||
4404 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 4366 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -4473,12 +4435,10 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, | |||
4473 | case IEEE80211_NOTIFY_RE_ASSOC: | 4435 | case IEEE80211_NOTIFY_RE_ASSOC: |
4474 | rcu_read_lock(); | 4436 | rcu_read_lock(); |
4475 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 4437 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
4438 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
4439 | continue; | ||
4476 | 4440 | ||
4477 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 4441 | ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta); |
4478 | ieee80211_sta_req_auth(sdata->dev, | ||
4479 | &sdata->u.sta); | ||
4480 | } | ||
4481 | |||
4482 | } | 4442 | } |
4483 | rcu_read_unlock(); | 4443 | rcu_read_unlock(); |
4484 | break; | 4444 | break; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 742c5b06cffd..a914ba73ccf5 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -259,8 +259,8 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
259 | 259 | ||
260 | /* Don't update the state if we're not controlling the rate. */ | 260 | /* Don't update the state if we're not controlling the rate. */ |
261 | sdata = sta->sdata; | 261 | sdata = sta->sdata; |
262 | if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { | 262 | if (sdata->force_unicast_rateidx > -1) { |
263 | sta->txrate_idx = sdata->bss->max_ratectrl_rateidx; | 263 | sta->txrate_idx = sdata->max_ratectrl_rateidx; |
264 | goto unlock; | 264 | goto unlock; |
265 | } | 265 | } |
266 | 266 | ||
@@ -337,8 +337,8 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | |||
337 | 337 | ||
338 | /* If a forced rate is in effect, select it. */ | 338 | /* If a forced rate is in effect, select it. */ |
339 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 339 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
340 | if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) | 340 | if (sdata->force_unicast_rateidx > -1) |
341 | sta->txrate_idx = sdata->bss->force_unicast_rateidx; | 341 | sta->txrate_idx = sdata->force_unicast_rateidx; |
342 | 342 | ||
343 | rateidx = sta->txrate_idx; | 343 | rateidx = sta->txrate_idx; |
344 | 344 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fab443d717eb..6d9ae67c27ca 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -334,13 +334,18 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
334 | else | 334 | else |
335 | rx->flags &= ~IEEE80211_RX_AMSDU; | 335 | rx->flags &= ~IEEE80211_RX_AMSDU; |
336 | } else { | 336 | } else { |
337 | if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { | 337 | /* |
338 | /* Separate TID for management frames */ | 338 | * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): |
339 | tid = NUM_RX_DATA_QUEUES - 1; | 339 | * |
340 | } else { | 340 | * Sequence numbers for management frames, QoS data |
341 | /* no qos control present */ | 341 | * frames with a broadcast/multicast address in the |
342 | tid = 0; /* 802.1d - Best Effort */ | 342 | * Address 1 field, and all non-QoS data frames sent |
343 | } | 343 | * by QoS STAs are assigned using an additional single |
344 | * modulo-4096 counter, [...] | ||
345 | * | ||
346 | * We also use that counter for non-QoS STAs. | ||
347 | */ | ||
348 | tid = NUM_RX_DATA_QUEUES - 1; | ||
344 | } | 349 | } |
345 | 350 | ||
346 | rx->queue = tid; | 351 | rx->queue = tid; |
@@ -647,8 +652,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | |||
647 | 652 | ||
648 | sdata = sta->sdata; | 653 | sdata = sta->sdata; |
649 | 654 | ||
650 | if (sdata->bss) | 655 | atomic_inc(&sdata->bss->num_sta_ps); |
651 | atomic_inc(&sdata->bss->num_sta_ps); | ||
652 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 656 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
653 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 657 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
654 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 658 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
@@ -667,8 +671,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
667 | 671 | ||
668 | sdata = sta->sdata; | 672 | sdata = sta->sdata; |
669 | 673 | ||
670 | if (sdata->bss) | 674 | atomic_dec(&sdata->bss->num_sta_ps); |
671 | atomic_dec(&sdata->bss->num_sta_ps); | ||
672 | 675 | ||
673 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 676 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
674 | 677 | ||
@@ -742,7 +745,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
742 | sta->last_qual = rx->status->qual; | 745 | sta->last_qual = rx->status->qual; |
743 | sta->last_noise = rx->status->noise; | 746 | sta->last_noise = rx->status->noise; |
744 | 747 | ||
745 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 748 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
749 | (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP || | ||
750 | rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) { | ||
746 | /* Change STA power saving mode only in the end of a frame | 751 | /* Change STA power saving mode only in the end of a frame |
747 | * exchange sequence */ | 752 | * exchange sequence */ |
748 | if (test_sta_flags(sta, WLAN_STA_PS) && | 753 | if (test_sta_flags(sta, WLAN_STA_PS) && |
@@ -1772,11 +1777,6 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1772 | return 0; | 1777 | return 0; |
1773 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1778 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1774 | } | 1779 | } |
1775 | if (sdata->dev == sdata->local->mdev && | ||
1776 | !(rx->flags & IEEE80211_RX_IN_SCAN)) | ||
1777 | /* do not receive anything via | ||
1778 | * master device when not scanning */ | ||
1779 | return 0; | ||
1780 | break; | 1780 | break; |
1781 | case IEEE80211_IF_TYPE_WDS: | 1781 | case IEEE80211_IF_TYPE_WDS: |
1782 | if (bssid || !ieee80211_is_data(hdr->frame_control)) | 1782 | if (bssid || !ieee80211_is_data(hdr->frame_control)) |
@@ -2046,8 +2046,8 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2046 | 2046 | ||
2047 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 2047 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
2048 | 2048 | ||
2049 | /* null data frames are excluded */ | 2049 | /* qos null data frames are excluded */ |
2050 | if (unlikely(ieee80211_is_nullfunc(hdr->frame_control))) | 2050 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
2051 | goto end_reorder; | 2051 | goto end_reorder; |
2052 | 2052 | ||
2053 | /* new un-ordered ampdu frame - process it */ | 2053 | /* new un-ordered ampdu frame - process it */ |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 47d2c1bbfcaa..f2ba653b9d69 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -320,7 +320,9 @@ int sta_info_insert(struct sta_info *sta) | |||
320 | /* notify driver */ | 320 | /* notify driver */ |
321 | if (local->ops->sta_notify) { | 321 | if (local->ops->sta_notify) { |
322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) |
323 | sdata = sdata->u.vlan.ap; | 323 | sdata = container_of(sdata->bss, |
324 | struct ieee80211_sub_if_data, | ||
325 | u.ap); | ||
324 | 326 | ||
325 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
326 | STA_NOTIFY_ADD, sta->addr); | 328 | STA_NOTIFY_ADD, sta->addr); |
@@ -375,8 +377,10 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid) | |||
375 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | 377 | static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, |
376 | struct sta_info *sta) | 378 | struct sta_info *sta) |
377 | { | 379 | { |
378 | if (bss) | 380 | BUG_ON(!bss); |
379 | __bss_tim_set(bss, sta->aid); | 381 | |
382 | __bss_tim_set(bss, sta->aid); | ||
383 | |||
380 | if (sta->local->ops->set_tim) { | 384 | if (sta->local->ops->set_tim) { |
381 | sta->local->tim_in_locked_section = true; | 385 | sta->local->tim_in_locked_section = true; |
382 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | 386 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); |
@@ -388,6 +392,8 @@ void sta_info_set_tim_bit(struct sta_info *sta) | |||
388 | { | 392 | { |
389 | unsigned long flags; | 393 | unsigned long flags; |
390 | 394 | ||
395 | BUG_ON(!sta->sdata->bss); | ||
396 | |||
391 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 397 | spin_lock_irqsave(&sta->local->sta_lock, flags); |
392 | __sta_info_set_tim_bit(sta->sdata->bss, sta); | 398 | __sta_info_set_tim_bit(sta->sdata->bss, sta); |
393 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 399 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
@@ -396,8 +402,10 @@ void sta_info_set_tim_bit(struct sta_info *sta) | |||
396 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | 402 | static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, |
397 | struct sta_info *sta) | 403 | struct sta_info *sta) |
398 | { | 404 | { |
399 | if (bss) | 405 | BUG_ON(!bss); |
400 | __bss_tim_clear(bss, sta->aid); | 406 | |
407 | __bss_tim_clear(bss, sta->aid); | ||
408 | |||
401 | if (sta->local->ops->set_tim) { | 409 | if (sta->local->ops->set_tim) { |
402 | sta->local->tim_in_locked_section = true; | 410 | sta->local->tim_in_locked_section = true; |
403 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | 411 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); |
@@ -409,6 +417,8 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
409 | { | 417 | { |
410 | unsigned long flags; | 418 | unsigned long flags; |
411 | 419 | ||
420 | BUG_ON(!sta->sdata->bss); | ||
421 | |||
412 | spin_lock_irqsave(&sta->local->sta_lock, flags); | 422 | spin_lock_irqsave(&sta->local->sta_lock, flags); |
413 | __sta_info_clear_tim_bit(sta->sdata->bss, sta); | 423 | __sta_info_clear_tim_bit(sta->sdata->bss, sta); |
414 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 424 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
@@ -437,8 +447,9 @@ void __sta_info_unlink(struct sta_info **sta) | |||
437 | list_del(&(*sta)->list); | 447 | list_del(&(*sta)->list); |
438 | 448 | ||
439 | if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { | 449 | if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) { |
440 | if (sdata->bss) | 450 | BUG_ON(!sdata->bss); |
441 | atomic_dec(&sdata->bss->num_sta_ps); | 451 | |
452 | atomic_dec(&sdata->bss->num_sta_ps); | ||
442 | __sta_info_clear_tim_bit(sdata->bss, *sta); | 453 | __sta_info_clear_tim_bit(sdata->bss, *sta); |
443 | } | 454 | } |
444 | 455 | ||
@@ -446,7 +457,9 @@ void __sta_info_unlink(struct sta_info **sta) | |||
446 | 457 | ||
447 | if (local->ops->sta_notify) { | 458 | if (local->ops->sta_notify) { |
448 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 459 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) |
449 | sdata = sdata->u.vlan.ap; | 460 | sdata = container_of(sdata->bss, |
461 | struct ieee80211_sub_if_data, | ||
462 | u.ap); | ||
450 | 463 | ||
451 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 464 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
452 | STA_NOTIFY_REMOVE, (*sta)->addr); | 465 | STA_NOTIFY_REMOVE, (*sta)->addr); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 94311dcfe043..109db787ccb7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -285,6 +285,7 @@ struct sta_info { | |||
285 | unsigned long tx_fragments; | 285 | unsigned long tx_fragments; |
286 | int txrate_idx; | 286 | int txrate_idx; |
287 | int last_txrate_idx; | 287 | int last_txrate_idx; |
288 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | ||
288 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 289 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
289 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; | 290 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; |
290 | #endif | 291 | #endif |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9bd9faac3c3c..0fbadd8b983c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -38,16 +38,6 @@ | |||
38 | 38 | ||
39 | /* misc utils */ | 39 | /* misc utils */ |
40 | 40 | ||
41 | static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata, | ||
42 | struct ieee80211_hdr *hdr) | ||
43 | { | ||
44 | /* Set the sequence number for this frame. */ | ||
45 | hdr->seq_ctrl = cpu_to_le16(sdata->sequence); | ||
46 | |||
47 | /* Increase the sequence number. */ | ||
48 | sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ; | ||
49 | } | ||
50 | |||
51 | #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP | 41 | #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP |
52 | static void ieee80211_dump_frame(const char *ifname, const char *title, | 42 | static void ieee80211_dump_frame(const char *ifname, const char *title, |
53 | const struct sk_buff *skb) | 43 | const struct sk_buff *skb) |
@@ -274,17 +264,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
274 | return TX_CONTINUE; | 264 | return TX_CONTINUE; |
275 | } | 265 | } |
276 | 266 | ||
277 | static ieee80211_tx_result debug_noinline | ||
278 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | ||
279 | { | ||
280 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
281 | |||
282 | if (ieee80211_hdrlen(hdr->frame_control) >= 24) | ||
283 | ieee80211_include_sequence(tx->sdata, hdr); | ||
284 | |||
285 | return TX_CONTINUE; | ||
286 | } | ||
287 | |||
288 | /* This function is called whenever the AP is about to exceed the maximum limit | 267 | /* This function is called whenever the AP is about to exceed the maximum limit |
289 | * of buffered frames for power saving STAs. This situation should not really | 268 | * of buffered frames for power saving STAs. This situation should not really |
290 | * happen often during normal operation, so dropping the oldest buffered packet | 269 | * happen often during normal operation, so dropping the oldest buffered packet |
@@ -303,8 +282,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
303 | 282 | ||
304 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 283 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
305 | struct ieee80211_if_ap *ap; | 284 | struct ieee80211_if_ap *ap; |
306 | if (sdata->dev == local->mdev || | 285 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) |
307 | sdata->vif.type != IEEE80211_IF_TYPE_AP) | ||
308 | continue; | 286 | continue; |
309 | ap = &sdata->u.ap; | 287 | ap = &sdata->u.ap; |
310 | skb = skb_dequeue(&ap->ps_bc_buf); | 288 | skb = skb_dequeue(&ap->ps_bc_buf); |
@@ -346,8 +324,12 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
346 | * This is done either by the hardware or us. | 324 | * This is done either by the hardware or us. |
347 | */ | 325 | */ |
348 | 326 | ||
349 | /* not AP/IBSS or ordered frame */ | 327 | /* powersaving STAs only in AP/VLAN mode */ |
350 | if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER)) | 328 | if (!tx->sdata->bss) |
329 | return TX_CONTINUE; | ||
330 | |||
331 | /* no buffering for ordered frames */ | ||
332 | if (tx->fc & IEEE80211_FCTL_ORDER) | ||
351 | return TX_CONTINUE; | 333 | return TX_CONTINUE; |
352 | 334 | ||
353 | /* no stations in PS mode */ | 335 | /* no stations in PS mode */ |
@@ -639,6 +621,49 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
639 | } | 621 | } |
640 | 622 | ||
641 | static ieee80211_tx_result debug_noinline | 623 | static ieee80211_tx_result debug_noinline |
624 | ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | ||
625 | { | ||
626 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | ||
627 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
628 | u16 *seq; | ||
629 | u8 *qc; | ||
630 | int tid; | ||
631 | |||
632 | /* only for injected frames */ | ||
633 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) | ||
634 | return TX_CONTINUE; | ||
635 | |||
636 | if (ieee80211_hdrlen(hdr->frame_control) < 24) | ||
637 | return TX_CONTINUE; | ||
638 | |||
639 | if (!ieee80211_is_data_qos(hdr->frame_control)) { | ||
640 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | ||
641 | return TX_CONTINUE; | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | * This should be true for injected/management frames only, for | ||
646 | * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ | ||
647 | * above since they are not QoS-data frames. | ||
648 | */ | ||
649 | if (!tx->sta) | ||
650 | return TX_CONTINUE; | ||
651 | |||
652 | /* include per-STA, per-TID sequence counter */ | ||
653 | |||
654 | qc = ieee80211_get_qos_ctl(hdr); | ||
655 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | ||
656 | seq = &tx->sta->tid_seq[tid]; | ||
657 | |||
658 | hdr->seq_ctrl = cpu_to_le16(*seq); | ||
659 | |||
660 | /* Increase the sequence number. */ | ||
661 | *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; | ||
662 | |||
663 | return TX_CONTINUE; | ||
664 | } | ||
665 | |||
666 | static ieee80211_tx_result debug_noinline | ||
642 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | 667 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) |
643 | { | 668 | { |
644 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 669 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
@@ -1107,12 +1132,12 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1107 | goto txh_done; | 1132 | goto txh_done; |
1108 | 1133 | ||
1109 | CALL_TXH(ieee80211_tx_h_check_assoc) | 1134 | CALL_TXH(ieee80211_tx_h_check_assoc) |
1110 | CALL_TXH(ieee80211_tx_h_sequence) | ||
1111 | CALL_TXH(ieee80211_tx_h_ps_buf) | 1135 | CALL_TXH(ieee80211_tx_h_ps_buf) |
1112 | CALL_TXH(ieee80211_tx_h_select_key) | 1136 | CALL_TXH(ieee80211_tx_h_select_key) |
1113 | CALL_TXH(ieee80211_tx_h_michael_mic_add) | 1137 | CALL_TXH(ieee80211_tx_h_michael_mic_add) |
1114 | CALL_TXH(ieee80211_tx_h_rate_ctrl) | 1138 | CALL_TXH(ieee80211_tx_h_rate_ctrl) |
1115 | CALL_TXH(ieee80211_tx_h_misc) | 1139 | CALL_TXH(ieee80211_tx_h_misc) |
1140 | CALL_TXH(ieee80211_tx_h_sequence) | ||
1116 | CALL_TXH(ieee80211_tx_h_fragment) | 1141 | CALL_TXH(ieee80211_tx_h_fragment) |
1117 | /* handlers after fragment must be aware of tx info fragmentation! */ | 1142 | /* handlers after fragment must be aware of tx info fragmentation! */ |
1118 | CALL_TXH(ieee80211_tx_h_encrypt) | 1143 | CALL_TXH(ieee80211_tx_h_encrypt) |
@@ -1785,17 +1810,17 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1785 | struct ieee80211_vif *vif) | 1810 | struct ieee80211_vif *vif) |
1786 | { | 1811 | { |
1787 | struct ieee80211_local *local = hw_to_local(hw); | 1812 | struct ieee80211_local *local = hw_to_local(hw); |
1788 | struct sk_buff *skb; | 1813 | struct sk_buff *skb = NULL; |
1789 | struct ieee80211_tx_info *info; | 1814 | struct ieee80211_tx_info *info; |
1790 | struct net_device *bdev; | 1815 | struct net_device *bdev; |
1791 | struct ieee80211_sub_if_data *sdata = NULL; | 1816 | struct ieee80211_sub_if_data *sdata = NULL; |
1792 | struct ieee80211_if_ap *ap = NULL; | 1817 | struct ieee80211_if_ap *ap = NULL; |
1818 | struct ieee80211_if_sta *ifsta = NULL; | ||
1793 | struct rate_selection rsel; | 1819 | struct rate_selection rsel; |
1794 | struct beacon_data *beacon; | 1820 | struct beacon_data *beacon; |
1795 | struct ieee80211_supported_band *sband; | 1821 | struct ieee80211_supported_band *sband; |
1796 | struct ieee80211_mgmt *mgmt; | 1822 | struct ieee80211_mgmt *mgmt; |
1797 | int *num_beacons; | 1823 | int *num_beacons; |
1798 | bool err = true; | ||
1799 | enum ieee80211_band band = local->hw.conf.channel->band; | 1824 | enum ieee80211_band band = local->hw.conf.channel->band; |
1800 | u8 *pos; | 1825 | u8 *pos; |
1801 | 1826 | ||
@@ -1824,9 +1849,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1824 | memcpy(skb_put(skb, beacon->head_len), beacon->head, | 1849 | memcpy(skb_put(skb, beacon->head_len), beacon->head, |
1825 | beacon->head_len); | 1850 | beacon->head_len); |
1826 | 1851 | ||
1827 | ieee80211_include_sequence(sdata, | ||
1828 | (struct ieee80211_hdr *)skb->data); | ||
1829 | |||
1830 | /* | 1852 | /* |
1831 | * Not very nice, but we want to allow the driver to call | 1853 | * Not very nice, but we want to allow the driver to call |
1832 | * ieee80211_beacon_get() as a response to the set_tim() | 1854 | * ieee80211_beacon_get() as a response to the set_tim() |
@@ -1849,9 +1871,24 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1849 | beacon->tail, beacon->tail_len); | 1871 | beacon->tail, beacon->tail_len); |
1850 | 1872 | ||
1851 | num_beacons = &ap->num_beacons; | 1873 | num_beacons = &ap->num_beacons; |
1874 | } else | ||
1875 | goto out; | ||
1876 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | ||
1877 | struct ieee80211_hdr *hdr; | ||
1878 | ifsta = &sdata->u.sta; | ||
1852 | 1879 | ||
1853 | err = false; | 1880 | if (!ifsta->probe_resp) |
1854 | } | 1881 | goto out; |
1882 | |||
1883 | skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC); | ||
1884 | if (!skb) | ||
1885 | goto out; | ||
1886 | |||
1887 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1888 | hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1889 | IEEE80211_STYPE_BEACON); | ||
1890 | |||
1891 | num_beacons = &ifsta->num_beacons; | ||
1855 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1892 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1856 | /* headroom, head length, tail length and maximum TIM length */ | 1893 | /* headroom, head length, tail length and maximum TIM length */ |
1857 | skb = dev_alloc_skb(local->tx_headroom + 400); | 1894 | skb = dev_alloc_skb(local->tx_headroom + 400); |
@@ -1878,17 +1915,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1878 | mesh_mgmt_ies_add(skb, sdata->dev); | 1915 | mesh_mgmt_ies_add(skb, sdata->dev); |
1879 | 1916 | ||
1880 | num_beacons = &sdata->u.sta.num_beacons; | 1917 | num_beacons = &sdata->u.sta.num_beacons; |
1881 | 1918 | } else { | |
1882 | err = false; | 1919 | WARN_ON(1); |
1883 | } | ||
1884 | |||
1885 | if (err) { | ||
1886 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1887 | if (net_ratelimit()) | ||
1888 | printk(KERN_DEBUG "no beacon data avail for %s\n", | ||
1889 | bdev->name); | ||
1890 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
1891 | skb = NULL; | ||
1892 | goto out; | 1920 | goto out; |
1893 | } | 1921 | } |
1894 | 1922 | ||
@@ -1910,14 +1938,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1910 | 1938 | ||
1911 | info->control.vif = vif; | 1939 | info->control.vif = vif; |
1912 | info->tx_rate_idx = rsel.rate_idx; | 1940 | info->tx_rate_idx = rsel.rate_idx; |
1941 | |||
1942 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1943 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
1944 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1945 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | ||
1913 | if (sdata->bss_conf.use_short_preamble && | 1946 | if (sdata->bss_conf.use_short_preamble && |
1914 | sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) | 1947 | sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) |
1915 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | 1948 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; |
1949 | |||
1916 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 1950 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
1917 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
1918 | info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
1919 | info->control.retry_limit = 1; | 1951 | info->control.retry_limit = 1; |
1920 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 1952 | |
1921 | (*num_beacons)++; | 1953 | (*num_beacons)++; |
1922 | out: | 1954 | out: |
1923 | rcu_read_unlock(); | 1955 | rcu_read_unlock(); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ce62b163b82c..89ce4e07bd84 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -428,8 +428,6 @@ void ieee80211_iterate_active_interfaces( | |||
428 | case IEEE80211_IF_TYPE_MESH_POINT: | 428 | case IEEE80211_IF_TYPE_MESH_POINT: |
429 | break; | 429 | break; |
430 | } | 430 | } |
431 | if (sdata->dev == local->mdev) | ||
432 | continue; | ||
433 | if (netif_running(sdata->dev)) | 431 | if (netif_running(sdata->dev)) |
434 | iterator(data, sdata->dev->dev_addr, | 432 | iterator(data, sdata->dev->dev_addr, |
435 | &sdata->vif); | 433 | &sdata->vif); |
@@ -463,8 +461,6 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
463 | case IEEE80211_IF_TYPE_MESH_POINT: | 461 | case IEEE80211_IF_TYPE_MESH_POINT: |
464 | break; | 462 | break; |
465 | } | 463 | } |
466 | if (sdata->dev == local->mdev) | ||
467 | continue; | ||
468 | if (netif_running(sdata->dev)) | 464 | if (netif_running(sdata->dev)) |
469 | iterator(data, sdata->dev->dev_addr, | 465 | iterator(data, sdata->dev->dev_addr, |
470 | &sdata->vif); | 466 | &sdata->vif); |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 736c32e340f2..34fa8ed1e784 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -296,15 +296,7 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, | |||
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | } | 297 | } |
298 | 298 | ||
299 | if (type == sdata->vif.type) | 299 | return ieee80211_if_change_type(sdata, type); |
300 | return 0; | ||
301 | if (netif_running(dev)) | ||
302 | return -EBUSY; | ||
303 | |||
304 | ieee80211_if_reinit(dev); | ||
305 | ieee80211_if_set_type(dev, type); | ||
306 | |||
307 | return 0; | ||
308 | } | 300 | } |
309 | 301 | ||
310 | 302 | ||
@@ -452,7 +444,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
452 | memset(sdata->u.ap.ssid + len, 0, | 444 | memset(sdata->u.ap.ssid + len, 0, |
453 | IEEE80211_MAX_SSID_LEN - len); | 445 | IEEE80211_MAX_SSID_LEN - len); |
454 | sdata->u.ap.ssid_len = len; | 446 | sdata->u.ap.ssid_len = len; |
455 | return ieee80211_if_config(dev); | 447 | return ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); |
456 | } | 448 | } |
457 | return -EOPNOTSUPP; | 449 | return -EOPNOTSUPP; |
458 | } | 450 | } |
@@ -627,16 +619,14 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, | |||
627 | struct ieee80211_supported_band *sband; | 619 | struct ieee80211_supported_band *sband; |
628 | 620 | ||
629 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 621 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
630 | if (!sdata->bss) | ||
631 | return -ENODEV; | ||
632 | 622 | ||
633 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 623 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
634 | 624 | ||
635 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates | 625 | /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates |
636 | * target_rate = X, rate->fixed = 1 means only rate X | 626 | * target_rate = X, rate->fixed = 1 means only rate X |
637 | * target_rate = X, rate->fixed = 0 means all rates <= X */ | 627 | * target_rate = X, rate->fixed = 0 means all rates <= X */ |
638 | sdata->bss->max_ratectrl_rateidx = -1; | 628 | sdata->max_ratectrl_rateidx = -1; |
639 | sdata->bss->force_unicast_rateidx = -1; | 629 | sdata->force_unicast_rateidx = -1; |
640 | if (rate->value < 0) | 630 | if (rate->value < 0) |
641 | return 0; | 631 | return 0; |
642 | 632 | ||
@@ -645,9 +635,9 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev, | |||
645 | int this_rate = brate->bitrate; | 635 | int this_rate = brate->bitrate; |
646 | 636 | ||
647 | if (target_rate == this_rate) { | 637 | if (target_rate == this_rate) { |
648 | sdata->bss->max_ratectrl_rateidx = i; | 638 | sdata->max_ratectrl_rateidx = i; |
649 | if (rate->fixed) | 639 | if (rate->fixed) |
650 | sdata->bss->force_unicast_rateidx = i; | 640 | sdata->force_unicast_rateidx = i; |
651 | err = 0; | 641 | err = 0; |
652 | break; | 642 | break; |
653 | } | 643 | } |
@@ -1009,6 +999,45 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, | |||
1009 | return 0; | 999 | return 0; |
1010 | } | 1000 | } |
1011 | 1001 | ||
1002 | static int ieee80211_ioctl_siwpower(struct net_device *dev, | ||
1003 | struct iw_request_info *info, | ||
1004 | struct iw_param *wrq, | ||
1005 | char *extra) | ||
1006 | { | ||
1007 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1008 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1009 | |||
1010 | if (wrq->disabled) { | ||
1011 | conf->flags &= ~IEEE80211_CONF_PS; | ||
1012 | return ieee80211_hw_config(local); | ||
1013 | } | ||
1014 | |||
1015 | switch (wrq->flags & IW_POWER_MODE) { | ||
1016 | case IW_POWER_ON: /* If not specified */ | ||
1017 | case IW_POWER_MODE: /* If set all mask */ | ||
1018 | case IW_POWER_ALL_R: /* If explicitely state all */ | ||
1019 | conf->flags |= IEEE80211_CONF_PS; | ||
1020 | break; | ||
1021 | default: /* Otherwise we don't support it */ | ||
1022 | return -EINVAL; | ||
1023 | } | ||
1024 | |||
1025 | return ieee80211_hw_config(local); | ||
1026 | } | ||
1027 | |||
1028 | static int ieee80211_ioctl_giwpower(struct net_device *dev, | ||
1029 | struct iw_request_info *info, | ||
1030 | union iwreq_data *wrqu, | ||
1031 | char *extra) | ||
1032 | { | ||
1033 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1034 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1035 | |||
1036 | wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS); | ||
1037 | |||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
1012 | static int ieee80211_ioctl_siwauth(struct net_device *dev, | 1041 | static int ieee80211_ioctl_siwauth(struct net_device *dev, |
1013 | struct iw_request_info *info, | 1042 | struct iw_request_info *info, |
1014 | struct iw_param *data, char *extra) | 1043 | struct iw_param *data, char *extra) |
@@ -1211,8 +1240,8 @@ static const iw_handler ieee80211_handler[] = | |||
1211 | (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ | 1240 | (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */ |
1212 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ | 1241 | (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */ |
1213 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ | 1242 | (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */ |
1214 | (iw_handler) NULL, /* SIOCSIWPOWER */ | 1243 | (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ |
1215 | (iw_handler) NULL, /* SIOCGIWPOWER */ | 1244 | (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ |
1216 | (iw_handler) NULL, /* -- hole -- */ | 1245 | (iw_handler) NULL, /* -- hole -- */ |
1217 | (iw_handler) NULL, /* -- hole -- */ | 1246 | (iw_handler) NULL, /* -- hole -- */ |
1218 | (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */ | 1247 | (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */ |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 79270903bda6..ab015c62d561 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -29,3 +29,14 @@ config WIRELESS_EXT | |||
29 | 29 | ||
30 | Say N (if you can) unless you know you need wireless | 30 | Say N (if you can) unless you know you need wireless |
31 | extensions for external modules. | 31 | extensions for external modules. |
32 | |||
33 | config WIRELESS_EXT_SYSFS | ||
34 | bool "Wireless extensions sysfs files" | ||
35 | default y | ||
36 | depends on WIRELESS_EXT && SYSFS | ||
37 | help | ||
38 | This option enables the deprecated wireless statistics | ||
39 | files in /sys/class/net/*/wireless/. The same information | ||
40 | is available via the ioctls as well. | ||
41 | |||
42 | Say Y if you have programs using it (we don't know of any). | ||