aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorSimon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de>2013-08-28 07:41:33 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-09-26 07:27:15 -0400
commitee4bc9e75811d2c0cb5f2a2fc5b51ff037a01f47 (patch)
tree9c18e85641edb636efcc1ac14f5d1716a9d06457 /net/wireless
parent9449410f3b30a27824aa02adec485e18b740b756 (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.c49
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(&params, 0, sizeof(params)); 5658 memset(&params, 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, &params.beacon_after); 5675 err = nl80211_parse_beacon(info->attrs, &params.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
5714skip_beacons:
5702 err = nl80211_parse_chandef(rdev, info, &params.chandef); 5715 err = nl80211_parse_chandef(rdev, info, &params.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, &params.chandef)) 5719 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
5707 return -EINVAL; 5720 return -EINVAL;
5708 5721
5709 err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.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 &params.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;