net: wifi: rockchip: update broadcom drivers for kernel4.4
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / wl_android.c
index f8eb18e7fef9ac6fe9b3e7676dd93df6b34416f8..1e722fbe62d92b3f1b895856c87cb6cd47dd03fb 100755 (executable)
@@ -1,9 +1,30 @@
 /*
  * Linux cfg80211 driver - Android related functions
  *
- * $Copyright Open Broadcom Corporation$
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ * 
+ *      Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ * 
+ *      As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module.  An independent module is a module which is not
+ * derived from this software.  The special exception does not apply to any
+ * modifications of the software.
+ * 
+ *      Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: wl_android.c 505064 2014-09-26 09:40:28Z $
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: wl_android.c 608788 2015-12-29 10:59:33Z $
  */
 
 #include <linux/module.h>
@@ -35,6 +56,9 @@
 #ifdef WL_NAN
 #include <wl_cfgnan.h>
 #endif /* WL_NAN */
+#ifdef DHDTCPACK_SUPPRESS
+#include <dhd_ip.h>
+#endif /* DHDTCPACK_SUPPRESS */
 
 #ifndef WL_CFG80211
 #define htod32(i) i
@@ -85,16 +109,10 @@ uint android_msg_level = ANDROID_ERROR_LEVEL;
 #define        CMD_SCAN_PASSIVE        "SCAN-PASSIVE"
 #define CMD_RSSI               "RSSI"
 #define CMD_LINKSPEED          "LINKSPEED"
-#ifdef PKT_FILTER_SUPPORT
 #define CMD_RXFILTER_START     "RXFILTER-START"
 #define CMD_RXFILTER_STOP      "RXFILTER-STOP"
 #define CMD_RXFILTER_ADD       "RXFILTER-ADD"
 #define CMD_RXFILTER_REMOVE    "RXFILTER-REMOVE"
-#if defined(CUSTOM_PLATFORM_NV_TEGRA)
-#define CMD_PKT_FILTER_MODE            "PKT_FILTER_MODE"
-#define CMD_PKT_FILTER_PORTS   "PKT_FILTER_PORTS"
-#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
-#endif /* PKT_FILTER_SUPPORT */
 #define CMD_BTCOEXSCAN_START   "BTCOEXSCAN-START"
 #define CMD_BTCOEXSCAN_STOP    "BTCOEXSCAN-STOP"
 #define CMD_BTCOEXMODE         "BTCOEXMODE"
@@ -110,12 +128,21 @@ uint android_msg_level = ANDROID_ERROR_LEVEL;
 #define CMD_P2P_GET_NOA                        "P2P_GET_NOA"
 #endif /* WL_ENABLE_P2P_IF */
 #define CMD_P2P_SD_OFFLOAD             "P2P_SD_"
+#define CMD_P2P_LISTEN_OFFLOAD         "P2P_LO_"
 #define CMD_P2P_SET_PS         "P2P_SET_PS"
+#define CMD_P2P_ECSA           "P2P_ECSA"
 #define CMD_SET_AP_WPS_P2P_IE          "SET_AP_WPS_P2P_IE"
 #define CMD_SETROAMMODE        "SETROAMMODE"
 #define CMD_SETIBSSBEACONOUIDATA       "SETIBSSBEACONOUIDATA"
 #define CMD_MIRACAST           "MIRACAST"
+#ifdef WL_NAN
 #define CMD_NAN                "NAN_"
+#endif /* WL_NAN */
+#define CMD_COUNTRY_DELIMITER "/"
+#ifdef WL11ULB
+#define CMD_ULB_MODE "ULB_MODE"
+#define CMD_ULB_BW "ULB_BW"
+#endif /* WL11ULB */
 #define CMD_GET_CHANNEL                        "GET_CHANNEL"
 #define CMD_SET_ROAM                   "SET_ROAM_TRIGGER"
 #define CMD_GET_ROAM                   "GET_ROAM_TRIGGER"
@@ -128,20 +155,29 @@ uint android_msg_level = ANDROID_ERROR_LEVEL;
 #define CMD_GET_BEST_CHANNELS  "GET_BEST_CHANNELS"
 #endif /* WL_SUPPORT_AUTO_CHANNEL */
 
-#if defined(CUSTOM_PLATFORM_NV_TEGRA)
-#define CMD_SETMIRACAST        "SETMIRACAST"
-#define CMD_ASSOCRESPIE        "ASSOCRESPIE"
-#define CMD_RXRATESTATS        "RXRATESTATS"
-#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
-
+#define CMD_80211_MODE    "MODE"  /* 802.11 mode a/b/g/n/ac */
+#define CMD_CHANSPEC      "CHANSPEC"
+#define CMD_DATARATE      "DATARATE"
+#define CMD_ASSOC_CLIENTS "ASSOCLIST"
+#define CMD_SET_CSA       "SETCSA"
+#ifdef WL_SUPPORT_AUTO_CHANNEL
+#define CMD_SET_HAPD_AUTO_CHANNEL      "HAPD_AUTO_CHANNEL"
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
+#ifdef CUSTOMER_HW4_PRIVATE_CMD
+#ifdef SUPPORT_SET_LPC
+#define CMD_HAPD_LPC_ENABLED           "HAPD_LPC_ENABLED"
+#endif /* SUPPORT_SET_LPC */
+#ifdef SUPPORT_TRIGGER_HANG_EVENT
+#define CMD_TEST_FORCE_HANG            "TEST_FORCE_HANG"
+#endif /* SUPPORT_TRIGGER_HANG_EVENT */
+#ifdef TEST_TX_POWER_CONTROL
+#define CMD_TEST_SET_TX_POWER          "TEST_SET_TX_POWER"
+#define CMD_TEST_GET_TX_POWER          "TEST_GET_TX_POWER"
+#endif /* TEST_TX_POWER_CONTROL */
+#define CMD_SARLIMIT_TX_CONTROL                "SET_TX_POWER_CALLING"
+#endif /* CUSTOMER_HW4_PRIVATE_CMD */
 #define CMD_KEEP_ALIVE         "KEEPALIVE"
 
-/* CCX Private Commands */
-#ifdef BCMCCX
-#define CMD_GETCCKM_RN         "get cckm_rn"
-#define CMD_SETCCKM_KRK                "set cckm_krk"
-#define CMD_GET_ASSOC_RES_IES  "get assoc_res_ies"
-#endif
 
 #ifdef PNO_SUPPORT
 #define CMD_PNOSSIDCLR_SET     "PNOSSIDCLR"
@@ -151,38 +187,82 @@ uint android_msg_level = ANDROID_ERROR_LEVEL;
 #define CMD_WLS_BATCHING       "WLS_BATCHING"
 #endif /* PNO_SUPPORT */
 
-#define CMD_OKC_SET_PMK                "SET_PMK"
-#define CMD_OKC_ENABLE         "OKC_ENABLE"
-
 #define        CMD_HAPD_MAC_FILTER     "HAPD_MAC_FILTER"
 
-#ifdef WLFBT
-#define CMD_GET_FTKEY      "GET_FTKEY"
-#endif
+#ifdef CUSTOMER_HW4_PRIVATE_CMD
+
+
+#if defined(SUPPORT_RANDOM_MAC_SCAN)
+#define ENABLE_RANDOM_MAC "ENABLE_RANDOM_MAC"
+#define DISABLE_RANDOM_MAC "DISABLE_RANDOM_MAC"
+#endif /* SUPPORT_RANDOM_MAC_SCAN */
+
+
+#define CMD_CHANGE_RL  "CHANGE_RL"
+#define CMD_RESTORE_RL  "RESTORE_RL"
+
+#define CMD_SET_RMC_ENABLE                     "SETRMCENABLE"
+#define CMD_SET_RMC_TXRATE                     "SETRMCTXRATE"
+#define CMD_SET_RMC_ACTPERIOD          "SETRMCACTIONPERIOD"
+#define CMD_SET_RMC_IDLEPERIOD         "SETRMCIDLEPERIOD"
+#define CMD_SET_RMC_LEADER                     "SETRMCLEADER"
+#define CMD_SET_RMC_EVENT                      "SETRMCEVENT"
+
+#define CMD_SET_SCSCAN         "SETSINGLEANT"
+#define CMD_GET_SCSCAN         "GETSINGLEANT"
+
+/* FCC_PWR_LIMIT_2G */
+#define CUSTOMER_HW4_ENABLE            0
+#define CUSTOMER_HW4_DISABLE   -1
+#define CUSTOMER_HW4_EN_CONVERT(i)     (i += 1)
+
+#ifdef WLTDLS
+#define CMD_TDLS_RESET "TDLS_RESET"
+#endif /* WLTDLS */
+
+#ifdef IPV6_NDO_SUPPORT
+#define CMD_NDRA_LIMIT "NDRA_LIMIT"
+#endif /* IPV6_NDO_SUPPORT */
+
+#endif /* CUSTOMER_HW4_PRIVATE_CMD */
 
-#ifdef WLAIBSS
-#define CMD_SETIBSSTXFAILEVENT         "SETIBSSTXFAILEVENT"
-#define CMD_GET_IBSS_PEER_INFO         "GETIBSSPEERINFO"
-#define CMD_GET_IBSS_PEER_INFO_ALL     "GETIBSSPEERINFOALL"
-#define CMD_SETIBSSROUTETABLE          "SETIBSSROUTETABLE"
-#define CMD_SETIBSSAMPDU                       "SETIBSSAMPDU"
-#define CMD_SETIBSSANTENNAMODE         "SETIBSSANTENNAMODE"
-#endif /* WLAIBSS */
 
 #define CMD_ROAM_OFFLOAD                       "SETROAMOFFLOAD"
-#define CMD_ROAM_OFFLOAD_APLIST                "SETROAMOFFLAPLIST"
-#define CMD_GET_LINK_STATUS                    "GETLINKSTATUS"
+#define CMD_ROAM_OFFLOAD_APLIST                        "SETROAMOFFLAPLIST"
+#define CMD_INTERFACE_CREATE                   "INTERFACE_CREATE"
+#define CMD_INTERFACE_DELETE                   "INTERFACE_DELETE"
+
+#if defined(DHD_ENABLE_BIGDATA_LOGGING)
+#define CMD_GET_BSS_INFO            "GETBSSINFO"
+#define CMD_GET_ASSOC_REJECT_INFO   "GETASSOCREJECTINFO"
+#endif /* DHD_ENABLE_BIGDATA_LOGGING */
 
 #ifdef P2PRESP_WFDIE_SRC
 #define CMD_P2P_SET_WFDIE_RESP      "P2P_SET_WFDIE_RESP"
 #define CMD_P2P_GET_WFDIE_RESP      "P2P_GET_WFDIE_RESP"
 #endif /* P2PRESP_WFDIE_SRC */
 
-/* related with CMD_GET_LINK_STATUS */
-#define WL_ANDROID_LINK_VHT                                    0x01
-#define WL_ANDROID_LINK_MIMO                                   0x02
-#define WL_ANDROID_LINK_AP_VHT_SUPPORT         0x04
-#define WL_ANDROID_LINK_AP_MIMO_SUPPORT        0x08
+#define CMD_DFS_AP_MOVE                        "DFS_AP_MOVE"
+#define CMD_WBTEXT_ENABLE              "WBTEXT_ENABLE"
+#define CMD_WBTEXT_PROFILE_CONFIG      "WBTEXT_PROFILE_CONFIG"
+#define CMD_WBTEXT_WEIGHT_CONFIG       "WBTEXT_WEIGHT_CONFIG"
+#define CMD_WBTEXT_TABLE_CONFIG                "WBTEXT_TABLE_CONFIG"
+#define CMD_WBTEXT_DELTA_CONFIG                "WBTEXT_DELTA_CONFIG"
+
+#ifdef WLWFDS
+#define CMD_ADD_WFDS_HASH      "ADD_WFDS_HASH"
+#define CMD_DEL_WFDS_HASH      "DEL_WFDS_HASH"
+#endif /* WLWFDS */
+
+#ifdef SET_RPS_CPUS
+#define CMD_RPSMODE  "RPSMODE"
+#endif /* SET_RPS_CPUS */
+
+#ifdef BT_WIFI_HANDOVER
+#define CMD_TBOW_TEARDOWN "TBOW_TEARDOWN"
+#endif /* BT_WIFI_HANDOVER */
+
+#define CMD_MURX_BFE_CAP "MURX_BFE_CAP"
 
 /* miracast related definition */
 #define MIRACAST_MODE_OFF      0
@@ -226,6 +306,15 @@ static LIST_HEAD(miracast_resume_list);
 static u8 miracast_cur_mode;
 #endif
 
+#ifdef DHD_LOG_DUMP
+#define CMD_NEW_DEBUG_PRINT_DUMP                       "DEBUG_DUMP"
+extern void dhd_schedule_log_dump(dhd_pub_t *dhdp);
+extern int dhd_bus_mem_dump(dhd_pub_t *dhd);
+#endif /* DHD_LOG_DUMP */
+#ifdef DHD_TRACE_WAKE_LOCK
+extern void dhd_wk_lock_stats_dump(dhd_pub_t *dhdp);
+#endif /* DHD_TRACE_WAKE_LOCK */
+
 struct io_cfg {
        s8 *iovar;
        s32 param;
@@ -263,63 +352,6 @@ typedef struct _compat_android_wifi_priv_cmd {
                                           (JOIN_PREF_WPA_TUPLE_SIZE * JOIN_PREF_MAX_WPA_TUPLES))
 #endif /* BCMFW_ROAM_ENABLE */
 
-#ifdef WL_GENL
-static s32 wl_genl_handle_msg(struct sk_buff *skb, struct genl_info *info);
-static int wl_genl_init(void);
-static int wl_genl_deinit(void);
-
-extern struct net init_net;
-/* attribute policy: defines which attribute has which type (e.g int, char * etc)
- * possible values defined in net/netlink.h
- */
-static struct nla_policy wl_genl_policy[BCM_GENL_ATTR_MAX + 1] = {
-       [BCM_GENL_ATTR_STRING] = { .type = NLA_NUL_STRING },
-       [BCM_GENL_ATTR_MSG] = { .type = NLA_BINARY },
-};
-
-#define WL_GENL_VER 1
-/* family definition */
-static struct genl_family wl_genl_family = {
-       .id = GENL_ID_GENERATE,    /* Genetlink would generate the ID */
-       .hdrsize = 0,
-       .name = "bcm-genl",        /* Netlink I/F for Android */
-       .version = WL_GENL_VER,     /* Version Number */
-       .maxattr = BCM_GENL_ATTR_MAX,
-};
-
-/* commands: mapping between the command enumeration and the actual function */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
-struct genl_ops wl_genl_ops[] = {
-       {
-       .cmd = BCM_GENL_CMD_MSG,
-       .flags = 0,
-       .policy = wl_genl_policy,
-       .doit = wl_genl_handle_msg,
-       .dumpit = NULL,
-       },
-};
-#else
-struct genl_ops wl_genl_ops = {
-       .cmd = BCM_GENL_CMD_MSG,
-       .flags = 0,
-       .policy = wl_genl_policy,
-       .doit = wl_genl_handle_msg,
-       .dumpit = NULL,
-
-};
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
-static struct genl_multicast_group wl_genl_mcast[] = {
-        { .name = "bcm-genl-mcast", },
-};
-#else
-static struct genl_multicast_group wl_genl_mcast = {
-       .id = GENL_ID_GENERATE,    /* Genetlink would generate the ID */
-       .name = "bcm-genl-mcast",
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */
-#endif /* WL_GENL */
 
 /**
  * Extern function declarations (TODO: move them to dhd_linux.h)
@@ -338,6 +370,8 @@ int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
 { return 0; }
 int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
 { return 0; }
+int wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
+{ return 0; }
 #endif /* WL_CFG80211 */
 
 
@@ -363,6 +397,43 @@ int g_wifi_on = TRUE;
 /**
  * Local (static) function definitions
  */
+
+#ifdef WLWFDS
+static int wl_android_set_wfds_hash(
+       struct net_device *dev, char *command, int total_len, bool enable)
+{
+       int error = 0;
+       wl_p2p_wfds_hash_t *wfds_hash = NULL;
+       char *smbuf = NULL;
+       smbuf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+
+       if (smbuf == NULL) {
+               ANDROID_ERROR(("%s: failed to allocated memory %d bytes\n",
+                       __FUNCTION__, WLC_IOCTL_MAXLEN));
+               return -ENOMEM;
+       }
+
+       if (enable) {
+               wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_ADD_WFDS_HASH) + 1);
+               error = wldev_iovar_setbuf(dev, "p2p_add_wfds_hash", wfds_hash,
+                       sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
+       }
+       else {
+               wfds_hash = (wl_p2p_wfds_hash_t *)(command + strlen(CMD_DEL_WFDS_HASH) + 1);
+               error = wldev_iovar_setbuf(dev, "p2p_del_wfds_hash", wfds_hash,
+                       sizeof(wl_p2p_wfds_hash_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
+       }
+
+       if (error) {
+               ANDROID_ERROR(("%s: failed to %s, error=%d\n", __FUNCTION__, command, error));
+       }
+
+       if (smbuf)
+               kfree(smbuf);
+       return error;
+}
+#endif /* WLWFDS */
+
 static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len)
 {
        int link_speed;
@@ -383,15 +454,42 @@ static int wl_android_get_link_speed(struct net_device *net, char *command, int
 static int wl_android_get_rssi(struct net_device *net, char *command, int total_len)
 {
        wlc_ssid_t ssid = {0};
-       int rssi;
        int bytes_written = 0;
-       int error;
+       int error = 0;
+       scb_val_t scbval;
+       char *delim = NULL;
+
+       delim = strchr(command, ' ');
+       /* For Ap mode rssi command would be
+        * driver rssi <sta_mac_addr>
+        * for STA/GC mode
+        * driver rssi
+       */
+       if (delim) {
+               /* Ap/GO mode
+               * driver rssi <sta_mac_addr>
+               */
+               ANDROID_TRACE(("%s: cmd:%s\n", __FUNCTION__, delim));
+               /* skip space from delim after finding char */
+               delim++;
+               if (!(bcm_ether_atoe((delim), &scbval.ea)))
+               {
+                       ANDROID_ERROR(("%s:address err\n", __FUNCTION__));
+                       return -1;
+               }
+               scbval.val = htod32(0);
+               ANDROID_TRACE(("%s: address:"MACDBG, __FUNCTION__, MAC2STRDBG(scbval.ea.octet)));
+       }
+       else {
+               /* STA/GC mode */
+               memset(&scbval, 0, sizeof(scb_val_t));
+       }
 
-       error = wldev_get_rssi(net, &rssi);
+       error = wldev_get_rssi(net, &scbval);
        if (error)
                return -1;
 #if defined(RSSIOFFSET)
-       rssi = wl_update_rssi_offset(net, rssi);
+       scbval.val = wl_update_rssi_offset(net, scbval.val);
 #endif
 
        error = wldev_get_ssid(net, &ssid);
@@ -403,8 +501,8 @@ static int wl_android_get_rssi(struct net_device *net, char *command, int total_
                memcpy(command, ssid.SSID, ssid.SSID_len);
                bytes_written = ssid.SSID_len;
        }
-       bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", rssi);
-       ANDROID_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
+       bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", scbval.val);
+       ANDROID_TRACE(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
        return bytes_written;
 }
 
@@ -416,17 +514,20 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int
 
        suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0';
 
-       if (suspend_flag != 0)
+       if (suspend_flag != 0) {
                suspend_flag = 1;
+       }
        ret_now = net_os_set_suspend_disable(dev, suspend_flag);
 
        if (ret_now != suspend_flag) {
-               if (!(ret = net_os_set_suspend(dev, ret_now, 1)))
+               if (!(ret = net_os_set_suspend(dev, ret_now, 1))) {
                        ANDROID_INFO(("%s: Suspend Flag %d -> %d\n",
                                __FUNCTION__, ret_now, suspend_flag));
-               else
+               } else {
                        ANDROID_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
+               }
        }
+
        return ret;
 }
 
@@ -450,6 +551,207 @@ static int wl_android_set_suspendmode(struct net_device *dev, char *command, int
        return ret;
 }
 
+int wl_android_get_80211_mode(struct net_device *dev, char *command, int total_len)
+{
+       uint8 mode[4];
+       int  error = 0;
+       int bytes_written = 0;
+
+       error = wldev_get_mode(dev, mode);
+       if (error)
+               return -1;
+
+       ANDROID_INFO(("%s: mode:%s\n", __FUNCTION__, mode));
+       bytes_written = snprintf(command, total_len, "%s %s", CMD_80211_MODE, mode);
+       ANDROID_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
+       return bytes_written;
+
+}
+
+extern chanspec_t
+wl_chspec_driver_to_host(chanspec_t chanspec);
+int wl_android_get_chanspec(struct net_device *dev, char *command, int total_len)
+{
+       int error = 0;
+       int bytes_written = 0;
+       int chsp = {0};
+       uint16 band = 0;
+       uint16 bw = 0;
+       uint16 channel = 0;
+       u32 sb = 0;
+       chanspec_t chanspec;
+
+       /* command is
+        * driver chanspec
+        */
+       error = wldev_iovar_getint(dev, "chanspec", &chsp);
+       if (error)
+               return -1;
+
+       chanspec = wl_chspec_driver_to_host(chsp);
+       ANDROID_INFO(("%s:return value of chanspec:%x\n", __FUNCTION__, chanspec));
+
+       channel = chanspec & WL_CHANSPEC_CHAN_MASK;
+       band = chanspec & WL_CHANSPEC_BAND_MASK;
+       bw = chanspec & WL_CHANSPEC_BW_MASK;
+
+       ANDROID_INFO(("%s:channel:%d band:%d bandwidth:%d\n", __FUNCTION__, channel, band, bw));
+
+       if (bw == WL_CHANSPEC_BW_80)
+               bw = WL_CH_BANDWIDTH_80MHZ;
+       else if (bw == WL_CHANSPEC_BW_40)
+               bw = WL_CH_BANDWIDTH_40MHZ;
+       else if (bw == WL_CHANSPEC_BW_20)
+               bw = WL_CH_BANDWIDTH_20MHZ;
+       else
+               bw = WL_CH_BANDWIDTH_20MHZ;
+
+       if (bw == WL_CH_BANDWIDTH_40MHZ) {
+               if (CHSPEC_SB_UPPER(chanspec)) {
+                       channel += CH_10MHZ_APART;
+               } else {
+                       channel -= CH_10MHZ_APART;
+               }
+       }
+       else if (bw == WL_CH_BANDWIDTH_80MHZ) {
+               sb = chanspec & WL_CHANSPEC_CTL_SB_MASK;
+               if (sb == WL_CHANSPEC_CTL_SB_LL) {
+                       channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
+               } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
+                       channel -= CH_10MHZ_APART;
+               } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
+                       channel += CH_10MHZ_APART;
+               } else {
+                       /* WL_CHANSPEC_CTL_SB_UU */
+                       channel += (CH_10MHZ_APART + CH_20MHZ_APART);
+               }
+       }
+       bytes_written = snprintf(command, total_len, "%s channel %d band %s bw %d", CMD_CHANSPEC,
+               channel, band == WL_CHANSPEC_BAND_5G ? "5G":"2G", bw);
+
+       ANDROID_INFO(("%s: command:%s EXIT\n", __FUNCTION__, command));
+       return bytes_written;
+
+}
+
+/* returns current datarate datarate returned from firmware are in 500kbps */
+int wl_android_get_datarate(struct net_device *dev, char *command, int total_len)
+{
+       int  error = 0;
+       int datarate = 0;
+       int bytes_written = 0;
+
+       error = wldev_get_datarate(dev, &datarate);
+       if (error)
+               return -1;
+
+       ANDROID_INFO(("%s:datarate:%d\n", __FUNCTION__, datarate));
+
+       bytes_written = snprintf(command, total_len, "%s %d", CMD_DATARATE, (datarate/2));
+       return bytes_written;
+}
+int wl_android_get_assoclist(struct net_device *dev, char *command, int total_len)
+{
+       int  error = 0;
+       int bytes_written = 0;
+       uint i;
+       char mac_buf[MAX_NUM_OF_ASSOCLIST *
+               sizeof(struct ether_addr) + sizeof(uint)] = {0};
+       struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+
+       ANDROID_TRACE(("%s: ENTER\n", __FUNCTION__));
+
+       assoc_maclist->count = htod32(MAX_NUM_OF_ASSOCLIST);
+
+       error = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, sizeof(mac_buf), false);
+       if (error)
+               return -1;
+
+       assoc_maclist->count = dtoh32(assoc_maclist->count);
+       bytes_written = snprintf(command, total_len, "%s listcount: %d Stations:",
+               CMD_ASSOC_CLIENTS, assoc_maclist->count);
+
+       for (i = 0; i < assoc_maclist->count; i++) {
+               bytes_written += snprintf(command + bytes_written, total_len, " " MACDBG,
+                       MAC2STRDBG(assoc_maclist->ea[i].octet));
+       }
+       return bytes_written;
+
+}
+extern chanspec_t
+wl_chspec_host_to_driver(chanspec_t chanspec);
+static int wl_android_set_csa(struct net_device *dev, char *command, int total_len)
+{
+       int error = 0;
+       char smbuf[WLC_IOCTL_SMLEN];
+       wl_chan_switch_t csa_arg;
+       u32 chnsp = 0;
+       int err = 0;
+
+       ANDROID_INFO(("%s: command:%s\n", __FUNCTION__, command));
+
+       command = (command + strlen(CMD_SET_CSA));
+       /* Order is mode, count channel */
+       if (!*++command) {
+               ANDROID_ERROR(("%s:error missing arguments\n", __FUNCTION__));
+               return -1;
+       }
+       csa_arg.mode = bcm_atoi(command);
+
+       if (csa_arg.mode != 0 && csa_arg.mode != 1) {
+               ANDROID_ERROR(("Invalid mode\n"));
+               return -1;
+       }
+
+       if (!*++command) {
+               ANDROID_ERROR(("%s:error missing count\n", __FUNCTION__));
+               return -1;
+       }
+       command++;
+       csa_arg.count = bcm_atoi(command);
+
+       csa_arg.reg = 0;
+       csa_arg.chspec = 0;
+       command += 2;
+       if (!*command) {
+               ANDROID_ERROR(("%s:error missing channel\n", __FUNCTION__));
+               return -1;
+       }
+
+       chnsp = wf_chspec_aton(command);
+       if (chnsp == 0) {
+               ANDROID_ERROR(("%s:chsp is not correct\n", __FUNCTION__));
+               return -1;
+       }
+       chnsp = wl_chspec_host_to_driver(chnsp);
+       csa_arg.chspec = chnsp;
+
+       if (chnsp & WL_CHANSPEC_BAND_5G) {
+               u32 chanspec = chnsp;
+               err = wldev_iovar_getint(dev, "per_chan_info", &chanspec);
+               if (!err) {
+                       if ((chanspec & WL_CHAN_RADAR) || (chanspec & WL_CHAN_PASSIVE)) {
+                               ANDROID_ERROR(("Channel is radar sensitive\n"));
+                               return -1;
+                       }
+                       if (chanspec == 0) {
+                               ANDROID_ERROR(("Invalid hw channel\n"));
+                               return -1;
+                       }
+               } else  {
+                       ANDROID_ERROR(("does not support per_chan_info\n"));
+                       return -1;
+               }
+               ANDROID_INFO(("non radar sensitivity\n"));
+       }
+       error = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(csa_arg),
+               smbuf, sizeof(smbuf), NULL);
+       if (error) {
+               ANDROID_ERROR(("%s:set csa failed:%d\n", __FUNCTION__, error));
+               return -1;
+       }
+       return 0;
+}
 static int wl_android_get_band(struct net_device *dev, char *command, int total_len)
 {
        uint band;
@@ -463,6 +765,222 @@ static int wl_android_get_band(struct net_device *dev, char *command, int total_
        return bytes_written;
 }
 
+#ifdef CUSTOMER_HW4_PRIVATE_CMD
+
+#ifdef FCC_PWR_LIMIT_2G
+int
+wl_android_set_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len)
+{
+       int error = 0;
+       int enable = 0;
+
+       sscanf(command+sizeof("SET_FCC_CHANNEL"), "%d", &enable);
+
+       if ((enable != CUSTOMER_HW4_ENABLE) && (enable != CUSTOMER_HW4_DISABLE)) {
+               ANDROID_ERROR(("%s: Invalid data\n", __FUNCTION__));
+               return BCME_ERROR;
+       }
+
+       CUSTOMER_HW4_EN_CONVERT(enable);
+
+       ANDROID_ERROR(("%s: fccpwrlimit2g set (%d)\n", __FUNCTION__, enable));
+       error = wldev_iovar_setint(dev, "fccpwrlimit2g", enable);
+       if (error) {
+               ANDROID_ERROR(("%s: fccpwrlimit2g set returned (%d)\n", __FUNCTION__, error));
+               return BCME_ERROR;
+       }
+
+       return error;
+}
+
+int
+wl_android_get_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len)
+{
+       int error = 0;
+       int enable = 0;
+       int bytes_written = 0;
+
+       error = wldev_iovar_getint(dev, "fccpwrlimit2g", &enable);
+       if (error) {
+               ANDROID_ERROR(("%s: fccpwrlimit2g get error (%d)\n", __FUNCTION__, error));
+               return BCME_ERROR;
+       }
+       ANDROID_ERROR(("%s: fccpwrlimit2g get (%d)\n", __FUNCTION__, enable));
+
+       bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_FCC_PWR_LIMIT_2G, enable);
+
+       return bytes_written;
+}
+#endif /* FCC_PWR_LIMIT_2G */
+
+#ifdef IPV6_NDO_SUPPORT
+int
+wl_android_nd_ra_limit(struct net_device *dev, char *command, int total_len)
+{
+       int err = 0;
+       int bytes_written = 0;
+       uint tokens;
+       char *pos, *token, *delim;
+       char smbuf[WLC_IOCTL_SMLEN];
+       char param[ND_PARAM_SIZE+1], value[ND_VALUE_SIZE+1];
+       uint16 type = 0xff, min = 0, per = 0, hold = 0;
+       nd_ra_ol_limits_t ra_ol_limit;
+
+       WL_TRACE(("command=%s, len=%d\n", command, total_len));
+       pos = command + strlen(CMD_NDRA_LIMIT) + 1;
+       memset(&ra_ol_limit, 0, sizeof(nd_ra_ol_limits_t));
+
+       if (!strncmp(pos, ND_RA_OL_SET, strlen(ND_RA_OL_SET))) {
+               WL_TRACE(("SET NDRA_LIMIT\n"));
+               pos += strlen(ND_RA_OL_SET) + 1;
+               while ((token = strsep(&pos, ND_PARAMS_DELIMETER)) != NULL) {
+                       memset(param, 0, sizeof(param));
+                       memset(value, 0, sizeof(value));
+
+                       delim = strchr(token, ND_PARAM_VALUE_DELLIMETER);
+                       if (delim != NULL)
+                               *delim = ' ';
+
+                       tokens = sscanf(token, ND_LIMIT_STR_FMT, param, value);
+                       if (!strncmp(param, ND_RA_TYPE, strlen(ND_RA_TYPE))) {
+                               type = simple_strtol(value, NULL, 0);
+                       } else if (!strncmp(param, ND_RA_MIN_TIME, strlen(ND_RA_MIN_TIME))) {
+                               min = simple_strtol(value, NULL, 0);
+                       } else if (!strncmp(param, ND_RA_PER, strlen(ND_RA_PER))) {
+                               per = simple_strtol(value, NULL, 0);
+                               if (per > 100) {
+                                       ANDROID_ERROR(("Invalid PERCENT %d\n", per));
+                                       err = BCME_BADARG;
+                                       goto exit;
+                               }
+                       } else if (!strncmp(param, ND_RA_HOLD, strlen(ND_RA_HOLD))) {
+                               hold = simple_strtol(value, NULL, 0);
+                       }
+               }
+
+               ra_ol_limit.version = htod32(ND_RA_OL_LIMITS_VER);
+               ra_ol_limit.type = htod32(type);
+               if (type == ND_RA_OL_LIMITS_REL_TYPE) {
+                       if ((min == 0) || (per == 0)) {
+                               ANDROID_ERROR(("Invalid min_time %d, percent %d\n", min, per));
+                               err = BCME_BADARG;
+                               goto exit;
+                       }
+                       ra_ol_limit.length = htod32(ND_RA_OL_LIMITS_REL_TYPE_LEN);
+                       ra_ol_limit.limits.lifetime_relative.min_time = htod32(min);
+                       ra_ol_limit.limits.lifetime_relative.lifetime_percent = htod32(per);
+               } else if (type == ND_RA_OL_LIMITS_FIXED_TYPE) {
+                       if (hold == 0) {
+                               ANDROID_ERROR(("Invalid hold_time %d\n", hold));
+                               err = BCME_BADARG;
+                               goto exit;
+                       }
+                       ra_ol_limit.length = htod32(ND_RA_OL_LIMITS_FIXED_TYPE_LEN);
+                       ra_ol_limit.limits.fixed.hold_time = htod32(hold);
+               } else {
+                       ANDROID_ERROR(("unknown TYPE %d\n", type));
+                       err = BCME_BADARG;
+                       goto exit;
+               }
+
+               err = wldev_iovar_setbuf(dev, "nd_ra_limit_intv", &ra_ol_limit,
+                       sizeof(nd_ra_ol_limits_t), smbuf, sizeof(smbuf), NULL);
+               if (err) {
+                       ANDROID_ERROR(("Failed to set nd_ra_limit_intv, error = %d\n", err));
+                       goto exit;
+               }
+
+               WL_TRACE(("TYPE %d, MIN %d, PER %d, HOLD %d\n", type, min, per, hold));
+       } else if (!strncmp(pos, ND_RA_OL_GET, strlen(ND_RA_OL_GET))) {
+               WL_TRACE(("GET NDRA_LIMIT\n"));
+               err = wldev_iovar_getbuf(dev, "nd_ra_limit_intv", NULL, 0,
+                       smbuf, sizeof(smbuf), NULL);
+               if (err) {
+                       ANDROID_ERROR(("Failed to get nd_ra_limit_intv, error = %d\n", err));
+                       goto exit;
+               }
+
+               memcpy(&ra_ol_limit, (uint8 *)smbuf, sizeof(nd_ra_ol_limits_t));
+               type = ra_ol_limit.type;
+               if (ra_ol_limit.version != ND_RA_OL_LIMITS_VER) {
+                       ANDROID_ERROR(("Invalid Version %d\n", ra_ol_limit.version));
+                       err = BCME_VERSION;
+                       goto exit;
+               }
+
+               if (ra_ol_limit.type == ND_RA_OL_LIMITS_REL_TYPE) {
+                       min = ra_ol_limit.limits.lifetime_relative.min_time;
+                       per = ra_ol_limit.limits.lifetime_relative.lifetime_percent;
+                       ANDROID_ERROR(("TYPE %d, MIN %d, PER %d\n", type, min, per));
+                       bytes_written = snprintf(command, total_len,
+                               "%s GET TYPE %d, MIN %d, PER %d", CMD_NDRA_LIMIT, type, min, per);
+               } else if (ra_ol_limit.type == ND_RA_OL_LIMITS_FIXED_TYPE) {
+                       hold = ra_ol_limit.limits.fixed.hold_time;
+                       ANDROID_ERROR(("TYPE %d, HOLD %d\n", type, hold));
+                       bytes_written = snprintf(command, total_len,
+                               "%s GET TYPE %d, HOLD %d", CMD_NDRA_LIMIT, type, hold);
+               } else {
+                       ANDROID_ERROR(("unknown TYPE %d\n", type));
+                       err = BCME_ERROR;
+                       goto exit;
+               }
+
+               return bytes_written;
+       } else {
+               ANDROID_ERROR(("unknown command\n"));
+               err = BCME_ERROR;
+               goto exit;
+       }
+
+exit:
+       return err;
+}
+#endif /* IPV6_NDO_SUPPORT */
+#ifdef WLTDLS
+int wl_android_tdls_reset(struct net_device *dev)
+{
+       int ret = 0;
+       ret = dhd_tdls_enable(dev, false, false, NULL);
+       if (ret < 0) {
+               ANDROID_ERROR(("Disable tdls failed. %d\n", ret));
+               return ret;
+       }
+       ret = dhd_tdls_enable(dev, true, true, NULL);
+       if (ret < 0) {
+               ANDROID_ERROR(("enable tdls failed. %d\n", ret));
+               return ret;
+       }
+       return 0;
+}
+#endif /* WLTDLS */
+#endif /* CUSTOMER_HW4_PRIVATE_CMD */
+static int wl_android_wbtext(struct net_device *dev, char *command, int total_len)
+{
+       int error = 0, argc = 0;
+       int data, bytes_written;
+
+       argc = sscanf(command+sizeof("WBTEXT_ENABLE"), "%d", &data);
+       if (!argc) {
+               error = wldev_iovar_getint(dev, "wnm_bsstrans_resp", &data);
+               if (error) {
+                       ANDROID_ERROR(("%s: Failed to set wbtext error = %d\n",
+                               __FUNCTION__, error));
+               }
+               bytes_written = snprintf(command, total_len, "WBTEXT %s\n",
+                               (data == WL_BSSTRANS_POLICY_PRODUCT)? "ENABLED" : "DISABLED");
+               return bytes_written;
+       } else {
+               if (data)
+                       data = WL_BSSTRANS_POLICY_PRODUCT;
+
+               error = wldev_iovar_setint(dev, "wnm_bsstrans_resp", data);
+               if (error) {
+                       ANDROID_ERROR(("%s: Failed to set wbtext error = %d\n",
+                               __FUNCTION__, error));
+               }
+       }
+       return error;
+}
 
 #ifdef PNO_SUPPORT
 #define PNO_PARAM_SIZE 50
@@ -551,7 +1069,7 @@ wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len)
                        ANDROID_ERROR(("failed to configure batch scan\n"));
                } else {
                        memset(command, 0, total_len);
-                       err = sprintf(command, "%d", err);
+                       err = snprintf(command, total_len, "%d", err);
                }
        } else if (!strncmp(pos, PNO_BATCHING_GET, strlen(PNO_BATCHING_GET))) {
                err = dhd_dev_pno_get_for_batch(dev, command, total_len);
@@ -566,7 +1084,7 @@ wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len)
                        ANDROID_ERROR(("failed to stop batching scan\n"));
                } else {
                        memset(command, 0, total_len);
-                       err = sprintf(command, "OK");
+                       err = snprintf(command, total_len, "OK");
                }
        } else {
                ANDROID_ERROR(("%s : unknown command\n", __FUNCTION__));
@@ -579,7 +1097,7 @@ exit:
 #ifndef WL_SCHED_SCAN
 static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
 {
-       wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+       wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
        int res = -1;
        int nssid = 0;
        cmd_tlv_t *cmd_tlv_temp;
@@ -691,89 +1209,6 @@ static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, i
        return bytes_written;
 }
 
-#ifdef BCMCCX
-static int wl_android_get_cckm_rn(struct net_device *dev, char *command)
-{
-       int error, rn;
-
-       ANDROID_TRACE(("%s:wl_android_get_cckm_rn\n", dev->name));
-
-       error = wldev_iovar_getint(dev, "cckm_rn", &rn);
-       if (unlikely(error)) {
-               ANDROID_ERROR(("wl_android_get_cckm_rn error (%d)\n", error));
-               return -1;
-       }
-       memcpy(command, &rn, sizeof(int));
-
-       return sizeof(int);
-}
-
-static int wl_android_set_cckm_krk(struct net_device *dev, char *command)
-{
-       int error;
-       unsigned char key[16];
-       static char iovar_buf[WLC_IOCTL_MEDLEN];
-
-       ANDROID_TRACE(("%s: wl_iw_set_cckm_krk\n", dev->name));
-
-       memset(iovar_buf, 0, sizeof(iovar_buf));
-       memcpy(key, command+strlen("set cckm_krk")+1, 16);
-
-       error = wldev_iovar_setbuf(dev, "cckm_krk", key, sizeof(key),
-               iovar_buf, WLC_IOCTL_MEDLEN, NULL);
-       if (unlikely(error))
-       {
-               ANDROID_ERROR((" cckm_krk set error (%d)\n", error));
-               return -1;
-       }
-       return 0;
-}
-
-static int wl_android_get_assoc_res_ies(struct net_device *dev, char *command)
-{
-       int error;
-       u8 buf[WL_ASSOC_INFO_MAX];
-       wl_assoc_info_t assoc_info;
-       u32 resp_ies_len = 0;
-       int bytes_written = 0;
-
-       ANDROID_TRACE(("%s: wl_iw_get_assoc_res_ies\n", dev->name));
-
-       error = wldev_iovar_getbuf(dev, "assoc_info", NULL, 0, buf, WL_ASSOC_INFO_MAX, NULL);
-       if (unlikely(error)) {
-               ANDROID_ERROR(("could not get assoc info (%d)\n", error));
-               return -1;
-       }
-
-       memcpy(&assoc_info, buf, sizeof(wl_assoc_info_t));
-       assoc_info.req_len = htod32(assoc_info.req_len);
-       assoc_info.resp_len = htod32(assoc_info.resp_len);
-       assoc_info.flags = htod32(assoc_info.flags);
-
-       if (assoc_info.resp_len) {
-               resp_ies_len = assoc_info.resp_len - sizeof(struct dot11_assoc_resp);
-       }
-
-       /* first 4 bytes are ie len */
-       memcpy(command, &resp_ies_len, sizeof(u32));
-       bytes_written = sizeof(u32);
-
-       /* get the association resp IE's if there are any */
-       if (resp_ies_len) {
-               error = wldev_iovar_getbuf(dev, "assoc_resp_ies", NULL, 0,
-                       buf, WL_ASSOC_INFO_MAX, NULL);
-               if (unlikely(error)) {
-                       ANDROID_ERROR(("could not get assoc resp_ies (%d)\n", error));
-                       return -1;
-               }
-
-               memcpy(command+sizeof(u32), buf, resp_ies_len);
-               bytes_written += resp_ies_len;
-       }
-       return bytes_written;
-}
-
-#endif /* BCMCCX */
 
 int
 wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist)
@@ -853,19 +1288,28 @@ wl_android_set_mac_address_filter(struct net_device *dev, const char* str)
        int macmode = MACLIST_MODE_DISABLED;
        struct maclist *list;
        char eabuf[ETHER_ADDR_STR_LEN];
+       char *token;
 
        /* string should look like below (macmode/macnum/maclist) */
        /*   1 2 00:11:22:33:44:55 00:11:22:33:44:ff  */
 
        /* get the MAC filter mode */
-       macmode = bcm_atoi(strsep((char**)&str, " "));
+       token = strsep((char**)&str, " ");
+       if (!token) {
+               return -1;
+       }
+       macmode = bcm_atoi(token);
 
        if (macmode < MACLIST_MODE_DISABLED || macmode > MACLIST_MODE_ALLOW) {
                ANDROID_ERROR(("%s : invalid macmode %d\n", __FUNCTION__, macmode));
                return -1;
        }
 
-       macnum = bcm_atoi(strsep((char**)&str, " "));
+       token = strsep((char**)&str, " ");
+       if (!token) {
+               return -1;
+       }
+       macnum = bcm_atoi(token);
        if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
                ANDROID_ERROR(("%s : invalid number of MAC address entries %d\n",
                        __FUNCTION__, macnum));
@@ -907,17 +1351,7 @@ wl_android_set_mac_address_filter(struct net_device *dev, const char* str)
 int wl_android_wifi_on(struct net_device *dev)
 {
        int ret = 0;
-#ifdef CONFIG_MACH_UNIVERSAL5433
-       int retry;
-       /* Do not retry old revision Helsinki Prime */
-       if (!check_rev()) {
-               retry = 1;
-       } else {
-               retry = POWERUP_MAX_RETRY;
-       }
-#else
        int retry = POWERUP_MAX_RETRY;
-#endif /* CONFIG_MACH_UNIVERSAL5433 */
 
        if (!dev) {
                ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
@@ -936,8 +1370,9 @@ int wl_android_wifi_on(struct net_device *dev)
 #ifdef BCMPCIE
                        ret = dhd_net_bus_devreset(dev, FALSE);
 #endif /* BCMPCIE */
-                       if (ret == 0)
+                       if (ret == 0) {
                                break;
+                       }
                        ANDROID_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n",
                                retry));
 #ifdef BCMPCIE
@@ -983,7 +1418,7 @@ err:
 #endif
 }
 
-int wl_android_wifi_off(struct net_device *dev)
+int wl_android_wifi_off(struct net_device *dev, bool on_failure)
 {
        int ret = 0;
 
@@ -994,8 +1429,8 @@ int wl_android_wifi_off(struct net_device *dev)
 
        printf("%s in 1\n", __FUNCTION__);
        dhd_net_if_lock(dev);
-       printf("%s in 2: g_wifi_on=%d\n", __FUNCTION__, g_wifi_on);
-       if (g_wifi_on) {
+       printf("%s in 2: g_wifi_on=%d, on_failure=%d\n", __FUNCTION__, g_wifi_on, on_failure);
+       if (g_wifi_on || on_failure) {
 #if defined(BCMSDIO) || defined(BCMPCIE)
                ret = dhd_net_bus_devreset(dev, TRUE);
 #ifdef BCMSDIO
@@ -1078,10 +1513,14 @@ static int
 wl_android_get_connection_stats(struct net_device *dev, char *command, int total_len)
 {
        wl_cnt_t* cnt = NULL;
+#ifndef DISABLE_IF_COUNTERS
+       wl_if_stats_t* if_stats = NULL;
+#endif /* DISABLE_IF_COUNTERS */
+
        int link_speed = 0;
        struct connection_stats *output;
        unsigned int bufsize = 0;
-       int bytes_written = 0;
+       int bytes_written = -1;
        int ret = 0;
 
        ANDROID_INFO(("%s: enter Get Connection Stats\n", __FUNCTION__));
@@ -1093,116 +1532,532 @@ wl_android_get_connection_stats(struct net_device *dev, char *command, int total
 
        bufsize = total_len;
        if (bufsize < sizeof(struct connection_stats)) {
-               ANDROID_ERROR(("%s: not enough buffer size, provided=%u, requires=%u\n",
+               ANDROID_ERROR(("%s: not enough buffer size, provided=%u, requires=%zu\n",
                        __FUNCTION__, bufsize,
                        sizeof(struct connection_stats)));
                goto error;
        }
 
-       if ((cnt = kmalloc(sizeof(*cnt), GFP_KERNEL)) == NULL) {
-               ANDROID_ERROR(("kmalloc failed\n"));
-               return -1;
+       output = (struct connection_stats *)command;
+
+#ifndef DISABLE_IF_COUNTERS
+       if ((if_stats = kmalloc(sizeof(*if_stats), GFP_KERNEL)) == NULL) {
+               ANDROID_ERROR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__));
+               goto error;
        }
-       memset(cnt, 0, sizeof(*cnt));
+       memset(if_stats, 0, sizeof(*if_stats));
 
-       ret = wldev_iovar_getbuf(dev, "counters", NULL, 0, (char *)cnt, sizeof(wl_cnt_t), NULL);
+       ret = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
+               (char *)if_stats, sizeof(*if_stats), NULL);
        if (ret) {
-               ANDROID_ERROR(("%s: wldev_iovar_getbuf() failed, ret=%d\n",
+               ANDROID_ERROR(("%s: if_counters not supported ret=%d\n",
                        __FUNCTION__, ret));
+
+               /* In case if_stats IOVAR is not supported, get information from counters. */
+#endif /* DISABLE_IF_COUNTERS */
+               if ((cnt = kmalloc(sizeof(*cnt), GFP_KERNEL)) == NULL) {
+                       ANDROID_ERROR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__));
+                       goto error;
+               }
+               memset(cnt, 0, sizeof(*cnt));
+
+               ret = wldev_iovar_getbuf(dev, "counters", NULL, 0,
+                       (char *)cnt, sizeof(wl_cnt_t), NULL);
+               if (ret) {
+                       ANDROID_ERROR(("%s: wldev_iovar_getbuf() failed, ret=%d\n",
+                               __FUNCTION__, ret));
+                       goto error;
+               }
+
+               if (dtoh16(cnt->version) > WL_CNT_T_VERSION) {
+                       ANDROID_ERROR(("%s: incorrect version of wl_cnt_t, expected=%u got=%u\n",
+                               __FUNCTION__,  WL_CNT_T_VERSION, cnt->version));
+                       goto error;
+               }
+
+               output->txframe   = dtoh32(cnt->txframe);
+               output->txbyte    = dtoh32(cnt->txbyte);
+               output->txerror   = dtoh32(cnt->txerror);
+               output->rxframe   = dtoh32(cnt->rxframe);
+               output->rxbyte    = dtoh32(cnt->rxbyte);
+               output->txfail    = dtoh32(cnt->txfail);
+               output->txretry   = dtoh32(cnt->txretry);
+               output->txretrie  = dtoh32(cnt->txretrie);
+               output->txrts     = dtoh32(cnt->txrts);
+               output->txnocts   = dtoh32(cnt->txnocts);
+               output->txexptime = dtoh32(cnt->txexptime);
+#ifndef DISABLE_IF_COUNTERS
+       } else {
+               /* Populate from if_stats. */
+               if (dtoh16(if_stats->version) > WL_IF_STATS_T_VERSION) {
+                       ANDROID_ERROR(("%s: incorrect version of wl_if_stats_t, expected=%u got=%u\n",
+                               __FUNCTION__,  WL_IF_STATS_T_VERSION, if_stats->version));
+                       goto error;
+               }
+
+               output->txframe   = (uint32)dtoh64(if_stats->txframe);
+               output->txbyte    = (uint32)dtoh64(if_stats->txbyte);
+               output->txerror   = (uint32)dtoh64(if_stats->txerror);
+               output->rxframe   = (uint32)dtoh64(if_stats->rxframe);
+               output->rxbyte    = (uint32)dtoh64(if_stats->rxbyte);
+               output->txfail    = (uint32)dtoh64(if_stats->txfail);
+               output->txretry   = (uint32)dtoh64(if_stats->txretry);
+               output->txretrie  = (uint32)dtoh64(if_stats->txretrie);
+               /* Unavailable */
+               output->txrts     = 0;
+               output->txnocts   = 0;
+               output->txexptime = 0;
+       }
+#endif /* DISABLE_IF_COUNTERS */
+
+       /* link_speed is in kbps */
+       ret = wldev_get_link_speed(dev, &link_speed);
+       if (ret || link_speed < 0) {
+               ANDROID_ERROR(("%s: wldev_get_link_speed() failed, ret=%d, speed=%d\n",
+                       __FUNCTION__, ret, link_speed));
                goto error;
        }
 
-       if (dtoh16(cnt->version) > WL_CNT_T_VERSION) {
-               ANDROID_ERROR(("%s: incorrect version of wl_cnt_t, expected=%u got=%u\n",
-                       __FUNCTION__,  WL_CNT_T_VERSION, cnt->version));
-               goto error;
+       output->txrate    = link_speed;
+
+       /* Channel idle ratio. */
+       if (wl_chanim_stats(dev, &(output->chan_idle)) < 0) {
+               output->chan_idle = 0;
+       };
+
+       bytes_written = sizeof(struct connection_stats);
+
+error:
+#ifndef DISABLE_IF_COUNTERS
+       if (if_stats) {
+               kfree(if_stats);
+       }
+#endif /* DISABLE_IF_COUNTERS */
+       if (cnt) {
+               kfree(cnt);
+       }
+
+       return bytes_written;
+}
+#endif /* CONNECTION_STATISTICS */
+
+
+#ifdef CUSTOMER_HW4_PRIVATE_CMD
+#endif /* CUSTOMER_HW4_PRIVATE_CMD */
+
+/* SoftAP feature */
+#define APCS_BAND_2G_LEGACY1   20
+#define APCS_BAND_2G_LEGACY2   0
+#define APCS_BAND_AUTO         "band=auto"
+#define APCS_BAND_2G           "band=2g"
+#define APCS_BAND_5G           "band=5g"
+#define APCS_MAX_2G_CHANNELS   11
+#define APCS_MAX_RETRY         10
+#define APCS_DEFAULT_2G_CH     1
+#define APCS_DEFAULT_5G_CH     149
+#if defined(WL_SUPPORT_AUTO_CHANNEL)
+static int
+wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
+       char* command, int total_len)
+{
+       int channel = 0;
+       int chosen = 0;
+       int retry = 0;
+       int ret = 0;
+       int spect = 0;
+       u8 *reqbuf = NULL;
+       uint32 band = WLC_BAND_2G;
+       uint32 buf_size;
+
+       if (cmd_str) {
+               ANDROID_INFO(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str)));
+               if (strncmp(cmd_str, APCS_BAND_AUTO, strlen(APCS_BAND_AUTO)) == 0) {
+                       band = WLC_BAND_AUTO;
+               } else if (strncmp(cmd_str, APCS_BAND_5G, strlen(APCS_BAND_5G)) == 0) {
+                       band = WLC_BAND_5G;
+               } else if (strncmp(cmd_str, APCS_BAND_2G, strlen(APCS_BAND_2G)) == 0) {
+                       band = WLC_BAND_2G;
+               } else {
+                       /*
+                        * For backward compatibility: Some platforms used to issue argument 20 or 0
+                        * to enforce the 2G channel selection
+                        */
+                       channel = bcm_atoi(cmd_str);
+                       if ((channel == APCS_BAND_2G_LEGACY1) ||
+                               (channel == APCS_BAND_2G_LEGACY2)) {
+                               band = WLC_BAND_2G;
+                       } else {
+                               ANDROID_ERROR(("Invalid argument\n"));
+                               return -EINVAL;
+                       }
+               }
+       } else {
+               /* If no argument is provided, default to 2G */
+               ANDROID_ERROR(("No argument given default to 2.4G scan\n"));
+               band = WLC_BAND_2G;
+       }
+       ANDROID_INFO(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band));
+
+       if ((ret = wldev_ioctl(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect), false)) < 0) {
+               ANDROID_ERROR(("ACS: error getting the spect\n"));
+               goto done;
+       }
+
+       if (spect > 0) {
+               /* If STA is connected, return is STA channel, else ACS can be issued,
+                * set spect to 0 and proceed with ACS
+                */
+               channel = wl_cfg80211_get_sta_channel();
+               if (channel) {
+                       channel = (channel <= CH_MAX_2G_CHANNEL) ? channel : APCS_DEFAULT_2G_CH;
+                       goto done2;
+               }
+
+               if ((ret = wl_cfg80211_set_spect(dev, 0) < 0)) {
+                       ANDROID_ERROR(("ACS: error while setting spect\n"));
+                       goto done;
+               }
+       }
+
+       reqbuf = kzalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
+       if (reqbuf == NULL) {
+               ANDROID_ERROR(("failed to allocate chanspec buffer\n"));
+               return -ENOMEM;
+       }
+
+       if (band == WLC_BAND_AUTO) {
+               ANDROID_INFO(("ACS full channel scan \n"));
+               reqbuf[0] = htod32(0);
+       } else if (band == WLC_BAND_5G) {
+               ANDROID_INFO(("ACS 5G band scan \n"));
+               if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
+                       ANDROID_ERROR(("ACS 5g chanspec retreival failed! \n"));
+                       goto done;
+               }
+       } else if (band == WLC_BAND_2G) {
+               /*
+                * If channel argument is not provided/ argument 20 is provided,
+                * Restrict channel to 2GHz, 20MHz BW, No SB
+                */
+               ANDROID_INFO(("ACS 2G band scan \n"));
+               if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
+                       ANDROID_ERROR(("ACS 2g chanspec retreival failed! \n"));
+                       goto done;
+               }
+       } else {
+               ANDROID_ERROR(("ACS: No band chosen\n"));
+               goto done2;
+       }
+
+       buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
+       ret = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
+               buf_size, true);
+       if (ret < 0) {
+               ANDROID_ERROR(("can't start auto channel scan, err = %d\n", ret));
+               channel = 0;
+               goto done;
+       }
+
+       /* Wait for auto channel selection, max 3000 ms */
+       if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G)) {
+               OSL_SLEEP(500);
+       } else {
+               /*
+                * Full channel scan at the minimum takes 1.2secs
+                * even with parallel scan. max wait time: 3500ms
+                */
+               OSL_SLEEP(1000);
+       }
+
+       retry = APCS_MAX_RETRY;
+       while (retry--) {
+               ret = wldev_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen,
+                       sizeof(chosen), false);
+               if (ret < 0) {
+                       chosen = 0;
+               } else {
+                       chosen = dtoh32(chosen);
+               }
+
+               if (chosen) {
+                       int chosen_band;
+                       int apcs_band;
+#ifdef D11AC_IOTYPES
+                       if (wl_cfg80211_get_ioctl_version() == 1) {
+                               channel = LCHSPEC_CHANNEL((chanspec_t)chosen);
+                       } else {
+                               channel = CHSPEC_CHANNEL((chanspec_t)chosen);
+                       }
+#else
+                       channel = CHSPEC_CHANNEL((chanspec_t)chosen);
+#endif /* D11AC_IOTYPES */
+                       apcs_band = (band == WLC_BAND_AUTO) ? WLC_BAND_2G : band;
+                       chosen_band = (channel <= CH_MAX_2G_CHANNEL) ? WLC_BAND_2G : WLC_BAND_5G;
+                       if (apcs_band == chosen_band) {
+                               ANDROID_ERROR(("selected channel = %d\n", channel));
+                               break;
+                       }
+               }
+               ANDROID_INFO(("%d tried, ret = %d, chosen = 0x%x\n",
+                       (APCS_MAX_RETRY - retry), ret, chosen));
+               OSL_SLEEP(250);
+       }
+
+done:
+       if ((retry == 0) || (ret < 0)) {
+               /* On failure, fallback to a default channel */
+               if ((band == WLC_BAND_5G)) {
+                       channel = APCS_DEFAULT_5G_CH;
+               } else {
+                       channel = APCS_DEFAULT_2G_CH;
+               }
+               ANDROID_ERROR(("ACS failed. Fall back to default channel (%d) \n", channel));
+       }
+done2:
+       if (spect > 0) {
+               if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) {
+                       ANDROID_ERROR(("ACS: error while setting spect\n"));
+               }
+       }
+
+       if (reqbuf) {
+               kfree(reqbuf);
+       }
+
+       if (channel) {
+               snprintf(command, 4, "%d", channel);
+               ANDROID_INFO(("command result is %s \n", command));
+               return strlen(command);
+       } else {
+               return ret;
+       }
+}
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
+
+#ifdef CUSTOMER_HW4_PRIVATE_CMD
+
+
+#ifdef SUPPORT_SET_LPC
+static int
+wl_android_set_lpc(struct net_device *dev, const char* string_num)
+{
+       int lpc_enabled, ret;
+       s32 val = 1;
+
+       lpc_enabled = bcm_atoi(string_num);
+       ANDROID_INFO(("%s : HAPD_LPC_ENABLED = %d\n", __FUNCTION__, lpc_enabled));
+
+       ret = wldev_ioctl(dev, WLC_DOWN, &val, sizeof(s32), true);
+       if (ret < 0)
+               ANDROID_ERROR(("WLC_DOWN error %d\n", ret));
+
+       wldev_iovar_setint(dev, "lpc", lpc_enabled);
+
+       ret = wldev_ioctl(dev, WLC_UP, &val, sizeof(s32), true);
+       if (ret < 0)
+               ANDROID_ERROR(("WLC_UP error %d\n", ret));
+
+       return 1;
+}
+#endif /* SUPPORT_SET_LPC */
+
+static int
+wl_android_ch_res_rl(struct net_device *dev, bool change)
+{
+       int error = 0;
+       s32 srl = 7;
+       s32 lrl = 4;
+       printk("%s enter\n", __FUNCTION__);
+       if (change) {
+               srl = 4;
+               lrl = 2;
+       }
+       error = wldev_ioctl(dev, WLC_SET_SRL, &srl, sizeof(s32), true);
+       if (error) {
+               ANDROID_ERROR(("Failed to set SRL, error = %d\n", error));
+       }
+       error = wldev_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(s32), true);
+       if (error) {
+               ANDROID_ERROR(("Failed to set LRL, error = %d\n", error));
+       }
+       return error;
+}
+
+
+static int
+wl_android_rmc_enable(struct net_device *net, int rmc_enable)
+{
+       int err;
+
+       err = wldev_iovar_setint(net, "rmc_ackreq", rmc_enable);
+       return err;
+}
+
+static int
+wl_android_rmc_set_leader(struct net_device *dev, const char* straddr)
+{
+       int error  = BCME_OK;
+       char smbuf[WLC_IOCTL_SMLEN];
+       wl_rmc_entry_t rmc_entry;
+       ANDROID_INFO(("%s: Set new RMC leader %s\n", __FUNCTION__, straddr));
+
+       memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
+       if (!bcm_ether_atoe(straddr, &rmc_entry.addr)) {
+               if (strlen(straddr) == 1 && bcm_atoi(straddr) == 0) {
+                       ANDROID_INFO(("%s: Set auto leader selection mode\n", __FUNCTION__));
+                       memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
+               } else {
+                       ANDROID_ERROR(("%s: No valid mac address provided\n",
+                               __FUNCTION__));
+                       return BCME_ERROR;
+               }
+       }
+
+       error = wldev_iovar_setbuf(dev, "rmc_ar", &rmc_entry, sizeof(wl_rmc_entry_t),
+               smbuf, sizeof(smbuf), NULL);
+
+       if (error != BCME_OK) {
+               ANDROID_ERROR(("%s: Unable to set RMC leader, error = %d\n",
+                       __FUNCTION__, error));
+       }
+
+       return error;
+}
+
+static int wl_android_set_rmc_event(struct net_device *dev, char *command, int total_len)
+{
+       int err = 0;
+       int pid = 0;
+
+       if (sscanf(command, CMD_SET_RMC_EVENT " %d", &pid) <= 0) {
+               ANDROID_ERROR(("Failed to get Parameter from : %s\n", command));
+               return -1;
+       }
+
+       /* set pid, and if the event was happened, let's send a notification through netlink */
+       wl_cfg80211_set_rmc_pid(pid);
+
+       ANDROID_TRACE(("RMC pid=%d\n", pid));
+
+       return err;
+}
+
+int wl_android_get_singlecore_scan(struct net_device *dev, char *command, int total_len)
+{
+       int error = 0;
+       int bytes_written = 0;
+       int mode = 0;
+
+       error = wldev_iovar_getint(dev, "scan_ps", &mode);
+       if (error) {
+               ANDROID_ERROR(("%s: Failed to get single core scan Mode, error = %d\n",
+                       __FUNCTION__, error));
+               return -1;
+       }
+
+       bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_SCSCAN, mode);
+
+       return bytes_written;
+}
+
+int wl_android_set_singlecore_scan(struct net_device *dev, char *command, int total_len)
+{
+       int error = 0;
+       int mode = 0;
+
+       if (sscanf(command, "%*s %d", &mode) != 1) {
+               ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
+               return -1;
        }
 
-       /* link_speed is in kbps */
-       ret = wldev_get_link_speed(dev, &link_speed);
-       if (ret || link_speed < 0) {
-               ANDROID_ERROR(("%s: wldev_get_link_speed() failed, ret=%d, speed=%d\n",
-                       __FUNCTION__, ret, link_speed));
-               goto error;
+       error = wldev_iovar_setint(dev, "scan_ps", mode);
+       if (error) {
+               ANDROID_ERROR(("%s[1]: Failed to set Mode %d, error = %d\n",
+               __FUNCTION__, mode, error));
+               return -1;
        }
 
-       output = (struct connection_stats *)command;
-       output->txframe   = dtoh32(cnt->txframe);
-       output->txbyte    = dtoh32(cnt->txbyte);
-       output->txerror   = dtoh32(cnt->txerror);
-       output->rxframe   = dtoh32(cnt->rxframe);
-       output->rxbyte    = dtoh32(cnt->rxbyte);
-       output->txfail    = dtoh32(cnt->txfail);
-       output->txretry   = dtoh32(cnt->txretry);
-       output->txretrie  = dtoh32(cnt->txretrie);
-       output->txrts     = dtoh32(cnt->txrts);
-       output->txnocts   = dtoh32(cnt->txnocts);
-       output->txexptime = dtoh32(cnt->txexptime);
-       output->txrate    = link_speed;
+       return error;
+}
+#ifdef TEST_TX_POWER_CONTROL
+static int
+wl_android_set_tx_power(struct net_device *dev, const char* string_num)
+{
+       int err = 0;
+       s32 dbm;
+       enum nl80211_tx_power_setting type;
 
-       /* Channel idle ratio. */
-       if (wl_chanim_stats(dev, &(output->chan_idle)) < 0) {
-               output->chan_idle = 0;
-       };
+       dbm = bcm_atoi(string_num);
 
-       kfree(cnt);
+       if (dbm < -1) {
+               ANDROID_ERROR(("%s: dbm is negative...\n", __FUNCTION__));
+               return -EINVAL;
+       }
 
-       bytes_written = sizeof(struct connection_stats);
-       return bytes_written;
+       if (dbm == -1)
+               type = NL80211_TX_POWER_AUTOMATIC;
+       else
+               type = NL80211_TX_POWER_FIXED;
 
-error:
-       if (cnt) {
-               kfree(cnt);
+       err = wl_set_tx_power(dev, type, dbm);
+       if (unlikely(err)) {
+               ANDROID_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
+               return err;
        }
-       return -1;
+
+       return 1;
 }
-#endif /* CONNECTION_STATISTICS */
 
 static int
-wl_android_set_pmk(struct net_device *dev, char *command, int total_len)
+wl_android_get_tx_power(struct net_device *dev, char *command, int total_len)
 {
-       uchar pmk[33];
-       int error = 0;
-       char smbuf[WLC_IOCTL_SMLEN];
-#ifdef OKC_DEBUG
-       int i = 0;
-#endif
+       int err;
+       int bytes_written;
+       s32 dbm = 0;
 
-       bzero(pmk, sizeof(pmk));
-       memcpy((char *)pmk, command + strlen("SET_PMK "), 32);
-       error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL);
-       if (error) {
-               ANDROID_ERROR(("Failed to set PMK for OKC, error = %d\n", error));
+       err = wl_get_tx_power(dev, &dbm);
+       if (unlikely(err)) {
+               ANDROID_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
+               return err;
        }
-#ifdef OKC_DEBUG
-       ANDROID_ERROR(("PMK is "));
-       for (i = 0; i < 32; i++)
-               ANDROID_ERROR(("%02X ", pmk[i]));
 
-       ANDROID_ERROR(("\n"));
-#endif
-       return error;
+       bytes_written = snprintf(command, total_len, "%s %d",
+               CMD_TEST_GET_TX_POWER, dbm);
+
+       ANDROID_ERROR(("%s: GET_TX_POWER: dBm=%d\n", __FUNCTION__, dbm));
+
+       return bytes_written;
 }
+#endif /* TEST_TX_POWER_CONTROL */
 
 static int
-wl_android_okc_enable(struct net_device *dev, char *command, int total_len)
+wl_android_set_sarlimit_txctrl(struct net_device *dev, const char* string_num)
 {
-       int error = 0;
-       char okc_enable = 0;
+       int err = 0;
+       int setval = 0;
+       s32 mode = bcm_atoi(string_num);
 
-       okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0';
-       error = wldev_iovar_setint(dev, "okc_enable", okc_enable);
-       if (error) {
-               ANDROID_ERROR(("Failed to %s OKC, error = %d\n",
-                       okc_enable ? "enable" : "disable", error));
+       /* As Samsung specific and their requirement, '0' means activate sarlimit
+        * and '-1' means back to normal state (deactivate sarlimit)
+        */
+       if (mode == 0) {
+               ANDROID_INFO(("%s: SAR limit control activated\n", __FUNCTION__));
+               setval = 1;
+       } else if (mode == -1) {
+               ANDROID_INFO(("%s: SAR limit control deactivated\n", __FUNCTION__));
+               setval = 0;
+       } else {
+               return -EINVAL;
        }
 
-       wldev_iovar_setint(dev, "ccx_enable", 0);
-
-       return error;
+       err = wldev_iovar_setint(dev, "sar_enable", setval);
+       if (unlikely(err)) {
+               ANDROID_ERROR(("%s: error (%d)\n", __FUNCTION__, err));
+               return err;
+       }
+       return 1;
 }
-
-
+#endif /* CUSTOMER_HW4_PRIVATE_CMD */
 
 int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len)
 {
@@ -1534,7 +2389,45 @@ wl_android_iolist_resume(struct net_device *dev, struct list_head *head)
                kfree(config);
        }
 }
+#ifdef WL11ULB
+static int
+wl_android_set_ulb_mode(struct net_device *dev, char *command, int total_len)
+{
+       int mode = 0;
+
+       ANDROID_INFO(("set ulb mode (%s) \n", command));
+       if (sscanf(command, "%*s %d", &mode) != 1) {
+               ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
+               return -1;
+       }
+       return wl_cfg80211_set_ulb_mode(dev, mode);
+}
+static int
+wl_android_set_ulb_bw(struct net_device *dev, char *command, int total_len)
+{
+       int bw = 0;
+       u8 *pos;
+       char *ifname = NULL;
+       ANDROID_INFO(("set ulb bw (%s) \n", command));
+
+       /*
+        * For sta/ap: IFNAME=<ifname> DRIVER ULB_BW <bw> ifname
+        * For p2p:    IFNAME=wlan0 DRIVER ULB_BW <bw> p2p-dev-wlan0
+        */
+       if (total_len < strlen(CMD_ULB_BW) + 2)
+               return -EINVAL;
+
+       pos = command + strlen(CMD_ULB_BW) + 1;
+       bw = bcm_atoi(pos);
+
+       if ((strlen(pos) >= 5)) {
+               ifname = pos + 2;
+       }
 
+       ANDROID_INFO(("[ULB] ifname:%s ulb_bw:%d \n", ifname, bw));
+       return wl_cfg80211_set_ulb_bw(dev, bw, ifname);
+}
+#endif /* WL11ULB */
 static int
 wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
 {
@@ -1549,8 +2442,9 @@ wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
 
        ANDROID_INFO(("%s: enter miracast mode %d\n", __FUNCTION__, mode));
 
-       if (miracast_cur_mode == mode)
+       if (miracast_cur_mode == mode) {
                return 0;
+       }
 
        wl_android_iolist_resume(dev, &miracast_resume_list);
        miracast_cur_mode = MIRACAST_MODE_OFF;
@@ -1566,27 +2460,29 @@ wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
                        ANDROID_ERROR(("%s: Connected station's beacon interval: "
                                "%d and set mchan_algo to %d \n",
                                __FUNCTION__, val, config.param));
-               }
-               else {
+               } else {
                        config.param = MIRACAST_MCHAN_ALGO;
                }
                ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-               if (ret)
+               if (ret) {
                        goto resume;
+               }
 
                /* setting mchan_bw to platform specific value */
                config.iovar = "mchan_bw";
                config.param = MIRACAST_MCHAN_BW;
                ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-               if (ret)
+               if (ret) {
                        goto resume;
+               }
 
                /* setting apmdu to platform specific value */
                config.iovar = "ampdu_mpdu";
                config.param = MIRACAST_AMPDU_SIZE;
                ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-               if (ret)
+               if (ret) {
                        goto resume;
+               }
                /* FALLTROUGH */
                /* Source mode shares most configurations with sink mode.
                 * Fall through here to avoid code duplication
@@ -1596,18 +2492,27 @@ wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
                config.iovar = "roam_off";
                config.param = 1;
                ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-               if (ret)
+               if (ret) {
                        goto resume;
+               }
+
                /* tunr off pm */
-               val = 0;
-               config.iovar = NULL;
-               config.ioctl = WLC_GET_PM;
-               config.arg = &val;
-               config.len = sizeof(int);
-               ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
-               if (ret)
+               ret = wldev_ioctl(dev, WLC_GET_PM, &val, sizeof(val), false);
+               if (ret) {
                        goto resume;
+               }
 
+               if (val != PM_OFF) {
+                       val = PM_OFF;
+                       config.iovar = NULL;
+                       config.ioctl = WLC_GET_PM;
+                       config.arg = &val;
+                       config.len = sizeof(int);
+                       ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
+                       if (ret) {
+                               goto resume;
+                       }
+               }
                break;
        case MIRACAST_MODE_OFF:
        default:
@@ -1710,300 +2615,6 @@ nlmsg_failure:
        return ret;
 }
 
-#ifdef WLAIBSS
-static int wl_android_set_ibss_txfail_event(struct net_device *dev, char *command, int total_len)
-{
-       int err = 0;
-       int retry = 0;
-       int pid = 0;
-       aibss_txfail_config_t txfail_config = {0, 0, 0, 0};
-       char smbuf[WLC_IOCTL_SMLEN];
-
-       if (sscanf(command, CMD_SETIBSSTXFAILEVENT " %d %d", &retry, &pid) <= 0) {
-               ANDROID_ERROR(("Failed to get Parameter from : %s\n", command));
-               return -1;
-       }
-
-       /* set pid, and if the event was happened, let's send a notification through netlink */
-       wl_cfg80211_set_txfail_pid(pid);
-
-       /* If retry value is 0, it disables the functionality for TX Fail. */
-       if (retry > 0) {
-               txfail_config.max_tx_retry = retry;
-               txfail_config.bcn_timeout = 0;  /* 0 : disable tx fail from beacon */
-       }
-       txfail_config.version = AIBSS_TXFAIL_CONFIG_VER_0;
-       txfail_config.len = sizeof(txfail_config);
-
-       err = wldev_iovar_setbuf(dev, "aibss_txfail_config", (void *) &txfail_config,
-               sizeof(aibss_txfail_config_t), smbuf, WLC_IOCTL_SMLEN, NULL);
-       ANDROID_TRACE(("retry=%d, pid=%d, err=%d\n", retry, pid, err));
-
-       return ((err == 0)?total_len:err);
-}
-
-static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command,
-       int total_len, bool bAll)
-{
-       int error;
-       int bytes_written = 0;
-       void *buf = NULL;
-       bss_peer_list_info_t peer_list_info;
-       bss_peer_info_t *peer_info;
-       int i;
-       bool found = false;
-       struct ether_addr mac_ea;
-
-       ANDROID_TRACE(("get ibss peer info(%s)\n", bAll?"true":"false"));
-
-       if (!bAll) {
-               if (sscanf (command, "GETIBSSPEERINFO %02x:%02x:%02x:%02x:%02x:%02x",
-                       (unsigned int *)&mac_ea.octet[0], (unsigned int *)&mac_ea.octet[1],
-                       (unsigned int *)&mac_ea.octet[2], (unsigned int *)&mac_ea.octet[3],
-                       (unsigned int *)&mac_ea.octet[4], (unsigned int *)&mac_ea.octet[5]) != 6) {
-                       ANDROID_TRACE(("invalid MAC address\n"));
-                       return -1;
-               }
-       }
-
-       if ((buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL)) == NULL) {
-               ANDROID_ERROR(("kmalloc failed\n"));
-               return -1;
-       }
-
-       error = wldev_iovar_getbuf(dev, "bss_peer_info", NULL, 0, buf, WLC_IOCTL_MAXLEN, NULL);
-       if (unlikely(error)) {
-               ANDROID_ERROR(("could not get ibss peer info (%d)\n", error));
-               kfree(buf);
-               return -1;
-       }
-
-       memcpy(&peer_list_info, buf, sizeof(peer_list_info));
-       peer_list_info.version = htod16(peer_list_info.version);
-       peer_list_info.bss_peer_info_len = htod16(peer_list_info.bss_peer_info_len);
-       peer_list_info.count = htod32(peer_list_info.count);
-
-       ANDROID_TRACE(("ver:%d, len:%d, count:%d\n", peer_list_info.version,
-               peer_list_info.bss_peer_info_len, peer_list_info.count));
-
-       if (peer_list_info.count > 0) {
-               if (bAll)
-                       bytes_written += sprintf(&command[bytes_written], "%u ",
-                               peer_list_info.count);
-
-               peer_info = (bss_peer_info_t *) ((void *)buf + BSS_PEER_LIST_INFO_FIXED_LEN);
-
-
-               for (i = 0; i < peer_list_info.count; i++) {
-
-                       ANDROID_TRACE(("index:%d rssi:%d, tx:%u, rx:%u\n", i, peer_info->rssi,
-                               peer_info->tx_rate, peer_info->rx_rate));
-
-                       if (!bAll &&
-                               memcmp(&mac_ea, &peer_info->ea, sizeof(struct ether_addr)) == 0) {
-                               found = true;
-                       }
-
-                       if (bAll || found) {
-                               bytes_written += sprintf(&command[bytes_written], MACF,
-                                       ETHER_TO_MACF(peer_info->ea));
-                               bytes_written += sprintf(&command[bytes_written], " %u %d ",
-                                       peer_info->tx_rate/1000, peer_info->rssi);
-                       }
-
-                       if (found)
-                               break;
-
-                       peer_info = (bss_peer_info_t *)((void *)peer_info+sizeof(bss_peer_info_t));
-               }
-       }
-       else {
-               ANDROID_ERROR(("could not get ibss peer info : no item\n"));
-       }
-       bytes_written += sprintf(&command[bytes_written], "%s", "\0");
-
-       ANDROID_TRACE(("command(%u):%s\n", total_len, command));
-       ANDROID_TRACE(("bytes_written:%d\n", bytes_written));
-
-       kfree(buf);
-       return bytes_written;
-}
-
-int wl_android_set_ibss_routetable(struct net_device *dev, char *command, int total_len)
-{
-
-       char *pcmd = command;
-       char *str = NULL;
-
-       ibss_route_tbl_t *route_tbl = NULL;
-       char *ioctl_buf = NULL;
-       u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
-       s32 err = BCME_OK;
-       uint32 route_tbl_len;
-       uint32 entries;
-       char *endptr;
-       uint32 i = 0;
-       struct ipv4_addr  dipaddr;
-       struct ether_addr ea;
-
-       route_tbl_len = sizeof(ibss_route_tbl_t) +
-               (MAX_IBSS_ROUTE_TBL_ENTRY - 1) * sizeof(ibss_route_entry_t);
-       route_tbl = (ibss_route_tbl_t *)kzalloc(route_tbl_len, kflags);
-       if (!route_tbl) {
-               ANDROID_ERROR(("Route TBL alloc failed\n"));
-               return -ENOMEM;
-       }
-       ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
-       if (!ioctl_buf) {
-               ANDROID_ERROR(("ioctl memory alloc failed\n"));
-               if (route_tbl) {
-                       kfree(route_tbl);
-               }
-               return -ENOMEM;
-       }
-       memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN);
-
-       /* drop command */
-       str = bcmstrtok(&pcmd, " ", NULL);
-
-       /* get count */
-       str = bcmstrtok(&pcmd, " ",  NULL);
-       if (!str) {
-               ANDROID_ERROR(("Invalid number parameter %s\n", str));
-               err = -EINVAL;
-               goto exit;
-       }
-       entries = bcm_strtoul(str, &endptr, 0);
-       if (*endptr != '\0') {
-               ANDROID_ERROR(("Invalid number parameter %s\n", str));
-               err = -EINVAL;
-               goto exit;
-       }
-       ANDROID_INFO(("Routing table count:%d\n", entries));
-       route_tbl->num_entry = entries;
-
-       for (i = 0; i < entries; i++) {
-               str = bcmstrtok(&pcmd, " ", NULL);
-               if (!str || !bcm_atoipv4(str, &dipaddr)) {
-                       ANDROID_ERROR(("Invalid ip string %s\n", str));
-                       err = -EINVAL;
-                       goto exit;
-               }
-
-
-               str = bcmstrtok(&pcmd, " ", NULL);
-               if (!str || !bcm_ether_atoe(str, &ea)) {
-                       ANDROID_ERROR(("Invalid ethernet string %s\n", str));
-                       err = -EINVAL;
-                       goto exit;
-               }
-               bcopy(&dipaddr, &route_tbl->route_entry[i].ipv4_addr, IPV4_ADDR_LEN);
-               bcopy(&ea, &route_tbl->route_entry[i].nexthop, ETHER_ADDR_LEN);
-       }
-
-       route_tbl_len = sizeof(ibss_route_tbl_t) +
-               ((!entries?0:(entries - 1)) * sizeof(ibss_route_entry_t));
-       err = wldev_iovar_setbuf(dev, "ibss_route_tbl",
-               route_tbl, route_tbl_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
-       if (err != BCME_OK) {
-               ANDROID_ERROR(("Fail to set iovar %d\n", err));
-               err = -EINVAL;
-       }
-
-exit:
-       if (route_tbl)
-               kfree(route_tbl);
-       if (ioctl_buf)
-               kfree(ioctl_buf);
-       return err;
-
-}
-
-int
-wl_android_set_ibss_ampdu(struct net_device *dev, char *command, int total_len)
-{
-       char *pcmd = command;
-       char *str = NULL, *endptr = NULL;
-       struct ampdu_aggr aggr;
-       char smbuf[WLC_IOCTL_SMLEN];
-       int idx;
-       int err = 0;
-       int wme_AC2PRIO[AC_COUNT][2] = {
-               {PRIO_8021D_VO, PRIO_8021D_NC},         /* AC_VO - 3 */
-               {PRIO_8021D_CL, PRIO_8021D_VI},         /* AC_VI - 2 */
-               {PRIO_8021D_BK, PRIO_8021D_NONE},       /* AC_BK - 1 */
-               {PRIO_8021D_BE, PRIO_8021D_EE}};        /* AC_BE - 0 */
-
-       ANDROID_TRACE(("set ibss ampdu:%s\n", command));
-
-       memset(&aggr, 0, sizeof(aggr));
-       /* Cofigure all priorities */
-       aggr.conf_TID_bmap = NBITMASK(NUMPRIO);
-
-       /* acquire parameters */
-       /* drop command */
-       str = bcmstrtok(&pcmd, " ", NULL);
-
-       for (idx = 0; idx < AC_COUNT; idx++) {
-               bool on;
-               str = bcmstrtok(&pcmd, " ", NULL);
-               if (!str) {
-                       ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
-                       return -EINVAL;
-               }
-               on = bcm_strtoul(str, &endptr, 0) ? TRUE : FALSE;
-               if (*endptr != '\0') {
-                       ANDROID_ERROR(("Invalid number format %s\n", str));
-                       return -EINVAL;
-               }
-               if (on) {
-                       setbit(&aggr.enab_TID_bmap, wme_AC2PRIO[idx][0]);
-                       setbit(&aggr.enab_TID_bmap, wme_AC2PRIO[idx][1]);
-               }
-       }
-
-       err = wldev_iovar_setbuf(dev, "ampdu_txaggr", (void *)&aggr,
-       sizeof(aggr), smbuf, WLC_IOCTL_SMLEN, NULL);
-
-       return ((err == 0) ? total_len : err);
-}
-
-int wl_android_set_ibss_antenna(struct net_device *dev, char *command, int total_len)
-{
-       char *pcmd = command;
-       char *str = NULL;
-       int txchain, rxchain;
-       int err = 0;
-
-       ANDROID_TRACE(("set ibss antenna:%s\n", command));
-
-       /* acquire parameters */
-       /* drop command */
-       str = bcmstrtok(&pcmd, " ", NULL);
-
-       /* TX chain */
-       str = bcmstrtok(&pcmd, " ", NULL);
-       if (!str) {
-               ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
-               return -EINVAL;
-       }
-       txchain = bcm_atoi(str);
-
-       /* RX chain */
-       str = bcmstrtok(&pcmd, " ", NULL);
-       if (!str) {
-               ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
-               return -EINVAL;
-       }
-       rxchain = bcm_atoi(str);
-
-       err = wldev_iovar_setint(dev, "txchain", txchain);
-       if (err != 0)
-               return err;
-       err = wldev_iovar_setint(dev, "rxchain", rxchain);
-       return ((err == 0)?total_len:err);
-}
-#endif /* WLAIBSS */
 
 int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len)
 {
@@ -2062,7 +2673,6 @@ int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len)
        return res;
 }
 
-
 static const char *
 get_string_by_separator(char *result, int result_len, const char *src, char separator)
 {
@@ -2071,11 +2681,13 @@ get_string_by_separator(char *result, int result_len, const char *src, char sepa
                *result++ = *src++;
        }
        *result = 0;
-       if (*src == separator)
+       if (*src == separator) {
                ++src;
+       }
        return src;
 }
 
+#ifdef WL_CFG80211
 int
 wl_android_set_roam_offload_bssid_list(struct net_device *dev, const char *cmd)
 {
@@ -2084,11 +2696,20 @@ wl_android_set_roam_offload_bssid_list(struct net_device *dev, const char *cmd)
        roamoffl_bssid_list_t *bssid_list;
        const char *str = cmd;
        char *ioctl_buf;
+       dhd_pub_t *dhdp = wl_cfg80211_get_dhdp();
 
        str = get_string_by_separator(sbuf, 32, str, ',');
        cnt = bcm_atoi(sbuf);
        cnt = MIN(cnt, MAX_ROAMOFFL_BSSID_NUM);
-       size = sizeof(int) + sizeof(struct ether_addr) * cnt;
+
+       if ((cnt > 0) &&
+               (((dhdp->op_mode & DHD_FLAG_STA_MODE) && (dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
+               FALSE)) {
+               ANDROID_ERROR(("Can't set ROAMOFFL_BSSID when enabled STA-SoftAP or WES\n"));
+               return -EINVAL;
+       }
+
+       size = sizeof(int32) + sizeof(struct ether_addr) * cnt;
        ANDROID_ERROR(("ROAM OFFLOAD BSSID LIST %d BSSIDs, size %d\n", cnt, size));
        bssid_list = kmalloc(size, GFP_KERNEL);
        if (bssid_list == NULL) {
@@ -2107,22 +2728,18 @@ wl_android_set_roam_offload_bssid_list(struct net_device *dev, const char *cmd)
 
        for (i = 0; i < cnt; i++) {
                str = get_string_by_separator(sbuf, 32, str, ',');
-               if (bcm_ether_atoe(sbuf, &bssid_list->bssid[i]) == 0) {
-                       ANDROID_ERROR(("%s: Invalid station MAC Address!!!\n", __FUNCTION__));
-                       kfree(bssid_list);
-                       kfree(ioctl_buf);
-                       return -1;
-               }
+               bcm_ether_atoe(sbuf, &bssid_list->bssid[i]);
        }
 
-       bssid_list->cnt = cnt;
+       bssid_list->cnt = (int32)cnt;
        err = wldev_iovar_setbuf(dev, "roamoffl_bssid_list",
-               bssid_list, size, ioctl_buf, ioctl_buf_len, NULL);
+                       bssid_list, size, ioctl_buf, ioctl_buf_len, NULL);
        kfree(bssid_list);
        kfree(ioctl_buf);
 
        return err;
 }
+#endif
 
 #ifdef P2PRESP_WFDIE_SRC
 static int wl_android_get_wfdie_resp(struct net_device *dev, char *command, int total_len)
@@ -2159,130 +2776,93 @@ static int wl_android_set_wfdie_resp(struct net_device *dev, int only_resp_wfdsr
 }
 #endif /* P2PRESP_WFDIE_SRC */
 
-static int wl_android_get_link_status(struct net_device *dev, char *command,
-       int total_len)
-{
-       int bytes_written, error, result = 0, single_stream, stf = -1, i, nss = 0, mcs_map;
-       uint32 rspec;
-       uint encode, rate, txexp;
-       struct wl_bss_info *bi;
-       int datalen = sizeof(uint32) + sizeof(wl_bss_info_t);
-       char buf[datalen];
-
-       /* get BSS information */
-       *(u32 *) buf = htod32(datalen);
-       error = wldev_ioctl(dev, WLC_GET_BSS_INFO, (void *)buf, datalen, false);
-       if (unlikely(error)) {
-               ANDROID_ERROR(("Could not get bss info %d\n", error));
-               return -1;
-       }
-
-       bi = (struct wl_bss_info *) (buf + sizeof(uint32));
-
-       for (i = 0; i < ETHER_ADDR_LEN; i++) {
-               if (bi->BSSID.octet[i] > 0) {
-                       break;
-               }
-       }
-
-       if (i == ETHER_ADDR_LEN) {
-               ANDROID_TRACE(("No BSSID\n"));
-               return -1;
-       }
-
-       /* check VHT capability at beacon */
-       if (bi->vht_cap) {
-               if (CHSPEC_IS5G(bi->chanspec)) {
-                       result |= WL_ANDROID_LINK_AP_VHT_SUPPORT;
-               }
-       }
-
-       /* get a rspec (radio spectrum) rate */
-       error = wldev_iovar_getint(dev, "nrate", &rspec);
-       if (unlikely(error) || rspec == 0) {
-               ANDROID_ERROR(("get link status error (%d)\n", error));
-               return -1;
-       }
-
-       encode = (rspec & WL_RSPEC_ENCODING_MASK);
-       rate = (rspec & WL_RSPEC_RATE_MASK);
-       txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
-
-       switch (encode) {
-       case WL_RSPEC_ENCODE_HT:
-               /* check Rx MCS Map for HT */
-               for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
-                       int8 bitmap = 0xFF;
-                       if (i == MAX_STREAMS_SUPPORTED-1) {
-                               bitmap = 0x7F;
-                       }
-                       if (bi->basic_mcs[i] & bitmap) {
-                               nss++;
-                       }
-               }
-               break;
-       case WL_RSPEC_ENCODE_VHT:
-               /* check Rx MCS Map for VHT */
-               for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
-                       mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
-                       if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
-                               nss++;
-                       }
-               }
-               break;
-       }
+#ifdef BT_WIFI_HANDOVER
+static int
+wl_tbow_teardown(struct net_device *dev, char *command, int total_len)
+{
+       int err = BCME_OK;
+       char buf[WLC_IOCTL_SMLEN];
+       tbow_setup_netinfo_t netinfo;
+       memset(&netinfo, 0, sizeof(netinfo));
+       netinfo.opmode = TBOW_HO_MODE_TEARDOWN;
 
-       /* check MIMO capability with nss in beacon */
-       if (nss > 1) {
-               result |= WL_ANDROID_LINK_AP_MIMO_SUPPORT;
+       err = wldev_iovar_setbuf_bsscfg(dev, "tbow_doho", &netinfo,
+                       sizeof(tbow_setup_netinfo_t), buf, WLC_IOCTL_SMLEN, 0, NULL);
+       if (err < 0) {
+               ANDROID_ERROR(("tbow_doho iovar error %d\n", err));
+                       return err;
        }
+       return err;
+}
+#endif /* BT_WIFI_HANOVER */
+
+#ifdef SET_RPS_CPUS
+static int
+wl_android_set_rps_cpus(struct net_device *dev, char *command, int total_len)
+{
+       int error, enable;
 
-       single_stream = (encode == WL_RSPEC_ENCODE_RATE) ||
-               ((encode == WL_RSPEC_ENCODE_HT) && rate < 8) ||
-               ((encode == WL_RSPEC_ENCODE_VHT) &&
-               ((rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT) == 1);
+       enable = command[strlen(CMD_RPSMODE) + 1] - '0';
+       error = dhd_rps_cpus_enable(dev, enable);
 
-       if (txexp == 0) {
-               if ((rspec & WL_RSPEC_STBC) && single_stream) {
-                       stf = OLD_NRATE_STF_STBC;
+#if defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211)
+       if (!error) {
+               void *dhdp = wl_cfg80211_get_dhdp();
+               if (enable) {
+                       ANDROID_TRACE(("%s : set ack suppress. TCPACK_SUP_HOLD.\n", __FUNCTION__));
+                       dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_HOLD);
                } else {
-                       stf = (single_stream) ? OLD_NRATE_STF_SISO : OLD_NRATE_STF_SDM;
+                       ANDROID_TRACE(("%s : clear ack suppress.\n", __FUNCTION__));
+                       dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF);
                }
-       } else if (txexp == 1 && single_stream) {
-               stf = OLD_NRATE_STF_CDD;
        }
+#endif /* DHDTCPACK_SUPPRESS && BCMPCIE && WL_CFG80211 */
 
-       /* check 11ac (VHT) */
-       if (encode == WL_RSPEC_ENCODE_VHT) {
-               if (CHSPEC_IS5G(bi->chanspec)) {
-                       result |= WL_ANDROID_LINK_VHT;
-               }
-       }
+       return error;
+}
+#endif /* SET_RPS_CPUS */
+#ifdef P2P_LISTEN_OFFLOADING
+s32
+wl_cfg80211_p2plo_offload(struct net_device *dev, char *cmd, char* buf, int len)
+{
+       int ret = 0;
 
-       /* check MIMO */
-       if (result & WL_ANDROID_LINK_AP_MIMO_SUPPORT) {
-               switch (stf) {
-               case OLD_NRATE_STF_SISO:
-                       break;
-               case OLD_NRATE_STF_CDD:
-               case OLD_NRATE_STF_STBC:
-                       result |= WL_ANDROID_LINK_MIMO;
-                       break;
-               case OLD_NRATE_STF_SDM:
-                       if (!single_stream) {
-                               result |= WL_ANDROID_LINK_MIMO;
-                       }
-                       break;
-               }
-       }
+       ANDROID_ERROR(("Entry cmd:%s arg_len:%d \n", cmd, len));
 
-       ANDROID_TRACE(("%s:result=%d, stf=%d, single_stream=%d, mcs map=%d\n",
-               __FUNCTION__, result, stf, single_stream, nss));
+       if (strncmp(cmd, "P2P_LO_START", strlen("P2P_LO_START")) == 0) {
+               ret = wl_cfg80211_p2plo_listen_start(dev, buf, len);
+       } else if (strncmp(cmd, "P2P_LO_STOP", strlen("P2P_LO_STOP")) == 0) {
+               ret = wl_cfg80211_p2plo_listen_stop(dev);
+       } else {
+               ANDROID_ERROR(("Request for Unsupported CMD:%s \n", buf));
+               ret = -EINVAL;
+       }
+       return ret;
+}
+#endif /* P2P_LISTEN_OFFLOADING */
 
-       bytes_written = sprintf(command, "%s %d", CMD_GET_LINK_STATUS, result);
+#ifdef WL_CFG80211
+int
+wl_android_murx_bfe_cap(struct net_device *dev, int val)
+{
+       int err = BCME_OK;
+       int iface_count = wl_cfg80211_iface_count();
 
-       return bytes_written;
+       if (iface_count > 1) {
+               ANDROID_ERROR(("%s: murx_bfe_cap change is not allowed when "
+                               "there are multiple interfaces\n", __FUNCTION__));
+               return -EINVAL;
+       }
+       /* Now there is only single interface */
+       err = wldev_iovar_setint(dev, "murx_bfe_cap", val);
+       if (err) {
+               ANDROID_ERROR(("%s: Failed to set murx_bfe_cap IOVAR to %d,"
+                               "error %d\n", __FUNCTION__, val, err));
+               err = -EINVAL;
+       }
+       return err;
 }
+#endif
 
 int
 wl_android_get_channel(
@@ -2521,14 +3101,16 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
        }
 
        if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
-               bytes_written = wl_android_wifi_off(net);
+               bytes_written = wl_android_wifi_off(net, FALSE);
        }
+#ifdef WL_CFG80211
        else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) {
-               /* TBD: SCAN-ACTIVE */
+               wl_cfg80211_set_passive_scan(net, command);
        }
        else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) {
-               /* TBD: SCAN-PASSIVE */
+               wl_cfg80211_set_passive_scan(net, command);
        }
+#endif
        else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
                bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len);
        }
@@ -2550,15 +3132,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
                bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
        }
-#if defined(CUSTOM_PLATFORM_NV_TEGRA)
-       else if (strnicmp(command, CMD_PKT_FILTER_MODE, strlen(CMD_PKT_FILTER_MODE)) == 0) {
-               dhd_set_packet_filter_mode(net, &command[strlen(CMD_PKT_FILTER_MODE) + 1]);
-       } else if (strnicmp(command, CMD_PKT_FILTER_PORTS, strlen(CMD_PKT_FILTER_PORTS)) == 0) {
-               bytes_written = dhd_set_packet_filter_ports(net,
-                       &command[strlen(CMD_PKT_FILTER_PORTS) + 1]);
-               ret = bytes_written;
-       }
-#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
 #endif /* PKT_FILTER_SUPPORT */
        else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) {
                /* TBD: BTCOEXSCAN-START */
@@ -2589,23 +3162,11 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
        }
        else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
                uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
-#ifdef WL_HOST_BAND_MGMT
-               s32 ret = 0;
-               if ((ret = wl_cfg80211_set_band(net, band)) < 0) {
-                       if (ret == BCME_UNSUPPORTED) {
-                               /* If roam_var is unsupported, fallback to the original method */
-                               ANDROID_ERROR(("WL_HOST_BAND_MGMT defined, "
-                                       "but roam_band iovar unsupported in the firmware\n"));
-                       } else {
-                               bytes_written = -1;
-                               goto exit;
-                       }
+               if (dhd_conf_get_band(dhd_get_pub(net)) != WLC_BAND_AUTO) {
+                       printf("%s: Band is fixed in config.txt\n", __FUNCTION__);
+                       goto exit;
                }
-               if ((band == WLC_BAND_AUTO) || (ret == BCME_UNSUPPORTED))
-                       bytes_written = wldev_set_band(net, band);
-#else
                bytes_written = wldev_set_band(net, band);
-#endif /* WL_HOST_BAND_MGMT */
        }
        else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
                bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
@@ -2613,16 +3174,49 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 #ifdef WL_CFG80211
        /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
        else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
+               /*
+                * Usage examples:
+                * DRIVER COUNTRY US
+                * DRIVER COUNTRY US/7
+                */
                char *country_code = command + strlen(CMD_COUNTRY) + 1;
-#ifdef CUSTOMER_HW5
-               /* Customer_hw5 want to keep connections */
-               bytes_written = wldev_set_country(net, country_code, true, false);
-#else
-               bytes_written = wldev_set_country(net, country_code, true, true);
-#endif
+               char *rev_info_delim = country_code + 2; /* 2 bytes of country code */
+               int revinfo = -1;
+               if ((rev_info_delim) &&
+                       (strnicmp(rev_info_delim, CMD_COUNTRY_DELIMITER,
+                       strlen(CMD_COUNTRY_DELIMITER)) == 0) &&
+                       (rev_info_delim + 1)) {
+                       revinfo  = bcm_atoi(rev_info_delim + 1);
+               }
+               bytes_written = wldev_set_country(net, country_code, true, true, revinfo);
+#ifdef FCC_PWR_LIMIT_2G
+               if (wldev_iovar_setint(net, "fccpwrlimit2g", FALSE)) {
+                       ANDROID_ERROR(("%s: fccpwrlimit2g deactivation is failed\n", __FUNCTION__));
+               } else {
+                       ANDROID_ERROR(("%s: fccpwrlimit2g is deactivated\n", __FUNCTION__));
+               }
+#endif /* FCC_PWR_LIMIT_2G */
        }
 #endif /* WL_CFG80211 */
-
+       else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
+               bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
+       } else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
+               bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
+       } else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
+               bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
+       } else if (strnicmp(command, CMD_DATARATE, strlen(CMD_DATARATE)) == 0) {
+               bytes_written = wl_android_get_datarate(net, command, priv_cmd.total_len);
+       } else if (strnicmp(command, CMD_ASSOC_CLIENTS, strlen(CMD_ASSOC_CLIENTS)) == 0) {
+               bytes_written = wl_android_get_assoclist(net, command, priv_cmd.total_len);
+       }
+
+#ifdef CUSTOMER_HW4_PRIVATE_CMD
+#ifdef WLTDLS
+       else if (strnicmp(command, CMD_TDLS_RESET, strlen(CMD_TDLS_RESET)) == 0) {
+               bytes_written = wl_android_tdls_reset(net);
+       }
+#endif /* WLTDLS */
+#endif /* CUSTOMER_HW4_PRIVATE_CMD */
 
 #ifdef PNO_SUPPORT
        else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
@@ -2649,22 +3243,13 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
                        priv_cmd.total_len - skip);
        }
-#ifdef WL_SDO
-       else if (strnicmp(command, CMD_P2P_SD_OFFLOAD, strlen(CMD_P2P_SD_OFFLOAD)) == 0) {
-               u8 *buf = command;
-               u8 *cmd_id = NULL;
-               int len;
-
-               cmd_id = strsep((char **)&buf, " ");
-               /* if buf == NULL, means no arg */
-               if (buf == NULL)
-                       len = 0;
-               else
-                       len = strlen(buf);
-
-               bytes_written = wl_cfg80211_sd_offload(net, cmd_id, buf, len);
+#ifdef P2P_LISTEN_OFFLOADING
+       else if (strnicmp(command, CMD_P2P_LISTEN_OFFLOAD, strlen(CMD_P2P_LISTEN_OFFLOAD)) == 0) {
+               u8 *sub_command = strchr(command, ' ');
+               bytes_written = wl_cfg80211_p2plo_offload(net, command, sub_command,
+                               sub_command ? strlen(sub_command) : 0);
        }
-#endif /* WL_SDO */
+#endif /* P2P_LISTEN_OFFLOADING */
 #ifdef WL_NAN
        else if (strnicmp(command, CMD_NAN, strlen(CMD_NAN)) == 0) {
                bytes_written = wl_cfg80211_nan_cmd_handler(net, command,
@@ -2681,6 +3266,11 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
                        priv_cmd.total_len - skip);
        }
+       else if (strnicmp(command, CMD_P2P_ECSA, strlen(CMD_P2P_ECSA)) == 0) {
+               int skip = strlen(CMD_P2P_ECSA) + 1;
+               bytes_written = wl_cfg80211_set_p2p_ecsa(net, command + skip,
+                       priv_cmd.total_len - skip);
+       }
 #ifdef WL_CFG80211
        else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE,
                strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) {
@@ -2688,28 +3278,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
                        priv_cmd.total_len - skip, *(command + skip - 2) - '0');
        }
-#ifdef WLFBT
-       else if (strnicmp(command, CMD_GET_FTKEY, strlen(CMD_GET_FTKEY)) == 0) {
-               wl_cfg80211_get_fbt_key(command);
-               bytes_written = FBT_KEYLEN;
-       }
-#endif /* WLFBT */
 #endif /* WL_CFG80211 */
-       else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0)
-               bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len);
-       else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0)
-               bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len);
-#ifdef BCMCCX
-       else if (strnicmp(command, CMD_GETCCKM_RN, strlen(CMD_GETCCKM_RN)) == 0) {
-               bytes_written = wl_android_get_cckm_rn(net, command);
-       }
-       else if (strnicmp(command, CMD_SETCCKM_KRK, strlen(CMD_SETCCKM_KRK)) == 0) {
-               bytes_written = wl_android_set_cckm_krk(net, command);
-       }
-       else if (strnicmp(command, CMD_GET_ASSOC_RES_IES, strlen(CMD_GET_ASSOC_RES_IES)) == 0) {
-               bytes_written = wl_android_get_assoc_res_ies(net, command);
-       }
-#endif /* BCMCCX */
 #if defined(WL_SUPPORT_AUTO_CHANNEL)
        else if (strnicmp(command, CMD_GET_BEST_CHANNELS,
                strlen(CMD_GET_BEST_CHANNELS)) == 0) {
@@ -2717,6 +3286,88 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                        priv_cmd.total_len);
        }
 #endif /* WL_SUPPORT_AUTO_CHANNEL */
+#if defined(WL_SUPPORT_AUTO_CHANNEL)
+       else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL,
+               strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) {
+               int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 1;
+               bytes_written = wl_android_set_auto_channel(net, (const char*)command+skip, command,
+                       priv_cmd.total_len);
+       }
+#endif /* WL_SUPPORT_AUTO_CHANNEL */
+#ifdef CUSTOMER_HW4_PRIVATE_CMD
+#ifdef SUPPORT_SET_LPC
+       else if (strnicmp(command, CMD_HAPD_LPC_ENABLED,
+               strlen(CMD_HAPD_LPC_ENABLED)) == 0) {
+               int skip = strlen(CMD_HAPD_LPC_ENABLED) + 3;
+               wl_android_set_lpc(net, (const char*)command+skip);
+       }
+#endif /* SUPPORT_SET_LPC */
+#ifdef SUPPORT_TRIGGER_HANG_EVENT
+       else if (strnicmp(command, CMD_TEST_FORCE_HANG,
+               strlen(CMD_TEST_FORCE_HANG)) == 0) {
+               int skip = strlen(CMD_TEST_FORCE_HANG) + 1;
+               net_os_send_hang_message_reason(net, (const char*)command+skip);
+       }
+#endif /* SUPPORT_TRIGGER_HANG_EVENT */
+       else if (strnicmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0)
+               bytes_written = wl_android_ch_res_rl(net, true);
+       else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0)
+               bytes_written = wl_android_ch_res_rl(net, false);
+       else if (strnicmp(command, CMD_SET_RMC_ENABLE, strlen(CMD_SET_RMC_ENABLE)) == 0) {
+               int rmc_enable = *(command + strlen(CMD_SET_RMC_ENABLE) + 1) - '0';
+               bytes_written = wl_android_rmc_enable(net, rmc_enable);
+       }
+       else if (strnicmp(command, CMD_SET_RMC_TXRATE, strlen(CMD_SET_RMC_TXRATE)) == 0) {
+               int rmc_txrate;
+               sscanf(command, "%*s %10d", &rmc_txrate);
+               bytes_written = wldev_iovar_setint(net, "rmc_txrate", rmc_txrate * 2);
+       }
+       else if (strnicmp(command, CMD_SET_RMC_ACTPERIOD, strlen(CMD_SET_RMC_ACTPERIOD)) == 0) {
+               int actperiod;
+               sscanf(command, "%*s %10d", &actperiod);
+               bytes_written = wldev_iovar_setint(net, "rmc_actf_time", actperiod);
+       }
+       else if (strnicmp(command, CMD_SET_RMC_IDLEPERIOD, strlen(CMD_SET_RMC_IDLEPERIOD)) == 0) {
+               int acktimeout;
+               sscanf(command, "%*s %10d", &acktimeout);
+               acktimeout *= 1000;
+               bytes_written = wldev_iovar_setint(net, "rmc_acktmo", acktimeout);
+       }
+       else if (strnicmp(command, CMD_SET_RMC_LEADER, strlen(CMD_SET_RMC_LEADER)) == 0) {
+               int skip = strlen(CMD_SET_RMC_LEADER) + 1;
+               bytes_written = wl_android_rmc_set_leader(net, (const char*)command+skip);
+       }
+       else if (strnicmp(command, CMD_SET_RMC_EVENT,
+               strlen(CMD_SET_RMC_EVENT)) == 0)
+               bytes_written = wl_android_set_rmc_event(net, command, priv_cmd.total_len);
+       else if (strnicmp(command, CMD_GET_SCSCAN, strlen(CMD_GET_SCSCAN)) == 0) {
+               bytes_written = wl_android_get_singlecore_scan(net, command, priv_cmd.total_len);
+       }
+       else if (strnicmp(command, CMD_SET_SCSCAN, strlen(CMD_SET_SCSCAN)) == 0) {
+               bytes_written = wl_android_set_singlecore_scan(net, command, priv_cmd.total_len);
+       }
+#ifdef TEST_TX_POWER_CONTROL
+       else if (strnicmp(command, CMD_TEST_SET_TX_POWER,
+               strlen(CMD_TEST_SET_TX_POWER)) == 0) {
+               int skip = strlen(CMD_TEST_SET_TX_POWER) + 1;
+               wl_android_set_tx_power(net, (const char*)command+skip);
+       }
+       else if (strnicmp(command, CMD_TEST_GET_TX_POWER,
+               strlen(CMD_TEST_GET_TX_POWER)) == 0) {
+               wl_android_get_tx_power(net, command, priv_cmd.total_len);
+       }
+#endif /* TEST_TX_POWER_CONTROL */
+       else if (strnicmp(command, CMD_SARLIMIT_TX_CONTROL,
+               strlen(CMD_SARLIMIT_TX_CONTROL)) == 0) {
+               int skip = strlen(CMD_SARLIMIT_TX_CONTROL) + 1;
+               wl_android_set_sarlimit_txctrl(net, (const char*)command+skip);
+       }
+#ifdef IPV6_NDO_SUPPORT
+       else if (strnicmp(command, CMD_NDRA_LIMIT, strlen(CMD_NDRA_LIMIT)) == 0) {
+               bytes_written = wl_android_nd_ra_limit(net, command, priv_cmd.total_len);
+       }
+#endif /* IPV6_NDO_SUPPORT */
+#endif /* CUSTOMER_HW4_PRIVATE_CMD */
        else if (strnicmp(command, CMD_HAPD_MAC_FILTER, strlen(CMD_HAPD_MAC_FILTER)) == 0) {
                int skip = strlen(CMD_HAPD_MAC_FILTER) + 1;
                wl_android_set_mac_address_filter(net, (const char*)command+skip);
@@ -2731,39 +3382,16 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 #ifdef WL_CFG80211
        else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)
                bytes_written = wl_android_set_miracast(net, command, priv_cmd.total_len);
-#if defined(CUSTOM_PLATFORM_NV_TEGRA)
-       else if (strnicmp(command, CMD_SETMIRACAST, strlen(CMD_SETMIRACAST)) == 0)
-               bytes_written = wldev_miracast_tuning(net, command, priv_cmd.total_len);
-       else if (strnicmp(command, CMD_ASSOCRESPIE, strlen(CMD_ASSOCRESPIE)) == 0)
-               bytes_written = wldev_get_assoc_resp_ie(net, command, priv_cmd.total_len);
-       else if (strnicmp(command, CMD_RXRATESTATS, strlen(CMD_RXRATESTATS)) == 0)
-               bytes_written = wldev_get_rx_rate_stats(net, command, priv_cmd.total_len);
-#endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
+#ifdef WL11ULB
+       else if (strnicmp(command, CMD_ULB_MODE, strlen(CMD_ULB_MODE)) == 0)
+               bytes_written = wl_android_set_ulb_mode(net, command, priv_cmd.total_len);
+       else if (strnicmp(command, CMD_ULB_BW, strlen(CMD_ULB_BW)) == 0)
+               bytes_written = wl_android_set_ulb_bw(net, command, priv_cmd.total_len);
+#endif /* WL11ULB */
        else if (strnicmp(command, CMD_SETIBSSBEACONOUIDATA, strlen(CMD_SETIBSSBEACONOUIDATA)) == 0)
                bytes_written = wl_android_set_ibss_beacon_ouidata(net,
                command, priv_cmd.total_len);
 #endif
-#ifdef WLAIBSS
-       else if (strnicmp(command, CMD_SETIBSSTXFAILEVENT,
-               strlen(CMD_SETIBSSTXFAILEVENT)) == 0)
-               bytes_written = wl_android_set_ibss_txfail_event(net, command, priv_cmd.total_len);
-       else if (strnicmp(command, CMD_GET_IBSS_PEER_INFO_ALL,
-               strlen(CMD_GET_IBSS_PEER_INFO_ALL)) == 0)
-               bytes_written = wl_android_get_ibss_peer_info(net, command, priv_cmd.total_len,
-                       TRUE);
-       else if (strnicmp(command, CMD_GET_IBSS_PEER_INFO,
-               strlen(CMD_GET_IBSS_PEER_INFO)) == 0)
-               bytes_written = wl_android_get_ibss_peer_info(net, command, priv_cmd.total_len,
-                       FALSE);
-       else if (strnicmp(command, CMD_SETIBSSROUTETABLE,
-               strlen(CMD_SETIBSSROUTETABLE)) == 0)
-               bytes_written = wl_android_set_ibss_routetable(net, command,
-                       priv_cmd.total_len);
-       else if (strnicmp(command, CMD_SETIBSSAMPDU, strlen(CMD_SETIBSSAMPDU)) == 0)
-               bytes_written = wl_android_set_ibss_ampdu(net, command, priv_cmd.total_len);
-       else if (strnicmp(command, CMD_SETIBSSANTENNAMODE, strlen(CMD_SETIBSSANTENNAMODE)) == 0)
-               bytes_written = wl_android_set_ibss_antenna(net, command, priv_cmd.total_len);
-#endif /* WLAIBSS */
        else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) {
                int skip = strlen(CMD_KEEP_ALIVE) + 1;
                bytes_written = wl_keep_alive_set(net, command + skip, priv_cmd.total_len - skip);
@@ -2778,6 +3406,18 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                        command + strlen(CMD_ROAM_OFFLOAD_APLIST) + 1);
        }
 #endif
+#if defined(WL_VIRTUAL_APSTA)
+       else if (strnicmp(command, CMD_INTERFACE_CREATE, strlen(CMD_INTERFACE_CREATE)) == 0) {
+               char *name = (command + strlen(CMD_INTERFACE_CREATE) +1);
+               ANDROID_INFO(("Creating %s interface\n", name));
+               bytes_written = wl_cfg80211_interface_create(net, name);
+       }
+       else if (strnicmp(command, CMD_INTERFACE_DELETE, strlen(CMD_INTERFACE_DELETE)) == 0) {
+               char *name = (command + strlen(CMD_INTERFACE_DELETE) +1);
+               ANDROID_INFO(("Deleteing %s interface\n", name));
+               bytes_written = wl_cfg80211_interface_delete(net, name);
+       }
+#endif /* defined (WL_VIRTUAL_APSTA) */
 #ifdef P2PRESP_WFDIE_SRC
        else if (strnicmp(command, CMD_P2P_SET_WFDIE_RESP,
                strlen(CMD_P2P_SET_WFDIE_RESP)) == 0) {
@@ -2788,16 +3428,106 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                bytes_written = wl_android_get_wfdie_resp(net, command, priv_cmd.total_len);
        }
 #endif /* P2PRESP_WFDIE_SRC */
-       else if (strnicmp(command, CMD_GET_LINK_STATUS, strlen(CMD_GET_LINK_STATUS)) == 0) {
-               bytes_written = wl_android_get_link_status(net, command, priv_cmd.total_len);
+#ifdef WL_CFG80211
+       else if (strnicmp(command, CMD_DFS_AP_MOVE, strlen(CMD_DFS_AP_MOVE)) == 0) {
+               char *data = (command + strlen(CMD_DFS_AP_MOVE) +1);
+               bytes_written = wl_cfg80211_dfs_ap_move(net, data, command, priv_cmd.total_len);
        }
-#ifdef CONNECTION_STATISTICS
-       else if (strnicmp(command, CMD_GET_CONNECTION_STATS,
-               strlen(CMD_GET_CONNECTION_STATS)) == 0) {
-               bytes_written = wl_android_get_connection_stats(net, command,
-                       priv_cmd.total_len);
+#endif
+       else if (strnicmp(command, CMD_WBTEXT_ENABLE, strlen(CMD_WBTEXT_ENABLE)) == 0) {
+               bytes_written = wl_android_wbtext(net, command, priv_cmd.total_len);
+       }
+#ifdef WL_CFG80211
+       else if (strnicmp(command, CMD_WBTEXT_PROFILE_CONFIG,
+                       strlen(CMD_WBTEXT_PROFILE_CONFIG)) == 0) {
+               char *data = (command + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
+               bytes_written = wl_cfg80211_wbtext_config(net, data, command, priv_cmd.total_len);
+       }
+       else if (strnicmp(command, CMD_WBTEXT_WEIGHT_CONFIG,
+                       strlen(CMD_WBTEXT_WEIGHT_CONFIG)) == 0) {
+               char *data = (command + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
+               bytes_written = wl_cfg80211_wbtext_weight_config(net, data,
+                               command, priv_cmd.total_len);
+       }
+       else if (strnicmp(command, CMD_WBTEXT_TABLE_CONFIG,
+                       strlen(CMD_WBTEXT_TABLE_CONFIG)) == 0) {
+               char *data = (command + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
+               bytes_written = wl_cfg80211_wbtext_table_config(net, data,
+                               command, priv_cmd.total_len);
+       }
+       else if (strnicmp(command, CMD_WBTEXT_DELTA_CONFIG,
+                       strlen(CMD_WBTEXT_DELTA_CONFIG)) == 0) {
+               char *data = (command + strlen(CMD_WBTEXT_DELTA_CONFIG) + 1);
+               bytes_written = wl_cfg80211_wbtext_delta_config(net, data,
+                               command, priv_cmd.total_len);
+       }
+#endif
+#ifdef SET_RPS_CPUS
+       else if (strnicmp(command, CMD_RPSMODE, strlen(CMD_RPSMODE)) == 0) {
+               bytes_written = wl_android_set_rps_cpus(net, command, priv_cmd.total_len);
+       }
+#endif /* SET_RPS_CPUS */
+#ifdef WLWFDS
+       else if (strnicmp(command, CMD_ADD_WFDS_HASH, strlen(CMD_ADD_WFDS_HASH)) == 0) {
+               bytes_written = wl_android_set_wfds_hash(net, command, priv_cmd.total_len, 1);
+       }
+       else if (strnicmp(command, CMD_DEL_WFDS_HASH, strlen(CMD_DEL_WFDS_HASH)) == 0) {
+               bytes_written = wl_android_set_wfds_hash(net, command, priv_cmd.total_len, 0);
+       }
+#endif /* WLWFDS */
+#ifdef BT_WIFI_HANDOVER
+       else if (strnicmp(command, CMD_TBOW_TEARDOWN, strlen(CMD_TBOW_TEARDOWN)) == 0) {
+           ret = wl_tbow_teardown(net, command, priv_cmd.total_len);
+       }
+#endif /* BT_WIFI_HANDOVER */
+#ifdef FCC_PWR_LIMIT_2G
+       else if (strnicmp(command, CMD_GET_FCC_PWR_LIMIT_2G,
+               strlen(CMD_GET_FCC_PWR_LIMIT_2G)) == 0) {
+               bytes_written = wl_android_get_fcc_pwr_limit_2g(net, command, priv_cmd.total_len);
+       }
+       else if (strnicmp(command, CMD_SET_FCC_PWR_LIMIT_2G,
+               strlen(CMD_SET_FCC_PWR_LIMIT_2G)) == 0) {
+               bytes_written = wl_android_set_fcc_pwr_limit_2g(net, command, priv_cmd.total_len);
+       }
+#endif /* FCC_PWR_LIMIT_2G */
+#ifdef WL_CFG80211
+       else if (strnicmp(command, CMD_MURX_BFE_CAP,
+                       strlen(CMD_MURX_BFE_CAP)) == 0) {
+               uint val = *(command + strlen(CMD_MURX_BFE_CAP) + 1) - '0';
+               bytes_written = wl_android_murx_bfe_cap(net, val);
        }
 #endif
+#if defined(DHD_ENABLE_BIGDATA_LOGGING)
+       else if (strnicmp(command, CMD_GET_BSS_INFO, strlen(CMD_GET_BSS_INFO)) == 0) {
+               bytes_written = wl_cfg80211_get_bss_info(net, command, priv_cmd.total_len);
+       }
+       else if (strnicmp(command, CMD_GET_ASSOC_REJECT_INFO, strlen(CMD_GET_ASSOC_REJECT_INFO))
+                       == 0) {
+               bytes_written = wl_cfg80211_get_connect_failed_status(net, command,
+                               priv_cmd.total_len);
+       }
+#endif /* DHD_ENABLE_BIGDATA_LOGGING */
+#if defined(SUPPORT_RANDOM_MAC_SCAN)
+       else if (strnicmp(command, ENABLE_RANDOM_MAC, strlen(ENABLE_RANDOM_MAC)) == 0) {
+               bytes_written = wl_cfg80211_set_random_mac(net, TRUE);
+       } else if (strnicmp(command, DISABLE_RANDOM_MAC, strlen(DISABLE_RANDOM_MAC)) == 0) {
+               bytes_written = wl_cfg80211_set_random_mac(net, FALSE);
+       }
+#endif /* SUPPORT_RANDOM_MAC_SCAN */
+#ifdef DHD_LOG_DUMP
+       else if (strnicmp(command, CMD_NEW_DEBUG_PRINT_DUMP,
+               strlen(CMD_NEW_DEBUG_PRINT_DUMP)) == 0) {
+               dhd_pub_t *dhdp = wl_cfg80211_get_dhdp();
+#ifdef DHD_TRACE_WAKE_LOCK
+               dhd_wk_lock_stats_dump(dhdp);
+#endif /* DHD_TRACE_WAKE_LOCK */
+               dhd_schedule_log_dump(dhdp);
+#if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
+               dhdp->memdump_type = DUMP_TYPE_BY_SYSDUMP;
+               dhd_bus_mem_dump(dhdp);
+#endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
+       }
+#endif /* DHD_LOG_DUMP */
        else if(strnicmp(command, CMD_GET_CHANNEL, strlen(CMD_GET_CHANNEL)) == 0) {
                bytes_written = wl_android_get_channel(net, command, priv_cmd.total_len);
        }
@@ -2840,6 +3570,13 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
                        ret = -EFAULT;
                }
        }
+#ifdef CONNECTION_STATISTICS
+       else if (strnicmp(command, CMD_GET_CONNECTION_STATS,
+               strlen(CMD_GET_CONNECTION_STATS)) == 0) {
+               bytes_written = wl_android_get_connection_stats(net, command,
+                       priv_cmd.total_len);
+       }
+#endif
        else {
                ret = bytes_written;
        }
@@ -2865,9 +3602,6 @@ int wl_android_init(void)
                bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
        }
 
-#ifdef WL_GENL
-       wl_genl_init();
-#endif
        wl_netlink_init();
 
        return ret;
@@ -2878,9 +3612,6 @@ int wl_android_exit(void)
        int ret = 0;
        struct io_cfg *cur, *q;
 
-#ifdef WL_GENL
-       wl_genl_deinit();
-#endif /* WL_GENL */
        wl_netlink_deinit();
 
        list_for_each_entry_safe(cur, q, &miracast_resume_list, list) {
@@ -2903,258 +3634,6 @@ void wl_android_post_init(void)
                g_wifi_on = FALSE;
 }
 
-#ifdef WL_GENL
-/* Generic Netlink Initializaiton */
-static int wl_genl_init(void)
-{
-       int ret;
-
-       ANDROID_TRACE(("GEN Netlink Init\n\n"));
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
-       /* register new family */
-       ret = genl_register_family(&wl_genl_family);
-       if (ret != 0)
-               goto failure;
-
-       /* register functions (commands) of the new family */
-       ret = genl_register_ops(&wl_genl_family, &wl_genl_ops);
-       if (ret != 0) {
-               ANDROID_ERROR(("register ops failed: %i\n", ret));
-               genl_unregister_family(&wl_genl_family);
-               goto failure;
-       }
-
-       ret = genl_register_mc_group(&wl_genl_family, &wl_genl_mcast);
-#else
-       ret = genl_register_family_with_ops_groups(&wl_genl_family, wl_genl_ops, wl_genl_mcast);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
-       if (ret != 0) {
-               ANDROID_ERROR(("register mc_group failed: %i\n", ret));
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
-               genl_unregister_ops(&wl_genl_family, &wl_genl_ops);
-#endif
-               genl_unregister_family(&wl_genl_family);
-               goto failure;
-       }
-
-       return 0;
-
-failure:
-       ANDROID_ERROR(("Registering Netlink failed!!\n"));
-       return -1;
-}
-
-/* Generic netlink deinit */
-static int wl_genl_deinit(void)
-{
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
-       if (genl_unregister_ops(&wl_genl_family, &wl_genl_ops) < 0)
-               ANDROID_ERROR(("Unregister wl_genl_ops failed\n"));
-#endif
-       if (genl_unregister_family(&wl_genl_family) < 0)
-               ANDROID_ERROR(("Unregister wl_genl_ops failed\n"));
-
-       return 0;
-}
-
-s32 wl_event_to_bcm_event(u16 event_type)
-{
-       u16 event = -1;
-
-       switch (event_type) {
-               case WLC_E_SERVICE_FOUND:
-                       event = BCM_E_SVC_FOUND;
-                       break;
-               case WLC_E_P2PO_ADD_DEVICE:
-                       event = BCM_E_DEV_FOUND;
-                       break;
-               case WLC_E_P2PO_DEL_DEVICE:
-                       event = BCM_E_DEV_LOST;
-                       break;
-       /* Above events are supported from BCM Supp ver 47 Onwards */
-#ifdef BT_WIFI_HANDOVER
-               case WLC_E_BT_WIFI_HANDOVER_REQ:
-                       event = BCM_E_DEV_BT_WIFI_HO_REQ;
-                       break;
-#endif /* BT_WIFI_HANDOVER */
-
-               default:
-                       ANDROID_ERROR(("Event not supported\n"));
-       }
-
-       return event;
-}
-
-s32
-wl_genl_send_msg(
-       struct net_device *ndev,
-       u32 event_type,
-       u8 *buf,
-       u16 len,
-       u8 *subhdr,
-       u16 subhdr_len)
-{
-       int ret = 0;
-       struct sk_buff *skb = NULL;
-       void *msg;
-       u32 attr_type = 0;
-       bcm_event_hdr_t *hdr = NULL;
-       int mcast = 1; /* By default sent as mutlicast type */
-       int pid = 0;
-       u8 *ptr = NULL, *p = NULL;
-       u32 tot_len = sizeof(bcm_event_hdr_t) + subhdr_len + len;
-       u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
-
-
-       ANDROID_TRACE(("Enter \n"));
-
-       /* Decide between STRING event and Data event */
-       if (event_type == 0)
-               attr_type = BCM_GENL_ATTR_STRING;
-       else
-               attr_type = BCM_GENL_ATTR_MSG;
-
-       skb = genlmsg_new(NLMSG_GOODSIZE, kflags);
-       if (skb == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       msg = genlmsg_put(skb, 0, 0, &wl_genl_family, 0, BCM_GENL_CMD_MSG);
-       if (msg == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-
-       if (attr_type == BCM_GENL_ATTR_STRING) {
-               /* Add a BCM_GENL_MSG attribute. Since it is specified as a string.
-                * make sure it is null terminated
-                */
-               if (subhdr || subhdr_len) {
-                       ANDROID_ERROR(("No sub hdr support for the ATTR STRING type \n"));
-                       ret =  -EINVAL;
-                       goto out;
-               }
-
-               ret = nla_put_string(skb, BCM_GENL_ATTR_STRING, buf);
-               if (ret != 0) {
-                       ANDROID_ERROR(("nla_put_string failed\n"));
-                       goto out;
-               }
-       } else {
-               /* ATTR_MSG */
-
-               /* Create a single buffer for all */
-               p = ptr = kzalloc(tot_len, kflags);
-               if (!ptr) {
-                       ret = -ENOMEM;
-                       ANDROID_ERROR(("ENOMEM!!\n"));
-                       goto out;
-               }
-
-               /* Include the bcm event header */
-               hdr = (bcm_event_hdr_t *)ptr;
-               hdr->event_type = wl_event_to_bcm_event(event_type);
-               hdr->len = len + subhdr_len;
-               ptr += sizeof(bcm_event_hdr_t);
-
-               /* Copy subhdr (if any) */
-               if (subhdr && subhdr_len) {
-                       memcpy(ptr, subhdr, subhdr_len);
-                       ptr += subhdr_len;
-               }
-
-               /* Copy the data */
-               if (buf && len) {
-                       memcpy(ptr, buf, len);
-               }
-
-               ret = nla_put(skb, BCM_GENL_ATTR_MSG, tot_len, p);
-               if (ret != 0) {
-                       ANDROID_ERROR(("nla_put_string failed\n"));
-                       goto out;
-               }
-       }
-
-       if (mcast) {
-               int err = 0;
-               /* finalize the message */
-               genlmsg_end(skb, msg);
-               /* NETLINK_CB(skb).dst_group = 1; */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
-               if ((err = genlmsg_multicast(skb, 0, wl_genl_mcast.id, GFP_ATOMIC)) < 0)
-#else
-               if ((err = genlmsg_multicast(&wl_genl_family, skb, 0, 0, GFP_ATOMIC)) < 0)
-#endif
-                       ANDROID_ERROR(("genlmsg_multicast for attr(%d) failed. Error:%d \n",
-                               attr_type, err));
-               else
-                       ANDROID_TRACE(("Multicast msg sent successfully. attr_type:%d len:%d \n",
-                               attr_type, tot_len));
-       } else {
-               NETLINK_CB(skb).dst_group = 0; /* Not in multicast group */
-
-               /* finalize the message */
-               genlmsg_end(skb, msg);
-
-               /* send the message back */
-               if (genlmsg_unicast(&init_net, skb, pid) < 0)
-                       ANDROID_ERROR(("genlmsg_unicast failed\n"));
-       }
-
-out:
-       if (p)
-               kfree(p);
-       if (ret)
-               nlmsg_free(skb);
-
-       return ret;
-}
-
-static s32
-wl_genl_handle_msg(
-       struct sk_buff *skb,
-       struct genl_info *info)
-{
-       struct nlattr *na;
-       u8 *data = NULL;
-
-       ANDROID_TRACE(("Enter \n"));
-
-       if (info == NULL) {
-               return -EINVAL;
-       }
-
-       na = info->attrs[BCM_GENL_ATTR_MSG];
-       if (!na) {
-               ANDROID_ERROR(("nlattribute NULL\n"));
-               return -EINVAL;
-       }
-
-       data = (char *)nla_data(na);
-       if (!data) {
-               ANDROID_ERROR(("Invalid data\n"));
-               return -EINVAL;
-       } else {
-               /* Handle the data */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) || defined(WL_COMPAT_WIRELESS)
-               ANDROID_TRACE(("%s: Data received from pid (%d) \n", __func__,
-                       info->snd_pid));
-#else
-               ANDROID_TRACE(("%s: Data received from pid (%d) \n", __func__,
-                       info->snd_portid));
-#endif /* (LINUX_VERSION < VERSION(3, 7, 0) || WL_COMPAT_WIRELESS */
-       }
-
-       return 0;
-}
-#endif /* WL_GENL */
-
-
 #if defined(RSSIAVG)
 void
 wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
@@ -3270,6 +3749,7 @@ wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rss
        wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
        int j, k=0;
        int rssi, error=0;
+       scb_val_t scbval;
        struct ether_addr bssid;
        struct timeval now, timeout;
 
@@ -3282,11 +3762,13 @@ wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rss
                return 0;
        }
        if (error) {
-               ANDROID_ERROR(("Could not get bssid (%d)\n", error));
+               ANDROID_ERROR(("%s: Could not get bssid (%d)\n", __FUNCTION__, error));
        }
-       error = wldev_get_rssi(net, &rssi);
+       memset(&scbval, 0, sizeof(scb_val_t));
+       error = wldev_get_rssi(net, &scbval);
+       rssi = scbval.val;
        if (error) {
-               ANDROID_ERROR(("Could not get rssi (%d)\n", error));
+               ANDROID_ERROR(("%s: Could not get rssi (%d)\n", __FUNCTION__, error));
                return error;
        }
 
@@ -3324,10 +3806,10 @@ wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rss
        leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL);
        if (!leaf) {
                ANDROID_ERROR(("%s: Memory alloc failure %d\n",
-                       __FUNCTION__, sizeof(wl_rssi_cache_t)));
+                       __FUNCTION__, (int)sizeof(wl_rssi_cache_t)));
                return 0;
        }
-       ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%d in the leaf\n",
+       ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d in the leaf\n",
                        __FUNCTION__, k, &bssid, rssi));
 
        leaf->next = NULL;
@@ -3380,7 +3862,7 @@ wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *s
                bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
                for (;node;) {
                        if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
-                               ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n",
+                               ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
                                        __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
                                for (j=0; j<RSSIAVG_LEN-1; j++)
                                        node->RSSI[j] = node->RSSI[j+1];
@@ -3400,10 +3882,10 @@ wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *s
                leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL);
                if (!leaf) {
                        ANDROID_ERROR(("%s: Memory alloc failure %d\n",
-                               __FUNCTION__, sizeof(wl_rssi_cache_t)));
+                               __FUNCTION__, (int)sizeof(wl_rssi_cache_t)));
                        return;
                }
-               ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n",
+               ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\" in the leaf\n",
                                __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
 
                leaf->next = NULL;
@@ -3453,32 +3935,27 @@ wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr)
 int
 wl_update_rssi_offset(struct net_device *net, int rssi)
 {
-       uint chip, chiprev;
+#if defined(RSSIOFFSET_NEW)
+       int j;
+#endif
 
        if (!g_wifi_on)
                return rssi;
 
-       chip = dhd_conf_get_chip(dhd_get_pub(net));
-       chiprev = dhd_conf_get_chiprev(dhd_get_pub(net));
-       if (chip == BCM4330_CHIP_ID && chiprev == BCM4330B2_CHIP_REV) {
 #if defined(RSSIOFFSET_NEW)
-               int j;
-               for (j=0; j<RSSI_OFFSET; j++) {
-                       if (rssi - (RSSI_OFFSET_MINVAL+RSSI_OFFSET_INTVAL*(j+1)) < 0)
-                               break;
-               }
-               rssi += j;
+       for (j=0; j<RSSI_OFFSET; j++) {
+               if (rssi - (RSSI_OFFSET_MINVAL+RSSI_OFFSET_INTVAL*(j+1)) < 0)
+                       break;
+       }
+       rssi += j;
 #else
-               rssi += RSSI_OFFSET;
+       rssi += RSSI_OFFSET;
 #endif
-       }
        return MIN(rssi, RSSI_MAXVAL);
 }
 #endif
 
 #if defined(BSSCACHE)
-#define WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN      32
-
 void
 wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
 {
@@ -3523,7 +4000,7 @@ wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
                                tmp = 0;
                                prev->next = node->next;
                        }
-                       ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n",
+                       ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
                                __FUNCTION__, i, &node->results.bss_info->BSSID,
                                dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID));
                        kfree(node);
@@ -3559,7 +4036,7 @@ wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, u8 *bssid)
                                tmp = 0;
                                prev->next = node->next;
                        }
-                       ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n",
+                       ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
                                __FUNCTION__, i, &node->results.bss_info->BSSID,
                                dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID));
                        kfree(node);
@@ -3591,12 +4068,41 @@ wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
        }
 }
 
+void dump_bss_cache(
+#if defined(RSSIAVG)
+       wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+#endif
+       wl_bss_cache_t *node)
+{
+       int k = 0;
+       int16 rssi;
+
+       for (;node;) {
+#if defined(RSSIAVG)
+               rssi = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
+#else
+               rssi = dtoh16(node->results.bss_info->RSSI);
+#endif
+               ANDROID_TRACE(("%s: dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
+                       __FUNCTION__, k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID));
+               k++;
+               node = node->next;
+       }
+}
+
 void
-wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_list)
+wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
+#if defined(RSSIAVG)
+       wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+#endif
+       wl_scan_results_t *ss_list)
 {
-       wl_bss_cache_t *node, *prev, *leaf, *tmp, **bss_head;
+       wl_bss_cache_t *node, *prev, *leaf, **bss_head;
        wl_bss_info_t *bi = NULL;
        int i, k=0;
+#if defined(SORT_BSS_BY_RSSI)
+       int16 rssi, rssi_node;
+#endif
        struct timeval now, timeout;
 
        if (!ss_list->count)
@@ -3622,47 +4128,30 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_l
 
                for (;node;) {
                        if (!memcmp(&node->results.bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
-                               tmp = node;
-                               leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
-                               if (!leaf) {
-                                       ANDROID_ERROR(("%s: Memory alloc failure %d and keep old BSS info\n",
-                                               __FUNCTION__, dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
-                                       break;
+                               if (node == *bss_head)
+                                       *bss_head = node->next;
+                               else {
+                                       prev->next = node->next;
                                }
-
-                               memcpy(leaf->results.bss_info, bi, dtoh32(bi->length));
-                               leaf->next = node->next;
-                               leaf->dirty = 0;
-                               leaf->tv = timeout;
-                               leaf->results.count = 1;
-                               leaf->results.version = ss_list->version;
-                               ANDROID_TRACE(("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\", length=%d\n",
-                                       __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID, dtoh32(bi->length)));
-                               if (!prev)
-                                       *bss_head = leaf;
-                               else
-                                       prev->next = leaf;
-                               node = leaf;
-                               prev = node;
-
-                               kfree(tmp);
-                               k++;
                                break;
                        }
                        prev = node;
                        node = node->next;
                }
 
-               if (node)
-                       continue;
-
-               leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
+               leaf = kmalloc(dtoh32(bi->length) + sizeof(wl_bss_cache_t), GFP_KERNEL);
                if (!leaf) {
                        ANDROID_ERROR(("%s: Memory alloc failure %d\n", __FUNCTION__,
-                               dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
+                               dtoh32(bi->length) + (int)sizeof(wl_bss_cache_t)));
                        return;
                }
-               ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n",
+               if (node) {
+                       kfree(node);
+                       node = NULL;
+                       ANDROID_TRACE(("%s: Update %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
+                               __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
+               } else
+                       ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
                                __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
 
                memcpy(leaf->results.bss_info, bi, dtoh32(bi->length));
@@ -3673,11 +4162,46 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_l
                leaf->results.version = ss_list->version;
                k++;
 
-               if (!prev)
+               if (*bss_head == NULL)
                        *bss_head = leaf;
-               else
-                       prev->next = leaf;
+               else {
+#if defined(SORT_BSS_BY_RSSI)
+                       node = *bss_head;
+#if defined(RSSIAVG)
+                       rssi = wl_get_avg_rssi(rssi_cache_ctrl, &leaf->results.bss_info->BSSID);
+#else
+                       rssi = dtoh16(leaf->results.bss_info->RSSI);
+#endif
+                       for (;node;) {
+#if defined(RSSIAVG)
+                               rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
+#else
+                               rssi_node = dtoh16(node->results.bss_info->RSSI);
+#endif
+                               if (rssi > rssi_node) {
+                                       leaf->next = node;
+                                       if (node == *bss_head)
+                                               *bss_head = leaf;
+                                       else
+                                               prev->next = leaf;
+                                       break;
+                               }
+                               prev = node;
+                               node = node->next;
+                       }
+                       if (node == NULL)
+                               prev->next = leaf;
+#else
+                       leaf->next = *bss_head;
+                       *bss_head = leaf;
+#endif
+               }
        }
+       dump_bss_cache(
+#if defined(RSSIAVG)
+               rssi_cache_ctrl,
+#endif
+               *bss_head);
 }
 
 void