Commit ee4bc9e7 authored by Simon Wunderlich's avatar Simon Wunderlich Committed by Johannes Berg

nl80211: enable IBSS support for channel switch announcements

Signed-off-by: default avatarSimon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: default avatarMathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9449410f
...@@ -5634,15 +5634,26 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) ...@@ -5634,15 +5634,26 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
u8 radar_detect_width = 0; u8 radar_detect_width = 0;
int err; int err;
bool need_new_beacon = false;
if (!rdev->ops->channel_switch || if (!rdev->ops->channel_switch ||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* may add IBSS support later */ switch (dev->ieee80211_ptr->iftype) {
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && case NL80211_IFTYPE_AP:
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) case NL80211_IFTYPE_P2P_GO:
need_new_beacon = true;
/* useless if AP is not running */
if (!wdev->beacon_interval)
return -EINVAL;
break;
case NL80211_IFTYPE_ADHOC:
break;
default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
...@@ -5651,15 +5662,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) ...@@ -5651,15 +5662,16 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL; return -EINVAL;
/* only important for AP, IBSS and mesh create IEs internally */ /* only important for AP, IBSS and mesh create IEs internally */
if (!info->attrs[NL80211_ATTR_CSA_IES]) if (need_new_beacon &&
return -EINVAL; (!info->attrs[NL80211_ATTR_CSA_IES] ||
!info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON]))
/* useless if AP is not running */
if (!wdev->beacon_interval)
return -EINVAL; return -EINVAL;
params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
if (!need_new_beacon)
goto skip_beacons;
err = nl80211_parse_beacon(info->attrs, &params.beacon_after); err = nl80211_parse_beacon(info->attrs, &params.beacon_after);
if (err) if (err)
return err; return err;
...@@ -5699,6 +5711,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) ...@@ -5699,6 +5711,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL; return -EINVAL;
} }
skip_beacons:
err = nl80211_parse_chandef(rdev, info, &params.chandef); err = nl80211_parse_chandef(rdev, info, &params.chandef);
if (err) if (err)
return err; return err;
...@@ -5706,12 +5719,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) ...@@ -5706,12 +5719,17 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef)) if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef))
return -EINVAL; return -EINVAL;
err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef); /* DFS channels are only supported for AP/P2P GO ... for now. */
if (err < 0) { if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
return err; dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
} else if (err) { err = cfg80211_chandef_dfs_required(wdev->wiphy,
radar_detect_width = BIT(params.chandef.width); &params.chandef);
params.radar_required = true; if (err < 0) {
return err;
} else if (err) {
radar_detect_width = BIT(params.chandef.width);
params.radar_required = true;
}
} }
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
...@@ -10740,7 +10758,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, ...@@ -10740,7 +10758,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev_lock(wdev); wdev_lock(wdev);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO)) wdev->iftype != NL80211_IFTYPE_P2P_GO &&
wdev->iftype != NL80211_IFTYPE_ADHOC))
goto out; goto out;
wdev->channel = chandef->chan; wdev->channel = chandef->chan;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment