]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
cfg80211: DFS get CAC time from regulatory database
authorJanusz Dziedzic <janusz.dziedzic@tieto.com>
Fri, 21 Feb 2014 18:46:13 +0000 (19:46 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 25 Feb 2014 16:32:54 +0000 (17:32 +0100)
Send Channel Availability Check time as a parameter
of start_radar_detection() callback.
Get CAC time from regulatory database.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/mac80211/cfg.c
net/wireless/chan.c
net/wireless/core.h
net/wireless/mlme.c
net/wireless/nl80211.c

index bfa9a0c7b2d7a6fbf09e474d6c639881c7b260f9..ff3af16eba21e92f06999458b50a7e1abb43867a 100644 (file)
@@ -2505,7 +2505,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,
@@ -3182,6 +3183,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
@@ -3237,6 +3239,7 @@ struct wireless_dev {
 
        bool cac_started;
        unsigned long cac_start_time;
+       unsigned int cac_time_ms;
 
 #ifdef CONFIG_CFG80211_WEXT
        /* wext data */
index 1acb29109b45dfc9d76d83b0506d8ed47932b10d..80534f524fd6551ae0e6aa80e6753f18debad657 100644 (file)
@@ -2914,11 +2914,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);
@@ -2937,9 +2937,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);
index 5946450c540676b75b726e20b016395ae08e6b7c..8659d5cee2a6ba01b4f17830608795768c92d107 100644 (file)
@@ -490,6 +490,62 @@ 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->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,
                                        u32 center_freq, u32 bandwidth,
index 40683004d52338fa8830a11cd38fdd42c74c156a..64fde38c1a7e2019809018efdac31b3dc2ad7f66 100644 (file)
@@ -402,6 +402,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,
index d47c9d127b1eef3bef4e8d00f65dcf1392d70c2d..c52ff59a3e96d7cabb892bff220b86c580069a43 100644 (file)
@@ -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;
index 9f7ebf94a0506016cbed541defeb16b5c379a615..8fa02a3fa7f78a53a1331e2d1dde3fa64ed86337 100644 (file)
@@ -5779,6 +5779,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);
@@ -5814,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
        if (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) {
                wdev->chandef = chandef;
                wdev->cac_started = true;
                wdev->cac_start_time = jiffies;
+               wdev->cac_time_ms = cac_time_ms;
        }
        return err;
 }