Loading net/wireless/nl80211.c +34 −15 Original line number Original line Diff line number Diff line Loading @@ -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(¶ms, 0, sizeof(params)); memset(¶ms, 0, sizeof(params)); Loading @@ -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, ¶ms.beacon_after); err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after); if (err) if (err) return err; return err; Loading Loading @@ -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, ¶ms.chandef); err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); if (err) if (err) return err; return err; Loading @@ -5706,13 +5719,18 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) return -EINVAL; return -EINVAL; err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef); /* DFS channels are only supported for AP/P2P GO ... for now. */ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef); if (err < 0) { if (err < 0) { return err; return err; } else if (err) { } else if (err) { radar_detect_width = BIT(params.chandef.width); radar_detect_width = BIT(params.chandef.width); params.radar_required = true; params.radar_required = true; } } } err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, params.chandef.chan, params.chandef.chan, Loading Loading @@ -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; Loading Loading
net/wireless/nl80211.c +34 −15 Original line number Original line Diff line number Diff line Loading @@ -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(¶ms, 0, sizeof(params)); memset(¶ms, 0, sizeof(params)); Loading @@ -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, ¶ms.beacon_after); err = nl80211_parse_beacon(info->attrs, ¶ms.beacon_after); if (err) if (err) return err; return err; Loading Loading @@ -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, ¶ms.chandef); err = nl80211_parse_chandef(rdev, info, ¶ms.chandef); if (err) if (err) return err; return err; Loading @@ -5706,13 +5719,18 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) return -EINVAL; return -EINVAL; err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef); /* DFS channels are only supported for AP/P2P GO ... for now. */ if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { err = cfg80211_chandef_dfs_required(wdev->wiphy, ¶ms.chandef); if (err < 0) { if (err < 0) { return err; return err; } else if (err) { } else if (err) { radar_detect_width = BIT(params.chandef.width); radar_detect_width = BIT(params.chandef.width); params.radar_required = true; params.radar_required = true; } } } err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, params.chandef.chan, params.chandef.chan, Loading Loading @@ -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; Loading