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

Reply via email to