diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-04-24 10:54:20 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-24 10:54:20 -0400 |
commit | 6ed0e321a0aef14a894e26658108bf7e895c36a6 (patch) | |
tree | f49428d68ebcb1beb757296ea1559079210babbe /net/wireless | |
parent | 3dec2246c2ff11beb24ca1950f074b2bcbc85953 (diff) | |
parent | b006ed545cbadf1ebd4683719554742d20dbcede (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.h | 3 | ||||
-rw-r--r-- | net/wireless/mlme.c | 5 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 285 | ||||
-rw-r--r-- | net/wireless/rdev-ops.h | 24 | ||||
-rw-r--r-- | net/wireless/reg.c | 2 | ||||
-rw-r--r-- | net/wireless/trace.h | 35 | ||||
-rw-r--r-- | net/wireless/util.c | 28 |
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 */ | 450 | static int nl80211_prepare_wdev_dump(struct sk_buff *skb, |
451 | static 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 | ||
470 | static 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 | ||
505 | static void nl80211_finish_netdev_dump(struct cfg80211_registered_device *rdev) | 512 | static 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 | ||
5650 | static int nl80211_dump_scan(struct sk_buff *skb, | 5670 | static 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 | ||
8223 | static 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 | |||
8265 | static 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 | ||
8892 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 8988 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -10632,6 +10728,45 @@ void cfg80211_ft_event(struct net_device *netdev, | |||
10632 | } | 10728 | } |
10633 | EXPORT_SYMBOL(cfg80211_ft_event); | 10729 | EXPORT_SYMBOL(cfg80211_ft_event); |
10634 | 10730 | ||
10731 | void 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 | } | ||
10768 | EXPORT_SYMBOL(cfg80211_crit_proto_stopped); | ||
10769 | |||
10635 | /* initialisation/exit functions */ | 10770 | /* initialisation/exit functions */ |
10636 | 10771 | ||
10637 | int nl80211_init(void) | 10772 | int 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 | ||
880 | static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev, | 880 | static 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 | ||
904 | static 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 | |||
918 | static 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 | ||
1809 | TRACE_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 | |||
1829 | TRACE_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 | } |
1156 | EXPORT_SYMBOL(cfg80211_get_p2p_attr); | 1156 | EXPORT_SYMBOL(cfg80211_get_p2p_attr); |
1157 | 1157 | ||
1158 | bool 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 | } | ||
1176 | EXPORT_SYMBOL(ieee80211_operating_class_to_band); | ||
1177 | |||
1158 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | 1178 | int 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 | } |