summaryrefslogtreecommitdiff
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c74
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 @@
#include <linux/skbuff.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
-#include <linux/wireless.h>
#include <linux/rtnetlink.h>
#include <linux/bitmap.h>
#include <linux/pm_qos_params.h>
@@ -32,7 +31,12 @@
#include "led.h"
#include "cfg.h"
#include "debugfs.h"
-#include "debugfs_netdev.h"
+
+
+bool ieee80211_disable_40mhz_24ghz;
+module_param(ieee80211_disable_40mhz_24ghz, bool, 0644);
+MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz,
+ "Disable 40MHz support in the 2.4GHz band");
void ieee80211_configure_filter(struct ieee80211_local *local)
{
@@ -102,6 +106,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
if (scan_chan) {
chan = scan_chan;
channel_type = NL80211_CHAN_NO_HT;
+ } else if (local->tmp_channel) {
+ chan = scan_chan = local->tmp_channel;
+ channel_type = local->tmp_channel_type;
} else {
chan = local->oper_channel;
channel_type = local->oper_channel_type;
@@ -114,6 +121,18 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
changed |= IEEE80211_CONF_CHANGE_CHANNEL;
}
+ if (!conf_is_ht(&local->hw.conf)) {
+ /*
+ * mac80211.h documents that this is only valid
+ * when the channel is set to an HT type, and
+ * that otherwise STATIC is used.
+ */
+ local->hw.conf.smps_mode = IEEE80211_SMPS_STATIC;
+ } else if (local->hw.conf.smps_mode != local->smps_mode) {
+ local->hw.conf.smps_mode = local->smps_mode;
+ changed |= IEEE80211_CONF_CHANGE_SMPS;
+ }
+
if (scan_chan)
power = chan->max_power;
else
@@ -173,7 +192,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
else if (sdata->vif.type == NL80211_IFTYPE_AP)
- sdata->vif.bss_conf.bssid = sdata->dev->dev_addr;
+ sdata->vif.bss_conf.bssid = sdata->vif.addr;
else if (ieee80211_vif_is_mesh(&sdata->vif)) {
sdata->vif.bss_conf.bssid = zero;
} else {
@@ -195,7 +214,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
- if (local->quiescing || !netif_running(sdata->dev) ||
+ if (local->quiescing || !ieee80211_sdata_running(sdata) ||
test_bit(SCAN_SW_SCANNING, &local->scanning)) {
sdata->vif.bss_conf.enable_beacon = false;
} else {
@@ -223,8 +242,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
}
}
- drv_bss_info_changed(local, &sdata->vif,
- &sdata->vif.bss_conf, changed);
+ drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
}
u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
@@ -299,6 +317,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(ieee80211_restart_hw);
+static void ieee80211_recalc_smps_work(struct work_struct *work)
+{
+ struct ieee80211_local *local =
+ container_of(work, struct ieee80211_local, recalc_smps);
+
+ mutex_lock(&local->iflist_mtx);
+ ieee80211_recalc_smps(local, NULL);
+ mutex_unlock(&local->iflist_mtx);
+}
+
struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
const struct ieee80211_ops *ops)
{
@@ -333,9 +361,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
WIPHY_FLAG_4ADDR_STATION;
wiphy->privid = mac80211_wiphy_privid;
- /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
- wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
- sizeof(struct cfg80211_bss);
+ wiphy->bss_priv_size = sizeof(struct ieee80211_bss);
local = wiphy_priv(wiphy);
@@ -358,6 +384,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
local->user_power_level = -1;
+ local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
INIT_LIST_HEAD(&local->interfaces);
mutex_init(&local->iflist_mtx);
@@ -369,9 +397,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
+ ieee80211_work_init(local);
+
INIT_WORK(&local->restart_work, ieee80211_restart_work);
INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
+ INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
+ local->smps_mode = IEEE80211_SMPS_OFF;
INIT_WORK(&local->dynamic_ps_enable_work,
ieee80211_dynamic_ps_enable_work);
@@ -461,6 +493,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC;
+ WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)
+ && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK),
+ "U-APSD not supported with HW_PS_NULLFUNC_STACK\n");
+
/*
* Calculate scan IE length -- we need this to alloc
* memory and to subtract from the driver limit. It
@@ -522,8 +558,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
debugfs_hw_add(local);
+ /*
+ * if the driver doesn't specify a max listen interval we
+ * use 5 which should be a safe default
+ */
if (local->hw.max_listen_interval == 0)
- local->hw.max_listen_interval = 1;
+ local->hw.max_listen_interval = 5;
local->hw.conf.listen_interval = local->hw.max_listen_interval;
@@ -674,11 +714,19 @@ static int __init ieee80211_init(void)
ret = rc80211_pid_init();
if (ret)
- return ret;
+ goto err_pid;
- ieee80211_debugfs_netdev_init();
+ ret = ieee80211_iface_init();
+ if (ret)
+ goto err_netdev;
return 0;
+ err_netdev:
+ rc80211_pid_exit();
+ err_pid:
+ rc80211_minstrel_exit();
+
+ return ret;
}
static void __exit ieee80211_exit(void)
@@ -695,7 +743,7 @@ static void __exit ieee80211_exit(void)
if (mesh_allocated)
ieee80211s_stop();
- ieee80211_debugfs_netdev_exit();
+ ieee80211_iface_exit();
}