diff options
author | Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> | 2013-08-28 07:41:33 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-09-26 07:27:15 -0400 |
commit | ee4bc9e75811d2c0cb5f2a2fc5b51ff037a01f47 (patch) | |
tree | 9c18e85641edb636efcc1ac14f5d1716a9d06457 /net/wireless | |
parent | 9449410f3b30a27824aa02adec485e18b740b756 (diff) |
nl80211: enable IBSS support for channel switch announcements
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index af8d84a4a5b2..ae617112b8f5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -5634,15 +5634,26 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5634 | static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; | 5634 | static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; |
5635 | u8 radar_detect_width = 0; | 5635 | u8 radar_detect_width = 0; |
5636 | int err; | 5636 | int err; |
5637 | bool need_new_beacon = false; | ||
5637 | 5638 | ||
5638 | if (!rdev->ops->channel_switch || | 5639 | if (!rdev->ops->channel_switch || |
5639 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) | 5640 | !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) |
5640 | return -EOPNOTSUPP; | 5641 | return -EOPNOTSUPP; |
5641 | 5642 | ||
5642 | /* may add IBSS support later */ | 5643 | switch (dev->ieee80211_ptr->iftype) { |
5643 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 5644 | case NL80211_IFTYPE_AP: |
5644 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 5645 | case NL80211_IFTYPE_P2P_GO: |
5646 | need_new_beacon = true; | ||
5647 | |||
5648 | /* useless if AP is not running */ | ||
5649 | if (!wdev->beacon_interval) | ||
5650 | return -EINVAL; | ||
5651 | break; | ||
5652 | case NL80211_IFTYPE_ADHOC: | ||
5653 | break; | ||
5654 | default: | ||
5645 | return -EOPNOTSUPP; | 5655 | return -EOPNOTSUPP; |
5656 | } | ||
5646 | 5657 | ||
5647 | memset(¶ms, 0, sizeof(params)); | 5658 | memset(¶ms, 0, sizeof(params)); |
5648 | 5659 | ||
@@ -5651,15 +5662,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5651 | return -EINVAL; | 5662 | return -EINVAL; |
5652 | 5663 | ||
5653 | /* only important for AP, IBSS and mesh create IEs internally */ | 5664 | /* only important for AP, IBSS and mesh create IEs internally */ |
5654 | if (!info->attrs[NL80211_ATTR_CSA_IES]) | 5665 | if (need_new_beacon && |
5655 | return -EINVAL; | 5666 | (!info->attrs[NL80211_ATTR_CSA_IES] || |
5656 | 5667 | !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON])) | |
5657 | /* useless if AP is not running */ | ||
5658 | if (!wdev->beacon_interval) | ||
5659 | return -EINVAL; | 5668 | return -EINVAL; |
5660 | 5669 | ||
5661 | params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); | 5670 | params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); |
5662 | 5671 | ||
5672 | if (!need_new_beacon) | ||
5673 | goto skip_beacons; | ||
5674 | |||
5663 | err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after); | 5675 | err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after); |
5664 | if (err) | 5676 | if (err) |
5665 | return err; | 5677 | return err; |
@@ -5699,6 +5711,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5699 | return -EINVAL; | 5711 | return -EINVAL; |
5700 | } | 5712 | } |
5701 | 5713 | ||
5714 | skip_beacons: | ||
5702 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); | 5715 | err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); |
5703 | if (err) | 5716 | if (err) |
5704 | return err; | 5717 | return err; |
@@ -5706,12 +5719,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
5706 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) | 5719 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) |
5707 | return -EINVAL; | 5720 | return -EINVAL; |
5708 | 5721 | ||
5709 | err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef); | 5722 | /* DFS channels are only supported for AP/P2P GO ... for now. */ |
5710 | if (err < 0) { | 5723 | if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || |
5711 | return err; | 5724 | dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { |
5712 | } else if (err) { | 5725 | err = cfg80211_chandef_dfs_required(wdev->wiphy, |
5713 | radar_detect_width = BIT(params.chandef.width); | 5726 | ¶ms.chandef); |
5714 | params.radar_required = true; | 5727 | if (err < 0) { |
5728 | return err; | ||
5729 | } else if (err) { | ||
5730 | radar_detect_width = BIT(params.chandef.width); | ||
5731 | params.radar_required = true; | ||
5732 | } | ||
5715 | } | 5733 | } |
5716 | 5734 | ||
5717 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 5735 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
@@ -10740,7 +10758,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, | |||
10740 | wdev_lock(wdev); | 10758 | wdev_lock(wdev); |
10741 | 10759 | ||
10742 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | 10760 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && |
10743 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | 10761 | wdev->iftype != NL80211_IFTYPE_P2P_GO && |
10762 | wdev->iftype != NL80211_IFTYPE_ADHOC)) | ||
10744 | goto out; | 10763 | goto out; |
10745 | 10764 | ||
10746 | wdev->channel = chandef->chan; | 10765 | wdev->channel = chandef->chan; |