nl80211: Enhance abort scan to also abort the vendor scan

This commit enhances the abort scan implementation to also abort the
vendor scan, if one was used to trigger the scan.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Sunil Dutt 2016-11-30 10:04:38 +05:30 committed by Jouni Malinen
parent 1a793f5c2b
commit eeb34a432e
5 changed files with 101 additions and 18 deletions

View file

@ -458,6 +458,20 @@ struct wpa_driver_scan_params {
*/ */
const u8 *bssid; const u8 *bssid;
/**
* scan_cookie - Unique identification representing the scan request
*
* This scan_cookie carries a unique identification representing the
* scan request if the host driver/kernel supports concurrent scan
* requests. This cookie is returned from the corresponding driver
* interface.
*
* Note: Unlike other parameters in this structure, scan_cookie is used
* only to return information instead of setting parameters for the
* scan.
*/
u64 scan_cookie;
/* /*
* NOTE: Whenever adding new parameters here, please make sure * NOTE: Whenever adding new parameters here, please make sure
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with * wpa_scan_clone_params() and wpa_scan_free_params() get updated with
@ -3595,9 +3609,12 @@ struct wpa_driver_ops {
/** /**
* abort_scan - Request the driver to abort an ongoing scan * abort_scan - Request the driver to abort an ongoing scan
* @priv: Private driver interface data * @priv: Private driver interface data
* @scan_cookie: Cookie identifying the scan request. This is used only
* when the vendor interface QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
* was used to trigger scan. Otherwise, 0 is used.
* Returns 0 on success, -1 on failure * Returns 0 on success, -1 on failure
*/ */
int (*abort_scan)(void *priv); int (*abort_scan)(void *priv, u64 scan_cookie);
/** /**
* configure_data_frame_filters - Request to configure frame filters * configure_data_frame_filters - Request to configure frame filters

View file

@ -299,7 +299,7 @@ int wpa_driver_nl80211_sched_scan(void *priv,
int wpa_driver_nl80211_stop_sched_scan(void *priv); int wpa_driver_nl80211_stop_sched_scan(void *priv);
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv); struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv); void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
int wpa_driver_nl80211_abort_scan(void *priv); int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie);
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss, int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params); struct wpa_driver_scan_params *params);
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len); int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);

View file

@ -85,6 +85,62 @@ static int nl80211_get_noise_for_scan_results(
} }
static int nl80211_abort_scan(struct i802_bss *bss)
{
int ret;
struct nl_msg *msg;
struct wpa_driver_nl80211_data *drv = bss->drv;
wpa_printf(MSG_DEBUG, "nl80211: Abort scan");
msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)",
ret, strerror(-ret));
}
return ret;
}
#ifdef CONFIG_DRIVER_NL80211_QCA
static int nl80211_abort_vendor_scan(struct wpa_driver_nl80211_data *drv,
u64 scan_cookie)
{
struct nl_msg *msg;
struct nlattr *params;
int ret;
wpa_printf(MSG_DEBUG, "nl80211: Abort vendor scan with cookie 0x%llx",
(long long unsigned int) scan_cookie);
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
if (!msg ||
nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN) ||
!(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
nla_put_u64(msg, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, scan_cookie))
goto fail;
nla_nest_end(msg, params);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
wpa_printf(MSG_INFO,
"nl80211: Aborting vendor scan with cookie 0x%llx failed: ret=%d (%s)",
(long long unsigned int) scan_cookie, ret,
strerror(-ret));
goto fail;
}
return 0;
fail:
nlmsg_free(msg);
return -1;
}
#endif /* CONFIG_DRIVER_NL80211_QCA */
/** /**
* wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion
* @eloop_ctx: Driver private data * @eloop_ctx: Driver private data
@ -98,7 +154,15 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
struct wpa_driver_nl80211_data *drv = eloop_ctx; struct wpa_driver_nl80211_data *drv = eloop_ctx;
wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it"); wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
if (!wpa_driver_nl80211_abort_scan(drv->first_bss)) #ifdef CONFIG_DRIVER_NL80211_QCA
if (drv->vendor_scan_cookie &&
nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0) {
drv->vendor_scan_cookie = 0;
return;
}
#endif /* CONFIG_DRIVER_NL80211_QCA */
if (!drv->vendor_scan_cookie &&
nl80211_abort_scan(drv->first_bss) == 0)
return; return;
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan"); wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
@ -863,22 +927,21 @@ void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
} }
int wpa_driver_nl80211_abort_scan(void *priv) int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie)
{ {
struct i802_bss *bss = priv; struct i802_bss *bss = priv;
#ifdef CONFIG_DRIVER_NL80211_QCA
struct wpa_driver_nl80211_data *drv = bss->drv; struct wpa_driver_nl80211_data *drv = bss->drv;
int ret;
struct nl_msg *msg;
wpa_printf(MSG_DEBUG, "nl80211: Abort scan"); /*
msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN); * If scan_cookie is zero, a normal scan through kernel (cfg80211)
ret = send_and_recv_msgs(drv, msg, NULL, NULL); * was triggered, hence abort the cfg80211 scan instead of the vendor
if (ret) { * scan.
wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)", */
ret, strerror(-ret)); if (drv->scan_vendor_cmd_avail && scan_cookie)
} return nl80211_abort_vendor_scan(drv, scan_cookie);
#endif /* CONFIG_DRIVER_NL80211_QCA */
return ret; return nl80211_abort_scan(bss);
} }
@ -1056,6 +1119,8 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
drv->vendor_scan_cookie = cookie; drv->vendor_scan_cookie = cookie;
drv->scan_state = SCAN_REQUESTED; drv->scan_state = SCAN_REQUESTED;
/* Pass the cookie to the caller to help distinguish the scans. */
params->scan_cookie = cookie;
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx", "nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",

View file

@ -916,11 +916,12 @@ static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq); return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq);
} }
static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s) static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s,
u64 scan_cookie)
{ {
if (!wpa_s->driver->abort_scan) if (!wpa_s->driver->abort_scan)
return -1; return -1;
return wpa_s->driver->abort_scan(wpa_s->drv_priv); return wpa_s->driver->abort_scan(wpa_s->drv_priv, scan_cookie);
} }
static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s, static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s,

View file

@ -2633,7 +2633,7 @@ int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
if (scan_work && wpa_s->own_scan_running) { if (scan_work && wpa_s->own_scan_running) {
wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan"); wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
return wpa_drv_abort_scan(wpa_s); return wpa_drv_abort_scan(wpa_s, 0);
} }
return 0; return 0;