2014-01-15 12:17:05

by Janusz Dziedzic

[permalink] [raw]
Subject: [RFC 1/2] cfg80211/mac80211: DFS pass CAC time as a parameter

Send Channel Availability Check time as a parameter
of start_radar_detection() callback.
We could have different CAC time configuration for
Off-channel CAC and for weather channels.

Signed-off-by: Janusz Dziedzic <[email protected]>
---
Based on patches: Implement DFS CAC time as regulatory param

include/net/cfg80211.h | 3 ++-
net/mac80211/cfg.c | 8 ++++----
net/wireless/nl80211.c | 3 ++-
3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f756b94..71ca782 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2487,7 +2487,8 @@ struct cfg80211_ops {

int (*start_radar_detection)(struct wiphy *wiphy,
struct net_device *dev,
- struct cfg80211_chan_def *chandef);
+ struct cfg80211_chan_def *chandef,
+ u32 cac_time_ms);
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie);
int (*crit_proto_start)(struct wiphy *wiphy,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 09d2e58..5c2b69c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2899,11 +2899,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,

static int ieee80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
- struct cfg80211_chan_def *chandef)
+ struct cfg80211_chan_def *chandef,
+ u32 cac_time_ms)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
- unsigned long timeout;
int err;

mutex_lock(&local->mtx);
@@ -2922,9 +2922,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
if (err)
goto out_unlock;

- timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
ieee80211_queue_delayed_work(&sdata->local->hw,
- &sdata->dfs_cac_timer_work, timeout);
+ &sdata->dfs_cac_timer_work,
+ msecs_to_jiffies(cac_time_ms));

out_unlock:
mutex_unlock(&local->mtx);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 53b31f2..8bb2064 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5764,7 +5764,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (err)
return err;

- err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
+ err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef,
+ IEEE80211_DFS_MIN_CAC_TIME_MS);
if (!err) {
wdev->channel = chandef.chan;
wdev->cac_started = true;
--
1.7.9.5



2014-01-15 13:28:00

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC 2/2] cfg80211: DFS get CAC time from regulatory

On Wed, 2014-01-15 at 13:16 +0100, Janusz Dziedzic wrote:

> @@ -3211,6 +3212,7 @@ struct wireless_dev {
>
> bool cac_started;
> unsigned long cac_start_time;
> + unsigned int cac_time_ms;

Why would that need to be stored here? Isn't it just a pretty much local
parameter of the radar detection startup?

johannes


2014-01-15 20:08:54

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC 2/2] cfg80211: DFS get CAC time from regulatory

On Wed, 2014-01-15 at 17:10 +0100, Janusz Dziedzic wrote:
> On 15 January 2014 14:27, Johannes Berg <[email protected]> wrote:
> > On Wed, 2014-01-15 at 13:16 +0100, Janusz Dziedzic wrote:
> >
> >> @@ -3211,6 +3212,7 @@ struct wireless_dev {
> >>
> >> bool cac_started;
> >> unsigned long cac_start_time;
> >> + unsigned int cac_time_ms;
> >
> > Why would that need to be stored here? Isn't it just a pretty much local
> > parameter of the radar detection startup?
> >
> Because of this WARN_ON
>
> @@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev,
> switch (event) {
> case NL80211_RADAR_CAC_FINISHED:
> timeout = wdev->cac_start_time +
> - msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
> + msecs_to_jiffies(wdev->cac_time_ms);
> WARN_ON(!time_after_eq(jiffies, timeout));
>
> We have to know this if we need this warning.

Oh, ok. Is it guaranteed to not be overwritten in the meantime though? I
guess you can't start two CACs at the same time, so I guess that's ok.

johannes


2014-01-15 12:17:05

by Janusz Dziedzic

[permalink] [raw]
Subject: [RFC 2/2] cfg80211: DFS get CAC time from regulatory

Get CAC time from regulatory database.

Signed-off-by: Janusz Dziedzic <[email protected]>
---
include/net/cfg80211.h | 2 ++
net/wireless/chan.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
net/wireless/core.h | 3 +++
net/wireless/mlme.c | 2 +-
net/wireless/nl80211.c | 8 ++++++-
5 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 71ca782..8fff253ed 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3154,6 +3154,7 @@ struct cfg80211_cached_keys;
* @p2p_started: true if this is a P2P Device that has been started
* @cac_started: true if DFS channel availability check has been started
* @cac_start_time: timestamp (jiffies) when the dfs state was entered.
+ * @cac_time_ms: CAC time in ms
* @ps: powersave mode is enabled
* @ps_timeout: dynamic powersave timeout
* @ap_unexpected_nlportid: (private) netlink port ID of application
@@ -3211,6 +3212,7 @@ struct wireless_dev {

bool cac_started;
unsigned long cac_start_time;
+ unsigned int cac_time_ms;

#ifdef CONFIG_CFG80211_WEXT
/* wext data */
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 78559b5..ac35bf3 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -490,6 +490,65 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
return r;
}

+static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy,
+ u32 center_freq,
+ u32 bandwidth)
+{
+ struct ieee80211_channel *c;
+ u32 start_freq, end_freq, freq;
+ unsigned int dfs_cac_ms = 0;
+
+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
+
+ for (freq = start_freq; freq <= end_freq; freq += 20) {
+ c = ieee80211_get_channel(wiphy, freq);
+ if (!c)
+ return 0;
+
+ if (c->flag & IEEE80211_CHAN_DISABLED)
+ return 0;
+
+ if (!(c->flags & IEEE80211_CHAN_RADAR))
+ continue;
+
+ if (c->dfs_cac_ms > dfs_cac_ms)
+ dfs_cac_ms = c->dfs_cac_ms;
+ }
+
+ return dfs_cac_ms;
+}
+
+unsigned int
+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef)
+{
+ int width;
+ unsigned int t1 = 0, t2 = 0;
+
+ if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+ return 0;
+
+ width = cfg80211_chandef_get_width(chandef);
+ if (width < 0)
+ return 0;
+
+ t1 = cfg80211_get_chans_dfs_cac_time(wiphy,
+ chandef->center_freq1,
+ width);
+
+ if (!chandef->center_freq2)
+ return t1;
+
+ t2 = cfg80211_get_chans_dfs_cac_time(wiphy,
+ chandef->center_freq2,
+ width);
+
+ if (t2 > t1)
+ t1 = t2;
+
+ return t1;
+}

static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 37ec16d..aa77277 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -398,6 +398,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,

void cfg80211_dfs_channels_update_work(struct work_struct *work);

+unsigned int
+cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef);

static inline int
cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 52cca05..6601e81 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev,
switch (event) {
case NL80211_RADAR_CAC_FINISHED:
timeout = wdev->cac_start_time +
- msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
+ msecs_to_jiffies(wdev->cac_time_ms);
WARN_ON(!time_after_eq(jiffies, timeout));
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
break;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8bb2064..112f240 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5729,6 +5729,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region;
+ unsigned int cac_time_ms;
int err;

dfs_region = reg_get_dfs_region(wdev->wiphy);
@@ -5764,12 +5765,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (err)
return err;

+ cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
+ if (WARN_ON(!cac_time_ms))
+ cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef,
- IEEE80211_DFS_MIN_CAC_TIME_MS);
+ cac_time_ms);
if (!err) {
wdev->channel = chandef.chan;
wdev->cac_started = true;
wdev->cac_start_time = jiffies;
+ wdev->cac_time_ms = cac_time_ms;
}
return err;
}
--
1.7.9.5


2014-01-15 16:10:27

by Janusz Dziedzic

[permalink] [raw]
Subject: Re: [RFC 2/2] cfg80211: DFS get CAC time from regulatory

On 15 January 2014 14:27, Johannes Berg <[email protected]> wrote:
> On Wed, 2014-01-15 at 13:16 +0100, Janusz Dziedzic wrote:
>
>> @@ -3211,6 +3212,7 @@ struct wireless_dev {
>>
>> bool cac_started;
>> unsigned long cac_start_time;
>> + unsigned int cac_time_ms;
>
> Why would that need to be stored here? Isn't it just a pretty much local
> parameter of the radar detection startup?
>
Because of this WARN_ON

@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev,
switch (event) {
case NL80211_RADAR_CAC_FINISHED:
timeout = wdev->cac_start_time +
- msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
+ msecs_to_jiffies(wdev->cac_time_ms);
WARN_ON(!time_after_eq(jiffies, timeout));

We have to know this if we need this warning.

BR
Janusz