wlan: Enable or disable aggregation dynamically

Add vendor command to enable or disable aggregation
at runtime.

CRs-Fixed: 2002690
Change-Id: I2e17a4dcd5109ee42da9ae5b3605be49c96a6f48
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index c8cca4b..9c53553 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -176,6 +176,7 @@
 #define  WE_SET_PROXIMITY_ENABLE  24
 #define  WE_CAP_TSF    25
 #define  WE_SET_MODULATED_DTIM    26
+#define WLAN_SET_DYNNAMIC_AGGREGATION 27
 
 /* Private ioctls and their sub-ioctls */
 #define WLAN_PRIV_SET_NONE_GET_INT    (SIOCIWFIRSTPRIV + 1)
@@ -390,6 +391,9 @@
 #define TX_PWR_MAX 22
 #define TX_PWR_DEF 50
 
+/* Dynamic Aggregation */
+#define DISABLE_AGGREGATION 0
+#define ENABLE_AGGREGATION 1
 /*
  * When supplicant sends SETBAND ioctl it queries for channels from
  * cfg80211 layer by sending itself EVENT_CHANNEL_LIST_CHANGED command.
@@ -5648,6 +5652,42 @@
 
     return eHAL_STATUS_SUCCESS;
 }
+
+static int hdd_set_dynamic_aggregation(int value, hdd_adapter_t *adapter)
+{
+    int ret = 0;
+    tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
+    tDelBaParams del_session;
+
+    del_session.session_id = adapter->sessionId;
+    hddLog(LOG1, FL("WLAN_SET_DYNNAMIC_AGGREGATION: %d"), value);
+
+    if ((value == DISABLE_AGGREGATION) || (value == ENABLE_AGGREGATION))
+    {
+        ret = ccmCfgSetInt(hal, WNI_CFG_ENABLE_TX_RX_AGGREGATION,
+                          value,NULL, eANI_BOOLEAN_FALSE);
+        if (ret != eHAL_STATUS_SUCCESS)
+        {
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                      FL("failed to set ini parameter, WNI_CFG_ENABLE_TX_RX_AGGREGATION"));
+            return -EIO;
+        }
+
+    } else {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("Invalid command input"));
+        return -EINVAL;
+    }
+    ret = sme_del_sta_ba_session_req(hal, del_session);
+    if (ret != VOS_STATUS_SUCCESS) {
+        hddLog(VOS_TRACE_LEVEL_ERROR, FL("send ba session req fail"));
+        return -EINVAL;
+    }
+
+     EXIT();
+     return ret;
+}
+
 /* set param sub-ioctls */
 static int __iw_setint_getnone(struct net_device *dev,
                                struct iw_request_info *info,
@@ -6356,6 +6396,13 @@
                 ret = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->
                           enableModulatedDTIM = set_value;
             }
+        }
+        case WLAN_SET_DYNNAMIC_AGGREGATION:
+        {
+            if (NULL == hHal)
+                return -EINVAL;
+
+            ret = hdd_set_dynamic_aggregation(set_value, pAdapter);
             break;
         }
         default:
@@ -10988,7 +11035,6 @@
 }
 #endif
 
-
 // Define the Wireless Extensions to the Linux Network Device structure
 // A number of these routines are NULL (meaning they are not implemented.)
 
@@ -11236,6 +11282,11 @@
     {   WE_SET_MODULATED_DTIM,
         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
         0, "setModDTIM" },
+    {
+        WLAN_SET_DYNNAMIC_AGGREGATION,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+        0, "setAggregation" },
+
     /* handlers for main ioctl */
     {   WLAN_PRIV_SET_NONE_GET_INT,
         0,
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 3f8edad..df39309 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -6364,4 +6364,11 @@
 };
 #endif
 
+/**
+ * struct tDelBaParams - Del BA Session req
+ * @session_id: adapter session id
+ */
+typedef struct {
+    tANI_U8 session_id;
+}tDelBaParams,*ptDelBaParams;
 #endif /* __SIR_API_H */
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index 6ed2bb0..6445286 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -395,6 +395,7 @@
     eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP,
 #endif
 
+    eWNI_SME_DEL_BA_SES_REQ,
     eWNI_SME_MSG_TYPES_END
 };
 
diff --git a/CORE/MAC/inc/wniCfg.h b/CORE/MAC/inc/wniCfg.h
index 3a62078..f0e6aac 100644
--- a/CORE/MAC/inc/wniCfg.h
+++ b/CORE/MAC/inc/wniCfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -395,7 +395,8 @@
      WNI_CFG_ENABLE_UNITS_BWAIT,
      WNI_CFG_ENABLE_CONC_BMISS,
      WNI_CFG_BTC_DISABLE_WLAN_LINK_CRITICAL,
-     WNI_CFG_DISABLE_SCAN_DURING_SCO
+     WNI_CFG_DISABLE_SCAN_DURING_SCO,
+     WNI_CFG_ENABLE_TX_RX_AGGREGATION
 };
 
 /*
@@ -1936,9 +1937,12 @@
 #define WNI_CFG_DISABLE_SCAN_DURING_SCO_MAX   1
 #define WNI_CFG_DISABLE_SCAN_DURING_SCO_DEF   0
 
+#define WNI_CFG_ENABLE_TX_RX_AGGREGATION_MIN  0
+#define WNI_CFG_ENABLE_TX_RX_AGGREGATION_MAX  1
+#define WNI_CFG_ENABLE_TX_RX_AGGREGATION_DEF  1
 
-#define CFG_PARAM_MAX_NUM        362
-#define CFG_STA_IBUF_MAX_SIZE    296
+#define CFG_PARAM_MAX_NUM        363
+#define CFG_STA_IBUF_MAX_SIZE    297
 #define CFG_STA_SBUF_MAX_SIZE    3389
 
 #define CFG_STA_MAGIC_DWORD    0xbeefbeef
diff --git a/CORE/MAC/src/cfg/cfgProcMsg.c b/CORE/MAC/src/cfg/cfgProcMsg.c
index afc19e2..a6ae4c2 100644
--- a/CORE/MAC/src/cfg/cfgProcMsg.c
+++ b/CORE/MAC/src/cfg/cfgProcMsg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1723,7 +1723,11 @@
      WNI_CFG_ENABLE_UNITS_BWAIT_STAMIN,
      WNI_CFG_ENABLE_UNITS_BWAIT_STAMAX,
      WNI_CFG_ENABLE_UNITS_BWAIT_STADEF},
-
+    {WNI_CFG_ENABLE_TX_RX_AGGREGATION,
+     CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
+     WNI_CFG_ENABLE_TX_RX_AGGREGATION_MIN,
+     WNI_CFG_ENABLE_TX_RX_AGGREGATION_MAX,
+     WNI_CFG_ENABLE_TX_RX_AGGREGATION_DEF},
 };
 
 tAniSirCfgStaticString cfgStaticString[CFG_MAX_STATIC_STRING] =
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index 24a0fa4..ddac0e6 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -2799,3 +2799,49 @@
 
     return eSIR_SUCCESS;
 }
+
+/**
+ * lim_process_sme_del_ba_ses_req()- process del ba req
+ * @pMac:Mac ctx
+ * @pMsgBuf: message buffer from sme
+ * Returns success on taking action based on cfg value, otherwise failure
+ */
+tSirRetStatus lim_process_sme_del_ba_ses_req(tpAniSirGlobal pMac,
+                                          tANI_U32 *pMsgBuf)
+{
+    tDelBaParams *pMsg = NULL;
+    tpPESession psessionEntry = NULL;
+    int val;
+
+    pMsg = (tDelBaParams*)pMsgBuf;
+    if (pMsg == NULL) {
+        limLog(pMac, LOGE, FL("NULL pMsg"));
+        return eSIR_FAILURE;
+    }
+
+    psessionEntry = peFindSessionBySessionId(pMac, pMsg->session_id);
+    if (NULL == psessionEntry)
+    {
+        limLog(pMac, LOGE, FL("NULL psessionEntry"));
+        return eSIR_FAILURE;
+    }
+
+    if (wlan_cfgGetInt
+       (pMac, WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val) !=
+              eSIR_SUCCESS)
+    {
+        limLog(pMac, LOGE,
+               FL( "Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION"));
+        return eSIR_FAILURE;
+    }
+
+    if (!val)
+    {
+        limLog(pMac, LOGW,
+               FL("user requested to disable all RX BA sessions"));
+        limDeleteBASessions(pMac, psessionEntry, BA_BOTH_DIRECTIONS,
+                             eSIR_MAC_PEER_TIMEDOUT_REASON);
+    }
+
+    return eSIR_SUCCESS;
+}
diff --git a/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
index 8b402d1..37c8457 100644
--- a/CORE/MAC/src/pe/lim/limProcessActionFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
@@ -1270,7 +1270,7 @@
     tpDphHashNode pSta;
     tSirMacStatusCodes status = eSIR_MAC_SUCCESS_STATUS;
     tANI_U16 aid;
-    tANI_U32 frameLen, nStatus,val;
+    tANI_U32 frameLen, nStatus,val, val1;
     tANI_U8 *pBody;
     tANI_U8 delBAFlag =0;
 
@@ -1278,6 +1278,7 @@
     pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo );
     frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo );
     val = 0;
+    val1 = 0;
 
     // Unpack the received frame
     nStatus = dot11fUnpackAddBAReq( pMac, pBody, frameLen, &frmAddBAReq );
@@ -1339,6 +1340,20 @@
     }
 #endif //WLAN_SOFTAP_VSTA_FEATURE
 
+    if (wlan_cfgGetInt(pMac, WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val1) !=
+                    eSIR_SUCCESS)
+    {
+        limLog(pMac, LOGE,
+               FL("Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION"));
+        val1 = 1;
+    }
+    if (!val1)
+    {
+        limLog(pMac, LOGE,
+               FL("aggregation disabled - ignoring ADDBA"));
+        goto returnAfterError;
+    }
+
     if (wlan_cfgGetInt(pMac, WNI_CFG_DEL_ALL_RX_TX_BA_SESSIONS_2_4_G_BTC, &val) !=
                     eSIR_SUCCESS)
     {
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 15d6c64..835a6e6 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -2534,6 +2534,11 @@
         vos_mem_free((v_VOID_t*)limMsg->bodyptr);
         limMsg->bodyptr = NULL;
         break;
+    case eWNI_SME_DEL_BA_SES_REQ:
+        lim_process_sme_del_ba_ses_req(pMac, limMsg->bodyptr);
+        vos_mem_free((v_VOID_t*)limMsg->bodyptr);
+        limMsg->bodyptr = NULL;
+        break;
     default:
         vos_mem_free((v_VOID_t*)limMsg->bodyptr);
         limMsg->bodyptr = NULL;
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index feaf1ed..6a8fb8d 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.h
@@ -1078,5 +1078,9 @@
 
 tSirRetStatus lim_process_sme_get_tsf_req(tpAniSirGlobal pMac,
                                           tANI_U32 *pMsgBuf);
+
+tSirRetStatus lim_process_sme_del_ba_ses_req(tpAniSirGlobal pMac,
+                                             tANI_U32 *pMsgBuf);
+
 #endif /* __LIM_TYPES_H */
 
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 0e78c84..5817358 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4028,4 +4028,6 @@
                                psetArpStatsParams pSetStatsParam);
 eHalStatus sme_get_nud_debug_stats(tHalHandle hHal,
                                pgetArpStatsParams pGetStatsParam);
+eHalStatus sme_del_sta_ba_session_req(tHalHandle hHal,
+                                      tDelBaParams sta_del_params);
 #endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/inc/sme_Trace.h b/CORE/SME/inc/sme_Trace.h
index d5a4ba0..77ff1d6 100644
--- a/CORE/SME/inc/sme_Trace.h
+++ b/CORE/SME/inc/sme_Trace.h
@@ -148,6 +148,7 @@
     TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE,
     TRACE_CODE_SME_TX_HDD_CAP_TSF_REQ,
     TRACE_CODE_SME_TX_HDD_GET_TSF_REQ,
+    TRACE_CODE_SME_DEL_STA_BA_SESSION_REQ,
     /* New trace commands to be added before this comment not at the end */
     /* Trace codes for SME commands */
     TRACE_CODE_SME_COMMAND = 250,
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 0dd99ae..6014a6f 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -15066,6 +15066,57 @@
     return(status);
 }
 
+eHalStatus sme_del_sta_ba_session_req(tHalHandle hHal,
+                                      tDelBaParams sta_del_params)
+{
+    eHalStatus          status    = eHAL_STATUS_SUCCESS;
+    tpAniSirGlobal      pMac      = PMAC_STRUCT(hHal);
+    vos_msg_t           vosMessage;
+    ptDelBaParams del_params = NULL;
+    VOS_STATUS vos_status;
+    tCsrRoamSession *pSession;
+
+    MTRACE(vos_trace(VOS_MODULE_ID_SME,
+                     TRACE_CODE_SME_DEL_STA_BA_SESSION_REQ, NO_SESSION, 0));
+    if (eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock(&pMac->sme)))
+    {
+        pSession = CSR_GET_SESSION(pMac, sta_del_params.session_id);
+        if (!pSession)
+        {
+            smsLog(pMac, LOGE, FL("session not found"));
+            sme_ReleaseGlobalLock( &pMac->sme );
+            return eHAL_STATUS_FAILURE;
+        }
+
+        del_params = (ptDelBaParams) vos_mem_malloc(sizeof(*del_params));
+
+        if (NULL == del_params)
+        {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                     "%s: Not able to allocate memory for sme_del_sta_ba_session_req", __func__);
+           sme_ReleaseGlobalLock( &pMac->sme );
+           return eHAL_STATUS_FAILURE;
+        }
+        vos_mem_copy(&del_params->session_id, &pSession->sessionId,
+                     sizeof(del_params->session_id));
+
+        vosMessage.bodyptr = del_params;
+        vosMessage.type    = eWNI_SME_DEL_BA_SES_REQ;
+
+        vos_status = vos_mq_post_message(VOS_MQ_ID_PE, &vosMessage);
+
+        if (!VOS_IS_STATUS_SUCCESS(vos_status))
+        {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                     "%s: Post Set TM Level MSG fail", __func__);
+           vos_mem_free(del_params);
+           status = eHAL_STATUS_FAILURE;
+        }
+        sme_ReleaseGlobalLock( &pMac->sme );
+    }
+    return(status);
+}
+
 /**
  * sme_get_tsf_req() - send tsf get request to firmware
  * @hHal: hal handle.
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 332051f..a7ea56f 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -19051,7 +19051,7 @@
    tANI_U8 size = 0 ;
    tANI_U8 baCandidateCount = 0 ;
    tANI_U8 newBaCandidate = 0 ;
-   tANI_U32 val;
+   tANI_U32 val, val1;
    WDI_TriggerBAReqCandidateType baCandidate[WDA_MAX_STA] = {{0}} ;
    tpAniSirGlobal pMac;
 
@@ -19093,6 +19093,14 @@
       val = 0;
    }
 
+   if (wlan_cfgGetInt(pMac,
+           WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val1) !=
+                                                      eSIR_SUCCESS)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+            "Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION");
+      val1 = 1;
+   }
    /* walk through all STA entries and find out TX packet count */ 
    for(curSta = 0 ; curSta < pWDA->wdaMaxSta ; curSta++)
    {
@@ -19127,6 +19135,12 @@
                         "%s: BTC disabled aggregation - dont start "
                          "TX ADDBA req",__func__);
             }
+            else if (!val1)
+            {
+                 VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                        "%s: aggregation disabled- dont start "
+                         "TX ADDBA req",__func__);
+            }
             else if(!WDA_GET_BA_TXFLAG(pWDA, curSta, tid)
                    && (WLANTL_STA_AUTHENTICATED == tlSTAState)
                    && WDA_AllowAddBA(pMac, curSta, tid)