wlan: Merge 32STA Host support changes

Merge 32STA Host support changes to Rel1.2: [APQ8064.LA.1.6 +
MDM9615.TN.3.7] only

Change-Id: Ia8d292fc63860a8f35bf3a0e8144007dd4a7351c
CR-Fixed: 426416

Conflicts:

	prima/CORE/HDD/inc/wlan_hdd_cfg.h
	prima/CORE/HDD/src/wlan_hdd_cfg.c

Conflicts:
	CORE/HDD/inc/wlan_hdd_cfg.h
	CORE/HDD/src/wlan_hdd_cfg.c
diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h
index 7939b56..dd08179 100644
--- a/CORE/HDD/inc/qc_sap_ioctl.h
+++ b/CORE/HDD/inc/qc_sap_ioctl.h
@@ -53,6 +53,7 @@
  */
 #define QCSAP_MAX_OPT_IE        256
 #define QCSAP_MAX_WSC_IE        256
+#define QCSAP_MAX_GET_STA_INFO  512
 
 typedef struct sSSID
 {
@@ -255,6 +256,7 @@
 #define QCSAP_IOCTL_MODIFY_ACL          (SIOCIWFIRSTPRIV+18)
 #define QCSAP_IOCTL_GET_CHANNEL_LIST    (SIOCIWFIRSTPRIV+19)
 #define QCSAP_IOCTL_SET_TX_POWER        (SIOCIWFIRSTPRIV+20) 
+#define QCSAP_IOCTL_GET_STA_INFO        (SIOCIWFIRSTPRIV+21) 
 
 #define MAX_VAR_ARGS         7
 #define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31)
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 4eb3b1b..397462c 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1442,6 +1442,16 @@
 #define CFG_ENABLE_RX_STBC_MAX                   ( 1 )
 #define CFG_ENABLE_RX_STBC_DEFAULT               ( 1 )
 
+/* 
+ * Enable/Disable vsta based on MAX Assoc limit 
+ * defined in WCNSS_qcom_cfg.ini.
+ */
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+#define CFG_VSTA_SUPPORT_ENABLE               "gEnableVSTASupport"
+#define CFG_VSTA_SUPPORT_ENABLE_MIN           ( 0 )
+#define CFG_VSTA_SUPPORT_ENABLE_MAX           ( 1 )
+#define CFG_VSTA_SUPPORT_ENABLE_DEFAULT       ( 0 )
+#endif
 
 #ifdef FEATURE_WLAN_TDLS
 #define CFG_TDLS_SUPPORT_ENABLE               "gEnableTDLSSupport"
@@ -1789,6 +1799,9 @@
    v_BOOL_t                    fEnableTDLSSupport;
 #endif
    v_U32_t                     enableLpwrImgTransition;
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+   v_BOOL_t                    fEnableVSTASupport;
+#endif
 #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
    v_BOOL_t                    fEnableActiveModeOffload;
 #endif
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index cca2a51..86842cc 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -1786,6 +1786,14 @@
               CFG_TDLS_SUPPORT_ENABLE_MAX ),
 #endif
 
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+REG_VARIABLE( CFG_VSTA_SUPPORT_ENABLE, WLAN_PARAM_Integer,
+              hdd_config_t, fEnableVSTASupport,
+              VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+              CFG_VSTA_SUPPORT_ENABLE_DEFAULT,
+              CFG_VSTA_SUPPORT_ENABLE_MIN,
+              CFG_VSTA_SUPPORT_ENABLE_MAX ),
+#endif
 REG_VARIABLE( CFG_ENABLE_LPWR_IMG_TRANSITION_NAME, WLAN_PARAM_Integer,
              hdd_config_t, enableLpwrImgTransition, 
              VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, 
@@ -2716,6 +2724,9 @@
 v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx )
 {
    v_BOOL_t  fStatus = TRUE;
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+   tANI_U32 val;
+#endif
 
    hdd_config_t *pConfig = pHddCtx->cfg_ini;
    tSirMacHTCapabilityInfo htCapInfo;
@@ -3217,6 +3228,25 @@
          fStatus = FALSE;
          hddLog(LOGE, "Could not pass on WNI_CFG_VHT_RXSTBC to CCM\n");
      }
+
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+     if(pConfig->fEnableVSTASupport)
+     {
+        ccmCfgGetInt(pHddCtx->hHal, WNI_CFG_ASSOC_STA_LIMIT, &val);
+        if( val <= WNI_CFG_ASSOC_STA_LIMIT_STADEF)
+            val = WNI_CFG_ASSOC_STA_LIMIT_STAMAX;
+     }
+     else
+     {
+            val = WNI_CFG_ASSOC_STA_LIMIT_STADEF;
+     }
+     if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ASSOC_STA_LIMIT, val, 
+         NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE)
+     {
+         fStatus = FALSE;
+         hddLog(LOGE,"Failure: Could not pass on WNI_CFG_ASSOC_STA_LIMIT configuration info to CCM\n"  );
+     }
+#endif
    if(ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_ENABLE_LPWR_IMG_TRANSITION, 
                    pConfig->enableLpwrImgTransition, NULL, eANI_BOOLEAN_FALSE)
        ==eHAL_STATUS_FAILURE)
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 26aea4a..30453e1 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -100,6 +100,8 @@
     (IS_UP((_ic)->ic_dev) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO)
 #define WE_WLAN_VERSION     1
 #define STATS_CONTEXT_MAGIC 0x53544154
+#define WE_GET_STA_INFO_SIZE 50
+#define WE_SAP_MAX_STA_INFO (WE_GET_STA_INFO_SIZE * WLAN_MAX_STA_COUNT)
 
 struct statsContext
 {
@@ -2426,6 +2428,46 @@
 #endif//TODO need to handle in prima
     return 0;
 }
+
+VOS_STATUS hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf)
+{
+    v_U8_t i;
+
+    for (i = 0; i < WLAN_MAX_STA_COUNT; i++)
+    {
+        if(pAdapter->aStaInfo[i].isUsed)
+        {
+            pBuf += snprintf(pBuf, WE_GET_STA_INFO_SIZE, "staIndex = %d staAddress =.%02x:%02x:%02x:%02x:%02x:%02x\n",
+                                       pAdapter->aStaInfo[i].ucSTAId,
+                                       pAdapter->aStaInfo[i].macAddrSTA.bytes[0],
+                                       pAdapter->aStaInfo[i].macAddrSTA.bytes[1],
+                                       pAdapter->aStaInfo[i].macAddrSTA.bytes[2],
+                                       pAdapter->aStaInfo[i].macAddrSTA.bytes[3],
+                                       pAdapter->aStaInfo[i].macAddrSTA.bytes[4],
+                                       pAdapter->aStaInfo[i].macAddrSTA.bytes[5]);
+        }
+    }
+    return VOS_STATUS_SUCCESS;
+}
+
+static int iw_softap_get_sta_info(struct net_device *dev,
+        struct iw_request_info *info,
+        union iwreq_data *wrqu, 
+        char *extra)
+{
+    hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev));
+    VOS_STATUS status;
+    ENTER();
+    status = hdd_softap_get_sta_info(pHostapdAdapter, extra);
+    if ( !VOS_IS_STATUS_SUCCESS( status ) ) {
+       hddLog(VOS_TRACE_LEVEL_ERROR, "%s Failed!!!\n",__func__);
+       return -EINVAL;
+    }
+    wrqu->data.length = strlen(extra);
+    EXIT();
+    return 0;
+}
+
 static int iw_set_ap_genie(struct net_device *dev,
         struct iw_request_info *info,
         union iwreq_data *wrqu, 
@@ -2666,6 +2708,8 @@
       IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED, 0, "stopbss" },
   { QCSAP_IOCTL_VERSION, 0,
       IW_PRIV_TYPE_CHAR | QCSAP_MAX_WSC_IE, "version" },
+  { QCSAP_IOCTL_GET_STA_INFO, 0,
+      IW_PRIV_TYPE_CHAR | WE_SAP_MAX_STA_INFO, "get_sta_info" },
   { QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES,
       IW_PRIV_TYPE_BYTE | sizeof(sQcSapreq_WPSPBCProbeReqIES_t) | IW_PRIV_SIZE_FIXED | 1, 0, "getProbeReqIEs" },
   { QCSAP_IOCTL_GET_CHANNEL, 0,
@@ -2757,6 +2801,7 @@
    [QCSAP_IOCTL_SET_CHANNEL_RANGE - SIOCIWFIRSTPRIV] = iw_softap_set_channel_range,
    [QCSAP_IOCTL_MODIFY_ACL - SIOCIWFIRSTPRIV]   = iw_softap_modify_acl,
    [QCSAP_IOCTL_GET_CHANNEL_LIST - SIOCIWFIRSTPRIV]   = iw_softap_get_channel_list,
+   [QCSAP_IOCTL_GET_STA_INFO - SIOCIWFIRSTPRIV] = iw_softap_get_sta_info,
    [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - SIOCIWFIRSTPRIV]     = iw_get_softap_linkspeed,
    [QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV]   = iw_softap_set_tx_power,
 };
diff --git a/CORE/MAC/inc/wniCfgAp.h b/CORE/MAC/inc/wniCfgAp.h
index 3befdb5..1149233 100644
--- a/CORE/MAC/inc/wniCfgAp.h
+++ b/CORE/MAC/inc/wniCfgAp.h
@@ -2355,11 +2355,11 @@
 #define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_APDEF    0
 
 #define WNI_CFG_ASSOC_STA_LIMIT_STAMIN    1
-#define WNI_CFG_ASSOC_STA_LIMIT_STAMAX    10
+#define WNI_CFG_ASSOC_STA_LIMIT_STAMAX    32
 #define WNI_CFG_ASSOC_STA_LIMIT_STADEF    10
 
 #define WNI_CFG_ASSOC_STA_LIMIT_APMIN    1
-#define WNI_CFG_ASSOC_STA_LIMIT_APMAX    10
+#define WNI_CFG_ASSOC_STA_LIMIT_APMAX    32
 #define WNI_CFG_ASSOC_STA_LIMIT_APDEF    10
 
 #define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMIN    1
diff --git a/CORE/MAC/inc/wniCfgSta.h b/CORE/MAC/inc/wniCfgSta.h
index dcf380c..70de087 100644
--- a/CORE/MAC/inc/wniCfgSta.h
+++ b/CORE/MAC/inc/wniCfgSta.h
@@ -1548,7 +1548,7 @@
 #define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD_STADEF    0
 
 #define WNI_CFG_ASSOC_STA_LIMIT_STAMIN    1
-#define WNI_CFG_ASSOC_STA_LIMIT_STAMAX    10
+#define WNI_CFG_ASSOC_STA_LIMIT_STAMAX    32
 #define WNI_CFG_ASSOC_STA_LIMIT_STADEF    10
 
 #define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL_STAMIN    1
diff --git a/CORE/MAC/src/cfg/cfgUtil/cfg.txt b/CORE/MAC/src/cfg/cfgUtil/cfg.txt
index 5f37b8e..69a9604 100644
--- a/CORE/MAC/src/cfg/cfgUtil/cfg.txt
+++ b/CORE/MAC/src/cfg/cfgUtil/cfg.txt
@@ -4310,10 +4310,10 @@
 WNI_CFG_ASSOC_STA_LIMIT    I   4   8
 V    RW    NP
 LIM
-1    10    10
+1    32    10
 V    RW    NP
 LIM
-1    10    10
+1    32    10
 
 *
 *  SAP channel select start channel number
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index fe7d1de..d3d690b 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -94,6 +94,7 @@
    DOT11AC = 2,
    SLM_SESSIONIZATION = 3,
    DOT11AC_OPMODE = 4,
+   SAP32STA = 5,
    TDLS = 6,
    P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7,
    WLANACTIVE_OFFLOAD = 8,
diff --git a/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c b/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c
index a98e214..9a0af5f 100644
--- a/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c
+++ b/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c
@@ -829,6 +829,15 @@
     if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) {
         limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" ));
     }
+    if( (!WDI_getFwWlanFeatCaps(SAP32STA)) && (val >= WNI_CFG_ASSOC_STA_LIMIT_STAMAX))
+    {
+        if(ccmCfgSetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, WNI_CFG_ASSOC_STA_LIMIT_STADEF,
+            NULL, eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS)
+        {
+           limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); 
+        }
+        val = WNI_CFG_ASSOC_STA_LIMIT_STADEF;
+    }
     pMac->lim.gLimAssocStaLimit = (tANI_U16)val;
 
 #if defined WLAN_FEATURE_VOWIFI
diff --git a/CORE/SME/inc/smeInside.h b/CORE/SME/inc/smeInside.h
index 7e3dde6..e6f6b23 100644
--- a/CORE/SME/inc/smeInside.h
+++ b/CORE/SME/inc/smeInside.h
@@ -84,7 +84,7 @@
   Type declarations
   ------------------------------------------------------------------------*/
 
-#define SME_TOTAL_COMMAND  20
+#define SME_TOTAL_COMMAND  30
 
 
 typedef struct sGenericPmcCmd
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index c7aa883..2880096 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -226,7 +226,7 @@
 #define WLANTL_STA_BMU_THRESHOLD_MAX (256)
 
 #define WLANTL_AC_MASK (0x7)
-#define WLANTL_STAID_OFFSET (0x4)
+#define WLANTL_STAID_OFFSET (0x6)
 #endif
 
 /* UINT32 type endian swap */
@@ -7010,7 +7010,7 @@
       vos_pkt_get_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                                  (v_PVOID_t *)&STAMetaInfo );
       wRxMetaInfo.ucUP = (v_U8_t)(STAMetaInfo & WLANTL_AC_MASK);
-      ucDesSTAId = ((v_U8_t)STAMetaInfo) >> WLANTL_STAID_OFFSET; 
+      ucDesSTAId = (v_U8_t)((STAMetaInfo) >> WLANTL_STAID_OFFSET); 
        
       vosStatus = vos_pkt_extract_data( vosDataBuff, 0, (v_VOID_t *)pDestMacAddress, &usMacAddSize);
       if ( VOS_STATUS_SUCCESS != vosStatus )
@@ -7125,7 +7125,7 @@
    WLANTL_RxMetaInfoType    wRxMetaInfo;
    static v_U8_t            ucPMPDUHLen;
 #ifdef WLAN_SOFTAP_FEATURE
-   v_U8_t*                  STAMetaInfoPtr;
+   v_U32_t*                  STAMetaInfoPtr;
 #endif
 #ifdef ANI_CHIPSET_VOLANS
    v_U8_t                   ucEsf=0; /* first subframe of AMSDU flag */
@@ -7337,7 +7337,7 @@
 #ifdef WLAN_SOFTAP_FEATURE
     if( WLAN_STA_SOFTAP == pTLCb->atlSTAClients[ucSTAId].wSTADesc.wSTAType)
     {
-       STAMetaInfoPtr = (v_U8_t *)(ucTid | (WDA_GET_RX_ADDR3_IDX(aucBDHeader) << WLANTL_STAID_OFFSET));
+       STAMetaInfoPtr = (v_U32_t *)(ucTid | (WDA_GET_RX_ADDR3_IDX(aucBDHeader) << WLANTL_STAID_OFFSET));
        vos_pkt_set_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_TL,
                                  (v_PVOID_t)STAMetaInfoPtr);
     }
@@ -7883,7 +7883,7 @@
       }
 
       ucAC = message->bodyval &  WLANTL_AC_MASK;
-      ucSTAId = (v_U8_t)message->bodyval >> WLANTL_STAID_OFFSET;  
+      ucSTAId = (v_U8_t)(message->bodyval >> WLANTL_STAID_OFFSET);  
       pTLCb->atlSTAClients[ucSTAId].aucACMask[ucAC] = 1; 
 
       vos_atomic_set_U8( &pTLCb->atlSTAClients[ucSTAId].ucPktPending, 1);
diff --git a/CORE/WDA/inc/legacy/halTypes.h b/CORE/WDA/inc/legacy/halTypes.h
index 79c6972..e1b9b99 100644
--- a/CORE/WDA/inc/legacy/halTypes.h
+++ b/CORE/WDA/inc/legacy/halTypes.h
@@ -395,10 +395,10 @@
                         ((__x) < HAL_NUM_BSSID)
 
 #ifdef WLAN_SOFTAP_VSTA_FEATURE
-#define HAL_NUM_ASSOC_STA           10
-#define HAL_NUM_STA                 14
-#define HAL_NUM_HW_STA              8
-#define HAL_NUM_GPSTA               2
+#define HAL_NUM_ASSOC_STA           32
+#define HAL_NUM_STA                 38
+#define HAL_NUM_HW_STA              16
+#define HAL_NUM_GPSTA               4
 #define HAL_NUM_VSTA                (HAL_NUM_STA - HAL_NUM_HW_STA)
 
 #define QWLANFW_MAX_NUM_VSTA        HAL_NUM_VSTA
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 0c0ef42..526ba74 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -380,9 +380,11 @@
    /* Tx Complete Timeout timer */
    TX_TIMER TxCompleteTimer ;
 }tWdaTimers ;
-
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+#define WDA_MAX_STA    (38)
+#else
 #define WDA_MAX_STA    (16)
-
+#endif
 typedef struct
 {
    v_PVOID_t            pVosContext;             /* global VOSS context*/
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 0e148e5..c20f6e0 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -1423,6 +1423,22 @@
       
    tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct 
                             + sizeof(tHalCfg) + tlvStruct->length) ; 
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+   tlvStruct->type = QWLAN_HAL_CFG_MAX_ASSOC_LIMIT;
+   tlvStruct->length = sizeof(tANI_U32);
+   configDataValue = (tANI_U32 *)(tlvStruct + 1);
+   if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, configDataValue)
+                                                     != eSIR_SUCCESS)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                    "Failed to get value for WNI_CFG_ASSOC_STA_LIMIT");
+      goto handle_failure;
+   }
+      
+   tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct
+                            + sizeof(tHalCfg) + tlvStruct->length) ;
+#endif
+
    wdiStartParams->usConfigBufferLen = (tANI_U8 *)tlvStruct - tlvStructStart ;
 #ifdef WLAN_DEBUG
    {
@@ -10538,8 +10554,15 @@
    /* walk through all STA entries and find out TX packet count */ 
    for(curSta = 0 ; curSta < pWDA->wdaMaxSta ; curSta++)
    {
-      for(tid = 0 ; tid < STACFG_MAX_TC ; tid++)
-      {
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+        // We can only do BA on "hard" STAs.  
+         if (!(IS_HWSTA_IDX(curSta)))
+         {
+             continue;
+         }
+#endif //WLAN_SOFTAP_VSTA_FEATURE
+    for(tid = 0 ; tid < STACFG_MAX_TC ; tid++)
+    {
          WLANTL_STAStateType tlSTAState ;
          tANI_U32 txPktCount = 0 ;
          tANI_U8 validStaIndex = pWDA->wdaStaInfo[curSta].ucValidStaIndex ;
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index 3c5dc02..cd44994 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -108,7 +108,12 @@
 /*In prima 12 HW stations are supported including BCAST STA(staId 0)
  and SELF STA(staId 1) so total ASSOC stations which can connect to Prima
  SoftAP = 12 - 1(Self STa) - 1(Bcast Sta) = 10 Stations. */
+ 
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+#define WDI_MAX_SUPPORTED_STAS    38 
+#else
 #define WDI_MAX_SUPPORTED_STAS    12 
+#endif
 #define WDI_MAX_SUPPORTED_BSS     5 
 
 /* Control transport channel size*/
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index a4b6b04..da7ed5b 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -22259,6 +22259,15 @@
     return WDI_STATUS_E_NOT_ALLOWED;
   }
 
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+  if (IS_VSTA_IDX(uSTAIdx))
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+              "STA %d is a Virtual STA, "
+              "HW frame translation disabled", uSTAIdx);
+    return eWLAN_PAL_FALSE;
+  }
+#endif
 
   return gWDICb.bFrameTransEnabled;
 }/*WDI_IsHwFrameTxTranslationCapable*/
@@ -25416,7 +25425,6 @@
       gpFwWlanFeatCaps->featCaps[2],
       gpFwWlanFeatCaps->featCaps[3]
      );
-
    wdiFeatureCapsExchangeCb = (WDI_featureCapsExchangeCb) pWDICtx -> pfncRspCB; 
 
    /*Notify UMAC - there is no callback right now but can be used in future if reqd */
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi_dp.c b/CORE/WDI/CP/src/wlan_qct_wdi_dp.c
index 03a2d7f..65e222f 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi_dp.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi_dp.c
@@ -894,6 +894,14 @@
             WPAL_TRACE( WPT_WDI_CONTROL_MODULE, WPT_MSG_LEVEL_HIGH, "halDpu_GetSignature() failed for dpuId = %d\n", pBd->dpuDescIdx));
             return VOS_STATUS_E_FAILURE;
         } */
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+       // if this is a Virtual Station then change the DPU Routing Flag so
+       // that the frame will be routed to Firmware for queuing & transmit
+       if (IS_VSTA_IDX(ucStaId))
+       {
+           pBd->dpuRF = BMUWQ_FW_DPU_TX;
+       }
+#endif
 
     } 
     
diff --git a/CORE/WDI/DP/inc/wlan_qct_wdi_ds_i.h b/CORE/WDI/DP/inc/wlan_qct_wdi_ds_i.h
index 15f2f54..f37d54e 100644
--- a/CORE/WDI/DP/inc/wlan_qct_wdi_ds_i.h
+++ b/CORE/WDI/DP/inc/wlan_qct_wdi_ds_i.h
@@ -118,8 +118,11 @@
 /* !!! MAX NUM STA is not identified yet, 16 is correct value,
    but need to get from correct common def
    This should be identified ASAP */
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+#define WDI_DS_MAX_STA_ID 38
+#else
 #define WDI_DS_MAX_STA_ID 16
-
+#endif
 /* !!! MAX NUM SUPPORTED BSS is not identified yet, 2 is correct value,
     but need to get from correct common def
    This should be identified ASAP */
diff --git a/Kbuild b/Kbuild
index d4abeff..d27c40c 100644
--- a/Kbuild
+++ b/Kbuild
@@ -522,7 +522,8 @@
 		-DWLAN_FEATURE_P2P_DEBUG \
 		-DWLAN_ENABLE_AGEIE_ON_SCAN_RESULTS \
 		-DWLAN_ACTIVEMODE_OFFLOAD_FEATURE \
-        -DWLAN_FEATURE_HOLD_RX_WAKELOCK
+        	-DWLAN_FEATURE_HOLD_RX_WAKELOCK \
+		-DWLAN_SOFTAP_VSTA_FEATURE
 
 ifneq ($(CONFIG_PRONTO_WLAN),)
 CDEFINES += -DWCN_PRONTO
diff --git a/riva/inc/wlan_qct_dev_defs.h b/riva/inc/wlan_qct_dev_defs.h
index 9a6ea8f..51a1263 100644
--- a/riva/inc/wlan_qct_dev_defs.h
+++ b/riva/inc/wlan_qct_dev_defs.h
@@ -58,7 +58,50 @@
  */
 
 #ifdef WCN_PRONTO
+
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+#define HAL_NUM_ASSOC_STA           16
+#define HAL_NUM_STA                 18
+#define HAL_NUM_HW_STA              10
+#define HAL_NUM_GPSTA               2
+#define HAL_NUM_UMA_DESC_ENTRIES    HAL_NUM_HW_STA // or HAL_NUM_STA
+
 #ifdef WCN_PRONTO_V1
+#define HAL_NUM_BSSID               2
+#define HAL_NUM_STA_WITHOUT_VSTA    9
+#else /* WCN_PRONTO_V1 */
+#define HAL_NUM_BSSID               4
+#define HAL_NUM_STA_WITHOUT_VSTA    14
+#endif
+
+
+#define HAL_NUM_VSTA                (HAL_NUM_STA - HAL_NUM_HW_STA)
+#define QWLANFW_MAX_NUM_VSTA        (HAL_NUM_VSTA)
+#define QWLANFW_VSTA_INVALID_IDX    (HAL_NUM_STA+1)
+#define QWLAN_VSTA_MIN_IDX          (HAL_NUM_HW_STA)
+#define QWLANFW_NUM_GPSTA           (HAL_NUM_GPSTA)
+
+
+#define IS_VSTA_VALID_IDX(__x) \
+                          ((__x) != QWLANFW_VSTA_INVALID_IDX)
+
+#define IS_VSTA_IDX(__x) \
+                   (((__x) >= QWLAN_VSTA_MIN_IDX) && ((__x) < HAL_NUM_STA))
+
+#define GET_VSTA_INDEX_FOR_STA_INDEX(__idx)    ((__idx) - QWLAN_VSTA_MIN_IDX)
+
+// is the STA a General Purpose STA?
+#define IS_GPSTA_IDX(__x) \
+    (((__x) >= (HAL_NUM_HW_STA-HAL_NUM_GPSTA)) && \
+     ((__x) < HAL_NUM_HW_STA))
+
+// is the STA a HW STA (excluding GP STAs)
+#define IS_HWSTA_IDX(__x) \
+    ((__x) < (HAL_NUM_HW_STA-HAL_NUM_GPSTA))
+
+#define HAL_NUM_STA_INCLUDING_VSTA  32
+
+#elif WCN_PRONTO_V1
 
 /* In Pronto 1.0 TPE descriptor size is increased to 1K per station
  * but not the cMEM allocated for hardware descriptors. Due to this
@@ -73,29 +116,83 @@
  * and SELF STA(staId 1). So total ASSOC stations which can connect to
  * Pronto 1.0 Softap = 9 - 1(self sta) - 1(Bcast sta) = 7 stations
  */
-#define HAL_NUM_STA                 9
+#define HAL_NUM_HW_STA              9
+#define HAL_NUM_STA                 (HAL_NUM_HW_STA)
 #define HAL_NUM_BSSID               2
 #define HAL_NUM_UMA_DESC_ENTRIES    9
+#define HAL_NUM_ASSOC_STA           7
+
 
 #else /* WCN_PRONTO_V1 */
 
-#define HAL_NUM_STA                 14
+#define HAL_NUM_HW_STA              14
+#define HAL_NUM_STA                 (HAL_NUM_HW_STA)
 #define HAL_NUM_BSSID               4
 #define HAL_NUM_UMA_DESC_ENTRIES    14
+#define HAL_NUM_ASSOC_STA           12
 
-#endif /* WCN_PRONTO_V1 */
+
+#endif /* WCN_PRONTO_V1 and WLAN_SOFTAP_VSTA_FEATURE*/
 #else  /* WCN_PRONTO */
 
-/*In prima 12 HW stations are supported including BCAST STA(staId 0)
- and SELF STA(staId 1) so total ASSOC stations which can connect to Prima
- SoftAP = 12 - 1(Self STa) - 1(Bcast Sta) = 10 Stations. */
+/*
+ * Riva supports 16 stations in hardware
+ *
+ * Riva without Virtual STA feature can only support 12 stations:
+ *    1 Broadcast STA (hard)
+ *    1 "Self" STA (hard)
+ *    10 Soft AP Stations (hard)
+ *
+ * Riva with Virtual STA feature supports 38 stations:
+ *    1 Broadcast STA (hard)
+ *    1 "Self" STA (hard)
+ *    4 General Purpose Stations to support Virtual STAs (hard)
+ *   32 Soft AP Stations (10 hard/22 virtual)
+ */
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+#define HAL_NUM_ASSOC_STA           32
+#define HAL_NUM_STA                 38
+#define HAL_NUM_HW_STA              16
+#define HAL_NUM_GPSTA               4
+#define HAL_NUM_VSTA                (HAL_NUM_STA - HAL_NUM_HW_STA)
+
+#define QWLANFW_MAX_NUM_VSTA        HAL_NUM_VSTA
+#define QWLANFW_VSTA_INVALID_IDX    (HAL_NUM_STA+1)
+#define QWLAN_VSTA_MIN_IDX          HAL_NUM_HW_STA
+#define QWLANFW_NUM_GPSTA           HAL_NUM_GPSTA
+
+
+#define IS_VSTA_VALID_IDX(__x) \
+                          ((__x) != QWLANFW_VSTA_INVALID_IDX)
+
+#define IS_VSTA_IDX(__x) \
+                   (((__x) >= QWLAN_VSTA_MIN_IDX) && ((__x) < HAL_NUM_STA))
+
+#define GET_VSTA_INDEX_FOR_STA_INDEX(__idx)    ((__idx) - QWLAN_VSTA_MIN_IDX)
+
+// is the STA a General Purpose STA?
+#define IS_GPSTA_IDX(__x) \
+    (((__x) >= (HAL_NUM_HW_STA-HAL_NUM_GPSTA)) && \
+     ((__x) < HAL_NUM_HW_STA))
+
+// is the STA a HW STA (excluding GP STAs)
+#define IS_HWSTA_IDX(__x) \
+    ((__x) < (HAL_NUM_HW_STA-HAL_NUM_GPSTA))
+
+#define HAL_NUM_STA_INCLUDING_VSTA  32
+#define HAL_NUM_STA_WITHOUT_VSTA    12
+
+#else
 #define HAL_NUM_STA                 12
+#define HAL_NUM_ASSOC_STA           10
+#define HAL_NUM_HW_STA              12
+#endif
+
 #define HAL_NUM_BSSID               2
-#define HAL_NUM_UMA_DESC_ENTRIES    12
+#define HAL_NUM_UMA_DESC_ENTRIES    HAL_NUM_HW_STA
 
 #endif /* WCN_PRONTO */
 
-
 #define HAL_INVALID_BSSIDX          HAL_NUM_BSSID
 
 #define MAX_NUM_OF_BACKOFFS         8