aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/debugfs.c25
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mlme.c38
-rw-r--r--net/mac80211/util.c25
-rw-r--r--net/mac80211/wext.c31
5 files changed, 79 insertions, 42 deletions
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 11c72311f35..6c439cd5cce 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -163,6 +163,29 @@ static const struct file_operations noack_ops = {
.open = mac80211_open_file_generic
};
+static ssize_t queues_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ unsigned long flags;
+ char buf[IEEE80211_MAX_QUEUES * 20];
+ int q, res = 0;
+
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ for (q = 0; q < local->hw.queues; q++)
+ res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q,
+ local->queue_stop_reasons[q],
+ __netif_subqueue_stopped(local->mdev, q));
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, res);
+}
+
+static const struct file_operations queues_ops = {
+ .read = queues_read,
+ .open = mac80211_open_file_generic
+};
+
/* statistics stuff */
#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \
@@ -298,6 +321,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_ADD(total_ps_buffered);
DEBUGFS_ADD(wep_iv);
DEBUGFS_ADD(tsf);
+ DEBUGFS_ADD(queues);
DEBUGFS_ADD_MODE(reset, 0200);
DEBUGFS_ADD(noack);
@@ -350,6 +374,7 @@ void debugfs_hw_del(struct ieee80211_local *local)
DEBUGFS_DEL(total_ps_buffered);
DEBUGFS_DEL(wep_iv);
DEBUGFS_DEL(tsf);
+ DEBUGFS_DEL(queues);
DEBUGFS_DEL(reset);
DEBUGFS_DEL(noack);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4dbc2896419..68eb5052179 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -783,6 +783,7 @@ struct ieee80211_local {
struct dentry *total_ps_buffered;
struct dentry *wep_iv;
struct dentry *tsf;
+ struct dentry *queues;
struct dentry *reset;
struct dentry *noack;
struct dentry *statistics;
@@ -1100,7 +1101,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
struct ieee802_11_elems *elems,
u64 filter, u32 crc);
-int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d779c57a822..aca22b00b6a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1102,14 +1102,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta;
u32 changed = 0, config_changed = 0;
- rcu_read_lock();
-
- sta = sta_info_get(local, ifmgd->bssid);
- if (!sta) {
- rcu_read_unlock();
- return;
- }
-
if (deauth) {
ifmgd->direct_probe_tries = 0;
ifmgd->auth_tries = 0;
@@ -1120,7 +1112,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
netif_tx_stop_all_queues(sdata->dev);
netif_carrier_off(sdata->dev);
- ieee80211_sta_tear_down_BA_sessions(sta);
+ rcu_read_lock();
+ sta = sta_info_get(local, ifmgd->bssid);
+ if (sta)
+ ieee80211_sta_tear_down_BA_sessions(sta);
+ rcu_read_unlock();
bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
conf->channel->center_freq,
@@ -1156,8 +1152,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ifmgd->ssid, ifmgd->ssid_len);
}
- rcu_read_unlock();
-
ieee80211_set_wmm_default(sdata);
ieee80211_recalc_idle(local);
@@ -2223,7 +2217,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
capa_mask, capa_val);
if (bss) {
- ieee80211_set_freq(sdata, bss->cbss.channel->center_freq);
+ local->oper_channel = bss->cbss.channel;
+ local->oper_channel_type = NL80211_CHAN_NO_HT;
+ ieee80211_hw_config(local, 0);
+
if (!(ifmgd->flags & IEEE80211_STA_SSID_SET))
ieee80211_sta_set_ssid(sdata, bss->ssid,
bss->ssid_len);
@@ -2445,6 +2442,14 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
ieee80211_set_disassoc(sdata, true, true,
WLAN_REASON_DEAUTH_LEAVING);
+ if (ifmgd->ssid_len == 0) {
+ /*
+ * Only allow association to be started if a valid SSID
+ * is configured.
+ */
+ return;
+ }
+
if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) ||
ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
@@ -2476,6 +2481,10 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size
ifmgd = &sdata->u.mgd;
if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) {
+ if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
+ ieee80211_set_disassoc(sdata, true, true,
+ WLAN_REASON_DEAUTH_LEAVING);
+
/*
* Do not use reassociation if SSID is changed (different ESS).
*/
@@ -2500,6 +2509,11 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ if (compare_ether_addr(bssid, ifmgd->bssid) != 0 &&
+ ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)
+ ieee80211_set_disassoc(sdata, true, true,
+ WLAN_REASON_DEAUTH_LEAVING);
+
if (is_valid_ether_addr(bssid)) {
memcpy(ifmgd->bssid, bssid, ETH_ALEN);
ifmgd->flags |= IEEE80211_STA_BSSID_SET;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 66ce96a69f3..915e7776931 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -774,31 +774,6 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
dev_queue_xmit(skb);
}
-int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
-{
- int ret = -EINVAL;
- struct ieee80211_channel *chan;
- struct ieee80211_local *local = sdata->local;
-
- chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
-
- if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
- if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
- chan->flags & IEEE80211_CHAN_NO_IBSS)
- return ret;
- local->oper_channel = chan;
- local->oper_channel_type = NL80211_CHAN_NO_HT;
-
- if (local->sw_scanning || local->hw_scanning)
- ret = 0;
- else
- ret = ieee80211_hw_config(
- local, IEEE80211_CONF_CHANGE_CHANNEL);
- }
-
- return ret;
-}
-
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band)
{
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index d2d81b10334..1da81f45674 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -55,6 +55,8 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
struct iw_freq *freq, char *extra)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_channel *chan;
if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
@@ -69,17 +71,38 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
IEEE80211_STA_AUTO_CHANNEL_SEL;
return 0;
} else
- return ieee80211_set_freq(sdata,
+ chan = ieee80211_get_channel(local->hw.wiphy,
ieee80211_channel_to_frequency(freq->m));
} else {
int i, div = 1000000;
for (i = 0; i < freq->e; i++)
div /= 10;
- if (div > 0)
- return ieee80211_set_freq(sdata, freq->m / div);
- else
+ if (div <= 0)
return -EINVAL;
+ chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div);
}
+
+ if (!chan)
+ return -EINVAL;
+
+ if (chan->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+
+ /*
+ * no change except maybe auto -> fixed, ignore the HT
+ * setting so you can fix a channel you're on already
+ */
+ if (local->oper_channel == chan)
+ return 0;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ ieee80211_sta_req_auth(sdata);
+
+ local->oper_channel = chan;
+ local->oper_channel_type = NL80211_CHAN_NO_HT;
+ ieee80211_hw_config(local, 0);
+
+ return 0;
}