Introduce NL80211_CMD_OFFCHAN_CHAIN command in order to configure offchannel chain if supported by the underlay driver. Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> --- include/uapi/linux/nl80211.h | 6 ++++++ net/wireless/nl80211.c | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c2efea98e060..51ddd6f198d4 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1200,6 +1200,10 @@ * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change * has completed * + * @NL80211_CMD_OFFCHAN_CHAIN: Configure dedicated chain available for radar + * detection on some hw. The driver is supposed to implement CAC + * management in sw or fw. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1440,6 +1444,8 @@ enum nl80211_commands { NL80211_CMD_COLOR_CHANGE_ABORTED, NL80211_CMD_COLOR_CHANGE_COMPLETED, + NL80211_CMD_OFFCHAN_CHAIN, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index bf7cd4752547..7c0902d35635 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9064,6 +9064,39 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb, return cfg80211_stop_sched_scan_req(rdev, req, false); } +static int nl80211_set_offchan_chain(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + enum nl80211_dfs_regions dfs_region; + struct wiphy *wiphy = &rdev->wiphy; + struct cfg80211_chan_def chandef; + int err; + + dfs_region = reg_get_dfs_region(wiphy); + if (dfs_region == NL80211_DFS_UNSET) + return -EINVAL; + + err = nl80211_parse_chandef(rdev, info, &chandef); + if (err) + return err; + + err = cfg80211_chandef_dfs_required(wiphy, &chandef, NL80211_IFTYPE_AP); + if (err < 0) + return err; + + if (!err) + return -EINVAL; + + if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) + return -EINVAL; + + if (!rdev->ops->set_offchan_chain) + return -EOPNOTSUPP; + + return rdev_set_offchan_chain(rdev, &chandef); +} + static int nl80211_start_radar_detection(struct sk_buff *skb, struct genl_info *info) { @@ -15907,6 +15940,14 @@ static const struct genl_small_ops nl80211_small_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | NL80211_FLAG_NEED_RTNL, }, + { + .cmd = NL80211_CMD_OFFCHAN_CHAIN, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = nl80211_set_offchan_chain, + .flags = GENL_UNS_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_WIPHY | + NL80211_FLAG_NEED_RTNL, + }, }; static struct genl_family nl80211_fam __ro_after_init = { -- 2.31.1