diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 74 |
1 files changed, 61 insertions, 13 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 0d2d94881f1f..06c33b68d8e5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
19 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
20 | #include <linux/wireless.h> | ||
21 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
22 | #include <linux/bitmap.h> | 21 | #include <linux/bitmap.h> |
23 | #include <linux/pm_qos_params.h> | 22 | #include <linux/pm_qos_params.h> |
@@ -32,7 +31,12 @@ | |||
32 | #include "led.h" | 31 | #include "led.h" |
33 | #include "cfg.h" | 32 | #include "cfg.h" |
34 | #include "debugfs.h" | 33 | #include "debugfs.h" |
35 | #include "debugfs_netdev.h" | 34 | |
35 | |||
36 | bool ieee80211_disable_40mhz_24ghz; | ||
37 | module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); | ||
38 | MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, | ||
39 | "Disable 40MHz support in the 2.4GHz band"); | ||
36 | 40 | ||
37 | void ieee80211_configure_filter(struct ieee80211_local *local) | 41 | void ieee80211_configure_filter(struct ieee80211_local *local) |
38 | { | 42 | { |
@@ -102,6 +106,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
102 | if (scan_chan) { | 106 | if (scan_chan) { |
103 | chan = scan_chan; | 107 | chan = scan_chan; |
104 | channel_type = NL80211_CHAN_NO_HT; | 108 | channel_type = NL80211_CHAN_NO_HT; |
109 | } else if (local->tmp_channel) { | ||
110 | chan = scan_chan = local->tmp_channel; | ||
111 | channel_type = local->tmp_channel_type; | ||
105 | } else { | 112 | } else { |
106 | chan = local->oper_channel; | 113 | chan = local->oper_channel; |
107 | channel_type = local->oper_channel_type; | 114 | channel_type = local->oper_channel_type; |
@@ -114,6 +121,18 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
114 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 121 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
115 | } | 122 | } |
116 | 123 | ||
124 | if (!conf_is_ht(&local->hw.conf)) { | ||
125 | /* | ||
126 | * mac80211.h documents that this is only valid | ||
127 | * when the channel is set to an HT type, and | ||
128 | * that otherwise STATIC is used. | ||
129 | */ | ||
130 | local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC; | ||
131 | } else if (local->hw.conf.smps_mode != local->smps_mode) { | ||
132 | local->hw.conf.smps_mode = local->smps_mode; | ||
133 | changed |= IEEE80211_CONF_CHANGE_SMPS; | ||
134 | } | ||
135 | |||
117 | if (scan_chan) | 136 | if (scan_chan) |
118 | power = chan->max_power; | 137 | power = chan->max_power; |
119 | else | 138 | else |
@@ -173,7 +192,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
173 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 192 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
174 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; | 193 | sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; |
175 | else if (sdata->vif.type == NL80211_IFTYPE_AP) | 194 | else if (sdata->vif.type == NL80211_IFTYPE_AP) |
176 | sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; | 195 | sdata->vif.bss_conf.bssid = sdata->vif.addr; |
177 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 196 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
178 | sdata->vif.bss_conf.bssid = zero; | 197 | sdata->vif.bss_conf.bssid = zero; |
179 | } else { | 198 | } else { |
@@ -195,7 +214,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
195 | } | 214 | } |
196 | 215 | ||
197 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 216 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
198 | if (local->quiescing || !netif_running(sdata->dev) || | 217 | if (local->quiescing || !ieee80211_sdata_running(sdata) || |
199 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { | 218 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { |
200 | sdata->vif.bss_conf.enable_beacon = false; | 219 | sdata->vif.bss_conf.enable_beacon = false; |
201 | } else { | 220 | } else { |
@@ -223,8 +242,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
223 | } | 242 | } |
224 | } | 243 | } |
225 | 244 | ||
226 | drv_bss_info_changed(local, &sdata->vif, | 245 | drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); |
227 | &sdata->vif.bss_conf, changed); | ||
228 | } | 246 | } |
229 | 247 | ||
230 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | 248 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) |
@@ -299,6 +317,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
299 | } | 317 | } |
300 | EXPORT_SYMBOL(ieee80211_restart_hw); | 318 | EXPORT_SYMBOL(ieee80211_restart_hw); |
301 | 319 | ||
320 | static void ieee80211_recalc_smps_work(struct work_struct *work) | ||
321 | { | ||
322 | struct ieee80211_local *local = | ||
323 | container_of(work, struct ieee80211_local, recalc_smps); | ||
324 | |||
325 | mutex_lock(&local->iflist_mtx); | ||
326 | ieee80211_recalc_smps(local, NULL); | ||
327 | mutex_unlock(&local->iflist_mtx); | ||
328 | } | ||
329 | |||
302 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 330 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
303 | const struct ieee80211_ops *ops) | 331 | const struct ieee80211_ops *ops) |
304 | { | 332 | { |
@@ -333,9 +361,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
333 | WIPHY_FLAG_4ADDR_STATION; | 361 | WIPHY_FLAG_4ADDR_STATION; |
334 | wiphy->privid = mac80211_wiphy_privid; | 362 | wiphy->privid = mac80211_wiphy_privid; |
335 | 363 | ||
336 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ | 364 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); |
337 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - | ||
338 | sizeof(struct cfg80211_bss); | ||
339 | 365 | ||
340 | local = wiphy_priv(wiphy); | 366 | local = wiphy_priv(wiphy); |
341 | 367 | ||
@@ -358,6 +384,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
358 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 384 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
359 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 385 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
360 | local->user_power_level = -1; | 386 | local->user_power_level = -1; |
387 | local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; | ||
388 | local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; | ||
361 | 389 | ||
362 | INIT_LIST_HEAD(&local->interfaces); | 390 | INIT_LIST_HEAD(&local->interfaces); |
363 | mutex_init(&local->iflist_mtx); | 391 | mutex_init(&local->iflist_mtx); |
@@ -369,9 +397,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
369 | 397 | ||
370 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 398 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
371 | 399 | ||
400 | ieee80211_work_init(local); | ||
401 | |||
372 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 402 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
373 | 403 | ||
374 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); | 404 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); |
405 | INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work); | ||
406 | local->smps_mode = IEEE80211_SMPS_OFF; | ||
375 | 407 | ||
376 | INIT_WORK(&local->dynamic_ps_enable_work, | 408 | INIT_WORK(&local->dynamic_ps_enable_work, |
377 | ieee80211_dynamic_ps_enable_work); | 409 | ieee80211_dynamic_ps_enable_work); |
@@ -461,6 +493,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
461 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 493 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
462 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; | 494 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; |
463 | 495 | ||
496 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | ||
497 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | ||
498 | "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"); | ||
499 | |||
464 | /* | 500 | /* |
465 | * Calculate scan IE length -- we need this to alloc | 501 | * Calculate scan IE length -- we need this to alloc |
466 | * memory and to subtract from the driver limit. It | 502 | * memory and to subtract from the driver limit. It |
@@ -522,8 +558,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
522 | 558 | ||
523 | debugfs_hw_add(local); | 559 | debugfs_hw_add(local); |
524 | 560 | ||
561 | /* | ||
562 | * if the driver doesn't specify a max listen interval we | ||
563 | * use 5 which should be a safe default | ||
564 | */ | ||
525 | if (local->hw.max_listen_interval == 0) | 565 | if (local->hw.max_listen_interval == 0) |
526 | local->hw.max_listen_interval = 1; | 566 | local->hw.max_listen_interval = 5; |
527 | 567 | ||
528 | local->hw.conf.listen_interval = local->hw.max_listen_interval; | 568 | local->hw.conf.listen_interval = local->hw.max_listen_interval; |
529 | 569 | ||
@@ -674,11 +714,19 @@ static int __init ieee80211_init(void) | |||
674 | 714 | ||
675 | ret = rc80211_pid_init(); | 715 | ret = rc80211_pid_init(); |
676 | if (ret) | 716 | if (ret) |
677 | return ret; | 717 | goto err_pid; |
678 | 718 | ||
679 | ieee80211_debugfs_netdev_init(); | 719 | ret = ieee80211_iface_init(); |
720 | if (ret) | ||
721 | goto err_netdev; | ||
680 | 722 | ||
681 | return 0; | 723 | return 0; |
724 | err_netdev: | ||
725 | rc80211_pid_exit(); | ||
726 | err_pid: | ||
727 | rc80211_minstrel_exit(); | ||
728 | |||
729 | return ret; | ||
682 | } | 730 | } |
683 | 731 | ||
684 | static void __exit ieee80211_exit(void) | 732 | static void __exit ieee80211_exit(void) |
@@ -695,7 +743,7 @@ static void __exit ieee80211_exit(void) | |||
695 | if (mesh_allocated) | 743 | if (mesh_allocated) |
696 | ieee80211s_stop(); | 744 | ieee80211s_stop(); |
697 | 745 | ||
698 | ieee80211_debugfs_netdev_exit(); | 746 | ieee80211_iface_exit(); |
699 | } | 747 | } |
700 | 748 | ||
701 | 749 | ||