source: G950FXXS5DSI1
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / drivers / net / wireless / bcmdhd4361 / wl_cfg80211.c
index 0fd4ff1fefa778364864c8c076799fce968b3f88..b6e4c04ef1862f62f24938203bbde72015232e83 100644 (file)
@@ -24,7 +24,7 @@
  *
  * <<Broadcom-WL-IPTag/Open:>>
  *
- * $Id: wl_cfg80211.c 798171 2019-01-07 09:10:40Z $
+ * $Id: wl_cfg80211.c 820080 2019-05-16 03:05:46Z $
  */
 /* */
 #include <typedefs.h>
@@ -909,12 +909,6 @@ static s32 __wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify);
 static s32 wl_check_vif_support(struct bcm_cfg80211 *cfg, wl_iftype_t wl_iftype);
 bool wl_is_wps_enrollee_active(struct net_device *ndev, const u8 *ie_ptr, u16 len);
 
-#ifdef WL_CFGVENDOR_SEND_HANG_EVENT
-static void wl_cfgvendor_send_hang_event(struct net_device *dev, u16 reason,
-               char *string, int hang_info_cnt);
-static void wl_copy_hang_info_if_falure(struct net_device *dev, u16 reason, s32 err);
-#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */
-
 #ifdef WL_WPS_SYNC
 static void wl_init_wps_reauth_sm(struct bcm_cfg80211 *cfg);
 static void wl_deinit_wps_reauth_sm(struct bcm_cfg80211 *cfg);
@@ -928,6 +922,11 @@ static void wl_wps_handle_ifdel(struct net_device *ndev);
 #endif /* WL_WPS_SYNC */
 const u8 *wl_find_attribute(const u8 *buf, u16 len, u16 element_id);
 
+#ifdef WL_BCNRECV
+static s32 wl_bcnrecv_aborted_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+               const wl_event_msg_t *e, void *data);
+#endif /* WL_BCNRECV */
+
 static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
        WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
 
@@ -953,20 +952,35 @@ static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80M
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) || (defined(CONFIG_ARCH_MSM) && \
-       defined(CFG80211_CONNECT_TIMEOUT_REASON_CODE))
-#define CFG80211_CONNECT_BSS(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) || \
+       defined(CFG80211_CONNECT_TIMEOUT_REASON_CODE)
+#define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
                resp_ie_len, status, gfp) \
        cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
                resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
 #else
-#define CFG80211_CONNECT_BSS(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
+#define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
                resp_ie_len, status, gfp) \
        cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
                resp_ie_len, status, gfp);
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || \
-       * (CONFIG_ARCH_MSM && CFG80211_CONNECT_TIMEOUT_REASON_CODE)
+         (CFG80211_CONNECT_TIMEOUT_REASON_CODE)
        */
+#elif defined(CFG80211_CONNECT_TIMEOUT_REASON_CODE)
+/* There are customer kernels with backported changes for
+ *  connect timeout. CFG80211_CONNECT_TIMEOUT_REASON_CODE define
+ * is available for kernels < 4.7 in such cases.
+ */
+#define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
+               resp_ie_len, status, gfp) \
+       cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie, \
+               resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
+#else
+/* Kernels < 4.7 doesn't support cfg80211_connect_bss */
+#define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
+               resp_ie_len, status, gfp) \
+       cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, resp_ie, \
+               resp_ie_len, status, gfp);
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) */
 
 #ifdef RSSI_OFFSET
@@ -1183,6 +1197,10 @@ static const struct {
 
 #define SOFT_AP_IF_NAME         "swlan0"
 
+#ifdef P2P_LISTEN_OFFLOADING
+void wl_cfg80211_cancel_p2plo(struct bcm_cfg80211 *cfg);
+#endif /* P2P_LISTEN_OFFLOADING */
+
 #ifdef CUSTOMER_HW4_DEBUG
 uint prev_dhd_console_ms = 0;
 u32 prev_wl_dbg_level = 0;
@@ -1759,7 +1777,6 @@ wl_cfg80211_p2p_if_add(struct bcm_cfg80211 *cfg,
 #if defined(WL_CFG80211_P2P_DEV_IF)
        if (wl_iftype == WL_IF_TYPE_P2P_DISC) {
                /* Handle Dedicated P2P discovery Interface */
-               cfg->down_disc_if = FALSE;
                return wl_cfgp2p_add_p2p_disc_if(cfg);
        }
 #endif /* WL_CFG80211_P2P_DEV_IF */
@@ -1931,6 +1948,10 @@ wl_cfg80211_iface_state_ops(struct wireless_dev *wdev,
 
        switch (state) {
                case WL_IF_CREATE_REQ:
+#ifdef WL_BCNRECV
+                       /* check fakeapscan in progress then abort */
+                       wl_android_bcnrecv_stop(ndev, WL_BCNRECV_CONCURRENCY);
+#endif /* WL_BCNRECV */
                        wl_cfg80211_scan_abort(cfg);
                        wl_wlfc_enable(cfg, true);
 
@@ -2017,17 +2038,7 @@ wl_cfg80211_p2p_if_del(struct wiphy *wiphy, struct wireless_dev *wdev)
 #ifdef WL_CFG80211_P2P_DEV_IF
        if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
                /* Handle dedicated P2P discovery interface. */
-#ifdef CUSTOMER_HW4
-               if (dhd_download_fw_on_driverload) {
-                       return wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
-               } else {
-                       WL_INFORM_MEM(("skipping del p2p discovery\n"));
-                       cfg->down_disc_if = TRUE;
-                       return 0;
-               }
-#else
                return wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
-#endif /* CUSTOMER_HW4 */
        }
 #endif /* WL_CFG80211_P2P_DEV_IF */
 
@@ -2784,6 +2795,11 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
                return -EINVAL;
        }
 
+       /* If any scan is going on, abort it */
+       if (wl_abort_scan_and_check(cfg) != TRUE) {
+               wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
+       }
+
        mutex_lock(&cfg->if_sync);
        netinfo = wl_get_netinfo_by_wdev(cfg, ndev->ieee80211_ptr);
        if (unlikely(!netinfo)) {
@@ -2805,11 +2821,6 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
                goto fail;
        }
 
-       /* If any scan is going on, abort it */
-       if (wl_abort_scan_and_check(cfg) != TRUE) {
-               wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
-       }
-
        /* perform pre-if-change tasks */
        wl_cfg80211_iface_state_ops(ndev->ieee80211_ptr,
                WL_IF_CHANGE_REQ, wl_iftype, wl_mode);
@@ -3637,6 +3648,10 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
                return -EOPNOTSUPP;
        }
+#ifdef WL_BCNRECV
+       /* check fakeapscan in progress then abort */
+       wl_android_bcnrecv_stop(ndev, WL_BCNRECV_SCANBUSY);
+#endif /* WL_BCNRECV */
 
 #ifdef P2P_LISTEN_OFFLOADING
        if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
@@ -3930,7 +3945,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                }
        }
 
-       mutex_lock(&cfg->usr_sync);
+       mutex_lock(&cfg->scan_sync);
        err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
        if (unlikely(err)) {
                WL_ERR(("scan error (%d)\n", err));
@@ -3939,7 +3954,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                mod_timer(&cfg->scan_timeout,
                        jiffies + msecs_to_jiffies(wl_get_scan_timeout_val(cfg)));
        }
-       mutex_unlock(&cfg->usr_sync);
+       mutex_unlock(&cfg->scan_sync);
 #ifdef WL_DRV_AVOID_SCANCACHE
        /* Reset roam cache after successful scan request */
 #ifdef ROAM_CHANNEL_CACHE
@@ -4786,6 +4801,7 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
        u16 wl_iftype;
 #ifdef WL_STATIC_IF
        int need_legacy_war = 0;
+       dhd_pub_t *dhd = NULL;
 #endif /* WL_STATIC_IF */
 
        if (!ndev || !event) {
@@ -4801,12 +4817,16 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
 
 #ifdef WL_STATIC_IF
        {
-               need_legacy_war = ((wl_legacy_chip_check(cfg) ||
-                       wl_check_interface_create_v0(cfg)) &&
-                       !strnicmp(name, SOFT_AP_IF_NAME, strlen(SOFT_AP_IF_NAME)));
-               if (need_legacy_war) {
-                       event->role = WLC_E_IF_ROLE_AP;
+               dhd = (dhd_pub_t *)(cfg->pub);
+               if (!DHD_OPMODE_SUPPORTED(dhd, DHD_FLAG_MFG_MODE) && name) {
+                       need_legacy_war = ((wl_legacy_chip_check(cfg) ||
+                               wl_check_interface_create_v0(cfg)) &&
+                               !strnicmp(name, SOFT_AP_IF_NAME, strlen(SOFT_AP_IF_NAME)));
+                       if (need_legacy_war) {
+                               event->role = WLC_E_IF_ROLE_AP;
+                       }
                }
+               WL_DBG(("name: %s\n", name));
        }
 #endif /* WL_STATIC_IF */
 
@@ -4855,8 +4875,23 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
                wdev = new_ndev->ieee80211_ptr;
 
                if (need_legacy_war) {
-                       s32 err;
+                       /* Check whether mac addr is in sync with fw. If not,
+                        * apply it using cur_etheraddr.
+                        */
+                       if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
+                               ret = wldev_iovar_setbuf_bsscfg(new_ndev, "cur_etheraddr",
+                                               addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
+                                               event->bssidx, &cfg->ioctl_buf_sync);
+                               if (unlikely(ret)) {
+                                       WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
+                                       goto fail;
+                               }
+                               memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
+                               WL_ERR(("Applying updated mac address to firmware\n"));
+                       }
+
                        if (!wl_get_drv_status(cfg, AP_CREATED, new_ndev)) {
+                               s32 err;
                                WL_INFORM_MEM(("[%s] Bringup SoftAP on bssidx:%d \n",
                                        new_ndev->name, event->bssidx));
                                if ((err = wl_cfg80211_add_del_bss(cfg, new_ndev,
@@ -6259,9 +6294,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 #ifdef ESCAN_CHANNEL_CACHE
        chanspec_t chanspec_list[MAX_ROAM_CHANNEL];
 #endif /* ESCAN_CHANNEL_CACHE */
-#if (defined(BCM4334_CHIP) || defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
        int wait_cnt;
-#endif // endif
 
        WL_DBG(("In\n"));
        if (!dev) {
@@ -6317,7 +6350,6 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        /*
         * Cancel ongoing scan to sync up with sme state machine of cfg80211.
         */
-#if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
        if (cfg->scan_request) {
                WL_TRACE_HW4(("Aborting the scan! \n"));
                wl_cfg80211_scan_abort(cfg);
@@ -6331,7 +6363,6 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                        wl_cfg80211_cancel_scan(cfg);
                }
        }
-#endif // endif
 #ifdef WL_SCHED_SCAN
        /* Locks are taken in wl_cfg80211_sched_scan_stop()
         * A start scan occuring during connect is unlikely
@@ -6372,6 +6403,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                }
        }
 
+       if (sme->bssid) {
+               wl_update_prof(cfg, dev, NULL, sme->bssid, WL_PROF_LATEST_BSSID);
+       } else {
+               wl_update_prof(cfg, dev, NULL, &ether_bcast, WL_PROF_LATEST_BSSID);
+       }
+
        /* 'connect' request received */
        wl_set_drv_status(cfg, CONNECTING, dev);
        /* clear nested connect bit on proceeding for connection */
@@ -6768,13 +6805,11 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
                /*
                * Cancel ongoing scan to sync up with sme state machine of cfg80211.
                */
-#if !defined(ESCAN_RESULT_PATCH)
                /* Let scan aborted by F/W */
                if (cfg->scan_request) {
                        WL_TRACE_HW4(("Aborting the scan! \n"));
                        wl_cfg80211_cancel_scan(cfg);
                }
-#endif /* ESCAN_RESULT_PATCH */
                if (wl_get_drv_status(cfg, CONNECTING, dev) ||
                        wl_get_drv_status(cfg, CONNECTED, dev)) {
                                wl_set_drv_status(cfg, DISCONNECTING, dev);
@@ -6802,8 +6837,19 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
                }
 #endif /* WPS_SYNC */
                wl_cfg80211_wait_for_disconnection(cfg, dev);
+               if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
+                       CFG80211_CONNECT_RESULT(dev, NULL, NULL,
+                               NULL, 0, NULL, 0,
+                               WLAN_STATUS_UNSPECIFIED_FAILURE,
+                               GFP_KERNEL);
+                       wl_clr_drv_status(cfg, DISCONNECTING, dev);
+               }
        } else {
                WL_INFORM_MEM(("act is false\n"));
+               CFG80211_CONNECT_RESULT(dev, NULL, NULL,
+                       NULL, 0, NULL, 0,
+                       WLAN_STATUS_UNSPECIFIED_FAILURE,
+                       GFP_KERNEL);
        }
 #ifdef CUSTOM_SET_CPUCORE
        /* set default cpucore */
@@ -8280,6 +8326,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
        struct net_device *ndev = NULL;
        struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
 
+       RETURN_EIO_IF_NOT_UP(cfg);
 #ifdef DHD_IFDEBUG
        PRINT_WDEV_INFO(cfgdev);
 #endif /* DHD_IFDEBUG */
@@ -8293,6 +8340,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
        }
 #endif /* WL_NAN */
 
+       mutex_lock(&cfg->usr_sync);
        WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
                ieee80211_frequency_to_channel(channel->center_freq),
                duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
@@ -8303,19 +8351,16 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
                goto exit;
        }
 
-#ifdef P2P_LISTEN_OFFLOADING
-       if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
-               WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
-               return -EAGAIN;
-       }
-#endif /* P2P_LISTEN_OFFLOADING */
-
 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
        if (wl_get_drv_status_all(cfg, SCANNING)) {
                wl_cfg80211_cancel_scan(cfg);
        }
 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
 
+#ifdef P2P_LISTEN_OFFLOADING
+       wl_cfg80211_cancel_p2plo(cfg);
+#endif /* P2P_LISTEN_OFFLOADING */
+
        target_channel = ieee80211_frequency_to_channel(channel->center_freq);
        memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
 #if defined(WL_ENABLE_P2P_IF)
@@ -8352,6 +8397,10 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
        }
 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
 
+#ifdef WL_BCNRECV
+       /* check fakeapscan in progress then abort */
+       wl_android_bcnrecv_stop(ndev, WL_BCNRECV_LISTENBUSY);
+#endif /* WL_BCNRECV */
 #ifdef WL_CFG80211_SYNC_GON
        if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
                /* do not enter listen mode again if we are in listen mode already for next af.
@@ -8418,6 +8467,7 @@ exit:
        } else {
                WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
        }
+       mutex_unlock(&cfg->usr_sync);
        return err;
 }
 
@@ -13030,6 +13080,10 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
 #ifdef BIGDATA_SOFTAP
                        wl_ap_stainfo_init(cfg);
 #endif /* BIGDATA_SOFTAP */
+#ifdef WL_BCNRECV
+                       /* check fakeapscan is in progress, if progress then abort */
+                       wl_android_bcnrecv_stop(ndev, WL_BCNRECV_CONCURRENCY);
+#endif /* WL_BCNRECV */
                        return 0;
                }
        }
@@ -14039,6 +14093,11 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                scb_val_t scbval;
                                u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
                                uint32 reason = 0;
+                               bcm_tlv_t *deauth_info = NULL;
+                               wips_detect_inform_t *wips_detect_info;
+                               uint8 wips_bssid[ETHER_ADDR_LEN];
+                               u32 len = ntoh32(e->datalen) + TLV_HDR_LEN;
+
                                struct ether_addr bssid_dongle = {{0, 0, 0, 0, 0, 0}};
                                struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
 
@@ -14049,6 +14108,23 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                                        "changed 0xFF\n", event, reason));
                                                reason = WLC_E_DEAUTH_MAX_REASON;
                                        }
+                                       if ((deauth_info = bcm_parse_tlvs(data, len,
+                                               TAG_DEAUTH_TLV_WIPS)) != NULL) {
+                                               wips_detect_info =
+                                                       (wips_detect_inform_t *)deauth_info->data;
+                                               memcpy(wips_bssid, &wips_detect_info->ea,
+                                                       ETHER_ADDR_LEN);
+                                               if (wips_detect_info->misdeauth > 1) {
+                                                       WL_ERR(("WIPS attack!! cnt=%d, curRSSI=%d, "
+                                                               "deauthRSSI=%d, time=%d, "
+                                                               "MAC="MACDBG"\n",
+                                                               wips_detect_info->misdeauth,
+                                                               wips_detect_info->cur_bsscfg_rssi,
+                                                               wips_detect_info->deauth_rssi,
+                                                               wips_detect_info->timestamp,
+                                                               MAC2STRDBG(wips_bssid)));
+                                               }
+                                       }
                                }
 #ifdef SET_SSID_FAIL_CUSTOM_RC
                                if (event == WLC_E_SET_SSID) {
@@ -14203,19 +14279,25 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                        /* Dump FW preserve buffer content */
                        wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
 
-                       if (wl_get_drv_status(cfg, DISCONNECTING, ndev) &&
-                               wl_get_drv_status(cfg, CONNECTING, ndev)) {
-                               wl_clr_drv_status(cfg, DISCONNECTING, ndev);
-                               wl_clr_drv_status(cfg, CONNECTING, ndev);
-                               wl_cfg80211_scan_abort(cfg);
-                               DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
-                               return err;
-                       }
                        /* Clean up any pending scan request */
                        wl_cfg80211_cancel_scan(cfg);
 
-                       if (wl_get_drv_status(cfg, CONNECTING, ndev))
+                       if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
+                               if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
+                                       WL_INFORM_MEM(("wl dissassoc\n"));
+                                       err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
+                                       if (err < 0) {
+                                               WL_ERR(("WLC_DISASSOC error %d\n", err));
+                                               err = 0;
+                                       }
+                               } else {
+                                       WL_DBG(("connect fail. clear disconnecting bit\n"));
+                                       wl_clr_drv_status(cfg, DISCONNECTING, ndev);
+                               }
                                wl_bss_connect_done(cfg, ndev, e, data, false);
+                               wl_clr_drv_status(cfg, CONNECTING, ndev);
+                               WL_INFORM_MEM(("connect fail reported\n"));
+                       }
                } else {
                        WL_DBG(("%s nothing\n", __FUNCTION__));
                }
@@ -15202,8 +15284,8 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                        completed = false;
                        sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
                }
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
-               CFG80211_CONNECT_BSS(ndev,
+
+               CFG80211_CONNECT_RESULT(ndev,
                        curbssid,
                        bss,
                        conn_info->req_ie,
@@ -15215,19 +15297,7 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                        sec->auth_assoc_res_status :
                        WLAN_STATUS_UNSPECIFIED_FAILURE,
                        GFP_KERNEL);
-#else
-               cfg80211_connect_result(ndev,
-                       curbssid,
-                       conn_info->req_ie,
-                       conn_info->req_ie_len,
-                       conn_info->resp_ie,
-                       conn_info->resp_ie_len,
-                       completed ? WLAN_STATUS_SUCCESS :
-                       (sec->auth_assoc_res_status) ?
-                       sec->auth_assoc_res_status :
-                       WLAN_STATUS_UNSPECIFIED_FAILURE,
-                       GFP_KERNEL);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) */
+
                if (completed) {
                        WL_INFORM_MEM(("[%s] Report connect result - "
                                "connection succeeded\n", ndev->name));
@@ -15459,7 +15529,7 @@ wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
        }
        ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
 
-       mutex_lock(&cfg->usr_sync);
+       mutex_lock(&cfg->scan_sync);
        wl_clr_drv_status(cfg, SCANNING, ndev);
        memset(&channel_inform, 0, sizeof(channel_inform));
        err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &channel_inform,
@@ -15499,7 +15569,7 @@ scan_done_out:
        }
        spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
        WL_DBG(("cfg80211_scan_done\n"));
-       mutex_unlock(&cfg->usr_sync);
+       mutex_unlock(&cfg->scan_sync);
        return err;
 }
 
@@ -16533,6 +16603,9 @@ static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
 #ifdef WL_BAM
        cfg->evt_handler[WLC_E_ADPS] = wl_adps_event_handler;
 #endif /* WL_BAM */
+#ifdef WL_BCNRECV
+       cfg->evt_handler[WLC_E_BCNRECV_ABORTED] = wl_bcnrecv_aborted_event_handler;
+#endif /* WL_BCNRECV */
 }
 
 #if defined(STATIC_WL_PRIV_STRUCT)
@@ -16758,10 +16831,27 @@ static void wl_scan_timeout(unsigned long data)
 #ifdef DHD_FW_COREDUMP
        uint32 prev_memdump_mode = dhdp->memdump_enabled;
 #endif /* DHD_FW_COREDUMP */
+       unsigned long flags;
 
+       spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
        if (!(cfg->scan_request)) {
                WL_ERR(("timer expired but no scan request\n"));
+               spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
                return;
+       } else {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+               if (cfg->scan_request->dev) {
+                       wdev = cfg->scan_request->dev->ieee80211_ptr;
+               }
+#else
+               wdev = cfg->scan_request->wdev;
+#endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
+               spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
+
+               if (!wdev) {
+                       WL_ERR(("No wireless_dev present\n"));
+                       return;
+               }
        }
 
 #if defined(DHD_KERNEL_SCHED_DEBUG) && defined(DHD_FW_COREDUMP)
@@ -16792,7 +16882,7 @@ static void wl_scan_timeout(unsigned long data)
                mutex_is_locked(&cfg->if_sync),
                mutex_is_locked(&cfg->usr_sync),
                mutex_is_locked(&cfg->pm_sync),
-               mutex_is_locked(&cfg->scan_complete),
+               mutex_is_locked(&cfg->scan_sync),
                spin_is_locked(&cfg->cfgdrv_lock),
                spin_is_locked(&cfg->eq_lock)));
        dhd_bus_intr_count_dump(dhdp);
@@ -16816,18 +16906,7 @@ static void wl_scan_timeout(unsigned long data)
                }
        }
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
-       if (cfg->scan_request->dev)
-               wdev = cfg->scan_request->dev->ieee80211_ptr;
-#else
-       wdev = cfg->scan_request->wdev;
-#endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
-       if (!wdev) {
-               WL_ERR(("No wireless_dev present\n"));
-               return;
-       }
        ndev = wdev_to_wlc_ndev(wdev, cfg);
-
        bzero(&msg, sizeof(wl_event_msg_t));
        WL_ERR(("timer expired\n"));
 #ifdef BCMPCIE
@@ -16984,8 +17063,10 @@ static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
        struct wireless_dev *wdev = NULL;
        struct net_device *ndev = NULL;
 
-       if (!cfg->scan_request)
-               return;
+       mutex_lock(&cfg->scan_sync);
+       if (!cfg->scan_request) {
+               goto exit;
+       }
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
        if (cfg->scan_request->dev)
@@ -16996,12 +17077,14 @@ static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
 
        if (!wdev) {
                WL_ERR(("No wireless_dev present\n"));
-               return;
+               goto exit;
        }
 
        ndev = wdev_to_wlc_ndev(wdev, cfg);
        wl_notify_escan_complete(cfg, ndev, true, true);
        WL_INFORM_MEM(("Scan aborted! \n"));
+exit:
+       mutex_unlock(&cfg->scan_sync);
 }
 
 void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
@@ -17047,7 +17130,6 @@ static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
        WL_DBG(("Enter \n"));
        BCM_REFERENCE(dhdp);
 
-       mutex_lock(&cfg->scan_complete);
        if (!ndev) {
                WL_ERR(("ndev is null\n"));
                err = BCME_ERROR;
@@ -17122,7 +17204,6 @@ static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
        spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
 
 out:
-       mutex_unlock(&cfg->scan_complete);
        return err;
 }
 
@@ -17371,6 +17452,69 @@ exit:
 
 }
 #endif /* WL_DRV_AVOID_SCANCACHE */
+
+#ifdef WL_BCNRECV
+/* Beacon recv results handler sending to upper layer */
+static s32
+wl_bcnrecv_result_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+               wl_bss_info_v109_2_t *bi, uint32 scan_status)
+{
+       s32 err = BCME_OK;
+       struct wiphy *wiphy = NULL;
+       wl_bcnrecv_result_t *bcn_recv = NULL;
+       struct timespec ts;
+       if (!bi) {
+               WL_ERR(("%s: bi is NULL\n", __func__));
+               err = BCME_NORESOURCE;
+               goto exit;
+       }
+       if ((bi->length - bi->ie_length) < sizeof(wl_bss_info_v109_2_t)) {
+               WL_ERR(("bi info version doesn't support bcn_recv attributes\n"));
+               goto exit;
+       }
+
+       if (scan_status == WLC_E_STATUS_RXBCN) {
+               wiphy = cfg->wdev->wiphy;
+               if (!wiphy) {
+                        WL_ERR(("wiphy is NULL\n"));
+                        err = BCME_NORESOURCE;
+                        goto exit;
+               }
+               bcn_recv = (wl_bcnrecv_result_t *)MALLOCZ(cfg->osh, sizeof(*bcn_recv));
+               if (unlikely(!bcn_recv)) {
+                       WL_ERR(("Failed to allocate memory\n"));
+                       return -ENOMEM;
+               }
+               memcpy((char *)bcn_recv->SSID, (char *)bi->SSID, DOT11_MAX_SSID_LEN);
+               memcpy(&bcn_recv->BSSID, &bi->BSSID, ETH_ALEN);
+               bcn_recv->channel = wf_chspec_ctlchan(
+                       wl_chspec_driver_to_host(bi->chanspec));
+               bcn_recv->beacon_interval = bi->beacon_period;
+
+               /* kernal timestamp */
+               get_monotonic_boottime(&ts);
+               bcn_recv->system_time = ((u64)ts.tv_sec*1000000)
+                               + ts.tv_nsec / 1000;
+               bcn_recv->timestamp[0] = bi->timestamp[0];
+               bcn_recv->timestamp[1] = bi->timestamp[1];
+               if (bcn_recv) {
+                       if ((err = wl_android_bcnrecv_event(cfgdev_to_wlc_ndev(cfgdev, cfg),
+                               BCNRECV_ATTR_BCNINFO, 0, 0, (uint8 *)bcn_recv, sizeof(*bcn_recv)))
+                                               != BCME_OK) {
+                               WL_ERR(("failed to send bcnrecv event, error:%d\n", err));
+                       }
+               }
+       } else {
+               WL_DBG(("Ignoring Escan Event:%d \n", scan_status));
+       }
+exit:
+       if (bcn_recv) {
+               MFREE(cfg->osh, bcn_recv, sizeof(*bcn_recv));
+       }
+       return err;
+}
+#endif /* WL_BCNRECV */
+
 static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
        const wl_event_msg_t *e, void *data)
 {
@@ -17393,15 +17537,25 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
 
        ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
 
-       mutex_lock(&cfg->usr_sync);
+       mutex_lock(&cfg->scan_sync);
        /* P2P SCAN is coming from primary interface */
        if (wl_get_p2p_status(cfg, SCANNING)) {
                if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
                        ndev = cfg->afx_hdl->dev;
                else
                        ndev = cfg->escan_info.ndev;
-
        }
+       escan_result = (wl_escan_result_t *)data;
+#ifdef WL_BCNRECV
+       if (cfg->bcnrecv_info.bcnrecv_state == BEACON_RECV_STARTED &&
+               status == WLC_E_STATUS_RXBCN) {
+               /* handle beacon recv scan results */
+               wl_bss_info_v109_2_t *bi_info;
+               bi_info = (wl_bss_info_v109_2_t *)escan_result->bss_info;
+               err = wl_bcnrecv_result_handler(cfg, cfgdev, bi_info, status);
+               goto exit;
+       }
+#endif /* WL_BCNRECV */
        if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
                WL_ERR_RLMT(("escan is not ready. drv_scan_status 0x%x"
                " e_type %d e_states %d\n",
@@ -17409,7 +17563,6 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                ntoh32(e->event_type), ntoh32(e->status)));
                goto exit;
        }
-       escan_result = (wl_escan_result_t *)data;
 
 #ifndef WL_DRV_AVOID_SCANCACHE
        if (status == WLC_E_STATUS_PARTIAL) {
@@ -17762,7 +17915,7 @@ static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
        err = wl_escan_without_scan_cache(cfg, escan_result, ndev, e, status);
 #endif /* WL_DRV_AVOID_SCANCACHE */
 exit:
-       mutex_unlock(&cfg->usr_sync);
+       mutex_unlock(&cfg->scan_sync);
        return err;
 }
 
@@ -18108,11 +18261,14 @@ static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
        wl_init_event_handler(cfg);
        mutex_init(&cfg->usr_sync);
        mutex_init(&cfg->event_sync);
-       mutex_init(&cfg->scan_complete);
        mutex_init(&cfg->if_sync);
+       mutex_init(&cfg->scan_sync);
 #ifdef WLTDLS
        mutex_init(&cfg->tdls_sync);
 #endif /* WLTDLS */
+#ifdef WL_BCNRECV
+       mutex_init(&cfg->bcn_sync);
+#endif /* WL_BCNRECV */
 #ifdef WL_WPS_SYNC
        wl_init_wps_reauth_sm(cfg);
 #endif /* WL_WPS_SYNC */
@@ -19231,6 +19387,78 @@ static s32 __wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
        return 0;
 }
 
+#ifdef WL_BCNRECV
+static s32
+wl_bcnrecv_aborted_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
+               const wl_event_msg_t *e, void *data)
+{
+       s32 status = ntoh32(e->status);
+       struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+       /* Abort fakeapscan, when Roam is in progress */
+       if (status == WLC_E_STATUS_RXBCN_ABORT) {
+               wl_android_bcnrecv_stop(ndev, WL_BCNRECV_ROAMABORT);
+       } else {
+               WL_ERR(("UNKNOWN STATUS. status:%d\n", status));
+       }
+       return BCME_OK;
+}
+#endif /* WL_BCNRECV */
+
+/* Get the concurrency mode */
+int wl_cfg80211_get_concurrency_mode(struct bcm_cfg80211 *cfg)
+{
+       struct net_info *iter, *next;
+       uint cmode = CONCURRENCY_MODE_NONE;
+       u32 connected_cnt = 0;
+       u32 pre_channel = 0, channel = 0;
+       u32 pre_band = 0;
+       u32 chanspec = 0;
+       u32 band = 0;
+
+       connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
+       if (connected_cnt <= 1) {
+               return cmode;
+       }
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+       4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#endif // endif
+       for_each_ndev(cfg, iter, next) {
+               if (iter->ndev) {
+                       if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
+                               if (wldev_iovar_getint(iter->ndev, "chanspec",
+                                       (s32 *)&chanspec) == BCME_OK) {
+                                       channel = wf_chspec_ctlchan(
+                                               wl_chspec_driver_to_host(chanspec));
+                                       band = (channel <= CH_MAX_2G_CHANNEL) ?
+                                               IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+                               }
+                               if ((!pre_channel && channel)) {
+                                       pre_band = band;
+                                       pre_channel = channel;
+                               } else if (pre_channel) {
+                                       if ((pre_band == band) && (pre_channel == channel)) {
+                                               cmode = CONCURRENCY_SCC_MODE;
+                                               goto exit;
+                                       } else if ((pre_band == band) && (pre_channel != channel)) {
+                                               cmode = CONCURRENCY_VSDB_MODE;
+                                               goto exit;
+                                       } else if (pre_band != band) {
+                                               cmode = CONCURRENCY_RSDB_MODE;
+                                               goto exit;
+                                       }
+                               }
+                       }
+               }
+       }
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+       4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic pop")
+#endif // endif
+exit:
+       return cmode;
+}
 s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
 {
        s32 err;
@@ -19471,10 +19699,36 @@ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
                if (iter->ndev == NULL)
                        continue;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+               WL_INFORM_MEM(("wl_cfg80211_down. connection state bit status: [%u:%u:%u:%u]\n",
+                       wl_get_drv_status(cfg, CONNECTING, ndev),
+                       wl_get_drv_status(cfg, CONNECTED, ndev),
+                       wl_get_drv_status(cfg, DISCONNECTING, ndev),
+                       wl_get_drv_status(cfg, NESTED_CONNECT, ndev)));
+
                if ((iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) &&
                        wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
                        CFG80211_DISCONNECTED(iter->ndev, 0, NULL, 0, false, GFP_KERNEL);
                }
+
+               if ((iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) &&
+                       wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
+                       u8 *latest_bssid = wl_read_prof(cfg, ndev, WL_PROF_LATEST_BSSID);
+                       struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+                       struct wireless_dev *wdev = ndev->ieee80211_ptr;
+                       struct cfg80211_bss *bss = CFG80211_GET_BSS(wiphy, NULL, latest_bssid,
+                               wdev->ssid, wdev->ssid_len);
+
+                       prhex("bssid:", (uchar *)latest_bssid, ETHER_ADDR_LEN);
+                       prhex("ssid:", (uchar *)wdev->ssid, wdev->ssid_len);
+                       if (!bss) {
+                               WL_DBG(("null bss\n"));
+                       }
+
+                       CFG80211_CONNECT_RESULT(ndev,
+                                       latest_bssid, bss, NULL, 0, NULL, 0,
+                                       WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                       GFP_KERNEL);
+               }
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
                wl_clr_drv_status(cfg, READY, iter->ndev);
                wl_clr_drv_status(cfg, SCANNING, iter->ndev);
@@ -19767,6 +20021,9 @@ static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32
        case WL_PROF_CHAN:
                rptr = &profile->channel;
                break;
+       case WL_PROF_LATEST_BSSID:
+               rptr = profile->latest_bssid;
+               break;
        }
        spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
        if (!rptr)
@@ -19815,6 +20072,13 @@ wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
        case WL_PROF_CHAN:
                profile->channel = *(const u32*)data;
                break;
+       case WL_PROF_LATEST_BSSID:
+               if (data) {
+                       memcpy(profile->latest_bssid, data, ETHER_ADDR_LEN);
+               } else {
+                       memset(profile->latest_bssid, 0, ETHER_ADDR_LEN);
+               }
+               break;
        default:
                err = -EOPNOTSUPP;
                break;
@@ -22267,6 +22531,11 @@ wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgde
        struct net_info *netinfo;
        struct wireless_dev *wdev;
 
+       if (!cfgdev) {
+               WL_ERR(("cfgdev is NULL\n"));
+               return -EINVAL;
+       }
+
        ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
        wdev = cfgdev_to_wdev(cfgdev);
 
@@ -22768,9 +23037,8 @@ void wl_cfg80211_del_p2p_wdev(struct net_device *dev)
                wdev = cfg->p2p_wdev;
        }
 
-       if (wdev && cfg->down_disc_if) {
+       if (wdev) {
                wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
-               cfg->down_disc_if = FALSE;
        }
 }
 #endif /* WL_CFG80211_P2P_DEV_IF */
@@ -24738,175 +25006,6 @@ wl_flush_fw_log_buffer(struct net_device *dev, uint32 logset_mask)
 }
 #endif /* DHD_LOG_DUMP */
 
-#ifdef WL_CFGVENDOR_SEND_HANG_EVENT
-static void
-wl_cfgvendor_send_hang_event(struct net_device *dev, u16 reason, char *string, int hang_info_cnt)
-{
-       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
-       struct wiphy *wiphy;
-       char *hang_info;
-       int len = 0;
-       int bytes_written;
-       uint32 dumy_data = 0;
-       int reason_hang_info = 0;
-       int cnt = 0;
-       dhd_pub_t *dhd;
-       int hang_reason_mismatch = FALSE;
-
-       if (!cfg || !cfg->wdev) {
-               WL_ERR(("cfg=%p wdev=%p\n", cfg, (cfg ? cfg->wdev : NULL)));
-               return;
-       }
-
-       wiphy = cfg->wdev->wiphy;
-
-       if (!wiphy) {
-               WL_ERR(("wiphy is NULL\n"));
-               return;
-       }
-
-       hang_info = MALLOCZ(cfg->osh, VENDOR_SEND_HANG_EXT_INFO_LEN);
-       if (hang_info == NULL) {
-               WL_ERR(("alloc hang_info failed\n"));
-               return;
-       }
-
-       dhd = (dhd_pub_t *)(cfg->pub);
-
-       sscanf(string, "%d", &reason_hang_info);
-       bytes_written = 0;
-       len = VENDOR_SEND_HANG_EXT_INFO_LEN - bytes_written;
-       if (strlen(string) == 0 || (reason_hang_info != reason)) {
-               WL_ERR(("hang reason mismatch: string len %d reason_hang_info %d\n",
-                       (int)strlen(string), reason_hang_info));
-               hang_reason_mismatch = TRUE;
-               if (dhd) {
-                       get_debug_dump_time(dhd->debug_dump_time_hang_str);
-                       copy_debug_dump_time(dhd->debug_dump_time_str,
-                                       dhd->debug_dump_time_hang_str);
-               }
-               bytes_written += scnprintf(&hang_info[bytes_written], len,
-                               "%d %d %s %08x %08x %08x %08x %08x %08x %08x",
-                               reason, VENDOR_SEND_HANG_EXT_INFO_VER,
-                               dhd->debug_dump_time_hang_str,
-                               0, 0, 0, 0, 0, 0, 0);
-               if (dhd) {
-                       clear_debug_dump_time(dhd->debug_dump_time_hang_str);
-               }
-       } else {
-               bytes_written += scnprintf(&hang_info[bytes_written], len, "%s", string);
-       }
-
-       WL_ERR(("hang reason: %d info cnt: %d\n", reason, hang_info_cnt));
-
-       if (hang_reason_mismatch == FALSE) {
-               cnt = hang_info_cnt;
-       } else {
-               cnt = HANG_FIELD_MISMATCH_CNT;
-       }
-
-       while (cnt < HANG_FIELD_CNT_MAX) {
-               len = VENDOR_SEND_HANG_EXT_INFO_LEN - bytes_written;
-               bytes_written += scnprintf(&hang_info[bytes_written], len,
-                               "%c%08x", HANG_RAW_DEL, dumy_data);
-               cnt++;
-       }
-
-       WL_ERR(("hang info cnt: %d len: %d\n", cnt, (int)strlen(hang_info)));
-       WL_ERR(("hang info data: %s\n", hang_info));
-
-       wl_cfgvendor_send_async_event(wiphy,
-                       bcmcfg_to_prmry_ndev(cfg), BRCM_VENDOR_EVENT_HANGED,
-                       hang_info, (int)strlen(hang_info));
-
-       memset(string, 0, VENDOR_SEND_HANG_EXT_INFO_LEN);
-
-       if (hang_info) {
-               MFREE(cfg->osh, hang_info, VENDOR_SEND_HANG_EXT_INFO_LEN);
-       }
-
-#ifdef DHD_LOG_DUMP
-       if (dhd->debug_dump_time_hang_str) {
-               dhd_logdump_cookie_save(dhd, dhd->debug_dump_time_hang_str, "HANG");
-       }
-#endif /* DHD_LOG_DUMP */
-
-       if (dhd) {
-               clear_debug_dump_time(dhd->debug_dump_time_str);
-       }
-}
-
-void
-wl_copy_hang_info_if_falure(struct net_device *dev, u16 reason, s32 ret)
-{
-       struct bcm_cfg80211 *cfg = NULL;
-       dhd_pub_t *dhd;
-       s32 err = 0;
-       char ioctl_buf[WLC_IOCTL_SMLEN];
-       memuse_info_t mu;
-       int bytes_written = 0;
-       int remain_len = 0;
-
-       if (!dev) {
-               WL_ERR(("dev is null"));
-               return;
-
-       }
-
-       cfg = wl_get_cfg(dev);
-       if (!cfg) {
-               WL_ERR(("dev=%p cfg=%p\n", dev, cfg));
-               return;
-       }
-
-       dhd = (dhd_pub_t *)(cfg->pub);
-
-       if (!dhd || !dhd->hang_info) {
-               WL_ERR(("%s dhd=%p hang_info=%p\n", __FUNCTION__,
-                       dhd, (dhd ? dhd->hang_info : NULL)));
-               return;
-       }
-
-       err = wldev_iovar_getbuf_bsscfg(dev, "memuse",
-                       NULL, 0, ioctl_buf, WLC_IOCTL_SMLEN, 0, NULL);
-       if (unlikely(err)) {
-               WL_ERR(("error (%d)\n", err));
-               return;
-       }
-
-       memcpy(&mu, ioctl_buf, sizeof(memuse_info_t));
-
-       if (mu.len >= sizeof(memuse_info_t)) {
-               WL_ERR(("Heap Total: %d(%dK)\n", mu.arena_size, KB(mu.arena_size)));
-               WL_ERR(("Free: %d(%dK), LWM: %d(%dK)\n",
-                       mu.arena_free, KB(mu.arena_free),
-                       mu.free_lwm, KB(mu.free_lwm)));
-               WL_ERR(("In use: %d(%dK), HWM: %d(%dK)\n",
-                       mu.inuse_size, KB(mu.inuse_size),
-                       mu.inuse_hwm, KB(mu.inuse_hwm)));
-               WL_ERR(("Malloc failure count: %d\n", mu.mf_count));
-       }
-
-       memset(dhd->hang_info, 0, VENDOR_SEND_HANG_EXT_INFO_LEN);
-       remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - bytes_written;
-
-       get_debug_dump_time(dhd->debug_dump_time_hang_str);
-       copy_debug_dump_time(dhd->debug_dump_time_str, dhd->debug_dump_time_hang_str);
-
-       bytes_written += scnprintf(&dhd->hang_info[bytes_written], remain_len,
-                       "%d %d %s %d %d %d %d %d %08x %08x",
-                       reason, VENDOR_SEND_HANG_EXT_INFO_VER,
-                       dhd->debug_dump_time_hang_str,
-                       ret, mu.arena_size, mu.arena_free, mu.inuse_size, mu.mf_count, 0, 0);
-
-       dhd->hang_info_cnt = HANG_FIELD_IF_FAILURE_CNT;
-
-       clear_debug_dump_time(dhd->debug_dump_time_hang_str);
-
-       return;
-}
-#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */
-
 s32
 wl_cfg80211_set_dbg_verbose(struct net_device *ndev, u32 level)
 {