mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
nl80211: Add support to notify radar event info received from STA
Currently radar detection and corresponding channel switch is handled at the AP device. STA ignores these detected radar events since the radar signal can be seen mostly by the AP as well. But in scenarios where a radar signal is seen only at STA, notifying this event to the AP which can trigger a channel switch can be useful. Stations can report such radar events autonomously through Spectrum management (Measurement Report) action frame to its AP. The userspace on processing the report can notify the kernel with the use of the added NL80211_CMD_NOTIFY_RADAR to indicate the detected event and inturn adding the reported channel to NOL. Signed-off-by: Sriram R <srirrama@codeaurora.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
344f8e0093
commit
30c63115e2
@ -1060,6 +1060,11 @@
|
||||
* the measurement completed, using the measurement cookie
|
||||
* (%NL80211_ATTR_COOKIE).
|
||||
*
|
||||
* @NL80211_CMD_NOTIFY_RADAR: Notify the kernel that a radar signal was
|
||||
* detected and reported by a neighboring device on the channel
|
||||
* indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes
|
||||
* determining the width and type.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -1278,6 +1283,8 @@ enum nl80211_commands {
|
||||
NL80211_CMD_PEER_MEASUREMENT_RESULT,
|
||||
NL80211_CMD_PEER_MEASUREMENT_COMPLETE,
|
||||
|
||||
NL80211_CMD_NOTIFY_RADAR,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
|
@ -7990,6 +7990,60 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_notify_radar_detection(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct wiphy *wiphy = wdev->wiphy;
|
||||
struct cfg80211_chan_def chandef;
|
||||
enum nl80211_dfs_regions dfs_region;
|
||||
int err;
|
||||
|
||||
dfs_region = reg_get_dfs_region(wiphy);
|
||||
if (dfs_region == NL80211_DFS_UNSET) {
|
||||
GENL_SET_ERR_MSG(info,
|
||||
"DFS Region is not set. Unexpected Radar indication");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nl80211_parse_chandef(rdev, info, &chandef);
|
||||
if (err) {
|
||||
GENL_SET_ERR_MSG(info, "Unable to extract chandef info");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
|
||||
if (err < 0) {
|
||||
GENL_SET_ERR_MSG(info, "chandef is invalid");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
GENL_SET_ERR_MSG(info,
|
||||
"Unexpected Radar indication for chandef/iftype");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Do not process this notification if radar is already detected
|
||||
* by kernel on this channel, and return success.
|
||||
*/
|
||||
if (chandef.chan->dfs_state == NL80211_DFS_UNAVAILABLE)
|
||||
return 0;
|
||||
|
||||
cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_UNAVAILABLE);
|
||||
|
||||
cfg80211_sched_dfs_chan_update(rdev);
|
||||
|
||||
memcpy(&rdev->radar_chandef, &chandef, sizeof(chandef));
|
||||
|
||||
/* Propagate this notification to other radios as well */
|
||||
queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
@ -14074,6 +14128,14 @@ static const struct genl_ops nl80211_ops[] = {
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_NOTIFY_RADAR,
|
||||
.doit = nl80211_notify_radar_detection,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_family nl80211_fam __ro_after_init = {
|
||||
|
Loading…
Reference in New Issue
Block a user