aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c106
1 files changed, 73 insertions, 33 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0d2d94881f1f..22a384dfab65 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
36bool ieee80211_disable_40mhz_24ghz;
37module_param(ieee80211_disable_40mhz_24ghz, bool, 0644);
38MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz,
39 "Disable 40MHz support in the 2.4GHz band");
36 40
37void ieee80211_configure_filter(struct ieee80211_local *local) 41void ieee80211_configure_filter(struct ieee80211_local *local)
38{ 42{
@@ -67,7 +71,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
67 spin_lock_bh(&local->filter_lock); 71 spin_lock_bh(&local->filter_lock);
68 changed_flags = local->filter_flags ^ new_flags; 72 changed_flags = local->filter_flags ^ new_flags;
69 73
70 mc = drv_prepare_multicast(local, local->mc_count, local->mc_list); 74 mc = drv_prepare_multicast(local, &local->mc_list);
71 spin_unlock_bh(&local->filter_lock); 75 spin_unlock_bh(&local->filter_lock);
72 76
73 /* be a bit nasty */ 77 /* be a bit nasty */
@@ -102,9 +106,12 @@ 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;
108 } 115 }
109 116
110 if (chan != local->hw.conf.channel || 117 if (chan != local->hw.conf.channel ||
@@ -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 {
@@ -206,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
206 switch (sdata->vif.type) { 225 switch (sdata->vif.type) {
207 case NL80211_IFTYPE_AP: 226 case NL80211_IFTYPE_AP:
208 sdata->vif.bss_conf.enable_beacon = 227 sdata->vif.bss_conf.enable_beacon =
209 !!rcu_dereference(sdata->u.ap.beacon); 228 !!sdata->u.ap.beacon;
210 break; 229 break;
211 case NL80211_IFTYPE_ADHOC: 230 case NL80211_IFTYPE_ADHOC:
212 sdata->vif.bss_conf.enable_beacon = 231 sdata->vif.bss_conf.enable_beacon =
213 !!rcu_dereference(sdata->u.ibss.presp); 232 !!sdata->u.ibss.presp;
214 break; 233 break;
215 case NL80211_IFTYPE_MESH_POINT: 234 case NL80211_IFTYPE_MESH_POINT:
216 sdata->vif.bss_conf.enable_beacon = true; 235 sdata->vif.bss_conf.enable_beacon = true;
@@ -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
230u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) 248u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
@@ -291,6 +309,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
291{ 309{
292 struct ieee80211_local *local = hw_to_local(hw); 310 struct ieee80211_local *local = hw_to_local(hw);
293 311
312 trace_api_restart_hw(local);
313
294 /* use this reason, __ieee80211_resume will unblock it */ 314 /* use this reason, __ieee80211_resume will unblock it */
295 ieee80211_stop_queues_by_reason(hw, 315 ieee80211_stop_queues_by_reason(hw,
296 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 316 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
@@ -299,6 +319,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
299} 319}
300EXPORT_SYMBOL(ieee80211_restart_hw); 320EXPORT_SYMBOL(ieee80211_restart_hw);
301 321
322static void ieee80211_recalc_smps_work(struct work_struct *work)
323{
324 struct ieee80211_local *local =
325 container_of(work, struct ieee80211_local, recalc_smps);
326
327 mutex_lock(&local->iflist_mtx);
328 ieee80211_recalc_smps(local, NULL);
329 mutex_unlock(&local->iflist_mtx);
330}
331
302struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 332struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
303 const struct ieee80211_ops *ops) 333 const struct ieee80211_ops *ops)
304{ 334{
@@ -333,9 +363,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
333 WIPHY_FLAG_4ADDR_STATION; 363 WIPHY_FLAG_4ADDR_STATION;
334 wiphy->privid = mac80211_wiphy_privid; 364 wiphy->privid = mac80211_wiphy_privid;
335 365
336 /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ 366 wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
337 wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
338 sizeof(struct cfg80211_bss);
339 367
340 local = wiphy_priv(wiphy); 368 local = wiphy_priv(wiphy);
341 369
@@ -358,8 +386,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
358 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; 386 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
359 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; 387 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
360 local->user_power_level = -1; 388 local->user_power_level = -1;
389 local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
390 local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
361 391
362 INIT_LIST_HEAD(&local->interfaces); 392 INIT_LIST_HEAD(&local->interfaces);
393
394 __hw_addr_init(&local->mc_list);
395
363 mutex_init(&local->iflist_mtx); 396 mutex_init(&local->iflist_mtx);
364 mutex_init(&local->scan_mtx); 397 mutex_init(&local->scan_mtx);
365 398
@@ -369,9 +402,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
369 402
370 INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); 403 INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
371 404
405 ieee80211_work_init(local);
406
372 INIT_WORK(&local->restart_work, ieee80211_restart_work); 407 INIT_WORK(&local->restart_work, ieee80211_restart_work);
373 408
374 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); 409 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
410 INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
411 local->smps_mode = IEEE80211_SMPS_OFF;
375 412
376 INIT_WORK(&local->dynamic_ps_enable_work, 413 INIT_WORK(&local->dynamic_ps_enable_work,
377 ieee80211_dynamic_ps_enable_work); 414 ieee80211_dynamic_ps_enable_work);
@@ -405,7 +442,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
405 struct ieee80211_local *local = hw_to_local(hw); 442 struct ieee80211_local *local = hw_to_local(hw);
406 int result; 443 int result;
407 enum ieee80211_band band; 444 enum ieee80211_band band;
408 int channels, i, j, max_bitrates; 445 int channels, max_bitrates;
409 bool supp_ht; 446 bool supp_ht;
410 static const u32 cipher_suites[] = { 447 static const u32 cipher_suites[] = {
411 WLAN_CIPHER_SUITE_WEP40, 448 WLAN_CIPHER_SUITE_WEP40,
@@ -461,6 +498,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
461 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 498 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
462 local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; 499 local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
463 500
501 WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
502 && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
503 "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");
504
464 /* 505 /*
465 * Calculate scan IE length -- we need this to alloc 506 * Calculate scan IE length -- we need this to alloc
466 * memory and to subtract from the driver limit. It 507 * memory and to subtract from the driver limit. It
@@ -522,11 +563,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
522 563
523 debugfs_hw_add(local); 564 debugfs_hw_add(local);
524 565
566 /*
567 * if the driver doesn't specify a max listen interval we
568 * use 5 which should be a safe default
569 */
525 if (local->hw.max_listen_interval == 0) 570 if (local->hw.max_listen_interval == 0)
526 local->hw.max_listen_interval = 1; 571 local->hw.max_listen_interval = 5;
527 572
528 local->hw.conf.listen_interval = local->hw.max_listen_interval; 573 local->hw.conf.listen_interval = local->hw.max_listen_interval;
529 574
575 local->hw.conf.dynamic_ps_forced_timeout = -1;
576
530 result = sta_info_start(local); 577 result = sta_info_start(local);
531 if (result < 0) 578 if (result < 0)
532 goto fail_sta_info; 579 goto fail_sta_info;
@@ -561,21 +608,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
561 608
562 ieee80211_led_init(local); 609 ieee80211_led_init(local);
563 610
564 /* alloc internal scan request */
565 i = 0;
566 local->int_scan_req->ssids = &local->scan_ssid;
567 local->int_scan_req->n_ssids = 1;
568 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
569 if (!hw->wiphy->bands[band])
570 continue;
571 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
572 local->int_scan_req->channels[i] =
573 &hw->wiphy->bands[band]->channels[j];
574 i++;
575 }
576 }
577 local->int_scan_req->n_channels = i;
578
579 local->network_latency_notifier.notifier_call = 611 local->network_latency_notifier.notifier_call =
580 ieee80211_max_network_latency; 612 ieee80211_max_network_latency;
581 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, 613 result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
@@ -674,11 +706,19 @@ static int __init ieee80211_init(void)
674 706
675 ret = rc80211_pid_init(); 707 ret = rc80211_pid_init();
676 if (ret) 708 if (ret)
677 return ret; 709 goto err_pid;
678 710
679 ieee80211_debugfs_netdev_init(); 711 ret = ieee80211_iface_init();
712 if (ret)
713 goto err_netdev;
680 714
681 return 0; 715 return 0;
716 err_netdev:
717 rc80211_pid_exit();
718 err_pid:
719 rc80211_minstrel_exit();
720
721 return ret;
682} 722}
683 723
684static void __exit ieee80211_exit(void) 724static void __exit ieee80211_exit(void)
@@ -695,7 +735,7 @@ static void __exit ieee80211_exit(void)
695 if (mesh_allocated) 735 if (mesh_allocated)
696 ieee80211s_stop(); 736 ieee80211s_stop();
697 737
698 ieee80211_debugfs_netdev_exit(); 738 ieee80211_iface_exit();
699} 739}
700 740
701 741