aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-11-08 09:03:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-11-08 09:03:10 -0500
commitc1f3bb6bd317994beb3af7bbec4bf54ed0035509 (patch)
tree878833c714ddcb35f1574f2b11e1f69d1130d206 /net/wireless
parentdcd607718385d02ce3741de225927a57f528f93b (diff)
parent3c57e865cfb2dcbb48fdfa08e7d4e3479e9b40f0 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/chan.c3
-rw-r--r--net/wireless/ibss.c24
-rw-r--r--net/wireless/mlme.c6
-rw-r--r--net/wireless/nl80211.c62
-rw-r--r--net/wireless/reg.c14
-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/util.c14
9 files changed, 108 insertions, 27 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 16f3c3a7b2c1..9b8cc877eb19 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -504,7 +504,8 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
504 case NL80211_IFTYPE_ADHOC: 504 case NL80211_IFTYPE_ADHOC:
505 if (wdev->current_bss) { 505 if (wdev->current_bss) {
506 *chan = wdev->current_bss->pub.channel; 506 *chan = wdev->current_bss->pub.channel;
507 *chanmode = wdev->ibss_fixed 507 *chanmode = (wdev->ibss_fixed &&
508 !wdev->ibss_dfs_possible)
508 ? CHAN_MODE_SHARED 509 ? CHAN_MODE_SHARED
509 : CHAN_MODE_EXCLUSIVE; 510 : CHAN_MODE_EXCLUSIVE;
510 return; 511 return;
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,
83 struct cfg80211_cached_keys *connkeys) 83 struct cfg80211_cached_keys *connkeys)
84{ 84{
85 struct wireless_dev *wdev = dev->ieee80211_ptr; 85 struct wireless_dev *wdev = dev->ieee80211_ptr;
86 struct ieee80211_channel *check_chan;
87 u8 radar_detect_width = 0;
86 int err; 88 int err;
87 89
88 ASSERT_WDEV_LOCK(wdev); 90 ASSERT_WDEV_LOCK(wdev);
@@ -114,14 +116,28 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
114 wdev->connect_keys = connkeys; 116 wdev->connect_keys = connkeys;
115 117
116 wdev->ibss_fixed = params->channel_fixed; 118 wdev->ibss_fixed = params->channel_fixed;
119 wdev->ibss_dfs_possible = params->userspace_handles_dfs;
117#ifdef CONFIG_CFG80211_WEXT 120#ifdef CONFIG_CFG80211_WEXT
118 wdev->wext.ibss.chandef = params->chandef; 121 wdev->wext.ibss.chandef = params->chandef;
119#endif 122#endif
123 check_chan = params->chandef.chan;
124 if (params->userspace_handles_dfs) {
125 /* use channel NULL to check for radar even if the current
126 * channel is not a radar channel - it might decide to change
127 * to DFS channel later.
128 */
129 radar_detect_width = BIT(params->chandef.width);
130 check_chan = NULL;
131 }
132
133 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
134 check_chan,
135 (params->channel_fixed &&
136 !radar_detect_width)
137 ? CHAN_MODE_SHARED
138 : CHAN_MODE_EXCLUSIVE,
139 radar_detect_width);
120 140
121 err = cfg80211_can_use_chan(rdev, wdev, params->chandef.chan,
122 params->channel_fixed
123 ? CHAN_MODE_SHARED
124 : CHAN_MODE_EXCLUSIVE);
125 if (err) { 141 if (err) {
126 wdev->connect_keys = NULL; 142 wdev->connect_keys = NULL;
127 return err; 143 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)
707 if (c->dfs_state != NL80211_DFS_UNAVAILABLE) 707 if (c->dfs_state != NL80211_DFS_UNAVAILABLE)
708 continue; 708 continue;
709 709
710 timeout = c->dfs_state_entered + 710 timeout = c->dfs_state_entered + msecs_to_jiffies(
711 IEEE80211_DFS_MIN_NOP_TIME_MS; 711 IEEE80211_DFS_MIN_NOP_TIME_MS);
712 712
713 if (time_after_eq(jiffies, timeout)) { 713 if (time_after_eq(jiffies, timeout)) {
714 c->dfs_state = NL80211_DFS_USABLE; 714 c->dfs_state = NL80211_DFS_USABLE;
715 c->dfs_state_entered = jiffies;
716
715 cfg80211_chandef_create(&chandef, c, 717 cfg80211_chandef_create(&chandef, c,
716 NL80211_CHAN_NO_HT); 718 NL80211_CHAN_NO_HT);
717 719
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cbbef88a8ebd..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] = {
354 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED }, 354 [NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
355 [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, 355 [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
356 [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 }, 356 [NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
357 [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
358 [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
359 [NL80211_ATTR_HANDLE_DFS] = { .type = NLA_FLAG },
357}; 360};
358 361
359/* policy for the key attributes */ 362/* policy for the key attributes */
@@ -3896,9 +3899,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info,
3896 return 0; 3899 return 0;
3897} 3900}
3898 3901
3902static int nl80211_parse_sta_channel_info(struct genl_info *info,
3903 struct station_parameters *params)
3904{
3905 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
3906 params->supported_channels =
3907 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
3908 params->supported_channels_len =
3909 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
3910 /*
3911 * Need to include at least one (first channel, number of
3912 * channels) tuple for each subband, and must have proper
3913 * tuples for the rest of the data as well.
3914 */
3915 if (params->supported_channels_len < 2)
3916 return -EINVAL;
3917 if (params->supported_channels_len % 2)
3918 return -EINVAL;
3919 }
3920
3921 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
3922 params->supported_oper_classes =
3923 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
3924 params->supported_oper_classes_len =
3925 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
3926 /*
3927 * The value of the Length field of the Supported Operating
3928 * Classes element is between 2 and 253.
3929 */
3930 if (params->supported_oper_classes_len < 2 ||
3931 params->supported_oper_classes_len > 253)
3932 return -EINVAL;
3933 }
3934 return 0;
3935}
3936
3899static int nl80211_set_station_tdls(struct genl_info *info, 3937static int nl80211_set_station_tdls(struct genl_info *info,
3900 struct station_parameters *params) 3938 struct station_parameters *params)
3901{ 3939{
3940 int err;
3902 /* Dummy STA entry gets updated once the peer capabilities are known */ 3941 /* Dummy STA entry gets updated once the peer capabilities are known */
3903 if (info->attrs[NL80211_ATTR_PEER_AID]) 3942 if (info->attrs[NL80211_ATTR_PEER_AID])
3904 params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); 3943 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,
3909 params->vht_capa = 3948 params->vht_capa =
3910 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); 3949 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
3911 3950
3951 err = nl80211_parse_sta_channel_info(info, params);
3952 if (err)
3953 return err;
3954
3912 return nl80211_parse_sta_wme(info, params); 3955 return nl80211_parse_sta_wme(info, params);
3913} 3956}
3914 3957
@@ -4089,6 +4132,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
4089 return -EINVAL; 4132 return -EINVAL;
4090 } 4133 }
4091 4134
4135 err = nl80211_parse_sta_channel_info(info, &params);
4136 if (err)
4137 return err;
4138
4092 err = nl80211_parse_sta_wme(info, &params); 4139 err = nl80211_parse_sta_wme(info, &params);
4093 if (err) 4140 if (err)
4094 return err; 4141 return err;
@@ -5653,6 +5700,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5653 return -EINVAL; 5700 return -EINVAL;
5654 break; 5701 break;
5655 case NL80211_IFTYPE_ADHOC: 5702 case NL80211_IFTYPE_ADHOC:
5703 case NL80211_IFTYPE_MESH_POINT:
5656 break; 5704 break;
5657 default: 5705 default:
5658 return -EOPNOTSUPP; 5706 return -EOPNOTSUPP;
@@ -5665,9 +5713,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
5665 return -EINVAL; 5713 return -EINVAL;
5666 5714
5667 /* only important for AP, IBSS and mesh create IEs internally */ 5715 /* only important for AP, IBSS and mesh create IEs internally */
5668 if (need_new_beacon && 5716 if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
5669 (!info->attrs[NL80211_ATTR_CSA_IES] ||
5670 !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON]))
5671 return -EINVAL; 5717 return -EINVAL;
5672 5718
5673 params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); 5719 params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
@@ -5722,9 +5768,9 @@ skip_beacons:
5722 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef)) 5768 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
5723 return -EINVAL; 5769 return -EINVAL;
5724 5770
5725 /* DFS channels are only supported for AP/P2P GO ... for now. */
5726 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || 5771 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
5727 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { 5772 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO ||
5773 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC) {
5728 err = cfg80211_chandef_dfs_required(wdev->wiphy, 5774 err = cfg80211_chandef_dfs_required(wdev->wiphy,
5729 &params.chandef); 5775 &params.chandef);
5730 if (err < 0) { 5776 if (err < 0) {
@@ -6556,6 +6602,9 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
6556 ibss.control_port = 6602 ibss.control_port =
6557 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]); 6603 nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
6558 6604
6605 ibss.userspace_handles_dfs =
6606 nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS]);
6607
6559 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 6608 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
6560 if (err) 6609 if (err)
6561 kfree(connkeys); 6610 kfree(connkeys);
@@ -10762,7 +10811,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
10762 10811
10763 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && 10812 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
10764 wdev->iftype != NL80211_IFTYPE_P2P_GO && 10813 wdev->iftype != NL80211_IFTYPE_P2P_GO &&
10765 wdev->iftype != NL80211_IFTYPE_ADHOC)) 10814 wdev->iftype != NL80211_IFTYPE_ADHOC &&
10815 wdev->iftype != NL80211_IFTYPE_MESH_POINT))
10766 goto out; 10816 goto out;
10767 10817
10768 wdev->channel = chandef->chan; 10818 wdev->channel = chandef->chan;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index a0ec143ba3dc..7da67fd0b418 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -787,7 +787,6 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
787EXPORT_SYMBOL(reg_initiator_name); 787EXPORT_SYMBOL(reg_initiator_name);
788 788
789#ifdef CONFIG_CFG80211_REG_DEBUG 789#ifdef CONFIG_CFG80211_REG_DEBUG
790
791static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, 790static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan,
792 const struct ieee80211_reg_rule *reg_rule) 791 const struct ieee80211_reg_rule *reg_rule)
793{ 792{
@@ -974,6 +973,13 @@ static bool reg_dev_ignore_cell_hint(struct wiphy *wiphy)
974} 973}
975#endif 974#endif
976 975
976static bool wiphy_strict_alpha2_regd(struct wiphy *wiphy)
977{
978 if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY &&
979 !(wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY))
980 return true;
981 return false;
982}
977 983
978static bool ignore_reg_update(struct wiphy *wiphy, 984static bool ignore_reg_update(struct wiphy *wiphy,
979 enum nl80211_reg_initiator initiator) 985 enum nl80211_reg_initiator initiator)
@@ -1000,7 +1006,7 @@ static bool ignore_reg_update(struct wiphy *wiphy,
1000 * wiphy->regd will be set once the device has its own 1006 * wiphy->regd will be set once the device has its own
1001 * desired regulatory domain set 1007 * desired regulatory domain set
1002 */ 1008 */
1003 if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && 1009 if (wiphy_strict_alpha2_regd(wiphy) && !wiphy->regd &&
1004 initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && 1010 initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1005 !is_world_regdom(lr->alpha2)) { 1011 !is_world_regdom(lr->alpha2)) {
1006 REG_DBG_PRINT("Ignoring regulatory request set by %s " 1012 REG_DBG_PRINT("Ignoring regulatory request set by %s "
@@ -1706,8 +1712,8 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
1706} 1712}
1707EXPORT_SYMBOL(regulatory_hint); 1713EXPORT_SYMBOL(regulatory_hint);
1708 1714
1709void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, 1715void regulatory_hint_country_ie(struct wiphy *wiphy, enum ieee80211_band band,
1710 const u8 *country_ie, u8 country_ie_len) 1716 const u8 *country_ie, u8 country_ie_len)
1711{ 1717{
1712 char alpha2[2]; 1718 char alpha2[2];
1713 enum environment_cap env = ENVIRON_ANY; 1719 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,
58 gfp_t gfp); 58 gfp_t gfp);
59 59
60/** 60/**
61 * regulatory_hint_11d - hints a country IE as a regulatory domain 61 * regulatory_hint_country_ie - hints a country IE as a regulatory domain
62 * @wiphy: the wireless device giving the hint (used only for reporting 62 * @wiphy: the wireless device giving the hint (used only for reporting
63 * conflicts) 63 * conflicts)
64 * @band: the band on which the country IE was received on. This determines 64 * @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,
78 * not observed. For this reason if a triplet is seen with channel 78 * not observed. For this reason if a triplet is seen with channel
79 * information for a band the BSS is not present in it will be ignored. 79 * information for a band the BSS is not present in it will be ignored.
80 */ 80 */
81void regulatory_hint_11d(struct wiphy *wiphy, 81void regulatory_hint_country_ie(struct wiphy *wiphy,
82 enum ieee80211_band band, 82 enum ieee80211_band band,
83 const u8 *country_ie, 83 const u8 *country_ie,
84 u8 country_ie_len); 84 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)
254 rdev = container_of(wk, struct cfg80211_registered_device, 254 rdev = container_of(wk, struct cfg80211_registered_device,
255 sched_scan_results_wk); 255 sched_scan_results_wk);
256 256
257 request = rdev->sched_scan_req;
258
259 rtnl_lock(); 257 rtnl_lock();
260 258
259 request = rdev->sched_scan_req;
260
261 /* we don't have sched_scan_req anymore if the scan is stopping */ 261 /* we don't have sched_scan_req anymore if the scan is stopping */
262 if (request) { 262 if (request) {
263 if (request->flags & NL80211_SCAN_FLAG_FLUSH) { 263 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,
682 * - country_ie + 2, the start of the country ie data, and 682 * - country_ie + 2, the start of the country ie data, and
683 * - and country_ie[1] which is the IE length 683 * - and country_ie[1] which is the IE length
684 */ 684 */
685 regulatory_hint_11d(wdev->wiphy, bss->channel->band, 685 regulatory_hint_country_ie(wdev->wiphy, bss->channel->band,
686 country_ie + 2, country_ie[1]); 686 country_ie + 2, country_ie[1]);
687 kfree(country_ie); 687 kfree(country_ie);
688} 688}
689 689
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 3c8be6104ba4..935dea9485da 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1249,7 +1249,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1249 enum cfg80211_chan_mode chmode; 1249 enum cfg80211_chan_mode chmode;
1250 int num_different_channels = 0; 1250 int num_different_channels = 0;
1251 int total = 1; 1251 int total = 1;
1252 bool radar_required; 1252 bool radar_required = false;
1253 int i, j; 1253 int i, j;
1254 1254
1255 ASSERT_RTNL(); 1255 ASSERT_RTNL();
@@ -1264,14 +1264,20 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1264 case NL80211_IFTYPE_MESH_POINT: 1264 case NL80211_IFTYPE_MESH_POINT:
1265 case NL80211_IFTYPE_P2P_GO: 1265 case NL80211_IFTYPE_P2P_GO:
1266 case NL80211_IFTYPE_WDS: 1266 case NL80211_IFTYPE_WDS:
1267 radar_required = !!(chan && 1267 /* if the interface could potentially choose a DFS channel,
1268 (chan->flags & IEEE80211_CHAN_RADAR)); 1268 * then mark DFS as required.
1269 */
1270 if (!chan) {
1271 if (chanmode != CHAN_MODE_UNDEFINED && radar_detect)
1272 radar_required = true;
1273 break;
1274 }
1275 radar_required = !!(chan->flags & IEEE80211_CHAN_RADAR);
1269 break; 1276 break;
1270 case NL80211_IFTYPE_P2P_CLIENT: 1277 case NL80211_IFTYPE_P2P_CLIENT:
1271 case NL80211_IFTYPE_STATION: 1278 case NL80211_IFTYPE_STATION:
1272 case NL80211_IFTYPE_P2P_DEVICE: 1279 case NL80211_IFTYPE_P2P_DEVICE:
1273 case NL80211_IFTYPE_MONITOR: 1280 case NL80211_IFTYPE_MONITOR:
1274 radar_required = false;
1275 break; 1281 break;
1276 case NUM_NL80211_IFTYPES: 1282 case NUM_NL80211_IFTYPES:
1277 case NL80211_IFTYPE_UNSPECIFIED: 1283 case NL80211_IFTYPE_UNSPECIFIED: