summaryrefslogtreecommitdiff
path: root/net/wireless
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-13 17:40:34 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-13 17:40:34 +0900
commit42a2d923cc349583ebf6fdd52a7d35e1c2f7e6bd (patch)
tree2b2b0c03b5389c1301800119333967efafd994ca /net/wireless
parent5cbb3d216e2041700231bcfc383ee5f8b7fc8b74 (diff)
parent75ecab1df14d90e86cebef9ec5c76befde46e65f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) The addition of nftables. No longer will we need protocol aware firewall filtering modules, it can all live in userspace. At the core of nftables is a, for lack of a better term, virtual machine that executes byte codes to inspect packet or metadata (arriving interface index, etc.) and make verdict decisions. Besides support for loading packet contents and comparing them, the interpreter supports lookups in various datastructures as fundamental operations. For example sets are supports, and therefore one could create a set of whitelist IP address entries which have ACCEPT verdicts attached to them, and use the appropriate byte codes to do such lookups. Since the interpreted code is composed in userspace, userspace can do things like optimize things before giving it to the kernel. Another major improvement is the capability of atomically updating portions of the ruleset. In the existing netfilter implementation, one has to update the entire rule set in order to make a change and this is very expensive. Userspace tools exist to create nftables rules using existing netfilter rule sets, but both kernel implementations will need to co-exist for quite some time as we transition from the old to the new stuff. Kudos to Patrick McHardy, Pablo Neira Ayuso, and others who have worked so hard on this. 2) Daniel Borkmann and Hannes Frederic Sowa made several improvements to our pseudo-random number generator, mostly used for things like UDP port randomization and netfitler, amongst other things. In particular the taus88 generater is updated to taus113, and test cases are added. 3) Support 64-bit rates in HTB and TBF schedulers, from Eric Dumazet and Yang Yingliang. 4) Add support for new 577xx tigon3 chips to tg3 driver, from Nithin Sujir. 5) Fix two fatal flaws in TCP dynamic right sizing, from Eric Dumazet, Neal Cardwell, and Yuchung Cheng. 6) Allow IP_TOS and IP_TTL to be specified in sendmsg() ancillary control message data, much like other socket option attributes. From Francesco Fusco. 7) Allow applications to specify a cap on the rate computed automatically by the kernel for pacing flows, via a new SO_MAX_PACING_RATE socket option. From Eric Dumazet. 8) Make the initial autotuned send buffer sizing in TCP more closely reflect actual needs, from Eric Dumazet. 9) Currently early socket demux only happens for TCP sockets, but we can do it for connected UDP sockets too. Implementation from Shawn Bohrer. 10) Refactor inet socket demux with the goal of improving hash demux performance for listening sockets. With the main goals being able to use RCU lookups on even request sockets, and eliminating the listening lock contention. From Eric Dumazet. 11) The bonding layer has many demuxes in it's fast path, and an RCU conversion was started back in 3.11, several changes here extend the RCU usage to even more locations. From Ding Tianhong and Wang Yufen, based upon suggestions by Nikolay Aleksandrov and Veaceslav Falico. 12) Allow stackability of segmentation offloads to, in particular, allow segmentation offloading over tunnels. From Eric Dumazet. 13) Significantly improve the handling of secret keys we input into the various hash functions in the inet hashtables, TCP fast open, as well as syncookies. From Hannes Frederic Sowa. The key fundamental operation is "net_get_random_once()" which uses static keys. Hannes even extended this to ipv4/ipv6 fragmentation handling and our generic flow dissector. 14) The generic driver layer takes care now to set the driver data to NULL on device removal, so it's no longer necessary for drivers to explicitly set it to NULL any more. Many drivers have been cleaned up in this way, from Jingoo Han. 15) Add a BPF based packet scheduler classifier, from Daniel Borkmann. 16) Improve CRC32 interfaces and generic SKB checksum iterators so that SCTP's checksumming can more cleanly be handled. Also from Daniel Borkmann. 17) Add a new PMTU discovery mode, IP_PMTUDISC_INTERFACE, which forces using the interface MTU value. This helps avoid PMTU attacks, particularly on DNS servers. From Hannes Frederic Sowa. 18) Use generic XPS for transmit queue steering rather than internal (re-)implementation in virtio-net. From Jason Wang. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1622 commits) random32: add test cases for taus113 implementation random32: upgrade taus88 generator to taus113 from errata paper random32: move rnd_state to linux/random.h random32: add prandom_reseed_late() and call when nonblocking pool becomes initialized random32: add periodic reseeding random32: fix off-by-one in seeding requirement PHY: Add RTL8201CP phy_driver to realtek xtsonic: add missing platform_set_drvdata() in xtsonic_probe() macmace: add missing platform_set_drvdata() in mace_probe() ethernet/arc/arc_emac: add missing platform_set_drvdata() in arc_emac_probe() ipv6: protect for_each_sk_fl_rcu in mem_check with rcu_read_lock_bh vlan: Implement vlan_dev_get_egress_qos_mask as an inline. ixgbe: add warning when max_vfs is out of range. igb: Update link modes display in ethtool netfilter: push reasm skb through instead of original frag skbs ip6_output: fragment outgoing reassembled skb properly MAINTAINERS: mv643xx_eth: take over maintainership from Lennart net_sched: tbf: support of 64bit rates ixgbe: deleting dfwd stations out of order can cause null ptr deref ixgbe: fix build err, num_rx_queues is only available with CONFIG_RPS ...
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/chan.c4
-rw-r--r--net/wireless/core.h15
-rw-r--r--net/wireless/debugfs.c24
-rw-r--r--net/wireless/genregdb.awk6
-rw-r--r--net/wireless/ibss.c24
-rw-r--r--net/wireless/mlme.c6
-rw-r--r--net/wireless/nl80211.c102
-rw-r--r--net/wireless/reg.c53
-rw-r--r--net/wireless/reg.h4
-rw-r--r--net/wireless/scan.c4
-rw-r--r--net/wireless/sme.c4
-rw-r--r--net/wireless/sysfs.h4
-rw-r--r--net/wireless/util.c23
13 files changed, 201 insertions, 72 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 50f6195c8b70..9b8cc877eb19 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -328,6 +328,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2,
width);
}
+EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
@@ -503,7 +504,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
case NL80211_IFTYPE_ADHOC:
if (wdev->current_bss) {
*chan = wdev->current_bss->pub.channel;
- *chanmode = wdev->ibss_fixed
+ *chanmode = (wdev->ibss_fixed &&
+ !wdev->ibss_dfs_possible)
? CHAN_MODE_SHARED
: CHAN_MODE_EXCLUSIVE;
return;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3159e9c284c5..af10e59af2d8 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -234,10 +234,10 @@ struct cfg80211_beacon_registration {
};
/* free object */
-extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
+void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
-extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
- char *newname);
+int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
+ char *newname);
void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
@@ -382,15 +382,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
enum cfg80211_chan_mode chanmode,
u8 radar_detect);
-/**
- * cfg80211_chandef_dfs_required - checks if radar detection is required
- * @wiphy: the wiphy to validate against
- * @chandef: the channel definition to check
- * Return: 1 if radar detection is required, 0 if it is not, < 0 on error
- */
-int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
- const struct cfg80211_chan_def *c);
-
void cfg80211_set_dfs_state(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
enum nl80211_dfs_state dfs_state);
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 90d050036624..454157717efa 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -47,17 +47,19 @@ static int ht_print_chan(struct ieee80211_channel *chan,
return 0;
if (chan->flags & IEEE80211_CHAN_DISABLED)
- return snprintf(buf + offset,
- buf_size - offset,
- "%d Disabled\n",
- chan->center_freq);
-
- return snprintf(buf + offset,
- buf_size - offset,
- "%d HT40 %c%c\n",
- chan->center_freq,
- (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-',
- (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+');
+ return scnprintf(buf + offset,
+ buf_size - offset,
+ "%d Disabled\n",
+ chan->center_freq);
+
+ return scnprintf(buf + offset,
+ buf_size - offset,
+ "%d HT40 %c%c\n",
+ chan->center_freq,
+ (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ?
+ ' ' : '-',
+ (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ?
+ ' ' : '+');
}
static ssize_t ht40allow_map_read(struct file *file,
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
index 9392f8cbb901..42ed274e81f4 100644
--- a/net/wireless/genregdb.awk
+++ b/net/wireless/genregdb.awk
@@ -46,6 +46,12 @@ BEGIN {
sub(/:/, "", country)
printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
printf "\t.alpha2 = \"%s\",\n", country
+ if ($NF ~ /DFS-ETSI/)
+ printf "\t.dfs_region = NL80211_DFS_ETSI,\n"
+ else if ($NF ~ /DFS-FCC/)
+ printf "\t.dfs_region = NL80211_DFS_FCC,\n"
+ else if ($NF ~ /DFS-JP/)
+ printf "\t.dfs_region = NL80211_DFS_JP,\n"
printf "\t.reg_rules = {\n"
active = 1
regdb = regdb "\t&regdom_" country ",\n"
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 403fe29c024d..9d797df56649 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -83,6 +83,8 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct cfg80211_cached_keys *connkeys)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct ieee80211_channel *check_chan;
+ u8 radar_detect_width = 0;
int err;
ASSERT_WDEV_LOCK(wdev);
@@ -114,14 +116,28 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
wdev->connect_keys = connkeys;
wdev->ibss_fixed = params->channel_fixed;
+ wdev->ibss_dfs_possible = params->userspace_handles_dfs;
#ifdef CONFIG_CFG80211_WEXT
wdev->wext.ibss.chandef = params->chandef;
#endif
+ check_chan = params->chandef.chan;
+ if (params->userspace_handles_dfs) {
+ /* use channel NULL to check for radar even if the current
+ * channel is not a radar channel - it might decide to change
+ * to DFS channel later.
+ */
+ radar_detect_width = BIT(params->chandef.width);
+ check_chan = NULL;
+ }
+
+ err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
+ check_chan,
+ (params->channel_fixed &&
+ !radar_detect_width)
+ ? CHAN_MODE_SHARED
+ : CHAN_MODE_EXCLUSIVE,
+ radar_detect_width);
- err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan,
- params->channel_fixed
- ? CHAN_MODE_SHARED
- : CHAN_MODE_EXCLUSIVE);
if (err) {
wdev->connect_keys = NULL;
return err;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 8d49c1ce3dea..6a6b1c8e907d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -707,11 +707,13 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
if (c->dfs_state != NL80211_DFS_UNAVAILABLE)
continue;
- timeout = c->dfs_state_entered +
- IEEE80211_DFS_MIN_NOP_TIME_MS;
+ timeout = c->dfs_state_entered + msecs_to_jiffies(
+ IEEE80211_DFS_MIN_NOP_TIME_MS);
if (time_after_eq(jiffies, timeout)) {
c->dfs_state = NL80211_DFS_USABLE;
+ c->dfs_state_entered = jiffies;
+
cfg80211_chandef_create(&chandef, c,
NL80211_CHAN_NO_HT);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 626dc3b5fd8d..a7f4e7902104 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -354,6 +354,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
+ [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
+ [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
+ [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -3896,9 +3899,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info,
return 0;
}
+static int nl80211_parse_sta_channel_info(struct genl_info *info,
+ struct station_parameters *params)
+{
+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
+ params->supported_channels =
+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
+ params->supported_channels_len =
+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
+ /*
+ * Need to include at least one (first channel, number of
+ * channels) tuple for each subband, and must have proper
+ * tuples for the rest of the data as well.
+ */
+ if (params->supported_channels_len < 2)
+ return -EINVAL;
+ if (params->supported_channels_len % 2)
+ return -EINVAL;
+ }
+
+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
+ params->supported_oper_classes =
+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
+ params->supported_oper_classes_len =
+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
+ /*
+ * The value of the Length field of the Supported Operating
+ * Classes element is between 2 and 253.
+ */
+ if (params->supported_oper_classes_len < 2 ||
+ params->supported_oper_classes_len > 253)
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int nl80211_set_station_tdls(struct genl_info *info,
struct station_parameters *params)
{
+ int err;
/* Dummy STA entry gets updated once the peer capabilities are known */
if (info->attrs[NL80211_ATTR_PEER_AID])
params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
@@ -3909,6 +3948,10 @@ static int nl80211_set_station_tdls(struct genl_info *info,
params->vht_capa =
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
+ err = nl80211_parse_sta_channel_info(info, params);
+ if (err)
+ return err;
+
return nl80211_parse_sta_wme(info, params);
}
@@ -4089,6 +4132,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+ err = nl80211_parse_sta_channel_info(info, &params);
+ if (err)
+ return err;
+
err = nl80211_parse_sta_wme(info, &params);
if (err)
return err;
@@ -5591,6 +5638,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (err)
return err;
+ if (netif_carrier_ok(dev))
+ return -EBUSY;
+
if (wdev->cac_started)
return -EBUSY;
@@ -5634,15 +5684,27 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
u8 radar_detect_width = 0;
int err;
+ bool need_new_beacon = false;
if (!rdev->ops->channel_switch ||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
return -EOPNOTSUPP;
- /* may add IBSS support later */
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ switch (dev->ieee80211_ptr->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ need_new_beacon = true;
+
+ /* useless if AP is not running */
+ if (!wdev->beacon_interval)
+ return -EINVAL;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ break;
+ default:
return -EOPNOTSUPP;
+ }
memset(&params, 0, sizeof(params));
@@ -5651,15 +5713,14 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
/* only important for AP, IBSS and mesh create IEs internally */
- if (!info->attrs[NL80211_ATTR_CSA_IES])
- return -EINVAL;
-
- /* useless if AP is not running */
- if (!wdev->beacon_interval)
+ if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
return -EINVAL;
params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+ if (!need_new_beacon)
+ goto skip_beacons;
+
err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
if (err)
return err;
@@ -5699,6 +5760,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+skip_beacons:
err = nl80211_parse_chandef(rdev, info, &params.chandef);
if (err)
return err;
@@ -5706,12 +5768,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
return -EINVAL;
- err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef);
- if (err < 0) {
- return err;
- } else if (err) {
- radar_detect_width = BIT(params.chandef.width);
- params.radar_required = true;
+ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
+ dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO ||
+ dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC) {
+ err = cfg80211_chandef_dfs_required(wdev->wiphy,
+ &params.chandef);
+ if (err < 0) {
+ return err;
+ } else if (err) {
+ radar_detect_width = BIT(params.chandef.width);
+ params.radar_required = true;
+ }
}
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
@@ -6535,6 +6602,9 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
ibss.control_port =
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
+ ibss.userspace_handles_dfs =
+ nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
+
err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
if (err)
kfree(connkeys);
@@ -10740,7 +10810,9 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev_lock(wdev);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
- wdev->iftype != NL80211_IFTYPE_P2P_GO))
+ wdev->iftype != NL80211_IFTYPE_P2P_GO &&
+ wdev->iftype != NL80211_IFTYPE_ADHOC &&
+ wdev->iftype != NL80211_IFTYPE_MESH_POINT))
goto out;
wdev->channel = chandef->chan;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index de06d5d1287f..7da67fd0b418 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -172,11 +172,21 @@ static const struct ieee80211_regdomain world_regdom = {
NL80211_RRF_NO_IBSS |
NL80211_RRF_NO_OFDM),
/* IEEE 802.11a, channel 36..48 */
- REG_RULE(5180-10, 5240+10, 80, 6, 20,
+ REG_RULE(5180-10, 5240+10, 160, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),
- /* NB: 5260 MHz - 5700 MHz requires DFS */
+ /* IEEE 802.11a, channel 52..64 - DFS required */
+ REG_RULE(5260-10, 5320+10, 160, 6, 20,
+ NL80211_RRF_PASSIVE_SCAN |
+ NL80211_RRF_NO_IBSS |
+ NL80211_RRF_DFS),
+
+ /* IEEE 802.11a, channel 100..144 - DFS required */
+ REG_RULE(5500-10, 5720+10, 160, 6, 20,
+ NL80211_RRF_PASSIVE_SCAN |
+ NL80211_RRF_NO_IBSS |
+ NL80211_RRF_DFS),
/* IEEE 802.11a, channel 149..165 */
REG_RULE(5745-10, 5825+10, 80, 6, 20,
@@ -758,24 +768,25 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
}
EXPORT_SYMBOL(freq_reg_info);
-#ifdef CONFIG_CFG80211_REG_DEBUG
-static const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
+const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
{
switch (initiator) {
case NL80211_REGDOM_SET_BY_CORE:
- return "Set by core";
+ return "core";
case NL80211_REGDOM_SET_BY_USER:
- return "Set by user";
+ return "user";
case NL80211_REGDOM_SET_BY_DRIVER:
- return "Set by driver";
+ return "driver";
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
- return "Set by country IE";
+ return "country IE";
default:
WARN_ON(1);
- return "Set by bug";
+ return "bug";
}
}
+EXPORT_SYMBOL(reg_initiator_name);
+#ifdef CONFIG_CFG80211_REG_DEBUG
static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan,
const struct ieee80211_reg_rule *reg_rule)
{
@@ -962,6 +973,13 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
}
#endif
+static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
+{
+ if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY &&
+ !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY))
+ return true;
+ return false;
+}
static bool ignore_reg_update(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator)
@@ -969,14 +987,17 @@ static bool ignore_reg_update(struct wiphy *wiphy,
struct regulatory_request *lr = get_last_request();
if (!lr) {
- REG_DBG_PRINT("Ignoring regulatory request %s since last_request is not set\n",
+ REG_DBG_PRINT("Ignoring regulatory request set by %s "
+ "since last_request is not set\n",
reg_initiator_name(initiator));
return true;
}
if (initiator == NL80211_REGDOM_SET_BY_CORE &&
wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
- REG_DBG_PRINT("Ignoring regulatory request %s since the driver uses its own custom regulatory domain\n",
+ REG_DBG_PRINT("Ignoring regulatory request set by %s "
+ "since the driver uses its own custom "
+ "regulatory domain\n",
reg_initiator_name(initiator));
return true;
}
@@ -985,10 +1006,12 @@ static bool ignore_reg_update(struct wiphy *wiphy,
* wiphy->regd will be set once the device has its own
* desired regulatory domain set
*/
- if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd &&
+ if (wiphy_strict_alpha2_regd(wiphy) && !wiphy->regd &&
initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
!is_world_regdom(lr->alpha2)) {
- REG_DBG_PRINT("Ignoring regulatory request %s since the driver requires its own regulatory domain to be set first\n",
+ REG_DBG_PRINT("Ignoring regulatory request set by %s "
+ "since the driver requires its own regulatory "
+ "domain to be set first\n",
reg_initiator_name(initiator));
return true;
}
@@ -1689,8 +1712,8 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
}
EXPORT_SYMBOL(regulatory_hint);
-void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
- const u8 *country_ie, u8 country_ie_len)
+void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band,
+ const u8 *country_ie, u8 country_ie_len)
{
char alpha2[2];
enum environment_cap env = ENVIRON_ANY;
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index af2d5f8a5d82..9677e3c13da9 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -58,7 +58,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
gfp_t gfp);
/**
- * regulatory_hint_11d - hints a country IE as a regulatory domain
+ * regulatory_hint_country_ie - hints a country IE as a regulatory domain
* @wiphy: the wireless device giving the hint (used only for reporting
* conflicts)
* @band: the band on which the country IE was received on. This determines
@@ -78,7 +78,7 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
* not observed. For this reason if a triplet is seen with channel
* information for a band the BSS is not present in it will be ignored.
*/
-void regulatory_hint_11d(struct wiphy *wiphy,
+void regulatory_hint_country_ie(struct wiphy *wiphy,
enum ieee80211_band band,
const u8 *country_ie,
u8 country_ie_len);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index eeb71480f1af..d4397eba5408 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -254,10 +254,10 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device,
sched_scan_results_wk);
- request = rdev->sched_scan_req;
-
rtnl_lock();
+ request = rdev->sched_scan_req;
+
/* we don't have sched_scan_req anymore if the scan is stopping */
if (request) {
if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 20e86a95dc4e..65f800890d70 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -682,8 +682,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
* - country_ie + 2, the start of the country ie data, and
* - and country_ie[1] which is the IE length
*/
- regulatory_hint_11d(wdev->wiphy, bss->channel->band,
- country_ie + 2, country_ie[1]);
+ regulatory_hint_country_ie(wdev->wiphy, bss->channel->band,
+ country_ie + 2, country_ie[1]);
kfree(country_ie);
}
diff --git a/net/wireless/sysfs.h b/net/wireless/sysfs.h
index 65acbebd3711..b533ed71daff 100644
--- a/net/wireless/sysfs.h
+++ b/net/wireless/sysfs.h
@@ -1,8 +1,8 @@
#ifndef __WIRELESS_SYSFS_H
#define __WIRELESS_SYSFS_H
-extern int wiphy_sysfs_init(void);
-extern void wiphy_sysfs_exit(void);
+int wiphy_sysfs_init(void);
+void wiphy_sysfs_exit(void);
extern struct class ieee80211_class;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index ce090c1c5e4f..935dea9485da 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -10,6 +10,7 @@
#include <net/cfg80211.h>
#include <net/ip.h>
#include <net/dsfield.h>
+#include <linux/if_vlan.h>
#include "core.h"
#include "rdev-ops.h"
@@ -691,6 +692,7 @@ EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
unsigned int cfg80211_classify8021d(struct sk_buff *skb)
{
unsigned int dscp;
+ unsigned char vlan_priority;
/* skb->priority values from 256->263 are magic values to
* directly indicate a specific 802.1d priority. This is used
@@ -700,6 +702,13 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb)
if (skb->priority >= 256 && skb->priority <= 263)
return skb->priority - 256;
+ if (vlan_tx_tag_present(skb)) {
+ vlan_priority = (vlan_tx_tag_get(skb) & VLAN_PRIO_MASK)
+ >> VLAN_PRIO_SHIFT;
+ if (vlan_priority > 0)
+ return vlan_priority;
+ }
+
switch (skb->protocol) {
case htons(ETH_P_IP):
dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
@@ -1240,7 +1249,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
enum cfg80211_chan_mode chmode;
int num_different_channels = 0;
int total = 1;
- bool radar_required;
+ bool radar_required = false;
int i, j;
ASSERT_RTNL();
@@ -1255,14 +1264,20 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_WDS:
- radar_required = !!(chan &&
- (chan->flags & IEEE80211_CHAN_RADAR));
+ /* if the interface could potentially choose a DFS channel,
+ * then mark DFS as required.
+ */
+ if (!chan) {
+ if (chanmode != CHAN_MODE_UNDEFINED && radar_detect)
+ radar_required = true;
+ break;
+ }
+ radar_required = !!(chan->flags & IEEE80211_CHAN_RADAR);
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_MONITOR:
- radar_required = false;
break;
case NUM_NL80211_IFTYPES:
case NL80211_IFTYPE_UNSPECIFIED: