]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Enhance abort scan to also abort the vendor scan
authorSunil Dutt <usdutt@qti.qualcomm.com>
Wed, 30 Nov 2016 04:34:38 +0000 (10:04 +0530)
committerJouni Malinen <j@w1.fi>
Wed, 30 Nov 2016 17:33:39 +0000 (19:33 +0200)
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>
src/drivers/driver.h
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_scan.c
wpa_supplicant/driver_i.h
wpa_supplicant/scan.c

index 8a5899443ed89ee4e7a1522b7e77a6766d748604..ffe5560fb903f43100b155dde5db80de1dcaf350 100644 (file)
@@ -458,6 +458,20 @@ struct wpa_driver_scan_params {
         */
        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
         * 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
         * @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
         */
-       int (*abort_scan)(void *priv);
+       int (*abort_scan)(void *priv, u64 scan_cookie);
 
        /**
         * configure_data_frame_filters - Request to configure frame filters
index d0ec48c9f9734d0548e5f9cb2cd06d5be7fb46d6..8d12978bd8817bb1216c0da775cfabf14d2382ec 100644 (file)
@@ -299,7 +299,7 @@ int wpa_driver_nl80211_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);
 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,
                                   struct wpa_driver_scan_params *params);
 int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
index c115b6b31b7dc4b1f5ae9e5b82289e7a6926be41..e50323106448f64c716cc03fc4756642ce17b6c7 100644 (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
  * @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;
 
        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;
 
        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;
+#ifdef CONFIG_DRIVER_NL80211_QCA
        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);
-       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;
+       /*
+        * If scan_cookie is zero, a normal scan through kernel (cfg80211)
+        * was triggered, hence abort the cfg80211 scan instead of the vendor
+        * scan.
+        */
+       if (drv->scan_vendor_cmd_avail && scan_cookie)
+               return nl80211_abort_vendor_scan(drv, scan_cookie);
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+       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->scan_state = SCAN_REQUESTED;
+       /* Pass the cookie to the caller to help distinguish the scans. */
+       params->scan_cookie = cookie;
 
        wpa_printf(MSG_DEBUG,
                   "nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
index cf0855647f30c6c0bd444a65c67ccaf0d6edc6d8..4758c161c631868c1bd554ddc68904603e441beb 100644 (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);
 }
 
-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)
                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,
index 5698443c91720232f8c1ad2145a34e8bc33ea29f..8d0986cb75246b6610cc8e0a16e4063a3bf6b00f 100644 (file)
@@ -2633,7 +2633,7 @@ int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
 
        if (scan_work && wpa_s->own_scan_running) {
                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;