summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c50
-rw-r--r--net/mac80211/debugfs.c38
-rw-r--r--net/mac80211/ibss.c77
-rw-r--r--net/mac80211/ieee80211_i.h9
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/key.c21
-rw-r--r--net/mac80211/key.h3
-rw-r--r--net/mac80211/main.c14
-rw-r--r--net/mac80211/mlme.c41
-rw-r--r--net/mac80211/rx.c58
-rw-r--r--net/mac80211/scan.c32
-rw-r--r--net/mac80211/tx.c5
-rw-r--r--net/mac80211/util.c60
-rw-r--r--net/mac80211/wext.c282
-rw-r--r--net/mac80211/wme.c2
15 files changed, 313 insertions, 382 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d0ca6da33ca9..77e9ff5ec4f3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -112,7 +112,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
}
static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, u8 *mac_addr,
+ u8 key_idx, const u8 *mac_addr,
struct key_params *params)
{
struct ieee80211_sub_if_data *sdata;
@@ -141,7 +141,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL;
}
- key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
+ key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key,
+ params->seq_len, params->seq);
if (!key)
return -ENOMEM;
@@ -166,7 +167,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
}
static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, u8 *mac_addr)
+ u8 key_idx, const u8 *mac_addr)
{
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
@@ -208,7 +209,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
}
static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, u8 *mac_addr, void *cookie,
+ u8 key_idx, const u8 *mac_addr, void *cookie,
void (*callback)(void *cookie,
struct key_params *params))
{
@@ -629,34 +630,38 @@ static void sta_apply_parameters(struct ieee80211_local *local,
int i, j;
struct ieee80211_supported_band *sband;
struct ieee80211_sub_if_data *sdata = sta->sdata;
+ u32 mask, set;
sband = local->hw.wiphy->bands[local->oper_channel->band];
- /*
- * FIXME: updating the flags is racy when this function is
- * called from ieee80211_change_station(), this will
- * be resolved in a future patch.
- */
+ spin_lock_bh(&sta->lock);
+ mask = params->sta_flags_mask;
+ set = params->sta_flags_set;
- if (params->station_flags & STATION_FLAG_CHANGED) {
- spin_lock_bh(&sta->lock);
+ if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
sta->flags &= ~WLAN_STA_AUTHORIZED;
- if (params->station_flags & STATION_FLAG_AUTHORIZED)
+ if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
sta->flags |= WLAN_STA_AUTHORIZED;
+ }
+ if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
- if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE)
+ if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
sta->flags |= WLAN_STA_SHORT_PREAMBLE;
+ }
+ if (mask & BIT(NL80211_STA_FLAG_WME)) {
sta->flags &= ~WLAN_STA_WME;
- if (params->station_flags & STATION_FLAG_WME)
+ if (set & BIT(NL80211_STA_FLAG_WME))
sta->flags |= WLAN_STA_WME;
+ }
+ if (mask & BIT(NL80211_STA_FLAG_MFP)) {
sta->flags &= ~WLAN_STA_MFP;
- if (params->station_flags & STATION_FLAG_MFP)
+ if (set & BIT(NL80211_STA_FLAG_MFP))
sta->flags |= WLAN_STA_MFP;
- spin_unlock_bh(&sta->lock);
}
+ spin_unlock_bh(&sta->lock);
/*
* FIXME: updating the following information is racy when this
@@ -1253,6 +1258,19 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
if (ret)
return ret;
+ if (req->use_mfp) {
+ sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
+ sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
+ } else {
+ sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
+ }
+
+ if (req->control_port)
+ sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT;
+ else
+ sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
+
sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
ieee80211_sta_req_auth(sdata);
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index ac793201b701..e7682fe1c590 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -135,6 +135,42 @@ static const struct file_operations reset_ops = {
.open = mac80211_open_file_generic,
};
+static ssize_t noack_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ int res;
+ char buf[10];
+
+ res = scnprintf(buf, sizeof(buf), "%d\n", local->wifi_wme_noack_test);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, res);
+}
+
+static ssize_t noack_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ char buf[10];
+ size_t len;
+
+ len = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, len))
+ return -EFAULT;
+ buf[len] = '\0';
+
+ local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0);
+
+ return count;
+}
+
+static const struct file_operations noack_ops = {
+ .read = noack_read,
+ .write = noack_write,
+ .open = mac80211_open_file_generic
+};
+
/* statistics stuff */
#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \
@@ -275,6 +311,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_ADD(wep_iv);
DEBUGFS_ADD(tsf);
DEBUGFS_ADD_MODE(reset, 0200);
+ DEBUGFS_ADD(noack);
statsd = debugfs_create_dir("statistics", phyd);
local->debugfs.statistics = statsd;
@@ -330,6 +367,7 @@ void debugfs_hw_del(struct ieee80211_local *local)
DEBUGFS_DEL(wep_iv);
DEBUGFS_DEL(tsf);
DEBUGFS_DEL(reset);
+ DEBUGFS_DEL(noack);
DEBUGFS_STATS_DEL(transmitted_fragment_count);
DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index aa537681f87c..c236079ed38a 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -63,19 +63,18 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const u8 *bssid, const int beacon_int,
struct ieee80211_channel *chan,
- const size_t supp_rates_len,
- const u8 *supp_rates,
+ const u32 basic_rates,
const u16 capability, u64 tsf)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
- int rates, i, j;
+ int rates, i;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos;
struct ieee80211_supported_band *sband;
u32 bss_change;
-
+ u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local);
@@ -101,6 +100,16 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sband = local->hw.wiphy->bands[chan->band];
+ /* build supported rates array */
+ pos = supp_rates;
+ for (i = 0; i < sband->n_bitrates; i++) {
+ int rate = sband->bitrates[i].bitrate;
+ u8 basic = 0;
+ if (basic_rates & BIT(i))
+ basic = 0x80;
+ *pos++ = basic | (u8) (rate / 5);
+ }
+
/* Build IBSS probe response */
mgmt = (void *) skb_put(skb, 24 + sizeof(mgmt->u.beacon));
memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
@@ -118,7 +127,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
*pos++ = ifibss->ssid_len;
memcpy(pos, ifibss->ssid, ifibss->ssid_len);
- rates = supp_rates_len;
+ rates = sband->n_bitrates;
if (rates > 8)
rates = 8;
pos = skb_put(skb, 2 + rates);
@@ -140,8 +149,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
*pos++ = 0;
*pos++ = 0;
- if (supp_rates_len > 8) {
- rates = supp_rates_len - 8;
+ if (sband->n_bitrates > 8) {
+ rates = sband->n_bitrates - 8;
pos = skb_put(skb, 2 + rates);
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos++ = rates;
@@ -162,15 +171,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
bss_change |= BSS_CHANGED_BEACON_ENABLED;
ieee80211_bss_info_change_notify(sdata, bss_change);
- rates = 0;
- for (i = 0; i < supp_rates_len; i++) {
- int bitrate = (supp_rates[i] & 0x7f) * 5;
- for (j = 0; j < sband->n_bitrates; j++)
- if (sband->bitrates[j].bitrate == bitrate)
- rates |= BIT(j);
- }
-
- ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates);
+ ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates);
ifibss->state = IEEE80211_IBSS_MLME_JOINED;
mod_timer(&ifibss->timer,
@@ -184,15 +185,35 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct ieee80211_bss *bss)
{
+ struct ieee80211_supported_band *sband;
+ u32 basic_rates;
+ int i, j;
u16 beacon_int = bss->cbss.beacon_interval;
if (beacon_int < 10)
beacon_int = 10;
+ sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band];
+
+ basic_rates = 0;
+
+ for (i = 0; i < bss->supp_rates_len; i++) {
+ int rate = (bss->supp_rates[i] & 0x7f) * 5;
+ bool is_basic = !!(bss->supp_rates[i] & 0x80);
+
+ for (j = 0; j < sband->n_bitrates; j++) {
+ if (sband->bitrates[j].bitrate == rate) {
+ if (is_basic)
+ basic_rates |= BIT(j);
+ break;
+ }
+ }
+ }
+
__ieee80211_sta_join_ibss(sdata, bss->cbss.bssid,
beacon_int,
bss->cbss.channel,
- bss->supp_rates_len, bss->supp_rates,
+ basic_rates,
bss->cbss.capability,
bss->cbss.tsf);
}
@@ -449,9 +470,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
- u8 *pos;
u8 bssid[ETH_ALEN];
- u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
u16 capability;
int i;
@@ -480,15 +499,9 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
else
sdata->drop_unencrypted = 0;
- pos = supp_rates;
- for (i = 0; i < sband->n_bitrates; i++) {
- int rate = sband->bitrates[i].bitrate;
- *pos++ = (u8) (rate / 5);
- }
-
__ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
- ifibss->channel, sband->n_bitrates,
- supp_rates, capability, 0);
+ ifibss->channel, 3, /* first two are basic */
+ capability, 0);
}
static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
@@ -499,6 +512,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
struct ieee80211_channel *chan = NULL;
const u8 *bssid = NULL;
int active_ibss;
+ u16 capability;
active_ibss = ieee80211_sta_active_ibss(sdata);
#ifdef CONFIG_MAC80211_IBSS_DEBUG
@@ -509,6 +523,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
if (active_ibss)
return;
+ capability = WLAN_CAPABILITY_IBSS;
+ if (sdata->default_key)
+ capability |= WLAN_CAPABILITY_PRIVACY;
+
if (ifibss->fixed_bssid)
bssid = ifibss->bssid;
if (ifibss->fixed_channel)
@@ -517,8 +535,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
bssid = ifibss->bssid;
bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
ifibss->ssid, ifibss->ssid_len,
- WLAN_CAPABILITY_IBSS,
- WLAN_CAPABILITY_IBSS);
+ capability,
+ WLAN_CAPABILITY_IBSS |
+ WLAN_CAPABILITY_PRIVACY);
#ifdef CONFIG_MAC80211_IBSS_DEBUG
if (bss)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 03e0d22603c8..9d1514727f6e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -235,7 +235,7 @@ struct mesh_preq_queue {
#define IEEE80211_STA_ASSOCIATED BIT(4)
#define IEEE80211_STA_PROBEREQ_POLL BIT(5)
#define IEEE80211_STA_CREATE_IBSS BIT(6)
-/* hole at 7, please re-use */
+#define IEEE80211_STA_CONTROL_PORT BIT(7)
#define IEEE80211_STA_WMM_ENABLED BIT(8)
/* hole at 9, please re-use */
#define IEEE80211_STA_AUTO_SSID_SEL BIT(10)
@@ -427,6 +427,12 @@ struct ieee80211_sub_if_data {
int drop_unencrypted;
+ /*
+ * keep track of whether the HT opmode (stored in
+ * vif.bss_info.ht_operation_mode) is valid.
+ */
+ bool ht_opmode_valid;
+
/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
@@ -760,6 +766,7 @@ struct ieee80211_local {
struct dentry *wep_iv;
struct dentry *tsf;
struct dentry *reset;
+ struct dentry *noack;
struct dentry *statistics;
struct local_debugfsdentries_statsdentries {
struct dentry *transmitted_fragment_count;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8b6daf0219f4..8c9f1c722cdb 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -964,5 +964,6 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)
mutex_lock(&local->iflist_mtx);
chg = __ieee80211_recalc_idle(local);
mutex_unlock(&local->iflist_mtx);
- ieee80211_hw_config(local, chg);
+ if (chg)
+ ieee80211_hw_config(local, chg);
}
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index b7e1350273bb..827ea8e6ee0a 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -290,9 +290,11 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
int idx,
size_t key_len,
- const u8 *key_data)
+ const u8 *key_data,
+ size_t seq_len, const u8 *seq)
{
struct ieee80211_key *key;
+ int i, j;
BUG_ON(idx < 0 || idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS);
@@ -318,14 +320,31 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
case ALG_TKIP:
key->conf.iv_len = TKIP_IV_LEN;
key->conf.icv_len = TKIP_ICV_LEN;
+ if (seq && seq_len == 6) {
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+ key->u.tkip.rx[i].iv32 =
+ get_unaligned_le32(&seq[2]);
+ key->u.tkip.rx[i].iv16 =
+ get_unaligned_le16(seq);
+ }
+ }
break;
case ALG_CCMP:
key->conf.iv_len = CCMP_HDR_LEN;
key->conf.icv_len = CCMP_MIC_LEN;
+ if (seq && seq_len == CCMP_PN_LEN) {
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ for (j = 0; j < CCMP_PN_LEN; j++)
+ key->u.ccmp.rx_pn[i][j] =
+ seq[CCMP_PN_LEN - j - 1];
+ }
break;
case ALG_AES_CMAC:
key->conf.iv_len = 0;
key->conf.icv_len = sizeof(struct ieee80211_mmie);
+ if (seq && seq_len == 6)
+ for (j = 0; j < 6; j++)
+ key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
break;
}
memcpy(key->conf.key, key_data, key_len);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 215d3ef42a4f..9572e00f532c 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -144,7 +144,8 @@ struct ieee80211_key {
struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
int idx,
size_t key_len,
- const u8 *key_data);
+ const u8 *key_data,
+ size_t seq_len, const u8 *seq);
/*
* Insert a key into data structures (sdata, sta if necessary)
* to make it used, free old key.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b80bc80e46cf..76df5eabf268 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -154,15 +154,17 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev)
int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
{
- struct ieee80211_channel *chan;
+ struct ieee80211_channel *chan, *scan_chan;
int ret = 0;
int power;
enum nl80211_channel_type channel_type;
might_sleep();
- if (local->sw_scanning) {
- chan = local->scan_channel;
+ scan_chan = local->scan_channel;
+
+ if (scan_chan) {
+ chan = scan_chan;
channel_type = NL80211_CHAN_NO_HT;
} else {
chan = local->oper_channel;
@@ -176,7 +178,7 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
changed |= IEEE80211_CONF_CHANGE_CHANNEL;
}
- if (local->sw_scanning)
+ if (scan_chan)
power = chan->max_power;
else
power = local->power_constr_level ?
@@ -859,8 +861,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (!local->oper_channel) {
/* init channel we're on */
local->hw.conf.channel =
- local->oper_channel =
- local->scan_channel = &sband->channels[0];
+ local->oper_channel = &sband->channels[0];
+ local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
}
channels += sband->n_channels;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 75c487229f2e..ae030688771f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -33,6 +33,7 @@
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_MAX_TRIES 3
#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
+#define IEEE80211_PROBE_WAIT (HZ / 20)
#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
@@ -95,16 +96,14 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_bss_ht_conf ht;
struct sta_info *sta;
u32 changed = 0;
+ u16 ht_opmode;
bool enable_ht = true, ht_changed;
enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- memset(&ht, 0, sizeof(ht));
-
/* HT is not supported */
if (!sband->ht_cap.ht_supported)
enable_ht = false;
@@ -148,19 +147,20 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
IEEE80211_RC_HT_CHANGED);
rcu_read_unlock();
-
}
/* disable HT */
if (!enable_ht)
return 0;
- ht.operation_mode = le16_to_cpu(hti->operation_mode);
+ ht_opmode = le16_to_cpu(hti->operation_mode);
/* if bss configuration changed store the new one */
- if (memcmp(&sdata->vif.bss_conf.ht, &ht, sizeof(ht))) {
+ if (!sdata->ht_opmode_valid ||
+ sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
changed |= BSS_CHANGED_HT;
- sdata->vif.bss_conf.ht = ht;
+ sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
+ sdata->ht_opmode_valid = true;
}
return changed;
@@ -1043,11 +1043,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
+ ieee80211_set_wmm_default(sdata);
+
ieee80211_recalc_idle(local);
/* channel(_type) changes are handled by ieee80211_hw_config */
local->oper_channel_type = NL80211_CHAN_NO_HT;
+ /* on the next assoc, re-program HT parameters */
+ sdata->ht_opmode_valid = false;
+
local->power_constr_level = 0;
del_timer_sync(&local->dynamic_ps_timer);
@@ -1178,6 +1183,17 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
u.mgd.beacon_loss_work);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ /*
+ * The driver has already reported this event and we have
+ * already sent a probe request. Maybe the AP died and the
+ * driver keeps reporting until we disassociate... We have
+ * to ignore that because otherwise we would continually
+ * reset the timer and never check whether we received a
+ * probe response!
+ */
+ if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
+ return;
+
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
@@ -1190,7 +1206,7 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
ifmgd->ssid_len, NULL, 0);
- mod_timer(&ifmgd->timer, jiffies + IEEE80211_MONITORING_INTERVAL);
+ mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
}
void ieee80211_beacon_loss(struct ieee80211_vif *vif)
@@ -1227,7 +1243,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
}
if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) &&
- time_after(jiffies, sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
+ time_after(jiffies, sta->last_rx + IEEE80211_PROBE_WAIT)) {
printk(KERN_DEBUG "%s: no probe response from AP %pM "
"- disassociating\n",
sdata->dev->name, ifmgd->bssid);
@@ -1577,8 +1593,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
* to between the sta_info_alloc() and sta_info_insert() above.
*/
- set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
- WLAN_STA_AUTHORIZED);
+ set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP);
+ if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
+ set_sta_flags(sta, WLAN_STA_AUTHORIZED);
rates = 0;
basic_rates = 0;
@@ -1658,6 +1675,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
if (elems.wmm_param)
ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
elems.wmm_param_len);
+ else
+ ieee80211_set_wmm_default(sdata);
if (elems.ht_info_elem && elems.wmm_param &&
(ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index d052f4004829..f962bd1b16e2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -630,15 +630,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
* possible.
*/
- if (!ieee80211_has_protected(hdr->frame_control)) {
- if (!ieee80211_is_mgmt(hdr->frame_control) ||
- rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP))
- return RX_CONTINUE;
- mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
- if (mmie_keyidx < 0)
- return RX_CONTINUE;
- }
-
/*
* No point in finding a key and decrypting if the frame is neither
* addressed to us nor a multicast frame.
@@ -649,8 +640,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
if (rx->sta)
stakey = rcu_dereference(rx->sta->key);
+ if (!ieee80211_has_protected(hdr->frame_control))
+ mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
+
if (!is_multicast_ether_addr(hdr->addr1) && stakey) {
rx->key = stakey;
+ /* Skip decryption if the frame is not protected. */
+ if (!ieee80211_has_protected(hdr->frame_control))
+ return RX_CONTINUE;
} else if (mmie_keyidx >= 0) {
/* Broadcast/multicast robust management frame / BIP */
if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
@@ -661,6 +658,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
return RX_DROP_MONITOR; /* unexpected BIP keyidx */
rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
+ } else if (!ieee80211_has_protected(hdr->frame_control)) {
+ /*
+ * The frame was not protected, so skip decryption. However, we
+ * need to set rx->key if there is a key that could have been
+ * used so that the frame may be dropped if encryption would
+ * have been expected.
+ */
+ struct ieee80211_key *key = NULL;
+ if (ieee80211_is_mgmt(hdr->frame_control) &&
+ is_multicast_ether_addr(hdr->addr1) &&
+ (key = rcu_dereference(rx->sdata->default_mgmt_key)))
+ rx->key = key;
+ else if ((key = rcu_dereference(rx->sdata->default_key)))
+ rx->key = key;
+ return RX_CONTINUE;
} else {
/*
* The device doesn't give us the IV so we won't be
@@ -1209,17 +1221,27 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
/* Drop unencrypted frames if key is set. */
if (unlikely(!ieee80211_has_protected(fc) &&
!ieee80211_is_nullfunc(fc) &&
- (!ieee80211_is_mgmt(fc) ||
- (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
- rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) &&
- (rx->key || rx->sdata->drop_unencrypted)))
- return -EACCES;
- /* BIP does not use Protected field, so need to check MMIE */
- if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) &&
- ieee80211_is_multicast_robust_mgmt_frame(rx->skb) &&
- ieee80211_get_mmie_keyidx(rx->skb) < 0 &&
+ ieee80211_is_data(fc) &&
(rx->key || rx->sdata->drop_unencrypted)))
return -EACCES;
+ if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
+ if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
+ rx->key))
+ return -EACCES;
+ /* BIP does not use Protected field, so need to check MMIE */
+ if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb)
+ && ieee80211_get_mmie_keyidx(rx->skb) < 0 &&
+ rx->key))
+ return -EACCES;
+ /*
+ * When using MFP, Action frames are not allowed prior to
+ * having configured keys.
+ */
+ if (unlikely(ieee80211_is_action(fc) && !rx->key &&
+ ieee80211_is_robust_mgmt_frame(
+ (struct ieee80211_hdr *) rx->skb->data)))
+ return -EACCES;
+ }
return 0;
}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index c99ef8d04d3d..e65d74ba404b 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -298,6 +298,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
was_hw_scan = local->hw_scanning;
local->hw_scanning = false;
local->sw_scanning = false;
+ local->scan_channel = NULL;
/* we only have to protect scan_req and hw/sw scan */
mutex_unlock(&local->scan_mtx);
@@ -558,24 +559,39 @@ void ieee80211_scan_work(struct work_struct *work)
if (skip)
break;
- next_delay = IEEE80211_PROBE_DELAY +
- usecs_to_jiffies(local->hw.channel_change_time);
+ /*
+ * Probe delay is used to update the NAV, cf. 11.1.3.2.2
+ * (which unfortunately doesn't say _why_ step a) is done,
+ * but it waits for the probe delay or until a frame is
+ * received - and the received frame would update the NAV).
+ * For now, we do not support waiting until a frame is
+ * received.
+ *
+ * In any case, it is not necessary for a passive scan.
+ */
+ if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+ !local->scan_req->n_ssids) {
+ next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ break;
+ }
+
+ next_delay = IEEE80211_PROBE_DELAY;
local->scan_state = SCAN_SEND_PROBE;
break;
case SCAN_SEND_PROBE:
- next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
- local->scan_state = SCAN_SET_CHANNEL;
-
- if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
- !local->scan_req->n_ssids)
- break;
for (i = 0; i < local->scan_req->n_ssids; i++)
ieee80211_send_probe_req(
sdata, NULL,
local->scan_req->ssids[i].ssid,
local->scan_req->ssids[i].ssid_len,
local->scan_req->ie, local->scan_req->ie_len);
+
+ /*
+ * After sending probe requests, wait for probe responses
+ * on the channel.
+ */
next_delay = IEEE80211_CHANNEL_TIME;
+ local->scan_state = SCAN_SET_CHANNEL;
break;
}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5f9a8d7af83d..8f68bf9746d0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1087,7 +1087,10 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
info->flags |= IEEE80211_TX_CTL_NO_ACK;
} else {
tx->flags |= IEEE80211_TX_UNICAST;
- info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
+ if (unlikely(local->wifi_wme_noack_test))
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
+ else
+ info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
}
if (tx->flags & IEEE80211_TX_FRAGMENTED) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 97b613affe08..0689a8fbd1e6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -708,26 +708,62 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_queue_params qparam;
- int i;
+ int queue;
+ bool use_11b;
+ int aCWmin, aCWmax;
if (!local->ops->conf_tx)
return;
memset(&qparam, 0, sizeof(qparam));
- qparam.aifs = 2;
-
- if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
- !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE))
- qparam.cw_min = 31;
- else
- qparam.cw_min = 15;
+ use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) &&
+ !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
- qparam.cw_max = 1023;
- qparam.txop = 0;
+ for (queue = 0; queue < local_to_hw(local)->queues; queue++) {
+ /* Set defaults according to 802.11-2007 Table 7-37 */
+ aCWmax = 1023;
+ if (use_11b)
+ aCWmin = 31;
+ else
+ aCWmin = 15;
+
+ switch (queue) {
+ case 3: /* AC_BK */
+ qparam.cw_max = aCWmin;
+ qparam.cw_min = aCWmax;
+ qparam.txop = 0;
+ qparam.aifs = 7;
+ break;
+ default: /* never happens but let's not leave undefined */
+ case 2: /* AC_BE */
+ qparam.cw_max = aCWmin;
+ qparam.cw_min = aCWmax;
+ qparam.txop = 0;
+ qparam.aifs = 3;
+ break;
+ case 1: /* AC_VI */
+ qparam.cw_max = aCWmin;
+ qparam.cw_min = (aCWmin + 1) / 2 - 1;
+ if (use_11b)
+ qparam.txop = 6016/32;
+ else
+ qparam.txop = 3008/32;
+ qparam.aifs = 2;
+ break;
+ case 0: /* AC_VO */
+ qparam.cw_max = (aCWmin + 1) / 2 - 1;
+ qparam.cw_min = (aCWmin + 1) / 4 - 1;
+ if (use_11b)
+ qparam.txop = 3264/32;
+ else
+ qparam.txop = 1504/32;
+ qparam.aifs = 2;
+ break;
+ }
- for (i = 0; i < local_to_hw(local)->queues; i++)
- drv_conf_tx(local, i, &qparam);
+ drv_conf_tx(local, queue, &qparam);
+ }
}
void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index 6b4eb8d43a4e..c14394744a9c 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -27,100 +27,6 @@
#include "aes_ccm.h"
-static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr,
- int idx, int alg, int remove,
- int set_tx_key, const u8 *_key,
- size_t key_len)
-{
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
- struct ieee80211_key *key;
- int err;
-
- if (alg == ALG_AES_CMAC) {
- if (idx < NUM_DEFAULT_KEYS ||
- idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
- printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d "
- "(BIP)\n", sdata->dev->name, idx);
- return -EINVAL;
- }
- } else if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
- printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
- sdata->dev->name, idx);
- return -EINVAL;
- }
-
- if (remove) {
- rcu_read_lock();
-
- err = 0;
-
- if (is_broadcast_ether_addr(sta_addr)) {
- key = sdata->keys[idx];
- } else {
- sta = sta_info_get(local, sta_addr);
- if (!sta) {
- err = -ENOENT;
- goto out_unlock;
- }
- key = sta->key;
- }
-
- ieee80211_key_free(key);
- } else {
- key = ieee80211_key_alloc(alg, idx, key_len, _key);
- if (!key)
- return -ENOMEM;
-
- sta = NULL;
- err = 0;
-
- rcu_read_lock();
-
- if (!is_broadcast_ether_addr(sta_addr)) {
- set_tx_key = 0;
- /*
- * According to the standard, the key index of a
- * pairwise key must be zero. However, some AP are
- * broken when it comes to WEP key indices, so we
- * work around this.
- */
- if (idx != 0 && alg != ALG_WEP) {
- ieee80211_key_free(key);
- err = -EINVAL;
- goto out_unlock;
- }
-
- sta = sta_info_get(local, sta_addr);
- if (!sta) {
- ieee80211_key_free(key);
- err = -ENOENT;
- goto out_unlock;
- }
- }
-
- if (alg == ALG_WEP &&
- key_len != LEN_WEP40 && key_len != LEN_WEP104) {
- ieee80211_key_free(key);
- err = -EINVAL;
- goto out_unlock;
- }
-
- ieee80211_key_link(key, sdata, sta);
-
- if (set_tx_key || (!sta && !sdata->default_key && key))
- ieee80211_set_default_key(sdata, idx);
- if (alg == ALG_AES_CMAC &&
- (set_tx_key || (!sta && !sdata->default_mgmt_key && key)))
- ieee80211_set_default_mgmt_key(sdata, idx);
- }
-
- out_unlock:
- rcu_read_unlock();
-
- return err;
-}
-
static int ieee80211_ioctl_siwgenie(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra)
@@ -135,6 +41,7 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
return ret;
sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
ieee80211_sta_req_auth(sdata);
return 0;
}
@@ -218,6 +125,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
return ret;
sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
ieee80211_sta_req_auth(sdata);
return 0;
}
@@ -275,6 +183,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
if (ret)
return ret;
sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+ sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
ieee80211_sta_req_auth(sdata);
return 0;
} else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
@@ -472,109 +381,6 @@ static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
return 0;
}
-static int ieee80211_ioctl_siwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *keybuf)
-{
- struct ieee80211_sub_if_data *sdata;
- int idx, i, alg = ALG_WEP;
- u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- int remove = 0, ret;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (idx == 0) {
- if (sdata->default_key)
- for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
- }
- }
- } else if (idx < 1 || idx > 4)
- return -EINVAL;
- else
- idx--;
-
- if (erq->flags & IW_ENCODE_DISABLED)
- remove = 1;
- else if (erq->length == 0) {
- /* No key data - just set the default TX key index */
- ieee80211_set_default_key(sdata, idx);
- return 0;
- }
-
- ret = ieee80211_set_encryption(
- sdata, bcaddr,
- idx, alg, remove,
- !sdata->default_key,
- keybuf, erq->length);
-
- if (!ret && sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (remove)
- sdata->u.mgd.flags &= ~IEEE80211_STA_TKIP_WEP_USED;
- else
- sdata->u.mgd.flags |= IEEE80211_STA_TKIP_WEP_USED;
- }
-
- return ret;
-}
-
-
-static int ieee80211_ioctl_giwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *key)
-{
- struct ieee80211_sub_if_data *sdata;
- int idx, i;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (idx < 1 || idx > 4) {
- idx = -1;
- if (!sdata->default_key)
- idx = 0;
- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
- }
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
-
- erq->flags = idx + 1;
-
- if (!sdata->keys[idx]) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
-
- memcpy(key, sdata->keys[idx]->conf.key,
- min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
- erq->length = sdata->keys[idx]->conf.keylen;
- erq->flags |= IW_ENCODE_ENABLED;
-
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- switch (sdata->u.mgd.auth_alg) {
- case WLAN_AUTH_OPEN:
- case WLAN_AUTH_LEAP:
- erq->flags |= IW_ENCODE_OPEN;
- break;
- case WLAN_AUTH_SHARED_KEY:
- erq->flags |= IW_ENCODE_RESTRICTED;
- break;
- }
- }
-
- return 0;
-}
-
static int ieee80211_ioctl_siwpower(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *wrq,
@@ -809,82 +615,6 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev,
}
-static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *extra)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
- int uninitialized_var(alg), idx, i, remove = 0;
-
- switch (ext->alg) {
- case IW_ENCODE_ALG_NONE:
- remove = 1;
- break;
- case IW_ENCODE_ALG_WEP:
- alg = ALG_WEP;
- break;
- case IW_ENCODE_ALG_TKIP:
- alg = ALG_TKIP;
- break;
- case IW_ENCODE_ALG_CCMP:
- alg = ALG_CCMP;
- break;
- case IW_ENCODE_ALG_AES_CMAC:
- alg = ALG_AES_CMAC;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- if (erq->flags & IW_ENCODE_DISABLED)
- remove = 1;
-
- idx = erq->flags & IW_ENCODE_INDEX;
- if (alg == ALG_AES_CMAC) {
- if (idx < NUM_DEFAULT_KEYS + 1 ||
- idx > NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) {
- idx = -1;
- if (!sdata->default_mgmt_key)
- idx = 0;
- else for (i = NUM_DEFAULT_KEYS;
- i < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS;
- i++) {
- if (sdata->default_mgmt_key == sdata->keys[i])
- {
- idx = i;
- break;
- }
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
- } else {
- if (idx < 1 || idx > 4) {
- idx = -1;
- if (!sdata->default_key)
- idx = 0;
- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
- }
- }
- if (idx < 0)
- return -EINVAL;
- } else
- idx--;
- }
-
- return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
- remove,
- ext->ext_flags &
- IW_ENCODE_EXT_SET_TX_KEY,
- ext->key, ext->key_len);
-}
-
-
/* Structures to export the Wireless Handlers */
static const iw_handler ieee80211_handler[] =
@@ -931,8 +661,8 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
(iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */
(iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */
- (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
- (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
+ (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */
+ (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */
(iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */
(iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
@@ -941,7 +671,7 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) NULL, /* SIOCGIWGENIE */
(iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
(iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
- (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */
(iw_handler) NULL, /* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
(iw_handler) NULL, /* -- hole -- */
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 0b8ad1f4ecdd..45b74f38b867 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -133,7 +133,7 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
u8 *p = ieee80211_get_qos_ctl(hdr);
u8 ack_policy = 0;
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
- if (local->wifi_wme_noack_test)
+ if (unlikely(local->wifi_wme_noack_test))
ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
QOS_CONTROL_ACK_POLICY_SHIFT;
/* qos header is 2 bytes, second reserved */
OpenPOWER on IntegriCloud