Skip to content

Commit

Permalink
cfg80211/nl80211: add support for scheduled scans
Browse files Browse the repository at this point in the history
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>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Luciano Coelho authored and John W. Linville committed May 11, 2011
1 parent 6bdbdbf commit 807f8a8
Show file tree
Hide file tree
Showing 7 changed files with 424 additions and 1 deletion.
25 changes: 25 additions & 0 deletions include/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -545,6 +565,11 @@ enum nl80211_commands {
NL80211_CMD_GET_WOWLAN,
NL80211_CMD_SET_WOWLAN,

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 */
Expand Down
57 changes: 57 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,33 @@ struct cfg80211_scan_request {
struct ieee80211_channel *channels[0];
};

/**
* struct cfg80211_sched_scan_request - scheduled scan request description
*
* @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
* @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
*
Expand Down Expand Up @@ -1292,6 +1319,10 @@ struct cfg80211_wowlan {
* @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
Expand Down Expand Up @@ -1478,6 +1509,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);
};

/*
Expand Down Expand Up @@ -1522,6 +1559,7 @@ struct cfg80211_ops {
* @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
* @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),
Expand All @@ -1534,6 +1572,7 @@ enum wiphy_flags {
WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7),
WIPHY_FLAG_IBSS_RSN = BIT(8),
WIPHY_FLAG_MESH_AUTH = BIT(10),
WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11),
};

struct mac_address {
Expand Down Expand Up @@ -2354,6 +2393,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
*
Expand Down
12 changes: 11 additions & 1 deletion net/wireless/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -672,6 +673,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);
Expand Down Expand Up @@ -759,6 +765,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);
Expand Down
7 changes: 7 additions & 0 deletions net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -411,6 +414,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,
Expand Down
Loading

0 comments on commit 807f8a8

Please sign in to comment.