Explorar el Código

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: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Janusz Dziedzic hace 11 años
padre
commit
31559f35c5
Se han modificado 6 ficheros con 76 adiciones y 7 borrados
  1. 4 1
      include/net/cfg80211.h
  2. 4 4
      net/mac80211/cfg.c
  3. 56 0
      net/wireless/chan.c
  4. 3 0
      net/wireless/core.h
  5. 1 1
      net/wireless/mlme.c
  6. 8 1
      net/wireless/nl80211.c

+ 4 - 1
include/net/cfg80211.h

@@ -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;
  * @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 {
 
 
 	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 */

+ 4 - 4
net/mac80211/cfg.c

@@ -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,
 	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);

+ 56 - 0
net/wireless/chan.c

@@ -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,

+ 3 - 0
net/wireless/core.h

@@ -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,

+ 1 - 1
net/wireless/mlme.c

@@ -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;

+ 8 - 1
net/wireless/nl80211.c

@@ -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,
 	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;
 }
 }