All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to scan command
@ 2012-06-21  9:33 Victor Goldenshtein
  2012-06-21  9:33 ` [PATCH v4 2/2] mac80211: handle channel times in " Victor Goldenshtein
  2012-06-21  9:45 ` [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to " Johannes Berg
  0 siblings, 2 replies; 3+ messages in thread
From: Victor Goldenshtein @ 2012-06-21  9:33 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, eliad

In order to give the usermode an ability to configure
scan channel times, and as it required for the beacon
reports in the 802.11k standard.

Add to the scan command min/max channel times. Add
min/max passive channel times, since a single scan
can contain both passive and active channels due to
regulatory constraints.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
---

v4:
	1. Use the scan time attributes only if NL80211_FEATURE_SCAN_TIMES is set.
	2. Use only a pair of both min and max scan times, otherwise return -EINVAL.
	3. Updated documentation for the scan time attributes. 


 include/linux/ieee80211.h |    9 +++++++++
 include/linux/nl80211.h   |   27 +++++++++++++++++++++++++++
 include/net/cfg80211.h    |   11 +++++++++++
 net/wireless/core.h       |    1 +
 net/wireless/nl80211.c    |   32 +++++++++++++++++++++++++++++++-
 net/wireless/scan.c       |   38 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 117 insertions(+), 1 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ce9af89..9522b7e 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1856,6 +1856,15 @@ static inline unsigned long ieee80211_tu_to_usec(unsigned long tu)
 }
 
 /**
+ * ieee80211_msec_to_tu - convert milliseconds to time units (TU)
+ * @msec: the milliseconds
+ */
+static inline unsigned long ieee80211_msec_to_tu(unsigned long msec)
+{
+	return msec * 1000 / 1024;
+}
+
+/**
  * ieee80211_check_tim - check if AID bit is set in TIM
  * @tim: the TIM IE
  * @tim_len: length of the TIM IE
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 970afdf..bee74ba 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1224,6 +1224,25 @@ enum nl80211_commands {
  * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
  *      or 0 to disable background scan.
  *
+ * @NL80211_ATTR_SCAN_MIN_CH_TIME: Minimum active scan time (in msec),
+ *	u32 attribute to setup minimum time to wait on each channel, if received
+ *	at least one probe_resp/beacon during this period will continue waiting
+ *	@NL80211_ATTR_SCAN_MAX_CH_TIME, otherwise will move to next channel.
+ * @NL80211_ATTR_SCAN_MAX_CH_TIME: Maximum active scan time (in msec),
+ *	u32 attribute to setup maximum time to wait on the channel.
+ * @NL80211_ATTR_SCAN_PSV_MIN_CH_TIME: Minimum passive scan time (in msec),
+ *	u32 attribute (similar to @NL80211_ATTR_SCAN_MIN_CH_TIME).
+ * @NL80211_ATTR_SCAN_PSV_MAX_CH_TIME: Maximum passive scan time (in msec),
+ *	u32 attribute (similar to @NL80211_ATTR_SCAN_MAX_CH_TIME).
+ *	Note:
+ *	 The above channel time attributes are for the %NL80211_CMD_TRIGGER_SCAN
+ *	 command. The attributes are optional, the driver will use default
+ *	 channel time values if the attributes are not in use. When using the
+ *	 attributes, the driver must support @NL80211_FEATURE_SCAN_TIMES and a
+ *	 pair of both min and max scan times must be set, moreover if one of the
+ *	 min times will be greater than max or set to zero, -EINVAL will be
+ *	 returned.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1475,6 +1494,11 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_BG_SCAN_PERIOD,
 
+	NL80211_ATTR_SCAN_MIN_CH_TIME,
+	NL80211_ATTR_SCAN_MAX_CH_TIME,
+	NL80211_ATTR_SCAN_PSV_MIN_CH_TIME,
+	NL80211_ATTR_SCAN_PSV_MAX_CH_TIME,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2875,11 +2899,14 @@ enum nl80211_ap_sme_features {
  * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
  * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up
  *	the connected inactive stations in AP mode.
+ * @NL80211_FEATURE_SCAN_TIMES: This driver supports min/max scan times
+ *	configuration for the %NL80211_CMD_TRIGGER_SCAN command.
  */
 enum nl80211_feature_flags {
 	NL80211_FEATURE_SK_TX_STATUS	= 1 << 0,
 	NL80211_FEATURE_HT_IBSS		= 1 << 1,
 	NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
+	NL80211_FEATURE_SCAN_TIMES	= 1 << 3,
 };
 
 /**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7319f25..4cc3a69 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -929,6 +929,12 @@ struct cfg80211_ssid {
  * @dev: the interface
  * @aborted: (internal) scan request was notified as aborted
  * @no_cck: used to send probe requests at non CCK rate in 2GHz band
+ * @min_ch_time: minimum time to wait on each channel for active scans
+ * @max_ch_time: maximum time to wait on each channel for active scans
+ * @min_passive_ch_time: minimum time to wait on each channel for passive scans
+ * @max_passive_ch_time: maximum time to wait on each channel for passive scans
+ *  Note: If the above channel times are not set, the default channel times
+ *  will be used. The channel times are in TUs.
  */
 struct cfg80211_scan_request {
 	struct cfg80211_ssid *ssids;
@@ -945,6 +951,11 @@ struct cfg80211_scan_request {
 	bool aborted;
 	bool no_cck;
 
+	u32 min_ch_time;
+	u32 max_ch_time;
+	u32 min_passive_ch_time;
+	u32 max_passive_ch_time;
+
 	/* keep last */
 	struct ieee80211_channel *channels[0];
 };
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 9348a47..95e2107 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -419,6 +419,7 @@ void cfg80211_sme_scan_done(struct net_device *dev);
 void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
 void cfg80211_sme_disassoc(struct net_device *dev,
 			   struct cfg80211_internal_bss *bss);
+int cfg80211_trigger_scan(struct cfg80211_registered_device *rdev);
 void __cfg80211_scan_done(struct work_struct *wk);
 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak);
 void __cfg80211_sched_scan_results(struct work_struct *wk);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7ae54b8..8dd8979 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -206,6 +206,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
 	[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
 	[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+	[NL80211_ATTR_SCAN_MIN_CH_TIME] = { .type = NLA_U32 },
+	[NL80211_ATTR_SCAN_MAX_CH_TIME] = { .type = NLA_U32 },
+	[NL80211_ATTR_SCAN_PSV_MIN_CH_TIME] = { .type = NLA_U32 },
+	[NL80211_ATTR_SCAN_PSV_MAX_CH_TIME] = { .type = NLA_U32 },
 };
 
 /* policy for the key attributes */
@@ -4020,6 +4024,32 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 		       request->ie_len);
 	}
 
+	if ((wiphy->features & NL80211_FEATURE_SCAN_TIMES) &&
+	    info->attrs[NL80211_ATTR_SCAN_MIN_CH_TIME] &&
+	    info->attrs[NL80211_ATTR_SCAN_MAX_CH_TIME]) {
+		request->min_ch_time =
+			nla_get_u32(info->attrs[NL80211_ATTR_SCAN_MIN_CH_TIME]);
+		request->max_ch_time =
+			nla_get_u32(info->attrs[NL80211_ATTR_SCAN_MAX_CH_TIME]);
+		if (!request->min_ch_time || !request->max_ch_time ||
+		    (request->min_ch_time > request->max_ch_time))
+			return -EINVAL;
+	}
+
+	if ((wiphy->features & NL80211_FEATURE_SCAN_TIMES) &&
+	    info->attrs[NL80211_ATTR_SCAN_PSV_MIN_CH_TIME] &&
+	    info->attrs[NL80211_ATTR_SCAN_PSV_MAX_CH_TIME]) {
+		request->min_passive_ch_time =
+		    nla_get_u32(info->attrs[NL80211_ATTR_SCAN_PSV_MIN_CH_TIME]);
+		request->max_passive_ch_time =
+		    nla_get_u32(info->attrs[NL80211_ATTR_SCAN_PSV_MAX_CH_TIME]);
+		if (!request->min_passive_ch_time ||
+		    !request->max_passive_ch_time ||
+		    (request->min_passive_ch_time >
+		     request->max_passive_ch_time))
+			return -EINVAL;
+	}
+
 	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
 		if (wiphy->bands[i])
 			request->rates[i] =
@@ -4051,7 +4081,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 	request->wiphy = &rdev->wiphy;
 
 	rdev->scan_req = request;
-	err = rdev->ops->scan(&rdev->wiphy, dev, request);
+	err = cfg80211_trigger_scan(rdev);
 
 	if (!err) {
 		nl80211_send_scan_start(rdev, dev);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index af2b1ca..4229efb 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -20,6 +20,30 @@
 
 #define IEEE80211_SCAN_RESULT_EXPIRE	(30 * HZ)
 
+#define IEEE80211_CH_TIME_MSEC		30
+#define IEEE80211_PSV_CH_TIME_MSEC	125
+
+int cfg80211_trigger_scan(struct cfg80211_registered_device *rdev)
+{
+	struct cfg80211_scan_request *request;
+
+	ASSERT_RDEV_LOCK(rdev);
+
+	request = rdev->scan_req;
+
+	if (!request)
+		return -EINVAL;
+
+	if (!request->min_passive_ch_time)
+		request->min_passive_ch_time =
+			ieee80211_msec_to_tu(IEEE80211_PSV_CH_TIME_MSEC);
+	if (!request->min_ch_time)
+		request->min_ch_time =
+			ieee80211_msec_to_tu(IEEE80211_CH_TIME_MSEC);
+
+	return rdev->ops->scan(&rdev->wiphy, request->dev, request);
+}
+
 void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
 {
 	struct cfg80211_scan_request *request;
@@ -1023,6 +1047,20 @@ int cfg80211_wext_siwscan(struct net_device *dev,
 		if (wiphy->bands[i])
 			creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
 
+	if (wreq->min_channel_time) {
+		creq->min_ch_time = wreq->min_channel_time;
+		if (wreq->scan_type == IW_SCAN_TYPE_ACTIVE)
+			creq->min_passive_ch_time =
+			       ieee80211_msec_to_tu(IEEE80211_PSV_CH_TIME_MSEC);
+		else
+			creq->min_passive_ch_time = wreq->min_channel_time;
+	} else {
+		creq->min_ch_time =
+			ieee80211_msec_to_tu(IEEE80211_CH_TIME_MSEC);
+		creq->min_passive_ch_time =
+			ieee80211_msec_to_tu(IEEE80211_PSV_CH_TIME_MSEC);
+	}
+
 	rdev->scan_req = creq;
 	err = rdev->ops->scan(wiphy, dev, creq);
 	if (err) {
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v4 2/2] mac80211: handle channel times in scan command
  2012-06-21  9:33 [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to scan command Victor Goldenshtein
@ 2012-06-21  9:33 ` Victor Goldenshtein
  2012-06-21  9:45 ` [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to " Johannes Berg
  1 sibling, 0 replies; 3+ messages in thread
From: Victor Goldenshtein @ 2012-06-21  9:33 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, eliad

Use the user scan times if those were set, otherwise
use the default values.

This patch handles both hw_scan and non-offload scan.

Signed-off-by: Victor Goldenshtein <victorg@ti.com>
---
 net/mac80211/scan.c |   31 ++++++++++++++++++++-----------
 1 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 379f178..5d2898a 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -26,8 +26,6 @@
 #include "mesh.h"
 
 #define IEEE80211_PROBE_DELAY (HZ / 33)
-#define IEEE80211_CHANNEL_TIME (HZ / 33)
-#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8)
 
 static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
 {
@@ -421,7 +419,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
 	 * After sending probe requests, wait for probe responses
 	 * on the channel.
 	 */
-	*next_delay = IEEE80211_CHANNEL_TIME;
+	*next_delay = TU_TO_JIFFIES(local->scan_req->min_ch_time);
 	local->next_scan_state = SCAN_DECISION;
 }
 
@@ -456,6 +454,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 
 		local->hw_scan_req->ssids = req->ssids;
 		local->hw_scan_req->n_ssids = req->n_ssids;
+		local->hw_scan_req->max_ch_time = req->max_ch_time;
+		local->hw_scan_req->min_ch_time = req->min_ch_time;
+		local->hw_scan_req->max_passive_ch_time =
+			req->max_passive_ch_time;
+		local->hw_scan_req->min_passive_ch_time =
+			req->min_passive_ch_time;
+
 		ies = (u8 *)local->hw_scan_req +
 			sizeof(*local->hw_scan_req) +
 			req->n_channels * sizeof(req->channels[0]);
@@ -502,10 +507,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 		if ((req->channels[0]->flags &
 		     IEEE80211_CHAN_PASSIVE_SCAN) ||
 		    !local->scan_req->n_ssids) {
-			next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+			next_delay = TU_TO_JIFFIES(req->min_passive_ch_time);
 		} else {
 			ieee80211_scan_state_send_probe(local, &next_delay);
-			next_delay = IEEE80211_CHANNEL_TIME;
+			next_delay = TU_TO_JIFFIES(req->min_ch_time);
 		}
 
 		/* Now, just wait a bit and we are all done! */
@@ -540,15 +545,16 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 }
 
 static unsigned long
-ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
+ieee80211_scan_get_channel_time(struct cfg80211_scan_request *scan_req,
+				struct ieee80211_channel *chan)
 {
 	/*
 	 * TODO: channel switching also consumes quite some time,
 	 * add that delay as well to get a better estimation
 	 */
 	if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-		return IEEE80211_PASSIVE_CHANNEL_TIME;
-	return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
+		return TU_TO_JIFFIES(scan_req->min_passive_ch_time);
+	return IEEE80211_PROBE_DELAY + TU_TO_JIFFIES(scan_req->min_ch_time);
 }
 
 static void ieee80211_scan_state_decision(struct ieee80211_local *local,
@@ -609,12 +615,14 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
 	 */
 
 	bad_latency = time_after(jiffies +
-			ieee80211_scan_get_channel_time(next_chan),
+			ieee80211_scan_get_channel_time(local->scan_req,
+							next_chan),
 			local->leave_oper_channel_time +
 			usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
 
 	listen_int_exceeded = time_after(jiffies +
-			ieee80211_scan_get_channel_time(next_chan),
+			ieee80211_scan_get_channel_time(local->scan_req,
+							next_chan),
 			local->leave_oper_channel_time +
 			usecs_to_jiffies(min_beacon_int * 1024) *
 			local->hw.conf.listen_interval);
@@ -662,7 +670,8 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
 	 */
 	if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
 	    !local->scan_req->n_ssids) {
-		*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+		*next_delay =
+			TU_TO_JIFFIES(local->scan_req->min_passive_ch_time);
 		local->next_scan_state = SCAN_DECISION;
 		return;
 	}
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to scan command
  2012-06-21  9:33 [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to scan command Victor Goldenshtein
  2012-06-21  9:33 ` [PATCH v4 2/2] mac80211: handle channel times in " Victor Goldenshtein
@ 2012-06-21  9:45 ` Johannes Berg
  1 sibling, 0 replies; 3+ messages in thread
From: Johannes Berg @ 2012-06-21  9:45 UTC (permalink / raw)
  To: Victor Goldenshtein; +Cc: linux-wireless, eliad

On Thu, 2012-06-21 at 12:33 +0300, Victor Goldenshtein wrote:

> + * @min_ch_time: minimum time to wait on each channel for active scans
> + * @max_ch_time: maximum time to wait on each channel for active scans
> + * @min_passive_ch_time: minimum time to wait on each channel for passive scans
> + * @max_passive_ch_time: maximum time to wait on each channel for passive scans
> + *  Note: If the above channel times are not set, the default channel times
> + *  will be used. The channel times are in TUs.

That note seems to be a bit unclear.

It's also starting to dawn on me that you actually wanted cases where
you only set the minimum time? Like in wireless extensions? You're also
only ever setting the minimum time defaults if none were given, this is
in cfg80211_trigger_scan().

So maybe you need to clarify the semantics? Clearly, I haven't
understood this yet from the documentation.

Otherwise it seems to me that there should be min/max always set, even
if mac80211 only ever uses min?

johannes


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-06-21  9:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-21  9:33 [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to scan command Victor Goldenshtein
2012-06-21  9:33 ` [PATCH v4 2/2] mac80211: handle channel times in " Victor Goldenshtein
2012-06-21  9:45 ` [PATCH v4 1/2] nl80211/cfg80211: add scan channel times to " Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.