* [PATCH 0/3] cfg80211/mac80211: implementation of scheduled scan
@ 2011-05-05 13:00 Luciano Coelho
2011-05-05 13:00 ` [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans Luciano Coelho
` (2 more replies)
0 siblings, 3 replies; 23+ messages in thread
From: Luciano Coelho @ 2011-05-05 13:00 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville
Hi,
Here's another version of my scheduled scan patches. I think these are now
good enough. I applied all comments by Johannes and added some improvements.
These are the main differences from RFCv2:
mac80211:
---------
* mac80211 checks if the driver has an op->sched_scan_start and sets
the WIPHY_FLAG_SUPPORTS_SCHED_SCAN flag accordingly;
* fixed a typo;
* moved drv_sched_scan_results to api_sched_scan_results;
* removed SCAN_SCHED_SCANNING as a scan_attribute and moved it to
a separate local boolean, so that it doesn't interfere with
normal scan scenarios;
* there was on comment that the sched_scan was "eating" beacons for
the whole time when it was scanning, but this doesn't apply anymore
because of commit b23b025fe246f3acc2988eb6d400df34c27cb8ae changed
the code so that beacons are passed up if they're on the operating
channel (see ieee80211_scan_rx());
* fixed allocation failure bug when allocating sched_scan_ies;
* removed lock in ieee80211_sched_scan_results();
* don't return a value in sched_scan_stop;
cfg80211:
---------
* fixed documentation in nl80211 so that it's clear that if an empty
SSID is passed (broadcast), we do broadcast probe_reqs and if no
SSID is passed, we do a passive scan;
* removed max_sched_scan_ssids, now we use max_scan_ssids instead;
* added __cfg80211_stop_sched_scan() and call that from
nl80211_stop_sched_scan(), wdev_cleanup_work() and
NETDEV_GOING_DOWN;
* removed unnecessary dev_hold() in nl80211_start_sched_scan();
* added the NL80211_CMD_SCHED_SCAN_STOPPED event and an interface for
the driver to stop the scan by itself;
* send a NL80211_CMD_SCHED_SCAN_STOPPED event instead of a
NL80211_CMD_STOP_SCHED_SCAN when the scan is stopped by a
NL80211_CMD_STOP_SCHED_SCAN command;
* don't return a value in sched_scan_stop;
* added a new patch to include the scan interval;
* a few minor cleanups.
There are still more things on my TODO list, but they're mostly improvements
and it will be much easier to add them step-by-step after this part is
included. This version is already functional and ready to be used. ;)
Please review and let me know if there are still some problems for inclusion.
Cheers,
Luca.
Luciano Coelho (3):
cfg80211/nl80211: add support for scheduled scans
mac80211: add support for HW scheduled scan
cfg80211/nl80211: add interval attribute for scheduled scans
include/linux/nl80211.h | 31 +++++
include/net/cfg80211.h | 59 ++++++++++
include/net/mac80211.h | 50 ++++++++
net/mac80211/cfg.c | 27 +++++
net/mac80211/driver-ops.h | 27 +++++
net/mac80211/driver-trace.h | 81 +++++++++++++
net/mac80211/ieee80211_i.h | 9 ++
net/mac80211/main.c | 8 +-
net/mac80211/rx.c | 6 +-
net/mac80211/scan.c | 99 ++++++++++++++++
net/wireless/core.c | 12 ++-
net/wireless/core.h | 7 +
net/wireless/nl80211.c | 261 +++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 4 +
net/wireless/scan.c | 62 ++++++++++
15 files changed, 738 insertions(+), 5 deletions(-)
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans
2011-05-05 13:00 [PATCH 0/3] cfg80211/mac80211: implementation of scheduled scan Luciano Coelho
@ 2011-05-05 13:00 ` Luciano Coelho
2011-05-09 8:12 ` Johannes Berg
2011-05-09 9:50 ` Eliad Peller
2011-05-05 13:00 ` [PATCH 2/3] mac80211: add support for HW scheduled scan Luciano Coelho
2011-05-05 13:00 ` [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans Luciano Coelho
2 siblings, 2 replies; 23+ messages in thread
From: Luciano Coelho @ 2011-05-05 13:00 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville
Implement new functionality for scheduled scan offload. With this feature we
can scan automatically at certain intervals.
The idea is that the hardware can perform scan automatically and filter on
desired results without waking up the host unnecessarily.
Add NL80211_CMD_START_SCHED_SCAN and NL80211_CMD_STOP_SCHED_SCAN
commands to the nl80211 interface. When results are available they are
reported by NL80211_CMD_SCHED_SCAN_RESULTS events. The userspace is
informed when the scheduled scan has stopped with a
NL80211_CMD_SCHED_SCAN_STOPPED event, which can be triggered either by
the driver or by a call to NL80211_CMD_STOP_SCHED_SCAN.
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
include/linux/nl80211.h | 25 +++++
include/net/cfg80211.h | 57 +++++++++++
net/wireless/core.c | 12 ++-
net/wireless/core.h | 7 ++
net/wireless/nl80211.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 4 +
net/wireless/scan.c | 62 ++++++++++++
7 files changed, 417 insertions(+), 1 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 216b1d8..355fb65 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -203,6 +203,26 @@
* @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
* partial scan results may be available
*
+ * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan. Like with normal
+ * scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) are passed, they are used
+ * in the probe requests. For broadcast, a broadcast SSID must be
+ * passed (ie. an empty string). If no SSID is passed, no probe
+ * requests are sent and a passive scan is performed.
+ * %NL80211_ATTR_SCAN_FREQUENCIES, if passed, define which channels
+ * should be scanned; if not passed, all channels allowed for the
+ * current regulatory domain are used. Extra IEs can also be passed
+ * from the userspace by using the %NL80211_ATTR_IE attribute.
+ * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan
+ * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan
+ * results available.
+ * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has
+ * stopped. The driver may issue this event at any time during a
+ * scheduled scan. One reason for stopping the scan is if the hardware
+ * does not support starting an association or a normal scan while running
+ * a scheduled scan. This event is also sent when the
+ * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface
+ * is brought down while a scheduled scan was running.
+ *
* @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
* or noise level
* @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
@@ -534,6 +554,11 @@ enum nl80211_commands {
NL80211_CMD_NEW_PEER_CANDIDATE,
+ NL80211_CMD_START_SCHED_SCAN,
+ NL80211_CMD_STOP_SCHED_SCAN,
+ NL80211_CMD_SCHED_SCAN_RESULTS,
+ NL80211_CMD_SCHED_SCAN_STOPPED,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d30eada..117df56 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -793,6 +793,33 @@ struct cfg80211_scan_request {
};
/**
+ * struct cfg80211_sched_scan_request - scheduled scan request description
+ *
+ * @ssids: SSIDs to report (other SSIDs will be filtered out)
+ * @n_ssids: number of SSIDs
+ * @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
+ * @wiphy: the wiphy this was for
+ * @dev: the interface
+ * @channels: channels to scan
+ */
+struct cfg80211_sched_scan_request {
+ struct cfg80211_ssid *ssids;
+ int n_ssids;
+ u32 n_channels;
+ const u8 *ie;
+ size_t ie_len;
+
+ /* internal */
+ struct wiphy *wiphy;
+ struct net_device *dev;
+
+ /* keep last */
+ struct ieee80211_channel *channels[0];
+};
+
+/**
* enum cfg80211_signal_type - signal type
*
* @CFG80211_SIGNAL_TYPE_NONE: no signal strength information available
@@ -1227,6 +1254,10 @@ struct cfg80211_pmksa {
* @set_power_mgmt: Configure WLAN power management. A timeout value of -1
* allows the driver to adjust the dynamic ps timeout value.
* @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold.
+ * @sched_scan_start: Tell the driver to start a scheduled scan.
+ * @sched_scan_stop: Tell the driver to stop an ongoing scheduled
+ * scan. The driver_initiated flag specifies whether the driver
+ * itself has informed that the scan has stopped.
*
* @mgmt_frame_register: Notify driver that a management frame type was
* registered. Note that this callback may not sleep, and cannot run
@@ -1413,6 +1444,12 @@ struct cfg80211_ops {
int (*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx);
void (*get_ringparam)(struct wiphy *wiphy,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
+
+ int (*sched_scan_start)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_sched_scan_request *request);
+ int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev,
+ bool driver_initiated);
};
/*
@@ -1459,6 +1496,7 @@ struct cfg80211_ops {
* unicast and multicast TX keys.
* @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
* auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
+ * @WIPHY_FLAG_SCHED_SCAN: The device supports scheduled scans.
*/
enum wiphy_flags {
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
@@ -1472,6 +1510,7 @@ enum wiphy_flags {
WIPHY_FLAG_IBSS_RSN = BIT(8),
WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9),
WIPHY_FLAG_MESH_AUTH = BIT(10),
+ WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11),
};
struct mac_address {
@@ -2257,6 +2296,24 @@ int cfg80211_wext_siwpmksa(struct net_device *dev,
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted);
/**
+ * cfg80211_sched_scan_results - notify that new scan results are available
+ *
+ * @wiphy: the wiphy which got scheduled scan results
+ */
+void cfg80211_sched_scan_results(struct wiphy *wiphy);
+
+/**
+ * cfg80211_sched_scan_stopped - notify that the scheduled scan has stopped
+ *
+ * @wiphy: the wiphy on which the scheduled scan stopped
+ *
+ * The driver can call this function to inform cfg80211 that the
+ * scheduled scan had to be stopped, for whatever reason. The driver
+ * is then called back via the sched_scan_stop operation when done.
+ */
+void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
+
+/**
* cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame
*
* @wiphy: the wiphy reporting the BSS
diff --git a/net/wireless/core.c b/net/wireless/core.c
index bbf1fa1..e99efe6 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -370,7 +370,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
spin_lock_init(&rdev->bss_lock);
INIT_LIST_HEAD(&rdev->bss_list);
INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
-
+ INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results);
+ INIT_WORK(&rdev->sched_scan_stopped_wk, __cfg80211_sched_scan_stopped);
#ifdef CONFIG_CFG80211_WEXT
rdev->wiphy.wext = &cfg80211_wext_handler;
#endif
@@ -664,6 +665,11 @@ static void wdev_cleanup_work(struct work_struct *work)
___cfg80211_scan_done(rdev, true);
}
+ if (WARN_ON(rdev->sched_scan_req &&
+ rdev->sched_scan_req->dev == wdev->netdev)) {
+ __cfg80211_stop_sched_scan(rdev, false);
+ }
+
cfg80211_unlock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx);
@@ -751,6 +757,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
+ cfg80211_lock_rdev(rdev);
+ __cfg80211_stop_sched_scan(rdev, false);
+ cfg80211_unlock_rdev(rdev);
+
wdev_lock(wdev);
#ifdef CONFIG_CFG80211_WEXT
kfree(wdev->wext.ie);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 26a0a08..8bb4b75 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -60,8 +60,11 @@ struct cfg80211_registered_device {
struct rb_root bss_tree;
u32 bss_generation;
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
+ struct cfg80211_sched_scan_request *sched_scan_req;
unsigned long suspend_at;
struct work_struct scan_done_wk;
+ struct work_struct sched_scan_results_wk;
+ struct work_struct sched_scan_stopped_wk;
#ifdef CONFIG_NL80211_TESTMODE
struct genl_info *testmode_info;
@@ -397,6 +400,10 @@ void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
void cfg80211_sme_disassoc(struct net_device *dev, int idx);
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);
+int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
+ bool driver_initiated);
+void __cfg80211_sched_scan_stopped(struct work_struct *wk);
void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
struct net_device *dev, enum nl80211_iftype ntype,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0efa7fd..a971501 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -749,6 +749,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
}
CMD(set_channel, SET_CHANNEL);
CMD(set_wds_peer, SET_WDS_PEER);
+ if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
+ CMD(sched_scan_start, START_SCHED_SCAN);
#undef CMD
@@ -3318,6 +3320,180 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
return err;
}
+static int nl80211_start_sched_scan(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_sched_scan_request *request;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct cfg80211_ssid *ssid;
+ struct ieee80211_channel *channel;
+ struct nlattr *attr;
+ struct wiphy *wiphy;
+ int err, tmp, n_ssids = 0, n_channels, i;
+ enum ieee80211_band band;
+ size_t ie_len;
+
+ if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
+ !rdev->ops->sched_scan_start)
+ return -EOPNOTSUPP;
+
+ if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+ return -EINVAL;
+
+ if (rdev->sched_scan_req)
+ return -EINPROGRESS;
+
+ wiphy = &rdev->wiphy;
+
+ if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+ n_channels = validate_scan_freqs(
+ info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
+ if (!n_channels)
+ return -EINVAL;
+ } else {
+ n_channels = 0;
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++)
+ if (wiphy->bands[band])
+ n_channels += wiphy->bands[band]->n_channels;
+ }
+
+ if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
+ nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
+ tmp)
+ n_ssids++;
+
+ if (n_ssids > wiphy->max_scan_ssids)
+ return -EINVAL;
+
+ if (info->attrs[NL80211_ATTR_IE])
+ ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ else
+ ie_len = 0;
+
+ if (ie_len > wiphy->max_scan_ie_len)
+ return -EINVAL;
+
+ request = kzalloc(sizeof(*request)
+ + sizeof(*ssid) * n_ssids
+ + sizeof(channel) * n_channels
+ + ie_len, GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
+
+ if (n_ssids)
+ request->ssids = (void *)&request->channels[n_channels];
+ request->n_ssids = n_ssids;
+ if (ie_len) {
+ if (request->ssids)
+ request->ie = (void *)(request->ssids + n_ssids);
+ else
+ request->ie = (void *)(request->channels + n_channels);
+ }
+
+ i = 0;
+ if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+ /* user specified, bail out if channel not found */
+ nla_for_each_nested(attr,
+ info->attrs[NL80211_ATTR_SCAN_FREQUENCIES],
+ tmp) {
+ struct ieee80211_channel *chan;
+
+ chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
+
+ if (!chan) {
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ /* ignore disabled channels */
+ if (chan->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ request->channels[i] = chan;
+ i++;
+ }
+ } else {
+ /* all channels */
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ int j;
+ if (!wiphy->bands[band])
+ continue;
+ for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
+ struct ieee80211_channel *chan;
+
+ chan = &wiphy->bands[band]->channels[j];
+
+ if (chan->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ request->channels[i] = chan;
+ i++;
+ }
+ }
+ }
+
+ if (!i) {
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ request->n_channels = i;
+
+ i = 0;
+ if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
+ nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
+ tmp) {
+ if (request->ssids[i].ssid_len >
+ IEEE80211_MAX_SSID_LEN) {
+ err = -EINVAL;
+ goto out_free;
+ }
+ memcpy(request->ssids[i].ssid, nla_data(attr),
+ nla_len(attr));
+ request->ssids[i].ssid_len = nla_len(attr);
+ i++;
+ }
+ }
+
+ if (info->attrs[NL80211_ATTR_IE]) {
+ request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ memcpy((void *)request->ie,
+ nla_data(info->attrs[NL80211_ATTR_IE]),
+ request->ie_len);
+ }
+
+ request->dev = dev;
+ request->wiphy = &rdev->wiphy;
+
+ rdev->sched_scan_req = request;
+
+ err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
+ if (!err)
+ nl80211_send_sched_scan(rdev, dev,
+ NL80211_CMD_START_SCHED_SCAN);
+ else {
+out_free:
+ kfree(request);
+ rdev->sched_scan_req = NULL;
+ }
+
+ return err;
+}
+
+static int nl80211_stop_sched_scan(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+
+ if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
+ !rdev->ops->sched_scan_stop)
+ return -EOPNOTSUPP;
+
+ return __cfg80211_stop_sched_scan(rdev, false);
+}
+
static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
@@ -5100,6 +5276,22 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_scan,
},
{
+ .cmd = NL80211_CMD_START_SCHED_SCAN,
+ .doit = nl80211_start_sched_scan,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_STOP_SCHED_SCAN,
+ .doit = nl80211_stop_sched_scan,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
.cmd = NL80211_CMD_AUTHENTICATE,
.doit = nl80211_authenticate,
.policy = nl80211_policy,
@@ -5409,6 +5601,28 @@ static int nl80211_send_scan_msg(struct sk_buff *msg,
return -EMSGSIZE;
}
+static int
+nl80211_send_sched_scan_msg(struct sk_buff *msg,
+ struct cfg80211_registered_device *rdev,
+ struct net_device *netdev,
+ u32 pid, u32 seq, int flags, u32 cmd)
+{
+ void *hdr;
+
+ hdr = nl80211hdr_put(msg, pid, seq, flags, cmd);
+ if (!hdr)
+ return -1;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+
+ return genlmsg_end(msg, hdr);
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return -EMSGSIZE;
+}
+
void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
struct net_device *netdev)
{
@@ -5466,6 +5680,43 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
nl80211_scan_mcgrp.id, GFP_KERNEL);
}
+void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev)
+{
+ struct sk_buff *msg;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0,
+ NL80211_CMD_SCHED_SCAN_RESULTS) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_scan_mcgrp.id, GFP_KERNEL);
+}
+
+void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u32 cmd)
+{
+ struct sk_buff *msg;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0, cmd) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_scan_mcgrp.id, GFP_KERNEL);
+}
+
/*
* This can happen on global regulatory changes or device specific settings
* based on custom world regulatory domains.
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index f2af695..2f1bfb8 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -12,6 +12,10 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
struct net_device *netdev);
void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
struct net_device *netdev);
+void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev, u32 cmd);
+void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
+ struct net_device *netdev);
void nl80211_send_reg_change_event(struct regulatory_request *request);
void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index fbf6f33..6e82215 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -93,6 +93,68 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
}
EXPORT_SYMBOL(cfg80211_scan_done);
+void __cfg80211_sched_scan_results(struct work_struct *wk)
+{
+ struct cfg80211_registered_device *rdev;
+
+ rdev = container_of(wk, struct cfg80211_registered_device,
+ sched_scan_results_wk);
+
+ cfg80211_lock_rdev(rdev);
+ nl80211_send_sched_scan_results(rdev, rdev->sched_scan_req->dev);
+ cfg80211_unlock_rdev(rdev);
+}
+
+void cfg80211_sched_scan_results(struct wiphy *wiphy)
+{
+ queue_work(cfg80211_wq, &wiphy_to_dev(wiphy)->sched_scan_results_wk);
+}
+EXPORT_SYMBOL(cfg80211_sched_scan_results);
+
+void __cfg80211_sched_scan_stopped(struct work_struct *wk)
+{
+ struct cfg80211_registered_device *rdev;
+
+ rdev = container_of(wk, struct cfg80211_registered_device,
+ sched_scan_stopped_wk);
+
+ cfg80211_lock_rdev(rdev);
+ __cfg80211_stop_sched_scan(rdev, true);
+ cfg80211_unlock_rdev(rdev);
+}
+
+void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
+{
+ queue_work(cfg80211_wq, &wiphy_to_dev(wiphy)->sched_scan_stopped_wk);
+}
+EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
+
+int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
+ bool driver_initiated)
+{
+ int err;
+ struct net_device *dev;
+
+ ASSERT_RDEV_LOCK(rdev);
+
+ if (!rdev->sched_scan_req)
+ return 0;
+
+ dev = rdev->sched_scan_req->dev;
+
+ err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev,
+ driver_initiated);
+ if (err)
+ return err;
+
+ nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);
+
+ kfree(rdev->sched_scan_req);
+ rdev->sched_scan_req = NULL;
+
+ return err;
+}
+
static void bss_release(struct kref *ref)
{
struct cfg80211_internal_bss *bss;
--
1.7.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 2/3] mac80211: add support for HW scheduled scan
2011-05-05 13:00 [PATCH 0/3] cfg80211/mac80211: implementation of scheduled scan Luciano Coelho
2011-05-05 13:00 ` [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans Luciano Coelho
@ 2011-05-05 13:00 ` Luciano Coelho
2011-05-09 8:22 ` Johannes Berg
2011-05-05 13:00 ` [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans Luciano Coelho
2 siblings, 1 reply; 23+ messages in thread
From: Luciano Coelho @ 2011-05-05 13:00 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville
Implement support for HW scheduled scan. The mac80211 code doesn't perform
scheduled scans itself, but calls the driver to start and stop scheduled
scans.
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
include/net/mac80211.h | 50 ++++++++++++++++++++++
net/mac80211/cfg.c | 27 ++++++++++++
net/mac80211/driver-ops.h | 27 ++++++++++++
net/mac80211/driver-trace.h | 81 +++++++++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 9 ++++
net/mac80211/main.c | 8 +++-
net/mac80211/rx.c | 6 ++-
net/mac80211/scan.c | 99 +++++++++++++++++++++++++++++++++++++++++++
8 files changed, 303 insertions(+), 4 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index db4b6b9..960fdd1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -537,6 +537,21 @@ struct ieee80211_tx_info {
};
};
+/**
+ * ieee80211_sched_scan_ies - scheduled scan IEs
+ *
+ * This structure is used to pass the appropriate IEs to be used in scheduled
+ * scans for all bands. It contains both the IEs passed from the userspace
+ * and the ones generated by mac80211.
+ *
+ * @ie: array with the IEs for each supported band
+ * @len: array with the total length of the IEs for each band
+ */
+struct ieee80211_sched_scan_ies {
+ u8 *ie[IEEE80211_NUM_BANDS];
+ size_t len[IEEE80211_NUM_BANDS];
+};
+
static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb)
{
return (struct ieee80211_tx_info *)skb->cb;
@@ -1681,6 +1696,13 @@ enum ieee80211_ampdu_mlme_action {
* any error unless this callback returned a negative error code.
* The callback can sleep.
*
+ * @sched_scan_start: Ask the hardware to start scanning repeatedly at
+ * specific intervals. The driver must call the
+ * ieee80211_sched_scan_results() function whenever it finds results.
+ * This process will continue until sched_scan_stop is called.
+ *
+ * @sched_scan_stop: Tell the hardware to stop an ongoing scheduled scan.
+ *
* @sw_scan_start: Notifier function that is called just before a software scan
* is started. Can be NULL, if the driver doesn't need this notification.
* The callback can sleep.
@@ -1861,6 +1883,12 @@ struct ieee80211_ops {
u32 iv32, u16 *phase1key);
int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
+ int (*sched_scan_start)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_sched_scan_ies *ies);
+ void (*sched_scan_stop)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
void (*sw_scan_start)(struct ieee80211_hw *hw);
void (*sw_scan_complete)(struct ieee80211_hw *hw);
int (*get_stats)(struct ieee80211_hw *hw,
@@ -2578,6 +2606,28 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw);
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted);
/**
+ * ieee80211_sched_scan_results - got results from scheduled scan
+ *
+ * When a scheduled scan is running, this function needs to be called by the
+ * driver whenever there are new scan results available.
+ *
+ * @hw: the hardware that is performing scheduled scans
+ */
+void ieee80211_sched_scan_results(struct ieee80211_hw *hw);
+
+/**
+ * ieee80211_sched_scan_stopped - inform that the scheduled scan has stopped
+ *
+ * When a scheduled scan is running, this function can be called by
+ * the driver if it needs to stop the scan to perform another task.
+ * Usual scenarios are drivers that cannot continue the scheduled scan
+ * while associating, for instance.
+ *
+ * @hw: the hardware that is performing scheduled scans
+ */
+void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
+
+/**
* ieee80211_iterate_active_interfaces - iterate active interfaces
*
* This function iterates over the interfaces associated with a given
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 12d52ce..9a1803a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1342,6 +1342,31 @@ static int ieee80211_scan(struct wiphy *wiphy,
return ieee80211_request_scan(sdata, req);
}
+static int
+ieee80211_sched_scan_start(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ if (!sdata->local->ops->sched_scan_start)
+ return -EOPNOTSUPP;
+
+ return ieee80211_request_sched_scan_start(sdata, req);
+}
+
+static int
+ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev,
+ bool driver_initiated)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ if (!sdata->local->ops->sched_scan_stop)
+ return -EOPNOTSUPP;
+
+ return ieee80211_request_sched_scan_stop(sdata, driver_initiated);
+}
+
static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_auth_request *req)
{
@@ -2083,6 +2108,8 @@ struct cfg80211_ops mac80211_config_ops = {
.suspend = ieee80211_suspend,
.resume = ieee80211_resume,
.scan = ieee80211_scan,
+ .sched_scan_start = ieee80211_sched_scan_start,
+ .sched_scan_stop = ieee80211_sched_scan_stop,
.auth = ieee80211_auth,
.assoc = ieee80211_assoc,
.deauth = ieee80211_deauth,
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 2ddb56e..87dc3e6 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -191,6 +191,33 @@ static inline int drv_hw_scan(struct ieee80211_local *local,
return ret;
}
+static inline int
+drv_sched_scan_start(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_sched_scan_ies *ies)
+{
+ int ret;
+
+ might_sleep();
+
+ trace_drv_sched_scan_start(local, sdata, req);
+ ret = local->ops->sched_scan_start(&local->hw, &sdata->vif,
+ req, ies);
+ trace_drv_return_int(local, ret);
+ return ret;
+}
+
+static inline void drv_sched_scan_stop(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
+{
+ might_sleep();
+
+ trace_drv_sched_scan_stop(local, sdata);
+ local->ops->sched_scan_stop(&local->hw, &sdata->vif);
+ trace_drv_return_void(local);
+}
+
static inline void drv_sw_scan_start(struct ieee80211_local *local)
{
might_sleep();
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 191e834..7c03091 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -438,6 +438,51 @@ TRACE_EVENT(drv_hw_scan,
)
);
+TRACE_EVENT(drv_sched_scan_start,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_sched_scan_request *req),
+
+ TP_ARGS(local, sdata, req),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT,
+ LOCAL_PR_ARG, VIF_PR_ARG
+ )
+);
+
+TRACE_EVENT(drv_sched_scan_stop,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata),
+
+ TP_ARGS(local, sdata),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT,
+ LOCAL_PR_ARG, VIF_PR_ARG
+ )
+);
+
DEFINE_EVENT(local_only_evt, drv_sw_scan_start,
TP_PROTO(struct ieee80211_local *local),
TP_ARGS(local)
@@ -1194,6 +1239,42 @@ TRACE_EVENT(api_scan_completed,
)
);
+TRACE_EVENT(api_sched_scan_results,
+ TP_PROTO(struct ieee80211_local *local),
+
+ TP_ARGS(local),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
+TRACE_EVENT(api_sched_scan_stopped,
+ TP_PROTO(struct ieee80211_local *local),
+
+ TP_ARGS(local),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT, LOCAL_PR_ARG
+ )
+);
+
TRACE_EVENT(api_sta_block_awake,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sta *sta, bool block),
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 027c046..5e20f96 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -840,6 +840,9 @@ struct ieee80211_local {
int scan_channel_idx;
int scan_ies_len;
+ bool sched_scanning;
+ struct ieee80211_sched_scan_ies sched_scan_ies;
+
unsigned long leave_oper_channel_time;
enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
@@ -1147,6 +1150,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
void ieee80211_rx_bss_put(struct ieee80211_local *local,
struct ieee80211_bss *bss);
+/* scheduled scan handling */
+int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_sched_scan_request *req);
+int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata,
+ bool driver_initiated);
+
/* off-channel helpers */
bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6187766..9a20671 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -47,7 +47,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
if (atomic_read(&local->iff_allmultis))
new_flags |= FIF_ALLMULTI;
- if (local->monitors || local->scanning)
+ if (local->monitors || local->scanning || local->sched_scanning)
new_flags |= FIF_BCN_PRBRESP_PROMISC;
if (local->fif_probe_req || local->probe_req_reg)
@@ -358,7 +358,8 @@ static void ieee80211_restart_work(struct work_struct *work)
flush_workqueue(local->workqueue);
mutex_lock(&local->mtx);
- WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
+ WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+ local->sched_scanning,
"%s called with hardware scan in progress\n", __func__);
mutex_unlock(&local->mtx);
@@ -827,6 +828,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (!local->ops->remain_on_channel)
local->hw.wiphy->max_remain_on_channel_duration = 5000;
+ if (local->ops->sched_scan_start)
+ local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
+
result = wiphy_register(local->hw.wiphy);
if (result < 0)
goto fail_wiphy_register;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 599fa90..1158164 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -408,7 +408,8 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
return RX_CONTINUE;
if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
- test_bit(SCAN_SW_SCANNING, &local->scanning))
+ test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ local->sched_scanning)
return ieee80211_scan_rx(rx->sdata, skb);
/* scanning finished during invoking of handlers */
@@ -2801,7 +2802,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
local->dot11ReceivedFragmentCount++;
if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
- test_bit(SCAN_SW_SCANNING, &local->scanning)))
+ test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ local->sched_scanning))
status->rx_flags |= IEEE80211_RX_IN_SCAN;
if (ieee80211_is_mgmt(fc))
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 489b6ad..07a021c 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -15,6 +15,7 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/pm_qos_params.h>
+#include <linux/slab.h>
#include <net/sch_generic.h>
#include <linux/slab.h>
#include <net/mac80211.h>
@@ -850,3 +851,101 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
}
mutex_unlock(&local->mtx);
}
+
+int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct ieee80211_local *local = sdata->local;
+ int ret, i;
+
+ mutex_lock(&sdata->local->mtx);
+
+ if (local->sched_scanning) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (!local->ops->sched_scan_start) {
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+ local->sched_scan_ies.ie[i] = kzalloc(2 +
+ IEEE80211_MAX_SSID_LEN +
+ local->scan_ies_len,
+ GFP_KERNEL);
+ if (!local->sched_scan_ies.ie[i]) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ local->sched_scan_ies.len[i] =
+ ieee80211_build_preq_ies(local,
+ local->sched_scan_ies.ie[i],
+ req->ie, req->ie_len, i,
+ (u32) -1, 0);
+ }
+
+ ret = drv_sched_scan_start(local, sdata, req,
+ &local->sched_scan_ies);
+ if (!ret)
+ local->sched_scanning = true;
+out:
+ mutex_unlock(&sdata->local->mtx);
+
+ return ret;
+
+out_free:
+ while (i > 0)
+ kfree(local->sched_scan_ies.ie[--i]);
+ goto out;
+}
+
+int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata,
+ bool driver_initiated)
+{
+ struct ieee80211_local *local = sdata->local;
+ int ret = 0, i;
+
+ mutex_lock(&sdata->local->mtx);
+
+ if (!local->ops->sched_scan_stop) {
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ if (local->sched_scanning) {
+ for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+ kfree(local->sched_scan_ies.ie[i]);
+
+ if (!driver_initiated)
+ drv_sched_scan_stop(local, sdata);
+ local->sched_scanning = false;
+ }
+
+out:
+ mutex_unlock(&sdata->local->mtx);
+
+ return ret;
+}
+
+void ieee80211_sched_scan_results(struct ieee80211_hw *hw)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+
+ trace_api_sched_scan_results(local);
+
+ cfg80211_sched_scan_results(hw->wiphy);
+}
+EXPORT_SYMBOL(ieee80211_sched_scan_results);
+
+void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+
+ trace_api_sched_scan_stopped(local);
+
+ cfg80211_sched_scan_stopped(hw->wiphy);
+}
+EXPORT_SYMBOL(ieee80211_sched_scan_stopped);
--
1.7.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 13:00 [PATCH 0/3] cfg80211/mac80211: implementation of scheduled scan Luciano Coelho
2011-05-05 13:00 ` [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans Luciano Coelho
2011-05-05 13:00 ` [PATCH 2/3] mac80211: add support for HW scheduled scan Luciano Coelho
@ 2011-05-05 13:00 ` Luciano Coelho
2011-05-05 14:43 ` Ben Greear
2 siblings, 1 reply; 23+ messages in thread
From: Luciano Coelho @ 2011-05-05 13:00 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville
Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
intervals the scheduled scan cycles should be executed.
Signed-off-by: Luciano Coelho <coelho@ti.com>
---
include/linux/nl80211.h | 24 +++++++++++++++---------
include/net/cfg80211.h | 2 ++
net/wireless/nl80211.c | 10 ++++++++++
3 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 355fb65..2ab1b92 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -203,15 +203,17 @@
* @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
* partial scan results may be available
*
- * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan. Like with normal
- * scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) are passed, they are used
- * in the probe requests. For broadcast, a broadcast SSID must be
- * passed (ie. an empty string). If no SSID is passed, no probe
- * requests are sent and a passive scan is performed.
- * %NL80211_ATTR_SCAN_FREQUENCIES, if passed, define which channels
- * should be scanned; if not passed, all channels allowed for the
- * current regulatory domain are used. Extra IEs can also be passed
- * from the userspace by using the %NL80211_ATTR_IE attribute.
+ * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain
+ * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL.
+ * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS)
+ * are passed, they are used in the probe requests. For
+ * broadcast, a broadcast SSID must be passed (ie. an empty
+ * string). If no SSID is passed, no probe requests are sent and
+ * a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES,
+ * if passed, define which channels should be scanned; if not
+ * passed, all channels allowed for the current regulatory domain
+ * are used. Extra IEs can also be passed from the userspace by
+ * using the %NL80211_ATTR_IE attribute.
* @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan
* @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan
* results available.
@@ -927,6 +929,8 @@ enum nl80211_commands {
* @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
* allows auth frames in a mesh to be passed to userspace for processing via
* the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
+ * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan
+ * cycles, in msecs.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1117,6 +1121,8 @@ enum nl80211_attrs {
NL80211_ATTR_SUPPORT_MESH_AUTH,
+ NL80211_ATTR_SCHED_SCAN_INTERVAL,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 117df56..d0460ee 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -798,6 +798,7 @@ struct cfg80211_scan_request {
* @ssids: SSIDs to report (other SSIDs will be filtered out)
* @n_ssids: number of SSIDs
* @n_channels: total number of channels to scan
+ * @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
* @wiphy: the wiphy this was for
@@ -808,6 +809,7 @@ struct cfg80211_sched_scan_request {
struct cfg80211_ssid *ssids;
int n_ssids;
u32 n_channels;
+ u32 interval;
const u8 *ie;
size_t ie_len;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a971501..5e1bb00 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -173,6 +173,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
[NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
[NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
+ [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
};
/* policy for the key attributes */
@@ -3331,6 +3332,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
struct nlattr *attr;
struct wiphy *wiphy;
int err, tmp, n_ssids = 0, n_channels, i;
+ u32 interval;
enum ieee80211_band band;
size_t ie_len;
@@ -3344,6 +3346,13 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
if (rdev->sched_scan_req)
return -EINPROGRESS;
+ if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
+ return -EINVAL;
+
+ interval = nla_get_u32(info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
+ if (interval == 0)
+ return -EINVAL;
+
wiphy = &rdev->wiphy;
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
@@ -3466,6 +3475,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
request->dev = dev;
request->wiphy = &rdev->wiphy;
+ request->interval = interval;
rdev->sched_scan_req = request;
--
1.7.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 13:00 ` [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans Luciano Coelho
@ 2011-05-05 14:43 ` Ben Greear
2011-05-05 14:51 ` Johannes Berg
0 siblings, 1 reply; 23+ messages in thread
From: Ben Greear @ 2011-05-05 14:43 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless, johannes, linville
On 05/05/2011 06:00 AM, Luciano Coelho wrote:
> Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
> NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
> intervals the scheduled scan cycles should be executed.
Please default to something useful instead of requiring
this so that things are backwards compatible.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 14:51 ` Johannes Berg
@ 2011-05-05 14:50 ` Ben Greear
2011-05-05 14:58 ` Johannes Berg
0 siblings, 1 reply; 23+ messages in thread
From: Ben Greear @ 2011-05-05 14:50 UTC (permalink / raw)
To: Johannes Berg; +Cc: Luciano Coelho, linux-wireless, linville
On 05/05/2011 07:51 AM, Johannes Berg wrote:
> On Thu, 2011-05-05 at 07:43 -0700, Ben Greear wrote:
>> On 05/05/2011 06:00 AM, Luciano Coelho wrote:
>>> Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
>>> NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
>>> intervals the scheduled scan cycles should be executed.
>>
>> Please default to something useful instead of requiring
>> this so that things are backwards compatible.
>
> Backward compatible to what?
To anything sending older style netlink messages?
Thanks,
Ben
>
> johannes
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 14:43 ` Ben Greear
@ 2011-05-05 14:51 ` Johannes Berg
2011-05-05 14:50 ` Ben Greear
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2011-05-05 14:51 UTC (permalink / raw)
To: Ben Greear; +Cc: Luciano Coelho, linux-wireless, linville
On Thu, 2011-05-05 at 07:43 -0700, Ben Greear wrote:
> On 05/05/2011 06:00 AM, Luciano Coelho wrote:
> > Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
> > NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
> > intervals the scheduled scan cycles should be executed.
>
> Please default to something useful instead of requiring
> this so that things are backwards compatible.
Backward compatible to what?
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 14:50 ` Ben Greear
@ 2011-05-05 14:58 ` Johannes Berg
2011-05-05 14:59 ` Johannes Berg
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2011-05-05 14:58 UTC (permalink / raw)
To: Ben Greear; +Cc: Luciano Coelho, linux-wireless, linville
On Thu, 2011-05-05 at 07:50 -0700, Ben Greear wrote:
> On 05/05/2011 07:51 AM, Johannes Berg wrote:
> > On Thu, 2011-05-05 at 07:43 -0700, Ben Greear wrote:
> >> On 05/05/2011 06:00 AM, Luciano Coelho wrote:
> >>> Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
> >>> NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
> >>> intervals the scheduled scan cycles should be executed.
> >>
> >> Please default to something useful instead of requiring
> >> this so that things are backwards compatible.
> >
> > Backward compatible to what?
>
> To anything sending older style netlink messages?
But this is a new feature, and a new command, so I don't quite
understand why an application would think it can send it without the
interval?
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 14:58 ` Johannes Berg
@ 2011-05-05 14:59 ` Johannes Berg
2011-05-05 15:48 ` Luciano Coelho
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2011-05-05 14:59 UTC (permalink / raw)
To: Ben Greear; +Cc: Luciano Coelho, linux-wireless, linville
On Thu, 2011-05-05 at 16:58 +0200, Johannes Berg wrote:
> On Thu, 2011-05-05 at 07:50 -0700, Ben Greear wrote:
> > On 05/05/2011 07:51 AM, Johannes Berg wrote:
> > > On Thu, 2011-05-05 at 07:43 -0700, Ben Greear wrote:
> > >> On 05/05/2011 06:00 AM, Luciano Coelho wrote:
> > >>> Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
> > >>> NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
> > >>> intervals the scheduled scan cycles should be executed.
> > >>
> > >> Please default to something useful instead of requiring
> > >> this so that things are backwards compatible.
> > >
> > > Backward compatible to what?
> >
> > To anything sending older style netlink messages?
>
> But this is a new feature, and a new command, so I don't quite
> understand why an application would think it can send it without the
> interval?
Oh wait, I guess you're right, or this should just be part of patch 1
instead so we never have the feature without the requirement to have the
interval given.
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 14:59 ` Johannes Berg
@ 2011-05-05 15:48 ` Luciano Coelho
2011-05-05 15:51 ` Luciano Coelho
0 siblings, 1 reply; 23+ messages in thread
From: Luciano Coelho @ 2011-05-05 15:48 UTC (permalink / raw)
To: Johannes Berg; +Cc: Ben Greear, linux-wireless, linville
On Thu, 2011-05-05 at 16:59 +0200, Johannes Berg wrote:
> On Thu, 2011-05-05 at 16:58 +0200, Johannes Berg wrote:
> > On Thu, 2011-05-05 at 07:50 -0700, Ben Greear wrote:
> > > On 05/05/2011 07:51 AM, Johannes Berg wrote:
> > > > On Thu, 2011-05-05 at 07:43 -0700, Ben Greear wrote:
> > > >> On 05/05/2011 06:00 AM, Luciano Coelho wrote:
> > > >>> Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
> > > >>> NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
> > > >>> intervals the scheduled scan cycles should be executed.
> > > >>
> > > >> Please default to something useful instead of requiring
> > > >> this so that things are backwards compatible.
> > > >
> > > > Backward compatible to what?
> > >
> > > To anything sending older style netlink messages?
> >
> > But this is a new feature, and a new command, so I don't quite
> > understand why an application would think it can send it without the
> > interval?
>
> Oh wait, I guess you're right, or this should just be part of patch 1
> instead so we never have the feature without the requirement to have the
> interval given.
Yeah, I could squish this with the previous patch (1/3), but I just
reckoned that patch was getting too big, so I decided to make a separate
one.
If this whole patch series is taken at the same time, I guess there
won't be backwards compatibility problems (except for bisecting,
maybe?).
Anyways, I'll leave it as your choice. Squishing the patch is easy
enough. ;)
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 15:48 ` Luciano Coelho
@ 2011-05-05 15:51 ` Luciano Coelho
2011-05-05 16:13 ` Johannes Berg
0 siblings, 1 reply; 23+ messages in thread
From: Luciano Coelho @ 2011-05-05 15:51 UTC (permalink / raw)
To: Johannes Berg; +Cc: Ben Greear, linux-wireless, linville
On Thu, 2011-05-05 at 18:48 +0300, Luciano Coelho wrote:
> On Thu, 2011-05-05 at 16:59 +0200, Johannes Berg wrote:
> > On Thu, 2011-05-05 at 16:58 +0200, Johannes Berg wrote:
> > > On Thu, 2011-05-05 at 07:50 -0700, Ben Greear wrote:
> > > > On 05/05/2011 07:51 AM, Johannes Berg wrote:
> > > > > On Thu, 2011-05-05 at 07:43 -0700, Ben Greear wrote:
> > > > >> On 05/05/2011 06:00 AM, Luciano Coelho wrote:
> > > > >>> Introduce NL80211_ATTR_SCHED_SCAN_INTERVAL as a required attribute for
> > > > >>> NL80211_CMD_START_SCHED_SCAN. This value informs the driver at which
> > > > >>> intervals the scheduled scan cycles should be executed.
> > > > >>
> > > > >> Please default to something useful instead of requiring
> > > > >> this so that things are backwards compatible.
> > > > >
> > > > > Backward compatible to what?
> > > >
> > > > To anything sending older style netlink messages?
> > >
> > > But this is a new feature, and a new command, so I don't quite
> > > understand why an application would think it can send it without the
> > > interval?
> >
> > Oh wait, I guess you're right, or this should just be part of patch 1
> > instead so we never have the feature without the requirement to have the
> > interval given.
>
> Yeah, I could squish this with the previous patch (1/3), but I just
> reckoned that patch was getting too big, so I decided to make a separate
> one.
>
> If this whole patch series is taken at the same time, I guess there
> won't be backwards compatibility problems (except for bisecting,
> maybe?).
>
> Anyways, I'll leave it as your choice. Squishing the patch is easy
> enough. ;)
Ah, and one more thought... There's no driver implementing this at this
point, so is there anything to really worry about?
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 15:51 ` Luciano Coelho
@ 2011-05-05 16:13 ` Johannes Berg
2011-05-05 16:22 ` Ben Greear
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2011-05-05 16:13 UTC (permalink / raw)
To: Luciano Coelho; +Cc: Ben Greear, linux-wireless, linville
On Thu, 2011-05-05 at 18:51 +0300, Luciano Coelho wrote:
> > > > But this is a new feature, and a new command, so I don't quite
> > > > understand why an application would think it can send it without the
> > > > interval?
> > >
> > > Oh wait, I guess you're right, or this should just be part of patch 1
> > > instead so we never have the feature without the requirement to have the
> > > interval given.
> >
> > Yeah, I could squish this with the previous patch (1/3), but I just
> > reckoned that patch was getting too big, so I decided to make a separate
> > one.
> >
> > If this whole patch series is taken at the same time, I guess there
> > won't be backwards compatibility problems (except for bisecting,
> > maybe?).
> >
> > Anyways, I'll leave it as your choice. Squishing the patch is easy
> > enough. ;)
>
> Ah, and one more thought... There's no driver implementing this at this
> point, so is there anything to really worry about?
Yeah, good point, no big deal. We can keep it -- I just didn't even
understand why Ben thought it would not be compatible but it makes sense
if you just look at the patch by itself.
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 16:13 ` Johannes Berg
@ 2011-05-05 16:22 ` Ben Greear
2011-05-05 16:29 ` Luciano Coelho
0 siblings, 1 reply; 23+ messages in thread
From: Ben Greear @ 2011-05-05 16:22 UTC (permalink / raw)
To: Johannes Berg; +Cc: Luciano Coelho, linux-wireless, linville
On 05/05/2011 09:13 AM, Johannes Berg wrote:
> On Thu, 2011-05-05 at 18:51 +0300, Luciano Coelho wrote:
>
>>>>> But this is a new feature, and a new command, so I don't quite
>>>>> understand why an application would think it can send it without the
>>>>> interval?
>>>>
>>>> Oh wait, I guess you're right, or this should just be part of patch 1
>>>> instead so we never have the feature without the requirement to have the
>>>> interval given.
>>>
>>> Yeah, I could squish this with the previous patch (1/3), but I just
>>> reckoned that patch was getting too big, so I decided to make a separate
>>> one.
>>>
>>> If this whole patch series is taken at the same time, I guess there
>>> won't be backwards compatibility problems (except for bisecting,
>>> maybe?).
>>>
>>> Anyways, I'll leave it as your choice. Squishing the patch is easy
>>> enough. ;)
>>
>> Ah, and one more thought... There's no driver implementing this at this
>> point, so is there anything to really worry about?
>
> Yeah, good point, no big deal. We can keep it -- I just didn't even
> understand why Ben thought it would not be compatible but it makes sense
> if you just look at the patch by itself.
I was a bit confused..didn't realize it was a new command that had just
been added. I thought someone was adding a required member to the existing
scan logic.
So, I have no complaints.
Thanks,
Ben
>
> johannes
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans
2011-05-05 16:22 ` Ben Greear
@ 2011-05-05 16:29 ` Luciano Coelho
0 siblings, 0 replies; 23+ messages in thread
From: Luciano Coelho @ 2011-05-05 16:29 UTC (permalink / raw)
To: Ben Greear; +Cc: Johannes Berg, linux-wireless, linville
On Thu, 2011-05-05 at 09:22 -0700, Ben Greear wrote:
> On 05/05/2011 09:13 AM, Johannes Berg wrote:
> > On Thu, 2011-05-05 at 18:51 +0300, Luciano Coelho wrote:
> >> Ah, and one more thought... There's no driver implementing this at this
> >> point, so is there anything to really worry about?
> >
> > Yeah, good point, no big deal. We can keep it -- I just didn't even
> > understand why Ben thought it would not be compatible but it makes sense
> > if you just look at the patch by itself.
>
> I was a bit confused..didn't realize it was a new command that had just
> been added. I thought someone was adding a required member to the existing
> scan logic.
>
> So, I have no complaints.
Okay, great. Thanks a lot for looking into it! :)
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans
2011-05-05 13:00 ` [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans Luciano Coelho
@ 2011-05-09 8:12 ` Johannes Berg
2011-05-09 8:17 ` Luciano Coelho
2011-05-09 9:50 ` Eliad Peller
1 sibling, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2011-05-09 8:12 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless, linville
On Thu, 2011-05-05 at 16:00 +0300, Luciano Coelho wrote:
> Implement new functionality for scheduled scan offload. With this feature we
> can scan automatically at certain intervals.
>
> The idea is that the hardware can perform scan automatically and filter on
> desired results without waking up the host unnecessarily.
>
> Add NL80211_CMD_START_SCHED_SCAN and NL80211_CMD_STOP_SCHED_SCAN
> commands to the nl80211 interface. When results are available they are
> reported by NL80211_CMD_SCHED_SCAN_RESULTS events. The userspace is
> informed when the scheduled scan has stopped with a
> NL80211_CMD_SCHED_SCAN_STOPPED event, which can be triggered either by
> the driver or by a call to NL80211_CMD_STOP_SCHED_SCAN.
Didn't you initially want to differentiate between SCAN_SSIDS and
SSIDS_FILTER?
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans
2011-05-09 8:12 ` Johannes Berg
@ 2011-05-09 8:17 ` Luciano Coelho
2011-05-09 8:23 ` Johannes Berg
0 siblings, 1 reply; 23+ messages in thread
From: Luciano Coelho @ 2011-05-09 8:17 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linville
On Mon, 2011-05-09 at 10:12 +0200, Johannes Berg wrote:
> On Thu, 2011-05-05 at 16:00 +0300, Luciano Coelho wrote:
> > Implement new functionality for scheduled scan offload. With this feature we
> > can scan automatically at certain intervals.
> >
> > The idea is that the hardware can perform scan automatically and filter on
> > desired results without waking up the host unnecessarily.
> >
> > Add NL80211_CMD_START_SCHED_SCAN and NL80211_CMD_STOP_SCHED_SCAN
> > commands to the nl80211 interface. When results are available they are
> > reported by NL80211_CMD_SCHED_SCAN_RESULTS events. The userspace is
> > informed when the scheduled scan has stopped with a
> > NL80211_CMD_SCHED_SCAN_STOPPED event, which can be triggered either by
> > the driver or by a call to NL80211_CMD_STOP_SCHED_SCAN.
>
> Didn't you initially want to differentiate between SCAN_SSIDS and
> SSIDS_FILTER?
Yes, I'll add SSID filtering soon, as separate patches, if that's okay.
For now, the SSIDs that you can pass via nl80211 are used in the
probe_reqs.
We can also filter on RSSI, SNR and/or group results into one event.
This are other features that our firmware supports. For now I have not
exposed this, but it could also be added to nl80211 in the future.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/3] mac80211: add support for HW scheduled scan
2011-05-05 13:00 ` [PATCH 2/3] mac80211: add support for HW scheduled scan Luciano Coelho
@ 2011-05-09 8:22 ` Johannes Berg
2011-05-09 8:22 ` Johannes Berg
2011-05-09 13:38 ` Luciano Coelho
0 siblings, 2 replies; 23+ messages in thread
From: Johannes Berg @ 2011-05-09 8:22 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless, linville
On Thu, 2011-05-05 at 16:00 +0300, Luciano Coelho wrote:
> +TRACE_EVENT(drv_sched_scan_start,
> + TP_PROTO(struct ieee80211_local *local,
> + struct ieee80211_sub_if_data *sdata,
> + struct cfg80211_sched_scan_request *req),
Since you're not tracing "req" (right now), could you please use
DECLARE_EVENT_CLASS() and define a common class for this and some others
that only have local and sdata?
> +TRACE_EVENT(api_sched_scan_results,
> + TP_PROTO(struct ieee80211_local *local),
and use the local_only_evt class here, cf. drv_start() for example.
> +TRACE_EVENT(api_sched_scan_stopped,
> + TP_PROTO(struct ieee80211_local *local),
ditto.
Also -- no API tracers for results/stopped?
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 6187766..9a20671 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -47,7 +47,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
> if (atomic_read(&local->iff_allmultis))
> new_flags |= FIF_ALLMULTI;
>
> - if (local->monitors || local->scanning)
> + if (local->monitors || local->scanning || local->sched_scanning)
> new_flags |= FIF_BCN_PRBRESP_PROMISC;
Hmm, that seems like an implementation detail of the driver in this
case. I'd rather not do this here, other drivers might not have a
special filter they need for scheduled scans.
> @@ -358,7 +358,8 @@ static void ieee80211_restart_work(struct work_struct *work)
> flush_workqueue(local->workqueue);
>
> mutex_lock(&local->mtx);
> - WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
> + WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
> + local->sched_scanning,
> "%s called with hardware scan in progress\n", __func__);
> mutex_unlock(&local->mtx);
Good catch, I should've thought of that in the remain-on-channel stuff,
would've saved me some debugging :)
> diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
> index 599fa90..1158164 100644
> --- a/net/mac80211/rx.c
> +++ b/net/mac80211/rx.c
> @@ -408,7 +408,8 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
> return RX_CONTINUE;
>
> if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
> - test_bit(SCAN_SW_SCANNING, &local->scanning))
> + test_bit(SCAN_SW_SCANNING, &local->scanning) ||
> + local->sched_scanning)
> return ieee80211_scan_rx(rx->sdata, skb);
I'm still not convinced that this is right.
> @@ -2801,7 +2802,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
> local->dot11ReceivedFragmentCount++;
>
> if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
> - test_bit(SCAN_SW_SCANNING, &local->scanning)))
> + test_bit(SCAN_SW_SCANNING, &local->scanning) ||
> + local->sched_scanning))
> status->rx_flags |= IEEE80211_RX_IN_SCAN;
Nor this I guess, though we don't use this much of course.
> + ret = drv_sched_scan_start(local, sdata, req,
> + &local->sched_scan_ies);
> + if (!ret)
> + local->sched_scanning = true;
> +out:
> + mutex_unlock(&sdata->local->mtx);
> +
> + return ret;
> +
> +out_free:
> + while (i > 0)
> + kfree(local->sched_scan_ies.ie[--i]);
> + goto out;
Not freeing it when the driver callback fails?
Seems like you should reorder:
ret = drv...();
if (ret == 0) {
... = true;
goto out;
}
out_free:
...
out:
...
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/3] mac80211: add support for HW scheduled scan
2011-05-09 8:22 ` Johannes Berg
@ 2011-05-09 8:22 ` Johannes Berg
2011-05-09 13:38 ` Luciano Coelho
1 sibling, 0 replies; 23+ messages in thread
From: Johannes Berg @ 2011-05-09 8:22 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless, linville
On Mon, 2011-05-09 at 10:22 +0200, Johannes Berg wrote:
> > +TRACE_EVENT(api_sched_scan_stopped,
> > + TP_PROTO(struct ieee80211_local *local),
>
> ditto.
>
>
> Also -- no API tracers for results/stopped?
Err ... sorry!
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans
2011-05-09 8:17 ` Luciano Coelho
@ 2011-05-09 8:23 ` Johannes Berg
2011-05-09 8:25 ` Luciano Coelho
0 siblings, 1 reply; 23+ messages in thread
From: Johannes Berg @ 2011-05-09 8:23 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless, linville
On Mon, 2011-05-09 at 11:17 +0300, Luciano Coelho wrote:
> > Didn't you initially want to differentiate between SCAN_SSIDS and
> > SSIDS_FILTER?
>
> Yes, I'll add SSID filtering soon, as separate patches, if that's okay.
> For now, the SSIDs that you can pass via nl80211 are used in the
> probe_reqs.
>
> We can also filter on RSSI, SNR and/or group results into one event.
> This are other features that our firmware supports. For now I have not
> exposed this, but it could also be added to nl80211 in the future.
Ok, makes sense. However:
> + * struct cfg80211_sched_scan_request - scheduled scan request
> description
> + *
> + * @ssids: SSIDs to report (other SSIDs will be filtered out)
That's wrong then, no?
johannes
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans
2011-05-09 8:23 ` Johannes Berg
@ 2011-05-09 8:25 ` Luciano Coelho
0 siblings, 0 replies; 23+ messages in thread
From: Luciano Coelho @ 2011-05-09 8:25 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linville
On Mon, 2011-05-09 at 10:23 +0200, Johannes Berg wrote:
> On Mon, 2011-05-09 at 11:17 +0300, Luciano Coelho wrote:
>
> > > Didn't you initially want to differentiate between SCAN_SSIDS and
> > > SSIDS_FILTER?
> >
> > Yes, I'll add SSID filtering soon, as separate patches, if that's okay.
> > For now, the SSIDs that you can pass via nl80211 are used in the
> > probe_reqs.
> >
> > We can also filter on RSSI, SNR and/or group results into one event.
> > This are other features that our firmware supports. For now I have not
> > exposed this, but it could also be added to nl80211 in the future.
>
> Ok, makes sense. However:
>
> > + * struct cfg80211_sched_scan_request - scheduled scan request
> > description
> > + *
> > + * @ssids: SSIDs to report (other SSIDs will be filtered out)
>
> That's wrong then, no?
Yes, you're right. I'll fix this.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans
2011-05-05 13:00 ` [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans Luciano Coelho
2011-05-09 8:12 ` Johannes Berg
@ 2011-05-09 9:50 ` Eliad Peller
2011-05-09 13:59 ` Luciano Coelho
1 sibling, 1 reply; 23+ messages in thread
From: Eliad Peller @ 2011-05-09 9:50 UTC (permalink / raw)
To: Luciano Coelho; +Cc: linux-wireless, johannes, linville
On Thu, May 5, 2011 at 4:00 PM, Luciano Coelho <coelho@ti.com> wrote:
> Implement new functionality for scheduled scan offload. With this feature we
> can scan automatically at certain intervals.
>
> The idea is that the hardware can perform scan automatically and filter on
> desired results without waking up the host unnecessarily.
>
> Add NL80211_CMD_START_SCHED_SCAN and NL80211_CMD_STOP_SCHED_SCAN
> commands to the nl80211 interface. When results are available they are
> reported by NL80211_CMD_SCHED_SCAN_RESULTS events. The userspace is
> informed when the scheduled scan has stopped with a
> NL80211_CMD_SCHED_SCAN_STOPPED event, which can be triggered either by
> the driver or by a call to NL80211_CMD_STOP_SCHED_SCAN.
>
> Signed-off-by: Luciano Coelho <coelho@ti.com>
> ---
[...]
> +
> + err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
> + if (!err)
> + nl80211_send_sched_scan(rdev, dev,
> + NL80211_CMD_START_SCHED_SCAN);
> + else {
> +out_free:
> + kfree(request);
> + rdev->sched_scan_req = NULL;
> + }
> +
> + return err;
> +}
i know it's the same in nl80211_trigger_scan(), but it still looks
very odd - goto into else block?!
Eliad.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 2/3] mac80211: add support for HW scheduled scan
2011-05-09 8:22 ` Johannes Berg
2011-05-09 8:22 ` Johannes Berg
@ 2011-05-09 13:38 ` Luciano Coelho
1 sibling, 0 replies; 23+ messages in thread
From: Luciano Coelho @ 2011-05-09 13:38 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, linville
On Mon, 2011-05-09 at 10:22 +0200, Johannes Berg wrote:
> On Thu, 2011-05-05 at 16:00 +0300, Luciano Coelho wrote:
>
> > +TRACE_EVENT(drv_sched_scan_start,
> > + TP_PROTO(struct ieee80211_local *local,
> > + struct ieee80211_sub_if_data *sdata,
> > + struct cfg80211_sched_scan_request *req),
>
> Since you're not tracing "req" (right now), could you please use
> DECLARE_EVENT_CLASS() and define a common class for this and some others
> that only have local and sdata?
>
> > +TRACE_EVENT(api_sched_scan_results,
> > + TP_PROTO(struct ieee80211_local *local),
>
> and use the local_only_evt class here, cf. drv_start() for example.
>
> > +TRACE_EVENT(api_sched_scan_stopped,
> > + TP_PROTO(struct ieee80211_local *local),
>
> ditto.
Sent a patch that combines a couple of traces into a class. I also will
change my sched_scan patch so that hw_scan and sched_start/sched_stop
are combined into a new class.
> Also -- no API tracers for results/stopped?
>
> > diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> > index 6187766..9a20671 100644
> > --- a/net/mac80211/main.c
> > +++ b/net/mac80211/main.c
> > @@ -47,7 +47,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
> > if (atomic_read(&local->iff_allmultis))
> > new_flags |= FIF_ALLMULTI;
> >
> > - if (local->monitors || local->scanning)
> > + if (local->monitors || local->scanning || local->sched_scanning)
> > new_flags |= FIF_BCN_PRBRESP_PROMISC;
>
> Hmm, that seems like an implementation detail of the driver in this
> case. I'd rather not do this here, other drivers might not have a
> special filter they need for scheduled scans.
You're right, we don't really need this. I'll remove it.
> > @@ -358,7 +358,8 @@ static void ieee80211_restart_work(struct work_struct *work)
> > flush_workqueue(local->workqueue);
> >
> > mutex_lock(&local->mtx);
> > - WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
> > + WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
> > + local->sched_scanning,
> > "%s called with hardware scan in progress\n", __func__);
> > mutex_unlock(&local->mtx);
>
>
> Good catch, I should've thought of that in the remain-on-channel stuff,
> would've saved me some debugging :)
:)
> > diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
> > index 599fa90..1158164 100644
> > --- a/net/mac80211/rx.c
> > +++ b/net/mac80211/rx.c
> > @@ -408,7 +408,8 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
> > return RX_CONTINUE;
> >
> > if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
> > - test_bit(SCAN_SW_SCANNING, &local->scanning))
> > + test_bit(SCAN_SW_SCANNING, &local->scanning) ||
> > + local->sched_scanning)
> > return ieee80211_scan_rx(rx->sdata, skb);
>
> I'm still not convinced that this is right.
As we discussed on IRC, it seems that this is indeed safe to do, as long
as we remove the check that drops frames smaller than 24 bytes in
length. As we agreed, I will do that in a separate patch.
> > @@ -2801,7 +2802,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
> > local->dot11ReceivedFragmentCount++;
> >
> > if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
> > - test_bit(SCAN_SW_SCANNING, &local->scanning)))
> > + test_bit(SCAN_SW_SCANNING, &local->scanning) ||
> > + local->sched_scanning))
> > status->rx_flags |= IEEE80211_RX_IN_SCAN;
>
> Nor this I guess, though we don't use this much of course.
You're right here. The reason why I was doing this was so that the
ieee80211_rx_h_passive_scan() would not return immediately. But this
would affect the IEEE80211_RX_RA_MATCH handling in ad-hoc ad AP.
I will add a different check in ieee80211_rx_h_passive_scan() instead.
> > + ret = drv_sched_scan_start(local, sdata, req,
> > + &local->sched_scan_ies);
> > + if (!ret)
> > + local->sched_scanning = true;
> > +out:
> > + mutex_unlock(&sdata->local->mtx);
> > +
> > + return ret;
> > +
> > +out_free:
> > + while (i > 0)
> > + kfree(local->sched_scan_ies.ie[--i]);
> > + goto out;
>
> Not freeing it when the driver callback fails?
>
> Seems like you should reorder:
> ret = drv...();
> if (ret == 0) {
> ... = true;
> goto out;
> }
> out_free:
> ...
> out:
> ...
Oops! I wonder where this mess came from. out_free calling goto out?
Horrible. I will fix it.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans
2011-05-09 9:50 ` Eliad Peller
@ 2011-05-09 13:59 ` Luciano Coelho
0 siblings, 0 replies; 23+ messages in thread
From: Luciano Coelho @ 2011-05-09 13:59 UTC (permalink / raw)
To: Eliad Peller; +Cc: linux-wireless, johannes, linville
On Mon, 2011-05-09 at 12:50 +0300, Eliad Peller wrote:
> On Thu, May 5, 2011 at 4:00 PM, Luciano Coelho <coelho@ti.com> wrote:
> > Implement new functionality for scheduled scan offload. With this feature we
> > can scan automatically at certain intervals.
> >
> > The idea is that the hardware can perform scan automatically and filter on
> > desired results without waking up the host unnecessarily.
> >
> > Add NL80211_CMD_START_SCHED_SCAN and NL80211_CMD_STOP_SCHED_SCAN
> > commands to the nl80211 interface. When results are available they are
> > reported by NL80211_CMD_SCHED_SCAN_RESULTS events. The userspace is
> > informed when the scheduled scan has stopped with a
> > NL80211_CMD_SCHED_SCAN_STOPPED event, which can be triggered either by
> > the driver or by a call to NL80211_CMD_STOP_SCHED_SCAN.
> >
> > Signed-off-by: Luciano Coelho <coelho@ti.com>
> > ---
> [...]
>
> > +
> > + err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request);
> > + if (!err)
> > + nl80211_send_sched_scan(rdev, dev,
> > + NL80211_CMD_START_SCHED_SCAN);
> > + else {
> > +out_free:
> > + kfree(request);
> > + rdev->sched_scan_req = NULL;
> > + }
> > +
> > + return err;
> > +}
>
> i know it's the same in nl80211_trigger_scan(), but it still looks
> very odd - goto into else block?!
Good point, looks a bit ugly and it was indeed copied. I'll clean it up
a bit.
--
Cheers,
Luca.
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2011-05-09 13:59 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-05 13:00 [PATCH 0/3] cfg80211/mac80211: implementation of scheduled scan Luciano Coelho
2011-05-05 13:00 ` [PATCH 1/3] cfg80211/nl80211: add support for scheduled scans Luciano Coelho
2011-05-09 8:12 ` Johannes Berg
2011-05-09 8:17 ` Luciano Coelho
2011-05-09 8:23 ` Johannes Berg
2011-05-09 8:25 ` Luciano Coelho
2011-05-09 9:50 ` Eliad Peller
2011-05-09 13:59 ` Luciano Coelho
2011-05-05 13:00 ` [PATCH 2/3] mac80211: add support for HW scheduled scan Luciano Coelho
2011-05-09 8:22 ` Johannes Berg
2011-05-09 8:22 ` Johannes Berg
2011-05-09 13:38 ` Luciano Coelho
2011-05-05 13:00 ` [PATCH 3/3] cfg80211/nl80211: add interval attribute for scheduled scans Luciano Coelho
2011-05-05 14:43 ` Ben Greear
2011-05-05 14:51 ` Johannes Berg
2011-05-05 14:50 ` Ben Greear
2011-05-05 14:58 ` Johannes Berg
2011-05-05 14:59 ` Johannes Berg
2011-05-05 15:48 ` Luciano Coelho
2011-05-05 15:51 ` Luciano Coelho
2011-05-05 16:13 ` Johannes Berg
2011-05-05 16:22 ` Ben Greear
2011-05-05 16:29 ` Luciano Coelho
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).