v6: move enum nl80211_scan_flags placeholder from 1/6 to 3/6,
and merge with new flag in 3/6 to avoid breaking build in 1/6.
This makes patch series friendly to bisect. (Fengguang Wu)
Other 4 patches are not changed.
---
Amitkumar Karwar (1):
cfg80211: code rearrangement to avoid forward declarations
Johannes Berg (1):
wireless: use OR operation to set wiphy features
Sam Leffler (4):
{nl,cfg}80211: add a flags word to scan requests
cfg80211: add scan flag to indicate its priority
cfg80211: add support for flushing old scan results
mac80211: add support for tx to abort low priority scan requests
drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +-
drivers/net/wireless/mwifiex/cfg80211.c | 4 +-
include/net/cfg80211.h | 7 ++
include/uapi/linux/nl80211.h | 23 +++++
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/main.c | 9 ++-
net/mac80211/scan.c | 21 ++++-
net/wireless/core.c | 2 +
net/wireless/nl80211.c | 30 +++++++
net/wireless/scan.c | 120 +++++++++++++++++-----------
net/wireless/sme.c | 1 +
11 files changed, 164 insertions(+), 57 deletions(-)
From: Johannes Berg <[email protected]>
The next patch will introduce a flag that is set
by default in cfg80211 so drivers and mac80211
need to use |= to set features they have so that
they don't clear the already-set feature.
We could set the flag in wiphy_register() instead
of wiphy_new() to avoid this patch, but then the
drivers couldn't *unset* flags they don't want to
use even though the implementation is generic.
Signed-off-by: Johannes Berg <[email protected]>
---
drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +-
drivers/net/wireless/mwifiex/cfg80211.c | 4 ++--
net/mac80211/main.c | 6 +++---
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index ad252d0..2770899 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3651,7 +3651,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
ar->fw_capabilities))
- ar->wiphy->features = NL80211_FEATURE_INACTIVITY_TIMER;
+ ar->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
ar->wiphy->probe_resp_offload =
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 0679458..38a5871 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2250,8 +2250,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
- wiphy->features = NL80211_FEATURE_HT_IBSS |
- NL80211_FEATURE_INACTIVITY_TIMER;
+ wiphy->features |= NL80211_FEATURE_HT_IBSS |
+ NL80211_FEATURE_INACTIVITY_TIMER;
/* Reserve space for mwifiex specific private data for BSS */
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 620f427..931f14f 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -598,9 +598,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
if (ops->remain_on_channel)
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- wiphy->features = NL80211_FEATURE_SK_TX_STATUS |
- NL80211_FEATURE_SAE |
- NL80211_FEATURE_HT_IBSS;
+ wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
+ NL80211_FEATURE_SAE |
+ NL80211_FEATURE_HT_IBSS;
if (!ops->set_key)
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
--
1.7.0.4
On Wed, 2012-10-24 at 11:59 +0300, Kalle Valo wrote:
> Is there a way to check that drivers don't accidentally clear the flags
> (ie. use '=' instead '|=')? For example by adding a dummy flag and
> checking afterwards that it's not cleared?
>
> I'm just worried that this detail might be too easy to miss, for example
> somehow I had missed this patch and noticed only when rebasing ath6kl
> patches.
Yes, that should be possible, set some dummy flag in wiphy_new() and
test & clear it in wiphy_register()?
johannes
From: Sam Leffler <[email protected]>
Add an NL80211_SCAN_FLAG_FLUSH flag that causes old bss cache
entries to be flushed on scan completion. This is useful for
collecting guaranteed fresh scan/survey result (e.g. on resume).
For normal scan, flushing only happens on successful completion
of a scan; i.e. it does not happen if the scan is aborted.
For scheduled scan, previous scan results are flushed everytime
when we get new scan results.
This feature is enabled by default. Drivers can disable it by
unsetting the NL80211_FEATURE_SCAN_FLUSH flag.
Signed-off-by: Sam Leffler <[email protected]>
Tested-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
[invert polarity of feature flag to account for old kernels]
Signed-off-by: Johannes Berg <[email protected]>
---
include/net/cfg80211.h | 3 ++
include/uapi/linux/nl80211.h | 4 ++
net/wireless/core.c | 2 +
net/wireless/nl80211.c | 14 ++++++--
net/wireless/scan.c | 66 +++++++++++++++++++++++++++++------------
net/wireless/sme.c | 1 +
6 files changed, 66 insertions(+), 24 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d95da8f..aa0e4a1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1005,6 +1005,7 @@ struct cfg80211_ssid {
* @flags: bit field of flags controlling operation
* @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for
+ * @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
@@ -1023,6 +1024,7 @@ struct cfg80211_scan_request {
/* internal */
struct wiphy *wiphy;
+ unsigned long scan_start;
bool aborted;
bool no_cck;
@@ -1074,6 +1076,7 @@ struct cfg80211_sched_scan_request {
/* internal */
struct wiphy *wiphy;
struct net_device *dev;
+ unsigned long scan_start;
/* keep last */
struct ieee80211_channel *channels[0];
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c68e15e..0e6277a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3049,6 +3049,7 @@ enum nl80211_ap_sme_features {
* equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
* mode
* @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan
+ * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3058,6 +3059,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
NL80211_FEATURE_SAE = 1 << 5,
NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6,
+ NL80211_FEATURE_SCAN_FLUSH = 1 << 7,
};
/**
@@ -3100,9 +3102,11 @@ enum nl80211_connect_failed_reason {
* requests.
*
* @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority
+ * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning
*/
enum nl80211_scan_flags {
NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
+ NL80211_SCAN_FLAG_FLUSH = 1<<1,
};
#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 443d4d7..48c2ea4 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -370,6 +370,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->wiphy.rts_threshold = (u32) -1;
rdev->wiphy.coverage_class = 0;
+ rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
+
return &rdev->wiphy;
}
EXPORT_SYMBOL(wiphy_new);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index aee252d..9e5a720 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4371,8 +4371,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
request->flags = nla_get_u32(
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
- if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
- !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
+ if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+ !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
+ ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
+ !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
err = -EOPNOTSUPP;
goto out_free;
}
@@ -4383,6 +4385,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->wdev = wdev;
request->wiphy = &rdev->wiphy;
+ request->scan_start = jiffies;
rdev->scan_req = request;
err = rdev->ops->scan(&rdev->wiphy, request);
@@ -4612,8 +4615,10 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
request->flags = nla_get_u32(
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
- if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
- !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
+ if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+ !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
+ ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
+ !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
err = -EOPNOTSUPP;
goto out_free;
}
@@ -4622,6 +4627,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
request->dev = dev;
request->wiphy = &rdev->wiphy;
request->interval = interval;
+ request->scan_start = jiffies;
err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
if (!err) {
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 2005096..a8d5a9a 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -47,6 +47,27 @@ static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
kref_put(&bss->ref, bss_release);
}
+/* must hold dev->bss_lock! */
+static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev,
+ unsigned long expire_time)
+{
+ struct cfg80211_internal_bss *bss, *tmp;
+ bool expired = false;
+
+ list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
+ if (atomic_read(&bss->hold))
+ continue;
+ if (!time_after(expire_time, bss->ts))
+ continue;
+
+ __cfg80211_unlink_bss(dev, bss);
+ expired = true;
+ }
+
+ if (expired)
+ dev->bss_generation++;
+}
+
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
{
struct cfg80211_scan_request *request;
@@ -72,10 +93,17 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
if (wdev->netdev)
cfg80211_sme_scan_done(wdev->netdev);
- if (request->aborted)
+ if (request->aborted) {
nl80211_send_scan_aborted(rdev, wdev);
- else
+ } else {
+ if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
+ /* flush entries from previous scans */
+ spin_lock_bh(&rdev->bss_lock);
+ __cfg80211_bss_expire(rdev, request->scan_start);
+ spin_unlock_bh(&rdev->bss_lock);
+ }
nl80211_send_scan_done(rdev, wdev);
+ }
#ifdef CONFIG_CFG80211_WEXT
if (wdev->netdev && !request->aborted) {
@@ -126,16 +154,27 @@ EXPORT_SYMBOL(cfg80211_scan_done);
void __cfg80211_sched_scan_results(struct work_struct *wk)
{
struct cfg80211_registered_device *rdev;
+ struct cfg80211_sched_scan_request *request;
rdev = container_of(wk, struct cfg80211_registered_device,
sched_scan_results_wk);
+ request = rdev->sched_scan_req;
+
mutex_lock(&rdev->sched_scan_mtx);
/* we don't have sched_scan_req anymore if the scan is stopping */
- if (rdev->sched_scan_req)
- nl80211_send_sched_scan_results(rdev,
- rdev->sched_scan_req->dev);
+ if (request) {
+ if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
+ /* flush entries from previous scans */
+ spin_lock_bh(&rdev->bss_lock);
+ __cfg80211_bss_expire(rdev, request->scan_start);
+ spin_unlock_bh(&rdev->bss_lock);
+ request->scan_start =
+ jiffies + msecs_to_jiffies(request->interval);
+ }
+ nl80211_send_sched_scan_results(rdev, request->dev);
+ }
mutex_unlock(&rdev->sched_scan_mtx);
}
@@ -197,23 +236,9 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
}
}
-/* must hold dev->bss_lock! */
void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
{
- struct cfg80211_internal_bss *bss, *tmp;
- bool expired = false;
-
- list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
- if (atomic_read(&bss->hold))
- continue;
- if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
- continue;
- __cfg80211_unlink_bss(dev, bss);
- expired = true;
- }
-
- if (expired)
- dev->bss_generation++;
+ __cfg80211_bss_expire(dev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
}
const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
@@ -962,6 +987,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
creq->ssids = (void *)&creq->channels[n_channels];
creq->n_channels = n_channels;
creq->n_ssids = 1;
+ creq->scan_start = jiffies;
/* translate "Scan on frequencies" request */
i = 0;
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 055d596..07d717e 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -138,6 +138,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
request->wdev = wdev;
request->wiphy = &rdev->wiphy;
+ request->scan_start = jiffies;
rdev->scan_req = request;
--
1.7.0.4
On 10/18/2012 08:44 PM, Bing Zhao wrote:
> Hi Arend,
>
>>> From: Sam Leffler <[email protected]>
>>>
>>> Add NL80211_SCAN_FLAG_LOW_PRIORITY flag support. It tells drivers
>>> that this is a low priority scan request, so that they can take
>>> necessary action.
>>> Drivers need to advertise low priority scan capability during
>>> registration.
>>
>> I missed the previous versions of this patch series, but what 'necessary
>> action' is needed for a low priority scan request. Patch #6 gives a clue
>> so my assumption is that a low prio scan will be *aborted* when
>> associated and data traffic is available. Is that correct? Could it also
>
> It's up to the driver to decide and implement the 'low priority scan' feature.
> The driver can defer or abort the low priority scan request depending on various conditions.
> For example, when heavy data traffic is on going you may want to abort the scan.
Thanks, Bing
I always find such answer tricky. Seeing where this is coming from I
suspect there is some high-level expectation from user-space
perspective. I suspect it is something like: A low-prio scan should not
affect a data transfer (iperf, nfs i/o, etc.) noticably.
Thanks for collecting the reading material ;-)
Gr. AvS
Hi Arend,
> > From: Sam Leffler <[email protected]>
> >
> > Add NL80211_SCAN_FLAG_LOW_PRIORITY flag support. It tells drivers
> > that this is a low priority scan request, so that they can take
> > necessary action.
> > Drivers need to advertise low priority scan capability during
> > registration.
>
> I missed the previous versions of this patch series, but what 'necessary
> action' is needed for a low priority scan request. Patch #6 gives a clue
> so my assumption is that a low prio scan will be *aborted* when
> associated and data traffic is available. Is that correct? Could it also
It's up to the driver to decide and implement the 'low priority scan' feature.
The driver can defer or abort the low priority scan request depending on various conditions.
For example, when heavy data traffic is on going you may want to abort the scan.
> *suspend* the low prio scan? Just curious whether there is an explicit
> behavioral requirement here. I probably should dig in previous versions
If you support this feature, driver should advertise LOW_PRIORITY_SCAN bit in wiphy->features.
> of this patch series. Too bad the cover letter of this one does not have
> full change log.
v6:
move enum nl80211_scan_flags placeholder from 1/6 to 3/6,
and merge with new flag in 3/6 to avoid breaking build in 1/6.
This makes patch series friendly to bisect. (Fengguang Wu)
Other 4 patches are not changed.
v5 (Johannes Berg):
I made two small changes (and inserted a patch in the middle to allow
for those changes).
One change is that I inverted the polarity of the "flush" feature flag
so that userspace can check if it's supported without having to worry
about the kernel version.
The other change is a fix in mac80211 to only set the "low prio" support
flag if *software* scan is used, not unconditionally.
Please make sure those still work for you, I haven't tested it.
It might be nice to also have a low-prio/flush flags patch for iw as
well if you find the time.
v4 (Amitkumar Karwar):
1) "wiphy->features" is used instead of "wiphy->flags" to advertise
scan features. (Johannes Berg)
2) Added support to disable scan flush if driver requests for it
explicitly. (Johannes Berg)
3) Used msecs_to_jiffies() to convert time interval into jiffies
for comparison (Johannes Berg)
v3 (Amitkumar Karwar):
1/5: Remove unnecessary "enum cfg80211_scan_flags" (Johannes Berg)
Add missing check for "nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS"
(Johannes Berg)
2/5: Add WIPHY_FLAG_LOW_PRIORITY_SCAN flag so that device can advertise
low priority scan capability. An error will be returned to the
application if device doesn't support this feature.
Flush scan table feature is by default enabled.
(Johannes Berg)
3/5, 4/5: Rearrange the code to avoid static forward declarations.
(Johannes Berg)
5/5: Removed use of unlikely() macro (Johannes Berg)
Advertise low priority scan capability (Johannes Berg)
v2 (Amitkumar Karwar):
1) TX_ABORT flag is renamed to LOW_PRIORITY to have more generic
approach. Let the drivers decide behaviour for background scan.
2) An extra parameter is added to __cfg80211_bss_expire() to
avoid race condition pointed by Johannes.
v1 (Sam Leffler):
These add per-scan request controls for optional behaviours we've found
useful (they've been in Chrome OS for a long time). A patch for iw will
follow separately and the mods for wpa_supplicant are in our repo and
I'll push them to Jouni if these are accepted.
Thanks,
Bing
>
> Gr. AvS
From: Amitkumar Karwar <[email protected]>
bss_release() and __cfg80211_unlink_bss() function definitions
are moved at the begining of the file. They are used in next
patch in this series.
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
net/wireless/scan.c | 54 +++++++++++++++++++++++++-------------------------
1 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 9730c98..2005096 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -20,6 +20,33 @@
#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
+static void bss_release(struct kref *ref)
+{
+ struct cfg80211_internal_bss *bss;
+
+ bss = container_of(ref, struct cfg80211_internal_bss, ref);
+ if (bss->pub.free_priv)
+ bss->pub.free_priv(&bss->pub);
+
+ if (bss->beacon_ies_allocated)
+ kfree(bss->pub.beacon_ies);
+ if (bss->proberesp_ies_allocated)
+ kfree(bss->pub.proberesp_ies);
+
+ BUG_ON(atomic_read(&bss->hold));
+
+ kfree(bss);
+}
+
+/* must hold dev->bss_lock! */
+static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
+ struct cfg80211_internal_bss *bss)
+{
+ list_del_init(&bss->list);
+ rb_erase(&bss->rbn, &dev->bss_tree);
+ kref_put(&bss->ref, bss_release);
+}
+
void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
{
struct cfg80211_scan_request *request;
@@ -158,24 +185,6 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
return 0;
}
-static void bss_release(struct kref *ref)
-{
- struct cfg80211_internal_bss *bss;
-
- bss = container_of(ref, struct cfg80211_internal_bss, ref);
- if (bss->pub.free_priv)
- bss->pub.free_priv(&bss->pub);
-
- if (bss->beacon_ies_allocated)
- kfree(bss->pub.beacon_ies);
- if (bss->proberesp_ies_allocated)
- kfree(bss->pub.proberesp_ies);
-
- BUG_ON(atomic_read(&bss->hold));
-
- kfree(bss);
-}
-
/* must hold dev->bss_lock! */
void cfg80211_bss_age(struct cfg80211_registered_device *dev,
unsigned long age_secs)
@@ -189,15 +198,6 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
}
/* must hold dev->bss_lock! */
-static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
- struct cfg80211_internal_bss *bss)
-{
- list_del_init(&bss->list);
- rb_erase(&bss->rbn, &dev->bss_tree);
- kref_put(&bss->ref, bss_release);
-}
-
-/* must hold dev->bss_lock! */
void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
{
struct cfg80211_internal_bss *bss, *tmp;
--
1.7.0.4
Bing Zhao <[email protected]> writes:
> From: Johannes Berg <[email protected]>
>
> The next patch will introduce a flag that is set
> by default in cfg80211 so drivers and mac80211
> need to use |= to set features they have so that
> they don't clear the already-set feature.
>
> We could set the flag in wiphy_register() instead
> of wiphy_new() to avoid this patch, but then the
> drivers couldn't *unset* flags they don't want to
> use even though the implementation is generic.
>
> Signed-off-by: Johannes Berg <[email protected]>
Is there a way to check that drivers don't accidentally clear the flags
(ie. use '=' instead '|=')? For example by adding a dummy flag and
checking afterwards that it's not cleared?
I'm just worried that this detail might be too easy to miss, for example
somehow I had missed this patch and noticed only when rebasing ath6kl
patches.
--
Kalle Valo
From: Sam Leffler <[email protected]>
Add NL80211_SCAN_FLAG_LOW_PRIORITY flag support. It tells drivers
that this is a low priority scan request, so that they can take
necessary action.
Drivers need to advertise low priority scan capability during
registration.
Signed-off-by: Sam Leffler <[email protected]>
Tested-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
include/uapi/linux/nl80211.h | 15 +++++++++++++++
net/wireless/nl80211.c | 16 ++++++++++++++--
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 751a292..c68e15e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3048,6 +3048,7 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
* equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
* mode
+ * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3056,6 +3057,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
NL80211_FEATURE_SAE = 1 << 5,
+ NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6,
};
/**
@@ -3090,4 +3092,17 @@ enum nl80211_connect_failed_reason {
NL80211_CONN_FAIL_BLOCKED_CLIENT,
};
+/**
+ * enum nl80211_scan_flags - scan request control flags
+ *
+ * Scan request control flags are used to control the handling
+ * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN
+ * requests.
+ *
+ * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority
+ */
+enum nl80211_scan_flags {
+ NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index dc08211..aee252d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4368,9 +4368,15 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
}
}
- if (info->attrs[NL80211_ATTR_SCAN_FLAGS])
+ if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
request->flags = nla_get_u32(
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
+ if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+ !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
+ err = -EOPNOTSUPP;
+ goto out_free;
+ }
+ }
request->no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
@@ -4603,9 +4609,15 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
request->ie_len);
}
- if (info->attrs[NL80211_ATTR_SCAN_FLAGS])
+ if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
request->flags = nla_get_u32(
info->attrs[NL80211_ATTR_SCAN_FLAGS]);
+ if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+ !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
+ err = -EOPNOTSUPP;
+ goto out_free;
+ }
+ }
request->dev = dev;
request->wiphy = &rdev->wiphy;
--
1.7.0.4
From: Sam Leffler <[email protected]>
Use NL80211_SCAN_FLAG_LOW_PRIORITY flag in mac80211's scan state
machine to prematurely terminate scan operations if outbound
traffic collides. This is useful for marking background scans so
they don't affect throughput.
Signed-off-by: Sam Leffler <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
[set feature flag only if software scan is used]
Signed-off-by: Johannes Berg <[email protected]>
---
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/main.c | 3 +++
net/mac80211/scan.c | 21 +++++++++++++++++----
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 64ae757..ebc1b5d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -866,6 +866,7 @@ enum {
* @SCAN_SUSPEND: Suspend the scan and go back to operating channel to
* send out data
* @SCAN_RESUME: Resume the scan and scan the next channel
+ * @SCAN_ABORT: Abort the scan and go back to operating channel
*/
enum mac80211_scan_state {
SCAN_DECISION,
@@ -873,6 +874,7 @@ enum mac80211_scan_state {
SCAN_SEND_PROBE,
SCAN_SUSPEND,
SCAN_RESUME,
+ SCAN_ABORT,
};
struct ieee80211_local {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 931f14f..ba5a232 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -602,6 +602,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
NL80211_FEATURE_SAE |
NL80211_FEATURE_HT_IBSS;
+ if (!ops->hw_scan)
+ wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN;
+
if (!ops->set_key)
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 987c75d..13d2329 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -466,6 +466,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
sizeof(*local->hw_scan_req) +
req->n_channels * sizeof(req->channels[0]);
local->hw_scan_req->ie = ies;
+ local->hw_scan_req->flags = req->flags;
local->hw_scan_band = 0;
@@ -566,6 +567,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
unsigned long min_beacon_int = 0;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *next_chan;
+ enum mac80211_scan_state next_scan_state;
/*
* check if at least one STA interface is associated,
@@ -624,10 +626,18 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
usecs_to_jiffies(min_beacon_int * 1024) *
local->hw.conf.listen_interval);
- if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
- local->next_scan_state = SCAN_SUSPEND;
- else
- local->next_scan_state = SCAN_SET_CHANNEL;
+ if (associated && !tx_empty) {
+ if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+ next_scan_state = SCAN_ABORT;
+ else
+ next_scan_state = SCAN_SUSPEND;
+ } else if (associated && (bad_latency || listen_int_exceeded)) {
+ next_scan_state = SCAN_SUSPEND;
+ } else {
+ next_scan_state = SCAN_SET_CHANNEL;
+ }
+
+ local->next_scan_state = next_scan_state;
*next_delay = 0;
}
@@ -798,6 +808,9 @@ void ieee80211_scan_work(struct work_struct *work)
case SCAN_RESUME:
ieee80211_scan_state_resume(local, &next_delay);
break;
+ case SCAN_ABORT:
+ aborted = true;
+ goto out_complete;
}
} while (next_delay == 0);
--
1.7.0.4
Johannes Berg <[email protected]> writes:
> On Wed, 2012-10-24 at 11:59 +0300, Kalle Valo wrote:
>
>> Is there a way to check that drivers don't accidentally clear the flags
>> (ie. use '=' instead '|=')? For example by adding a dummy flag and
>> checking afterwards that it's not cleared?
>>
>> I'm just worried that this detail might be too easy to miss, for example
>> somehow I had missed this patch and noticed only when rebasing ath6kl
>> patches.
>
> Yes, that should be possible, set some dummy flag in wiphy_new() and
> test & clear it in wiphy_register()?
The tricky part is to make sure that the dummy flag won't conflict with
a real feature flag value in the future :)
But I'll try to come up with a patch.
--
Kalle Valo
On Wed, 2012-10-24 at 12:03 +0300, Kalle Valo wrote:
> Johannes Berg <[email protected]> writes:
>
> > On Wed, 2012-10-24 at 11:59 +0300, Kalle Valo wrote:
> >
> >> Is there a way to check that drivers don't accidentally clear the flags
> >> (ie. use '=' instead '|=')? For example by adding a dummy flag and
> >> checking afterwards that it's not cleared?
> >>
> >> I'm just worried that this detail might be too easy to miss, for example
> >> somehow I had missed this patch and noticed only when rebasing ath6kl
> >> patches.
> >
> > Yes, that should be possible, set some dummy flag in wiphy_new() and
> > test & clear it in wiphy_register()?
>
> The tricky part is to make sure that the dummy flag won't conflict with
> a real feature flag value in the future :)
Seems like a non-issue? If you say use 1<<31 to test, and somebody adds
1<<31, they'll find that their flag never works and will figure it out?
johannes
On 10/18/2012 08:34 AM, Bing Zhao wrote:
> From: Sam Leffler <[email protected]>
>
> Add NL80211_SCAN_FLAG_LOW_PRIORITY flag support. It tells drivers
> that this is a low priority scan request, so that they can take
> necessary action.
> Drivers need to advertise low priority scan capability during
> registration.
I missed the previous versions of this patch series, but what 'necessary
action' is needed for a low priority scan request. Patch #6 gives a clue
so my assumption is that a low prio scan will be *aborted* when
associated and data traffic is available. Is that correct? Could it also
*suspend* the low prio scan? Just curious whether there is an explicit
behavioral requirement here. I probably should dig in previous versions
of this patch series. Too bad the cover letter of this one does not have
full change log.
Gr. AvS
From: Sam Leffler <[email protected]>
Add a flags word to direct and scheduled scan requests; it will
be used for control of optional behaviours such as flushing the
bss cache prior to doing a scan.
Signed-off-by: Sam Leffler <[email protected]>
Tested-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
Signed-off-by: Bing Zhao <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
include/net/cfg80211.h | 4 ++++
include/uapi/linux/nl80211.h | 4 ++++
net/wireless/nl80211.c | 12 ++++++++++++
3 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 607b5c0..d95da8f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1002,6 +1002,7 @@ struct cfg80211_ssid {
* @n_channels: total number of channels to scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
* @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for
* @wdev: the wireless device to scan for
@@ -1014,6 +1015,7 @@ struct cfg80211_scan_request {
u32 n_channels;
const u8 *ie;
size_t ie_len;
+ u32 flags;
u32 rates[IEEE80211_NUM_BANDS];
@@ -1046,6 +1048,7 @@ struct cfg80211_match_set {
* @interval: interval between each scheduled scan cycle
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
* @match_sets: sets of parameters to be matched for a scan result
* entry to be considered valid and to be passed to the host
* (others are filtered out).
@@ -1063,6 +1066,7 @@ struct cfg80211_sched_scan_request {
u32 interval;
const u8 *ie;
size_t ie_len;
+ u32 flags;
struct cfg80211_match_set *match_sets;
int n_match_sets;
s32 rssi_thold;
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 71ab23b..751a292 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1279,6 +1279,8 @@ enum nl80211_commands {
* @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
* association request when used with NL80211_CMD_NEW_STATION)
*
+ * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32)
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1540,6 +1542,8 @@ enum nl80211_attrs {
NL80211_ATTR_VHT_CAPABILITY,
+ NL80211_ATTR_SCAN_FLAGS,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ef170e9..dc08211 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -356,6 +356,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+ [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
};
/* policy for the key attributes */
@@ -4367,6 +4368,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
}
}
+ if (info->attrs[NL80211_ATTR_SCAN_FLAGS])
+ request->flags = nla_get_u32(
+ info->attrs[NL80211_ATTR_SCAN_FLAGS]);
+
request->no_cck =
nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
@@ -4598,6 +4603,10 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
request->ie_len);
}
+ if (info->attrs[NL80211_ATTR_SCAN_FLAGS])
+ request->flags = nla_get_u32(
+ info->attrs[NL80211_ATTR_SCAN_FLAGS]);
+
request->dev = dev;
request->wiphy = &rdev->wiphy;
request->interval = interval;
@@ -7663,6 +7672,9 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
nla_put(msg, NL80211_ATTR_IE, req->ie_len, req->ie))
goto nla_put_failure;
+ if (req->flags)
+ nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, req->flags);
+
return 0;
nla_put_failure:
return -ENOBUFS;
--
1.7.0.4