aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-04-24 10:54:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-24 10:54:20 -0400
commit6ed0e321a0aef14a894e26658108bf7e895c36a6 (patch)
treef49428d68ebcb1beb757296ea1559079210babbe /net/wireless
parent3dec2246c2ff11beb24ca1950f074b2bcbc85953 (diff)
parentb006ed545cbadf1ebd4683719554742d20dbcede (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/core.h3
-rw-r--r--net/wireless/mlme.c5
-rw-r--r--net/wireless/nl80211.c285
-rw-r--r--net/wireless/rdev-ops.h24
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/trace.h35
-rw-r--r--net/wireless/util.c28
7 files changed, 301 insertions, 81 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 124e5e773fbc..fd35dae547c4 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -88,6 +88,9 @@ struct cfg80211_registered_device {
88 88
89 struct delayed_work dfs_update_channels_wk; 89 struct delayed_work dfs_update_channels_wk;
90 90
91 /* netlink port which started critical protocol (0 means not started) */
92 u32 crit_proto_nlportid;
93
91 /* must be last because of the way we do wiphy_priv(), 94 /* must be last because of the way we do wiphy_priv(),
92 * and it should at least be aligned to NETDEV_ALIGN */ 95 * and it should at least be aligned to NETDEV_ALIGN */
93 struct wiphy wiphy __aligned(NETDEV_ALIGN); 96 struct wiphy wiphy __aligned(NETDEV_ALIGN);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 390198bf4b36..0c7b7dd855f6 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -648,6 +648,11 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
648 648
649 spin_unlock_bh(&wdev->mgmt_registrations_lock); 649 spin_unlock_bh(&wdev->mgmt_registrations_lock);
650 650
651 if (nlportid && rdev->crit_proto_nlportid == nlportid) {
652 rdev->crit_proto_nlportid = 0;
653 rdev_crit_proto_stop(rdev, wdev);
654 }
655
651 if (nlportid == wdev->ap_unexpected_nlportid) 656 if (nlportid == wdev->ap_unexpected_nlportid)
652 wdev->ap_unexpected_nlportid = 0; 657 wdev->ap_unexpected_nlportid = 0;
653} 658}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 671b69a3c136..afa283841e8c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -447,62 +447,69 @@ nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
447 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 }, 447 [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
448}; 448};
449 449
450/* ifidx get helper */ 450static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
451static int nl80211_get_ifidx(struct netlink_callback *cb) 451 struct netlink_callback *cb,
452 struct cfg80211_registered_device **rdev,
453 struct wireless_dev **wdev)
452{ 454{
453 int res; 455 int err;
454
455 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
456 nl80211_fam.attrbuf, nl80211_fam.maxattr,
457 nl80211_policy);
458 if (res)
459 return res;
460
461 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
462 return -EINVAL;
463 456
464 res = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]); 457 rtnl_lock();
465 if (!res) 458 mutex_lock(&cfg80211_mutex);
466 return -EINVAL;
467 return res;
468}
469 459
470static int nl80211_prepare_netdev_dump(struct sk_buff *skb, 460 if (!cb->args[0]) {
471 struct netlink_callback *cb, 461 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
472 struct cfg80211_registered_device **rdev, 462 nl80211_fam.attrbuf, nl80211_fam.maxattr,
473 struct net_device **dev) 463 nl80211_policy);
474{ 464 if (err)
475 int ifidx = cb->args[0]; 465 goto out_unlock;
476 int err;
477 466
478 if (!ifidx) 467 *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk),
479 ifidx = nl80211_get_ifidx(cb); 468 nl80211_fam.attrbuf);
480 if (ifidx < 0) 469 if (IS_ERR(*wdev)) {
481 return ifidx; 470 err = PTR_ERR(*wdev);
471 goto out_unlock;
472 }
473 *rdev = wiphy_to_dev((*wdev)->wiphy);
474 cb->args[0] = (*rdev)->wiphy_idx;
475 cb->args[1] = (*wdev)->identifier;
476 } else {
477 struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
478 struct wireless_dev *tmp;
482 479
483 cb->args[0] = ifidx; 480 if (!wiphy) {
481 err = -ENODEV;
482 goto out_unlock;
483 }
484 *rdev = wiphy_to_dev(wiphy);
485 *wdev = NULL;
484 486
485 rtnl_lock(); 487 mutex_lock(&(*rdev)->devlist_mtx);
488 list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
489 if (tmp->identifier == cb->args[1]) {
490 *wdev = tmp;
491 break;
492 }
493 }
494 mutex_unlock(&(*rdev)->devlist_mtx);
486 495
487 *dev = __dev_get_by_index(sock_net(skb->sk), ifidx); 496 if (!*wdev) {
488 if (!*dev) { 497 err = -ENODEV;
489 err = -ENODEV; 498 goto out_unlock;
490 goto out_rtnl; 499 }
491 } 500 }
492 501
493 *rdev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx); 502 cfg80211_lock_rdev(*rdev);
494 if (IS_ERR(*rdev)) {
495 err = PTR_ERR(*rdev);
496 goto out_rtnl;
497 }
498 503
504 mutex_unlock(&cfg80211_mutex);
499 return 0; 505 return 0;
500 out_rtnl: 506 out_unlock:
507 mutex_unlock(&cfg80211_mutex);
501 rtnl_unlock(); 508 rtnl_unlock();
502 return err; 509 return err;
503} 510}
504 511
505static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev) 512static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
506{ 513{
507 cfg80211_unlock_rdev(rdev); 514 cfg80211_unlock_rdev(rdev);
508 rtnl_unlock(); 515 rtnl_unlock();
@@ -1417,6 +1424,10 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev,
1417 } 1424 }
1418 CMD(start_p2p_device, START_P2P_DEVICE); 1425 CMD(start_p2p_device, START_P2P_DEVICE);
1419 CMD(set_mcast_rate, SET_MCAST_RATE); 1426 CMD(set_mcast_rate, SET_MCAST_RATE);
1427 if (split) {
1428 CMD(crit_proto_start, CRIT_PROTOCOL_START);
1429 CMD(crit_proto_stop, CRIT_PROTOCOL_STOP);
1430 }
1420 1431
1421#ifdef CONFIG_NL80211_TESTMODE 1432#ifdef CONFIG_NL80211_TESTMODE
1422 CMD(testmode_cmd, TESTMODE); 1433 CMD(testmode_cmd, TESTMODE);
@@ -3525,15 +3536,20 @@ static int nl80211_dump_station(struct sk_buff *skb,
3525{ 3536{
3526 struct station_info sinfo; 3537 struct station_info sinfo;
3527 struct cfg80211_registered_device *dev; 3538 struct cfg80211_registered_device *dev;
3528 struct net_device *netdev; 3539 struct wireless_dev *wdev;
3529 u8 mac_addr[ETH_ALEN]; 3540 u8 mac_addr[ETH_ALEN];
3530 int sta_idx = cb->args[1]; 3541 int sta_idx = cb->args[2];
3531 int err; 3542 int err;
3532 3543
3533 err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); 3544 err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
3534 if (err) 3545 if (err)
3535 return err; 3546 return err;
3536 3547
3548 if (!wdev->netdev) {
3549 err = -EINVAL;
3550 goto out_err;
3551 }
3552
3537 if (!dev->ops->dump_station) { 3553 if (!dev->ops->dump_station) {
3538 err = -EOPNOTSUPP; 3554 err = -EOPNOTSUPP;
3539 goto out_err; 3555 goto out_err;
@@ -3541,7 +3557,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
3541 3557
3542 while (1) { 3558 while (1) {
3543 memset(&sinfo, 0, sizeof(sinfo)); 3559 memset(&sinfo, 0, sizeof(sinfo));
3544 err = rdev_dump_station(dev, netdev, sta_idx, 3560 err = rdev_dump_station(dev, wdev->netdev, sta_idx,
3545 mac_addr, &sinfo); 3561 mac_addr, &sinfo);
3546 if (err == -ENOENT) 3562 if (err == -ENOENT)
3547 break; 3563 break;
@@ -3551,7 +3567,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
3551 if (nl80211_send_station(skb, 3567 if (nl80211_send_station(skb,
3552 NETLINK_CB(cb->skb).portid, 3568 NETLINK_CB(cb->skb).portid,
3553 cb->nlh->nlmsg_seq, NLM_F_MULTI, 3569 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3554 dev, netdev, mac_addr, 3570 dev, wdev->netdev, mac_addr,
3555 &sinfo) < 0) 3571 &sinfo) < 0)
3556 goto out; 3572 goto out;
3557 3573
@@ -3560,10 +3576,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
3560 3576
3561 3577
3562 out: 3578 out:
3563 cb->args[1] = sta_idx; 3579 cb->args[2] = sta_idx;
3564 err = skb->len; 3580 err = skb->len;
3565 out_err: 3581 out_err:
3566 nl80211_finish_netdev_dump(dev); 3582 nl80211_finish_wdev_dump(dev);
3567 3583
3568 return err; 3584 return err;
3569} 3585}
@@ -4167,13 +4183,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4167{ 4183{
4168 struct mpath_info pinfo; 4184 struct mpath_info pinfo;
4169 struct cfg80211_registered_device *dev; 4185 struct cfg80211_registered_device *dev;
4170 struct net_device *netdev; 4186 struct wireless_dev *wdev;
4171 u8 dst[ETH_ALEN]; 4187 u8 dst[ETH_ALEN];
4172 u8 next_hop[ETH_ALEN]; 4188 u8 next_hop[ETH_ALEN];
4173 int path_idx = cb->args[1]; 4189 int path_idx = cb->args[2];
4174 int err; 4190 int err;
4175 4191
4176 err = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); 4192 err = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
4177 if (err) 4193 if (err)
4178 return err; 4194 return err;
4179 4195
@@ -4182,14 +4198,14 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4182 goto out_err; 4198 goto out_err;
4183 } 4199 }
4184 4200
4185 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { 4201 if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
4186 err = -EOPNOTSUPP; 4202 err = -EOPNOTSUPP;
4187 goto out_err; 4203 goto out_err;
4188 } 4204 }
4189 4205
4190 while (1) { 4206 while (1) {
4191 err = rdev_dump_mpath(dev, netdev, path_idx, dst, next_hop, 4207 err = rdev_dump_mpath(dev, wdev->netdev, path_idx, dst,
4192 &pinfo); 4208 next_hop, &pinfo);
4193 if (err == -ENOENT) 4209 if (err == -ENOENT)
4194 break; 4210 break;
4195 if (err) 4211 if (err)
@@ -4197,7 +4213,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4197 4213
4198 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid, 4214 if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).portid,
4199 cb->nlh->nlmsg_seq, NLM_F_MULTI, 4215 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4200 netdev, dst, next_hop, 4216 wdev->netdev, dst, next_hop,
4201 &pinfo) < 0) 4217 &pinfo) < 0)
4202 goto out; 4218 goto out;
4203 4219
@@ -4206,10 +4222,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
4206 4222
4207 4223
4208 out: 4224 out:
4209 cb->args[1] = path_idx; 4225 cb->args[2] = path_idx;
4210 err = skb->len; 4226 err = skb->len;
4211 out_err: 4227 out_err:
4212 nl80211_finish_netdev_dump(dev); 4228 nl80211_finish_wdev_dump(dev);
4213 return err; 4229 return err;
4214} 4230}
4215 4231
@@ -5565,9 +5581,13 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
5565 5581
5566 genl_dump_check_consistent(cb, hdr, &nl80211_fam); 5582 genl_dump_check_consistent(cb, hdr, &nl80211_fam);
5567 5583
5568 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation) || 5584 if (nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation))
5585 goto nla_put_failure;
5586 if (wdev->netdev &&
5569 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex)) 5587 nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
5570 goto nla_put_failure; 5588 goto nla_put_failure;
5589 if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
5590 goto nla_put_failure;
5571 5591
5572 bss = nla_nest_start(msg, NL80211_ATTR_BSS); 5592 bss = nla_nest_start(msg, NL80211_ATTR_BSS);
5573 if (!bss) 5593 if (!bss)
@@ -5647,22 +5667,18 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
5647 return -EMSGSIZE; 5667 return -EMSGSIZE;
5648} 5668}
5649 5669
5650static int nl80211_dump_scan(struct sk_buff *skb, 5670static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
5651 struct netlink_callback *cb)
5652{ 5671{
5653 struct cfg80211_registered_device *rdev; 5672 struct cfg80211_registered_device *rdev;
5654 struct net_device *dev;
5655 struct cfg80211_internal_bss *scan; 5673 struct cfg80211_internal_bss *scan;
5656 struct wireless_dev *wdev; 5674 struct wireless_dev *wdev;
5657 int start = cb->args[1], idx = 0; 5675 int start = cb->args[2], idx = 0;
5658 int err; 5676 int err;
5659 5677
5660 err = nl80211_prepare_netdev_dump(skb, cb, &rdev, &dev); 5678 err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
5661 if (err) 5679 if (err)
5662 return err; 5680 return err;
5663 5681
5664 wdev = dev->ieee80211_ptr;
5665
5666 wdev_lock(wdev); 5682 wdev_lock(wdev);
5667 spin_lock_bh(&rdev->bss_lock); 5683 spin_lock_bh(&rdev->bss_lock);
5668 cfg80211_bss_expire(rdev); 5684 cfg80211_bss_expire(rdev);
@@ -5683,8 +5699,8 @@ static int nl80211_dump_scan(struct sk_buff *skb,
5683 spin_unlock_bh(&rdev->bss_lock); 5699 spin_unlock_bh(&rdev->bss_lock);
5684 wdev_unlock(wdev); 5700 wdev_unlock(wdev);
5685 5701
5686 cb->args[1] = idx; 5702 cb->args[2] = idx;
5687 nl80211_finish_netdev_dump(rdev); 5703 nl80211_finish_wdev_dump(rdev);
5688 5704
5689 return skb->len; 5705 return skb->len;
5690} 5706}
@@ -5753,14 +5769,19 @@ static int nl80211_dump_survey(struct sk_buff *skb,
5753{ 5769{
5754 struct survey_info survey; 5770 struct survey_info survey;
5755 struct cfg80211_registered_device *dev; 5771 struct cfg80211_registered_device *dev;
5756 struct net_device *netdev; 5772 struct wireless_dev *wdev;
5757 int survey_idx = cb->args[1]; 5773 int survey_idx = cb->args[2];
5758 int res; 5774 int res;
5759 5775
5760 res = nl80211_prepare_netdev_dump(skb, cb, &dev, &netdev); 5776 res = nl80211_prepare_wdev_dump(skb, cb, &dev, &wdev);
5761 if (res) 5777 if (res)
5762 return res; 5778 return res;
5763 5779
5780 if (!wdev->netdev) {
5781 res = -EINVAL;
5782 goto out_err;
5783 }
5784
5764 if (!dev->ops->dump_survey) { 5785 if (!dev->ops->dump_survey) {
5765 res = -EOPNOTSUPP; 5786 res = -EOPNOTSUPP;
5766 goto out_err; 5787 goto out_err;
@@ -5769,7 +5790,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
5769 while (1) { 5790 while (1) {
5770 struct ieee80211_channel *chan; 5791 struct ieee80211_channel *chan;
5771 5792
5772 res = rdev_dump_survey(dev, netdev, survey_idx, &survey); 5793 res = rdev_dump_survey(dev, wdev->netdev, survey_idx, &survey);
5773 if (res == -ENOENT) 5794 if (res == -ENOENT)
5774 break; 5795 break;
5775 if (res) 5796 if (res)
@@ -5791,17 +5812,16 @@ static int nl80211_dump_survey(struct sk_buff *skb,
5791 if (nl80211_send_survey(skb, 5812 if (nl80211_send_survey(skb,
5792 NETLINK_CB(cb->skb).portid, 5813 NETLINK_CB(cb->skb).portid,
5793 cb->nlh->nlmsg_seq, NLM_F_MULTI, 5814 cb->nlh->nlmsg_seq, NLM_F_MULTI,
5794 netdev, 5815 wdev->netdev, &survey) < 0)
5795 &survey) < 0)
5796 goto out; 5816 goto out;
5797 survey_idx++; 5817 survey_idx++;
5798 } 5818 }
5799 5819
5800 out: 5820 out:
5801 cb->args[1] = survey_idx; 5821 cb->args[2] = survey_idx;
5802 res = skb->len; 5822 res = skb->len;
5803 out_err: 5823 out_err:
5804 nl80211_finish_netdev_dump(dev); 5824 nl80211_finish_wdev_dump(dev);
5805 return res; 5825 return res;
5806} 5826}
5807 5827
@@ -8143,9 +8163,11 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
8143 if (!rdev->ops->stop_p2p_device) 8163 if (!rdev->ops->stop_p2p_device)
8144 return -EOPNOTSUPP; 8164 return -EOPNOTSUPP;
8145 8165
8166 mutex_lock(&rdev->devlist_mtx);
8146 mutex_lock(&rdev->sched_scan_mtx); 8167 mutex_lock(&rdev->sched_scan_mtx);
8147 cfg80211_stop_p2p_device(rdev, wdev); 8168 cfg80211_stop_p2p_device(rdev, wdev);
8148 mutex_unlock(&rdev->sched_scan_mtx); 8169 mutex_unlock(&rdev->sched_scan_mtx);
8170 mutex_unlock(&rdev->devlist_mtx);
8149 8171
8150 return 0; 8172 return 0;
8151} 8173}
@@ -8198,6 +8220,64 @@ static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
8198 return rdev_update_ft_ies(rdev, dev, &ft_params); 8220 return rdev_update_ft_ies(rdev, dev, &ft_params);
8199} 8221}
8200 8222
8223static int nl80211_crit_protocol_start(struct sk_buff *skb,
8224 struct genl_info *info)
8225{
8226 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8227 struct wireless_dev *wdev = info->user_ptr[1];
8228 enum nl80211_crit_proto_id proto = NL80211_CRIT_PROTO_UNSPEC;
8229 u16 duration;
8230 int ret;
8231
8232 if (!rdev->ops->crit_proto_start)
8233 return -EOPNOTSUPP;
8234
8235 if (WARN_ON(!rdev->ops->crit_proto_stop))
8236 return -EINVAL;
8237
8238 if (rdev->crit_proto_nlportid)
8239 return -EBUSY;
8240
8241 /* determine protocol if provided */
8242 if (info->attrs[NL80211_ATTR_CRIT_PROT_ID])
8243 proto = nla_get_u16(info->attrs[NL80211_ATTR_CRIT_PROT_ID]);
8244
8245 if (proto >= NUM_NL80211_CRIT_PROTO)
8246 return -EINVAL;
8247
8248 /* timeout must be provided */
8249 if (!info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION])
8250 return -EINVAL;
8251
8252 duration =
8253 nla_get_u16(info->attrs[NL80211_ATTR_MAX_CRIT_PROT_DURATION]);
8254
8255 if (duration > NL80211_CRIT_PROTO_MAX_DURATION)
8256 return -ERANGE;
8257
8258 ret = rdev_crit_proto_start(rdev, wdev, proto, duration);
8259 if (!ret)
8260 rdev->crit_proto_nlportid = info->snd_portid;
8261
8262 return ret;
8263}
8264
8265static int nl80211_crit_protocol_stop(struct sk_buff *skb,
8266 struct genl_info *info)
8267{
8268 struct cfg80211_registered_device *rdev = info->user_ptr[0];
8269 struct wireless_dev *wdev = info->user_ptr[1];
8270
8271 if (!rdev->ops->crit_proto_stop)
8272 return -EOPNOTSUPP;
8273
8274 if (rdev->crit_proto_nlportid) {
8275 rdev->crit_proto_nlportid = 0;
8276 rdev_crit_proto_stop(rdev, wdev);
8277 }
8278 return 0;
8279}
8280
8201#define NL80211_FLAG_NEED_WIPHY 0x01 8281#define NL80211_FLAG_NEED_WIPHY 0x01
8202#define NL80211_FLAG_NEED_NETDEV 0x02 8282#define NL80211_FLAG_NEED_NETDEV 0x02
8203#define NL80211_FLAG_NEED_RTNL 0x04 8283#define NL80211_FLAG_NEED_RTNL 0x04
@@ -8887,6 +8967,22 @@ static struct genl_ops nl80211_ops[] = {
8887 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 8967 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
8888 NL80211_FLAG_NEED_RTNL, 8968 NL80211_FLAG_NEED_RTNL,
8889 }, 8969 },
8970 {
8971 .cmd = NL80211_CMD_CRIT_PROTOCOL_START,
8972 .doit = nl80211_crit_protocol_start,
8973 .policy = nl80211_policy,
8974 .flags = GENL_ADMIN_PERM,
8975 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
8976 NL80211_FLAG_NEED_RTNL,
8977 },
8978 {
8979 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
8980 .doit = nl80211_crit_protocol_stop,
8981 .policy = nl80211_policy,
8982 .flags = GENL_ADMIN_PERM,
8983 .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
8984 NL80211_FLAG_NEED_RTNL,
8985 }
8890}; 8986};
8891 8987
8892static struct genl_multicast_group nl80211_mlme_mcgrp = { 8988static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -10632,6 +10728,45 @@ void cfg80211_ft_event(struct net_device *netdev,
10632} 10728}
10633EXPORT_SYMBOL(cfg80211_ft_event); 10729EXPORT_SYMBOL(cfg80211_ft_event);
10634 10730
10731void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
10732{
10733 struct cfg80211_registered_device *rdev;
10734 struct sk_buff *msg;
10735 void *hdr;
10736 u32 nlportid;
10737
10738 rdev = wiphy_to_dev(wdev->wiphy);
10739 if (!rdev->crit_proto_nlportid)
10740 return;
10741
10742 nlportid = rdev->crit_proto_nlportid;
10743 rdev->crit_proto_nlportid = 0;
10744
10745 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
10746 if (!msg)
10747 return;
10748
10749 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CRIT_PROTOCOL_STOP);
10750 if (!hdr)
10751 goto nla_put_failure;
10752
10753 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
10754 nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
10755 goto nla_put_failure;
10756
10757 genlmsg_end(msg, hdr);
10758
10759 genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
10760 return;
10761
10762 nla_put_failure:
10763 if (hdr)
10764 genlmsg_cancel(msg, hdr);
10765 nlmsg_free(msg);
10766
10767}
10768EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
10769
10635/* initialisation/exit functions */ 10770/* initialisation/exit functions */
10636 10771
10637int nl80211_init(void) 10772int nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index d77e1c1d3a0e..9f15f0ac824d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -875,7 +875,7 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
875 trace_rdev_stop_p2p_device(&rdev->wiphy, wdev); 875 trace_rdev_stop_p2p_device(&rdev->wiphy, wdev);
876 rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); 876 rdev->ops->stop_p2p_device(&rdev->wiphy, wdev);
877 trace_rdev_return_void(&rdev->wiphy); 877 trace_rdev_return_void(&rdev->wiphy);
878} 878}
879 879
880static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev, 880static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
881 struct net_device *dev, 881 struct net_device *dev,
@@ -901,4 +901,26 @@ static inline int rdev_update_ft_ies(struct cfg80211_registered_device *rdev,
901 return ret; 901 return ret;
902} 902}
903 903
904static inline int rdev_crit_proto_start(struct cfg80211_registered_device *rdev,
905 struct wireless_dev *wdev,
906 enum nl80211_crit_proto_id protocol,
907 u16 duration)
908{
909 int ret;
910
911 trace_rdev_crit_proto_start(&rdev->wiphy, wdev, protocol, duration);
912 ret = rdev->ops->crit_proto_start(&rdev->wiphy, wdev,
913 protocol, duration);
914 trace_rdev_return_int(&rdev->wiphy, ret);
915 return ret;
916}
917
918static inline void rdev_crit_proto_stop(struct cfg80211_registered_device *rdev,
919 struct wireless_dev *wdev)
920{
921 trace_rdev_crit_proto_stop(&rdev->wiphy, wdev);
922 rdev->ops->crit_proto_stop(&rdev->wiphy, wdev);
923 trace_rdev_return_void(&rdev->wiphy);
924}
925
904#endif /* __CFG80211_RDEV_OPS */ 926#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e6df52dc8c69..cc35fbaa4578 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -855,7 +855,7 @@ static void handle_channel(struct wiphy *wiphy,
855 return; 855 return;
856 856
857 REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); 857 REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq);
858 chan->flags = IEEE80211_CHAN_DISABLED; 858 chan->flags |= IEEE80211_CHAN_DISABLED;
859 return; 859 return;
860 } 860 }
861 861
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 3c2033b8f596..ecd4fcec3c94 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1806,6 +1806,41 @@ TRACE_EVENT(rdev_update_ft_ies,
1806 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md) 1806 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->md)
1807); 1807);
1808 1808
1809TRACE_EVENT(rdev_crit_proto_start,
1810 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
1811 enum nl80211_crit_proto_id protocol, u16 duration),
1812 TP_ARGS(wiphy, wdev, protocol, duration),
1813 TP_STRUCT__entry(
1814 WIPHY_ENTRY
1815 WDEV_ENTRY
1816 __field(u16, proto)
1817 __field(u16, duration)
1818 ),
1819 TP_fast_assign(
1820 WIPHY_ASSIGN;
1821 WDEV_ASSIGN;
1822 __entry->proto = protocol;
1823 __entry->duration = duration;
1824 ),
1825 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", proto=%x, duration=%u",
1826 WIPHY_PR_ARG, WDEV_PR_ARG, __entry->proto, __entry->duration)
1827);
1828
1829TRACE_EVENT(rdev_crit_proto_stop,
1830 TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
1831 TP_ARGS(wiphy, wdev),
1832 TP_STRUCT__entry(
1833 WIPHY_ENTRY
1834 WDEV_ENTRY
1835 ),
1836 TP_fast_assign(
1837 WIPHY_ASSIGN;
1838 WDEV_ASSIGN;
1839 ),
1840 TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
1841 WIPHY_PR_ARG, WDEV_PR_ARG)
1842);
1843
1809/************************************************************* 1844/*************************************************************
1810 * cfg80211 exported functions traces * 1845 * cfg80211 exported functions traces *
1811 *************************************************************/ 1846 *************************************************************/
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 6cbac99ae03d..f5ad4d94ba88 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1155,6 +1155,26 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
1155} 1155}
1156EXPORT_SYMBOL(cfg80211_get_p2p_attr); 1156EXPORT_SYMBOL(cfg80211_get_p2p_attr);
1157 1157
1158bool ieee80211_operating_class_to_band(u8 operating_class,
1159 enum ieee80211_band *band)
1160{
1161 switch (operating_class) {
1162 case 112:
1163 case 115 ... 127:
1164 *band = IEEE80211_BAND_5GHZ;
1165 return true;
1166 case 81:
1167 case 82:
1168 case 83:
1169 case 84:
1170 *band = IEEE80211_BAND_2GHZ;
1171 return true;
1172 }
1173
1174 return false;
1175}
1176EXPORT_SYMBOL(ieee80211_operating_class_to_band);
1177
1158int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 1178int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
1159 u32 beacon_int) 1179 u32 beacon_int)
1160{ 1180{
@@ -1258,12 +1278,12 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
1258 list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { 1278 list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
1259 if (wdev_iter == wdev) 1279 if (wdev_iter == wdev)
1260 continue; 1280 continue;
1261 if (wdev_iter->netdev) { 1281 if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1262 if (!netif_running(wdev_iter->netdev))
1263 continue;
1264 } else if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1265 if (!wdev_iter->p2p_started) 1282 if (!wdev_iter->p2p_started)
1266 continue; 1283 continue;
1284 } else if (wdev_iter->netdev) {
1285 if (!netif_running(wdev_iter->netdev))
1286 continue;
1267 } else { 1287 } else {
1268 WARN_ON(1); 1288 WARN_ON(1);
1269 } 1289 }