qtnfmac: add missing bss record to host scan cache
authorSergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Mon, 14 Jan 2019 09:39:47 +0000 (09:39 +0000)
committerKalle Valo <kvalo@codeaurora.org>
Fri, 1 Feb 2019 12:12:05 +0000 (14:12 +0200)
Make sure that valid BSS entry exists in wireless core record
even in the case of successful connect reported by firmware.

Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/quantenna/qtnfmac/event.c
drivers/net/wireless/quantenna/qtnfmac/qlink.h

index 3038a00..3fd1a92 100644 (file)
@@ -145,6 +145,12 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
                           const struct qlink_event_bss_join *join_info,
                           u16 len)
 {
+       struct wiphy *wiphy = priv_to_wiphy(vif->mac);
+       enum ieee80211_statuscode status = le16_to_cpu(join_info->status);
+       struct cfg80211_chan_def chandef;
+       struct cfg80211_bss *bss = NULL;
+       u8 *ie = NULL;
+
        if (unlikely(len < sizeof(*join_info))) {
                pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
                       vif->mac->macid, vif->vifid, len,
@@ -158,15 +164,80 @@ qtnf_event_handle_bss_join(struct qtnf_vif *vif,
                return -EPROTO;
        }
 
-       pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid,
-                join_info->bssid);
+       pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
+                vif->mac->macid, vif->vifid, join_info->bssid, status);
+
+       if (status == WLAN_STATUS_SUCCESS) {
+               qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
+               if (!cfg80211_chandef_valid(&chandef)) {
+                       pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
+                               vif->mac->macid, vif->vifid,
+                               chandef.chan->center_freq,
+                               chandef.center_freq1,
+                               chandef.center_freq2,
+                               chandef.width);
+                       status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                       goto done;
+               }
 
+               bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
+                                      NULL, 0, IEEE80211_BSS_TYPE_ESS,
+                                      IEEE80211_PRIVACY_ANY);
+               if (!bss) {
+                       pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
+                               vif->mac->macid, vif->vifid,
+                               join_info->bssid, chandef.chan->hw_value);
+
+                       if (!vif->wdev.ssid_len) {
+                               pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
+                                       vif->mac->macid, vif->vifid,
+                                       join_info->bssid);
+                               status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               goto done;
+                       }
+
+                       ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL);
+                       if (!ie) {
+                               pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n",
+                                       vif->mac->macid, vif->vifid,
+                                       join_info->bssid);
+                               status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               goto done;
+                       }
+
+                       ie[0] = WLAN_EID_SSID;
+                       ie[1] = vif->wdev.ssid_len;
+                       memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len);
+
+                       bss = cfg80211_inform_bss(wiphy, chandef.chan,
+                                                 CFG80211_BSS_FTYPE_UNKNOWN,
+                                                 join_info->bssid, 0,
+                                                 WLAN_CAPABILITY_ESS, 100,
+                                                 ie, 2 + vif->wdev.ssid_len,
+                                                 0, GFP_KERNEL);
+                       if (!bss) {
+                               pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n",
+                                       vif->mac->macid, vif->vifid,
+                                       join_info->bssid);
+                               status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               goto done;
+                       }
+               }
+       }
+
+done:
        cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL,
-                               0, le16_to_cpu(join_info->status), GFP_KERNEL);
+                               0, status, GFP_KERNEL);
+       if (bss) {
+               if (!ether_addr_equal(vif->bssid, join_info->bssid))
+                       ether_addr_copy(vif->bssid, join_info->bssid);
+               cfg80211_put_bss(wiphy, bss);
+       }
 
-       if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS)
+       if (status == WLAN_STATUS_SUCCESS)
                netif_carrier_on(vif->netdev);
 
+       kfree(ie);
        return 0;
 }
 
index d958b26..27fdb5b 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/ieee80211.h>
 
-#define QLINK_PROTO_VER                12
+#define QLINK_PROTO_VER                13
 
 #define QLINK_MACID_RSVD               0xFF
 #define QLINK_VIFID_RSVD               0xFF
@@ -975,11 +975,13 @@ struct qlink_event_sta_deauth {
 /**
  * struct qlink_event_bss_join - data for QLINK_EVENT_BSS_JOIN event
  *
+ * @chan: new operating channel definition
  * @bssid: BSSID of a BSS which interface tried to joined.
  * @status: status of joining attempt, see &enum ieee80211_statuscode.
  */
 struct qlink_event_bss_join {
        struct qlink_event ehdr;
+       struct qlink_chandef chan;
        u8 bssid[ETH_ALEN];
        __le16 status;
 } __packed;