On Thursday 26 January 2017 03:11 PM, Johannes Berg wrote: > On Wed, 2017-01-25 at 17:01 +0530, Vasanthakumar Thiagarajan wrote: >> Sharing DFS channel state across multiple wiphys (radios) could >> be useful with multiple radios on the system. When one radio >> completes CAC and marks the channel available another radio >> can use this information and start beaconing without really doing >> CAC. >> >> Whenever there is a state change in DFS channel associated to >> a particular wiphy the the same state change is propagated to >> other wiphys having the same DFS reg domain configuration. >> Also when a new wiphy is created the DFS channel state of >> other existing wiphys of same DFS domain is copied. >> >> Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@xxxxxxxxxxxxxxxx> >> --- >> net/wireless/chan.c | 24 +++++++++-- >> net/wireless/core.c | 37 +++++++++++++++++ >> net/wireless/core.h | 6 +++ >> net/wireless/mlme.c | 11 +++++- >> net/wireless/reg.c | 112 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++ >> net/wireless/reg.h | 22 +++++++++++ >> 6 files changed, 207 insertions(+), 5 deletions(-) >> >> diff --git a/net/wireless/chan.c b/net/wireless/chan.c >> index 090309a..40f1097 100644 >> --- a/net/wireless/chan.c >> +++ b/net/wireless/chan.c >> @@ -532,21 +532,37 @@ bool cfg80211_beaconing_iface_active(struct >> wireless_dev *wdev) >> return active; >> } >> >> +static bool cfg80211_5ghz_is_wiphy_oper_chan(struct wiphy *wiphy, >> + struct >> ieee80211_channel *chan) > > again, nothing really 5 GHz specific here, afaict? Sure. > >> + struct wireless_dev *wdev; >> + >> + list_for_each_entry(wdev, &wiphy->wdev_list, list) { >> + if (!cfg80211_beaconing_iface_active(wdev)) >> + continue; >> + >> + if (cfg80211_5ghz_sub_chan(&wdev->chandef, chan)) >> + return true; >> + } >> + >> + return false; >> +} >> + >> bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy, >> struct ieee80211_channel >> *chan) >> { >> - struct wireless_dev *wdev; >> + struct cfg80211_registered_device *rdev; >> >> ASSERT_RTNL(); >> >> if (!(chan->flags & IEEE80211_CHAN_RADAR)) >> return false; >> >> - list_for_each_entry(wdev, &wiphy->wdev_list, list) { >> - if (!cfg80211_beaconing_iface_active(wdev)) >> + list_for_each_entry(rdev, &cfg80211_rdev_list, list) { >> + if (!reg_dfs_domain_same(wiphy, &rdev->wiphy)) >> continue; >> >> - if (cfg80211_5ghz_sub_chan(&wdev->chandef, chan)) >> + if (cfg80211_5ghz_is_wiphy_oper_chan(&rdev->wiphy, >> chan)) >> return true; >> } >> >> diff --git a/net/wireless/core.c b/net/wireless/core.c >> index 903fc419..c3fe44b 100644 >> --- a/net/wireless/core.c >> +++ b/net/wireless/core.c >> @@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct >> work_struct *work) >> rtnl_unlock(); >> } >> >> +static void cfg80211_propagate_radar_detect_wk(struct work_struct >> *work) >> +{ >> + struct cfg80211_registered_device *rdev; >> + >> + rdev = container_of(work, struct cfg80211_registered_device, >> + porpagate_radar_detect_wk); >> + >> + rtnl_lock(); >> + >> + regulatory_propagate_dfs_state(&rdev->wiphy, &rdev- >>> radar_chandef, >> + NL80211_DFS_UNAVAILABLE, >> + NL80211_RADAR_DETECTED); >> + >> + rtnl_unlock(); >> +} >> + >> +static void cfg80211_propagate_cac_done_wk(struct work_struct *work) >> +{ >> + struct cfg80211_registered_device *rdev; >> + >> + rdev = container_of(work, struct cfg80211_registered_device, >> + propagate_cac_done_wk); >> + >> + rtnl_lock(); >> + >> + regulatory_propagate_dfs_state(&rdev->wiphy, &rdev- >>> cac_done_chandef, >> + NL80211_DFS_AVAILABLE, >> + NL80211_RADAR_CAC_FINISHED); >> + >> + rtnl_unlock(); >> +} >> + >> /* exported functions */ >> >> struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int >> sizeof_priv, >> @@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct >> cfg80211_ops *ops, int sizeof_priv, >> spin_lock_init(&rdev->destroy_list_lock); >> INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk); >> INIT_WORK(&rdev->sched_scan_stop_wk, >> cfg80211_sched_scan_stop_wk); >> + INIT_WORK(&rdev->porpagate_radar_detect_wk, >> + cfg80211_propagate_radar_detect_wk); >> + INIT_WORK(&rdev->propagate_cac_done_wk, >> cfg80211_propagate_cac_done_wk); >> >> #ifdef CONFIG_CFG80211_DEFAULT_PS >> rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; >> @@ -914,6 +949,8 @@ void wiphy_unregister(struct wiphy *wiphy) >> flush_work(&rdev->destroy_work); >> flush_work(&rdev->sched_scan_stop_wk); >> flush_work(&rdev->mlme_unreg_wk); >> + flush_work(&rdev->porpagate_radar_detect_wk); > > typo: propagate. > >> + flush_work(&rdev->propagate_cac_done_wk); > > You got it right here :) Thanks, some search replace issue. > >> #ifdef CONFIG_PM >> if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) >> diff --git a/net/wireless/core.h b/net/wireless/core.h >> index 327fe95..607c8be 100644 >> --- a/net/wireless/core.h >> +++ b/net/wireless/core.h >> @@ -97,6 +97,12 @@ struct cfg80211_registered_device { >> >> struct work_struct sched_scan_stop_wk; >> >> + struct cfg80211_chan_def radar_chandef; >> + struct work_struct porpagate_radar_detect_wk; > > Since it compiled, the typo exists everywhere this is referenced. > >> +++ b/net/wireless/mlme.c >> @@ -18,7 +18,6 @@ >> #include "nl80211.h" >> #include "rdev-ops.h" >> >> - >> void cfg80211_rx_assoc_resp(struct net_device *dev, struct >> cfg80211_bss *bss, > > please don't make unrelated "cleanups". Oops, sorry. > >> +bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2) >> +{ >> + const struct ieee80211_regdomain *wiphy1_regd = NULL; >> + const struct ieee80211_regdomain *wiphy2_regd = NULL; >> + const struct ieee80211_regdomain *cfg80211_regd = NULL; >> + bool dfs_domain_same = false; > > You can remove that initializer, > >> + rcu_read_lock(); >> + >> + cfg80211_regd = rcu_dereference(cfg80211_regdomain); >> + wiphy1_regd = rcu_dereference(wiphy1->regd); >> + if (!wiphy1_regd) >> + wiphy1_regd = cfg80211_regd; >> + >> + wiphy2_regd = rcu_dereference(wiphy2->regd); >> + if (!wiphy2_regd) >> + wiphy2_regd = cfg80211_regd; >> + >> + if (wiphy1_regd->dfs_region == wiphy2_regd->dfs_region) >> + dfs_domain_same = true; > > and just assign > dfs_domain_same = wiphy1... == wiphy2...; Ok. > >> +static void wiphy_share_dfs_chan_state(struct wiphy *dst_wiphy, >> + struct wiphy *src_wiphy) >> +{ >> + struct ieee80211_supported_band *src_sband, *dst_sband; >> + int i, j; >> + >> + dst_sband = dst_wiphy->bands[NL80211_BAND_5GHZ]; >> + src_sband = src_wiphy->bands[NL80211_BAND_5GHZ]; >> + if (!dst_sband || !src_sband) >> + return; > > Why make this 5 GHz specific? Perhaps some kind of radar stuff will > exist in future bands too. It shouldn't really cost much to iterate all > the bands, I think? Going over all the bands should not be an issue, i'll make the change. Thanks, Vasanth