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 <[email protected]>
> ---
> 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?
> + 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 :)
> #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".
> +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...;
> +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?
johannes