Re: [PATCH V2 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain

2017-04-18 Thread Vasanthakumar Thiagarajan
On Tuesday 18 April 2017 04:20 PM, Johannes Berg wrote:
>
>> +void regulatory_propagate_dfs_state(struct wiphy *wiphy,
>> +struct cfg80211_chan_def
>> *chandef,
>> +enum nl80211_dfs_state
>> dfs_state,
>> +enum nl80211_radar_event event)
>> +{
>> +struct cfg80211_registered_device *rdev;
>> +
>> +ASSERT_RTNL();
>> +
>> +if (WARN_ON(!cfg80211_chandef_valid(chandef)))
>> +return;
>> +
>> +if (WARN_ON(!(chandef->chan->flags & IEEE80211_CHAN_RADAR)))
>> +return;
>
>
> This warn on reliably triggers for me when I run the "ap_vht160" hwsim
> test from wpa_supplicant.
>
> I think there might be some confusion about this when parts of the 160
> MHz channel require radar and parts don't? But I haven't looked into
> this at all.

Correct, when some part of a bigger bandwidth channel falls in DFS channel range
channel definition of that channel's center freq is may not be a radar channel 
and
bailing out based on the channel flag there is not right.

Sorry for the bug and thanks for reporting it.

>
> Please send me a fix ASAP so Jouni doesn't shout at me for test
> failures :)

Sure.

Vasanth

Re: [PATCH V2 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain

2017-04-18 Thread Johannes Berg

> +void regulatory_propagate_dfs_state(struct wiphy *wiphy,
> + struct cfg80211_chan_def
> *chandef,
> + enum nl80211_dfs_state
> dfs_state,
> + enum nl80211_radar_event event)
> +{
> + struct cfg80211_registered_device *rdev;
> +
> + ASSERT_RTNL();
> +
> + if (WARN_ON(!cfg80211_chandef_valid(chandef)))
> + return;
> +
> + if (WARN_ON(!(chandef->chan->flags & IEEE80211_CHAN_RADAR)))
> + return;


This warn on reliably triggers for me when I run the "ap_vht160" hwsim
test from wpa_supplicant.

I think there might be some confusion about this when parts of the 160
MHz channel require radar and parts don't? But I haven't looked into
this at all.

Please send me a fix ASAP so Jouni doesn't shout at me for test
failures :)

johannes


[PATCH V2 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain

2017-02-27 Thread Vasanthakumar Thiagarajan
Sharing DFS channel state across multiple wiphys (radios) could
be useful with multiple radios on the system. When one radio
completes CAC and markes 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 
---

V2:

- Add a sanity check on the chandef in regulatory_propagate_dfs_state()
  to make sure the channel is valid before proceeding with dfs state
  propagation for the channel.

 net/wireless/chan.c |  30 ++---
 net/wireless/core.c |  37 
 net/wireless/core.h |   6 +++
 net/wireless/mlme.c |  10 +
 net/wireless/reg.c  | 120 
 net/wireless/reg.h  |  22 ++
 6 files changed, 218 insertions(+), 7 deletions(-)

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 099f13c..b8aa5a7 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -531,16 +531,11 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev 
*wdev)
return active;
 }
 
-bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
- struct ieee80211_channel *chan)
+static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy,
+   struct ieee80211_channel *chan)
 {
struct wireless_dev *wdev;
 
-   ASSERT_RTNL();
-
-   if (!(chan->flags & IEEE80211_CHAN_RADAR))
-   return false;
-
list_for_each_entry(wdev, >wdev_list, list) {
wdev_lock(wdev);
if (!cfg80211_beaconing_iface_active(wdev)) {
@@ -558,6 +553,27 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
return false;
 }
 
+bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
+ struct ieee80211_channel *chan)
+{
+   struct cfg80211_registered_device *rdev;
+
+   ASSERT_RTNL();
+
+   if (!(chan->flags & IEEE80211_CHAN_RADAR))
+   return false;
+
+   list_for_each_entry(rdev, _rdev_list, list) {
+   if (!reg_dfs_domain_same(wiphy, >wiphy))
+   continue;
+
+   if (cfg80211_is_wiphy_oper_chan(>wiphy, chan))
+   return true;
+   }
+
+   return false;
+}
+
 static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
 u32 center_freq,
 u32 bandwidth)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 04143df..a5630e9 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,
+   propagate_radar_detect_wk);
+
+   rtnl_lock();
+
+   regulatory_propagate_dfs_state(>wiphy, >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(>wiphy, >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(>destroy_list_lock);
INIT_WORK(>destroy_work, cfg80211_destroy_iface_wk);
INIT_WORK(>sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
+   INIT_WORK(>propagate_radar_detect_wk,
+ cfg80211_propagate_radar_detect_wk);
+   INIT_WORK(>propagate_cac_done_wk, cfg80211_propagate_cac_done_wk);
 
 #ifdef CONFIG_CFG80211_DEFAULT_PS
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -915,6 +950,8 @@ void wiphy_unregister(struct wiphy *wiphy)
flush_work(>destroy_work);
flush_work(>sched_scan_stop_wk);
flush_work(>mlme_unreg_wk);
+   flush_work(>propagate_radar_detect_wk);
+   flush_work(>propagate_cac_done_wk);
 
 #ifdef CONFIG_PM