wil6210: store bss object and use cfg80211_connect_bss()
authorDedy Lansky <qca_dlansky@qca.qualcomm.com>
Wed, 8 Mar 2017 11:52:15 +0000 (13:52 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Thu, 9 Mar 2017 08:04:23 +0000 (10:04 +0200)
In a fast disconnect/connect sequence, cfg80211_connect_result() can
fail to find the bss object which the driver is connecting to. Detailed
sequence of events:
* Driver is connected in STA mode
* Disconnect request arrives from user space. Driver disconnects and
  calls cfg80211_disconnected() which adds new event to the
  cfg80211_wq worker thread
* Connect request arrives from user space. cfg80211_connect() stores
  ssid/ssid_len and calls rdev_connect()
* __cfg80211_disconnected() runs in worker thread and zero
  wdev->ssid_len
* Connect succeeds. Driver calls cfg80211_connect_result() which fails
  to find the bss because wdev->ssid_len is zero

To overcome this, upon connect request, store the bss object in the
driver and upon connect completion pass it to kernel using
cfg80211_connect_bss().

Signed-off-by: Dedy Lansky <qca_dlansky@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/ath/wil6210/wmi.c

index 581a4e2966fc4d436813ca206ae04b775502d60f..39ee565ecf56cfc1386a756a287d5ba0e92c0d8a 100644 (file)
@@ -681,6 +681,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
        if (rc == 0) {
                netif_carrier_on(ndev);
                wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
+               wil->bss = bss;
                /* Connect can take lots of time */
                mod_timer(&wil->connect_timer,
                          jiffies + msecs_to_jiffies(2000));
index dddde94f03566cf26d422136aebc7bb3691466b4..5d45faca5d51d04d6b9f1f0fb48d02f79ab3fb23 100644 (file)
@@ -284,6 +284,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
                        cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
                                                WLAN_STATUS_UNSPECIFIED_FAILURE,
                                                GFP_KERNEL);
+                       wil->bss = NULL;
                }
                clear_bit(wil_status_fwconnecting, wil->status);
                break;
index 89e7eb7790faa6787f574625ad1dfcb93de5a873..09e2fcef4f07e5b7b307e69812c11fc32a1c1800 100644 (file)
@@ -613,6 +613,7 @@ struct wil6210_priv {
        u16 channel; /* relevant in AP mode */
        int sinfo_gen;
        u32 ap_isolate; /* no intra-BSS communication */
+       struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
        /* interrupt moderation */
        u32 tx_max_burst_duration;
        u32 tx_interframe_timeout;
index a7a4ac1a8eb7c6f001fbcd6c9c874c058464cec3..a2a895bee6d888edfcb2922a33bc552e400983d9 100644 (file)
@@ -573,12 +573,16 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
                                                GFP_KERNEL);
                        goto out;
                } else {
-                       cfg80211_connect_result(ndev, evt->bssid,
-                                               assoc_req_ie, assoc_req_ielen,
-                                               assoc_resp_ie, assoc_resp_ielen,
-                                               WLAN_STATUS_SUCCESS,
-                                               GFP_KERNEL);
+                       struct wiphy *wiphy = wil_to_wiphy(wil);
+
+                       cfg80211_ref_bss(wiphy, wil->bss);
+                       cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
+                                            assoc_req_ie, assoc_req_ielen,
+                                            assoc_resp_ie, assoc_resp_ielen,
+                                            WLAN_STATUS_SUCCESS, GFP_KERNEL,
+                                            NL80211_TIMEOUT_UNSPECIFIED);
                }
+               wil->bss = NULL;
        } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
                   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
                if (rc) {