Commit 31559f35 authored by Janusz Dziedzic's avatar Janusz Dziedzic Committed by Johannes Berg

cfg80211: DFS get CAC time from regulatory database

Send Channel Availability Check time as a parameter
of start_radar_detection() callback.
Get CAC time from regulatory database.
Signed-off-by: default avatarJanusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 089027e5
...@@ -2505,7 +2505,8 @@ struct cfg80211_ops { ...@@ -2505,7 +2505,8 @@ struct cfg80211_ops {
int (*start_radar_detection)(struct wiphy *wiphy, int (*start_radar_detection)(struct wiphy *wiphy,
struct net_device *dev, 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, int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie); struct cfg80211_update_ft_ies_params *ftie);
int (*crit_proto_start)(struct wiphy *wiphy, int (*crit_proto_start)(struct wiphy *wiphy,
...@@ -3182,6 +3183,7 @@ struct cfg80211_cached_keys; ...@@ -3182,6 +3183,7 @@ struct cfg80211_cached_keys;
* @p2p_started: true if this is a P2P Device that has been started * @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_started: true if DFS channel availability check has been started
* @cac_start_time: timestamp (jiffies) when the dfs state was entered. * @cac_start_time: timestamp (jiffies) when the dfs state was entered.
* @cac_time_ms: CAC time in ms
* @ps: powersave mode is enabled * @ps: powersave mode is enabled
* @ps_timeout: dynamic powersave timeout * @ps_timeout: dynamic powersave timeout
* @ap_unexpected_nlportid: (private) netlink port ID of application * @ap_unexpected_nlportid: (private) netlink port ID of application
...@@ -3237,6 +3239,7 @@ struct wireless_dev { ...@@ -3237,6 +3239,7 @@ struct wireless_dev {
bool cac_started; bool cac_started;
unsigned long cac_start_time; unsigned long cac_start_time;
unsigned int cac_time_ms;
#ifdef CONFIG_CFG80211_WEXT #ifdef CONFIG_CFG80211_WEXT
/* wext data */ /* wext data */
......
...@@ -2914,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, ...@@ -2914,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
static int ieee80211_start_radar_detection(struct wiphy *wiphy, static int ieee80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev, 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_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
unsigned long timeout;
int err; int err;
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
...@@ -2937,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, ...@@ -2937,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
if (err) if (err)
goto out_unlock; goto out_unlock;
timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
ieee80211_queue_delayed_work(&sdata->local->hw, 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: out_unlock:
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
......
...@@ -490,6 +490,62 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, ...@@ -490,6 +490,62 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy,
return r; 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->flags & 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);
return max(t1, t2);
}
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth, u32 center_freq, u32 bandwidth,
......
...@@ -402,6 +402,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, ...@@ -402,6 +402,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
void cfg80211_dfs_channels_update_work(struct work_struct *work); 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 static inline int
cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
......
...@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev, ...@@ -778,7 +778,7 @@ void cfg80211_cac_event(struct net_device *netdev,
switch (event) { switch (event) {
case NL80211_RADAR_CAC_FINISHED: case NL80211_RADAR_CAC_FINISHED:
timeout = wdev->cac_start_time + 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)); WARN_ON(!time_after_eq(jiffies, timeout));
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
break; break;
......
...@@ -5779,6 +5779,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, ...@@ -5779,6 +5779,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region; enum nl80211_dfs_regions dfs_region;
unsigned int cac_time_ms;
int err; int err;
dfs_region = reg_get_dfs_region(wdev->wiphy); dfs_region = reg_get_dfs_region(wdev->wiphy);
...@@ -5814,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, ...@@ -5814,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (err) if (err)
return err; return err;
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); 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,
cac_time_ms);
if (!err) { if (!err) {
wdev->chandef = chandef; wdev->chandef = chandef;
wdev->cac_started = true; wdev->cac_started = true;
wdev->cac_start_time = jiffies; wdev->cac_start_time = jiffies;
wdev->cac_time_ms = cac_time_ms;
} }
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment