wlan: Host driver changes to support batch scan

Host driver changes to support batch scan feature
CRs-fixed: 543172
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 09cabf4..cde55bf 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -209,6 +209,22 @@
 #define HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME 3
 typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN];
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+#define HDD_BATCH_SCAN_VERSION (17)
+#define HDD_SET_BATCH_SCAN_DEFAULT_FREQ (30)/*batch scan frequency default 30s*/
+#define HDD_SET_BATCH_SCAN_BEST_NETWORK (16)/*best network default value*/
+#define HDD_SET_BATCH_SCAN_DEFAULT_BAND (0)/*auto means both 2.4GHz and 5GHz*/
+#define HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY (1)/*only 2.4GHz band*/
+#define HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY (2)/*only 5GHz band*/
+#define HDD_SET_BATCH_SCAN_REQ_TIME_OUT (15000) /*Batch scan req timeout in ms*/
+#define HDD_GET_BATCH_SCAN_RSP_TIME_OUT (15000) /*Batch scan req timeout in ms*/
+#define HDD_BATCH_SCAN_AP_META_INFO_SIZE (150) /*AP meta info size in string*/
+
+#define MIN(a, b) (a > b ? b : a)
+
+#endif
+
+
 typedef struct hdd_tx_rx_stats_s
 {
    // start_xmit stats
@@ -707,6 +723,38 @@
 } t_multicast_add_list;
 #endif
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+
+/*Batch scan repsonse AP info*/
+typedef struct
+{
+    /*Batch ID*/
+    tANI_U32 batchId;
+    /*is it last AP in GET BATCH SCAN RSP*/
+    v_BOOL_t isLastAp;
+    /*BSSID*/
+    tANI_U8  bssid[SIR_MAC_ADDR_LEN];
+    /*SSID*/
+    tANI_U8  ssid[SIR_MAX_SSID_SIZE];
+    /*Channel*/
+    tANI_U8  ch;
+    /*RSSI or Level*/
+    tANI_U8  rssi;
+    /*Age*/
+    tANI_U32 age;
+}tHDDbatchScanRspApInfo;
+
+/*Batch scan response list*/
+struct tHDDBatchScanRspList
+{
+    tHDDbatchScanRspApInfo ApInfo;
+    struct tHDDBatchScanRspList *pNext;
+};
+
+typedef struct tHDDBatchScanRspList tHddBatchScanRsp;
+#endif
+
+
 #define WLAN_HDD_ADAPTER_MAGIC 0x574c414e //ASCII "WLAN"
 struct hdd_adapter_s
 {
@@ -843,6 +891,38 @@
    v_U32_t magic;
    v_BOOL_t higherDtimTransition;
    v_BOOL_t survey_idx;
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+   /*Completion variable for set batch scan request*/
+   struct completion hdd_set_batch_scan_req_var;
+   /*Completion variable for get batch scan request*/
+   struct completion hdd_get_batch_scan_req_var;
+   /*HDD batch scan lock*/
+   struct mutex hdd_batch_scan_lock;
+   /*HDD set batch scan request*/
+   tSirSetBatchScanReq  hddSetBatchScanReq;
+   /*HDD set batch scan response*/
+   tSirSetBatchScanRsp  hddSetBatchScanRsp;
+   /*HDD stop batch scan indication*/
+   tSirStopBatchScanInd hddStopBatchScanInd;
+   /*HDD get batch scan request*/
+   tSirTriggerBatchScanResultInd  hddTriggerBatchScanResultInd;
+   /*Batched scan reponse queue: new batch scan results added at the tail
+    and old batch scan results are deleted from head*/
+   tHddBatchScanRsp *pBatchScanRsp;
+   /*No of scans in batch scan rsp(MSCAN)*/
+   v_U32_t numScanList;
+   /*isTruncated = 1 batch scan rsp is truncated
+     isTruncated = 0 batch scan rsp is complete*/
+   v_BOOL_t isTruncated;
+   /*Wait for get batch scan response from FW or not*/
+   volatile v_BOOL_t hdd_wait_for_get_batch_scan_rsp;
+   /*Wait for set batch scan response from FW or not*/
+   volatile v_BOOL_t hdd_wait_for_set_batch_scan_rsp;
+   /*Previous batch scan ID*/
+   v_U32_t prev_batch_id;
+#endif
+
 };
 
 #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index edef39e..6cee911 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -551,6 +551,942 @@
 
 }
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
+                                               input string
+
+  This function extracts assigned integer from string in below format:
+  "STRING=10" : extracts integer 10 from this string
+
+  \param  - pInPtr Pointer to input string
+  \param  - base  Base for string to int conversion(10 for decimal 16 for hex)
+  \param  - pOutPtr Pointer to variable in which extracted integer needs to be
+            assigned
+  \param  - pLastArg to tell whether it is last arguement in input string or
+            not
+
+  \return - NULL for failure cases
+            pointer to next arguement in input string for success cases
+  --------------------------------------------------------------------------*/
+static tANI_U8 *
+hdd_extract_assigned_int_from_str
+(
+    tANI_U8 *pInPtr,
+    tANI_U8 base,
+    tANI_U32 *pOutPtr,
+    tANI_U8 *pLastArg
+)
+{
+    int tempInt;
+    int v = 0;
+    char buf[32];
+    int val = 0;
+    *pLastArg = FALSE;
+
+    pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
+    if (NULL == pInPtr)
+    {
+        return NULL;
+    }
+
+    pInPtr++;
+
+    while ((SPACE_ASCII_VALUE  == *pInPtr) && ('\0' !=  *pInPtr)) pInPtr++;
+
+    val = sscanf(pInPtr, "%32s ", buf);
+    if (val < 0 && val > strlen(pInPtr))
+    {
+        return NULL;
+    }
+    pInPtr += val;
+    v = kstrtos32(buf, base, &tempInt);
+    if (v < 0)
+    {
+        return NULL;
+    }
+    *pOutPtr = tempInt;
+
+    pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
+    if (NULL == pInPtr)
+    {
+        *pLastArg = TRUE;
+        return NULL;
+    }
+    while ((SPACE_ASCII_VALUE  == *pInPtr) && ('\0' !=  *pInPtr)) pInPtr++;
+
+    return pInPtr;
+}
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
+                                                input string
+
+  This function extracts assigned character from string in below format:
+  "STRING=A" : extracts char 'A' from this string
+
+  \param  - pInPtr Pointer to input string
+  \param  - pOutPtr Pointer to variable in which extracted char needs to be
+            assigned
+  \param  - pLastArg to tell whether it is last arguement in input string or
+            not
+
+  \return - NULL for failure cases
+            pointer to next arguement in input string for success cases
+  --------------------------------------------------------------------------*/
+static tANI_U8 *
+hdd_extract_assigned_char_from_str
+(
+    tANI_U8 *pInPtr,
+    tANI_U8 *pOutPtr,
+    tANI_U8 *pLastArg
+)
+{
+    *pLastArg = FALSE;
+
+    pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
+    if (NULL == pInPtr)
+    {
+        return NULL;
+    }
+
+    pInPtr++;
+
+    while ((SPACE_ASCII_VALUE  == *pInPtr) && ('\0' !=  *pInPtr)) pInPtr++;
+
+    *pOutPtr = *pInPtr;
+
+    pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
+    if (NULL == pInPtr)
+    {
+        *pLastArg = TRUE;
+        return NULL;
+    }
+    while ((SPACE_ASCII_VALUE  == *pInPtr) && ('\0' !=  *pInPtr)) pInPtr++;
+
+    return pInPtr;
+}
+
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
+
+  This function parses set batch scan command in below format:
+  WLS_BATCHING_SET <space> followed by below arguements
+  "SCANFREQ=XX"   : Optional defaults to 30 sec
+  "MSCAN=XX"      : Required number of scans to attempt to batch
+  "BESTN=XX"      : Best Network (RSSI) defaults to 16
+  "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
+                    A. implies  only 5 GHz , B. implies only 2.4GHz
+  "RTT=X"         : optional defaults to 0
+  returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
+  error
+
+  For example input commands:
+  1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
+     translated into set batch scan with following parameters:
+     a) Frequence 60 seconds
+     b) Batch 10 scans together
+     c) Best RSSI to be 20
+     d) 5GHz band only
+     e) RTT is equal to 0
+
+  \param  - pValue Pointer to input channel list
+  \param  - pHddSetBatchScanReq Pointer to HDD batch scan request structure
+
+  \return - 0 for success non-zero for failure
+
+  --------------------------------------------------------------------------*/
+static int
+hdd_parse_set_batchscan_command
+(
+    tANI_U8 *pValue,
+    tSirSetBatchScanReq *pHddSetBatchScanReq
+)
+{
+    tANI_U8 *inPtr = pValue;
+    tANI_U8 val = 0;
+    tANI_U8 lastArg = 0;
+
+    /*initialize default values*/
+    pHddSetBatchScanReq->scanFrequency = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
+    pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
+    pHddSetBatchScanReq->rtt = 0;
+    pHddSetBatchScanReq->bestNetwork = HDD_SET_BATCH_SCAN_BEST_NETWORK;
+
+    /*go to space after WLS_BATCHING_SET command*/
+    inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
+    /*no argument after the command*/
+    if (NULL == inPtr)
+    {
+        return -EINVAL;
+    }
+
+    /*no space after the command*/
+    else if (SPACE_ASCII_VALUE != *inPtr)
+    {
+        return -EINVAL;
+    }
+
+    /*removing empty spaces*/
+    while ((SPACE_ASCII_VALUE  == *inPtr) && ('\0' !=  *inPtr)) inPtr++;
+
+    /*no argument followed by spaces*/
+    if ('\0' == *inPtr)
+    {
+        return -EINVAL;
+    }
+
+    /*check and parse SCANFREQ*/
+    if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
+    {
+        inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
+                    &pHddSetBatchScanReq->scanFrequency, &lastArg);
+        if ( (NULL == inPtr) || (TRUE == lastArg))
+        {
+            return -EINVAL;
+        }
+    }
+
+    /*check and parse MSCAN*/
+    if ((strncmp(inPtr, "MSCAN", 5) == 0))
+    {
+        inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
+                    &pHddSetBatchScanReq->numberOfScansToBatch, &lastArg);
+        if (TRUE == lastArg)
+        {
+            goto done;
+        }
+        else if (NULL == inPtr)
+        {
+            return -EINVAL;
+        }
+    }
+    else
+    {
+        return -EINVAL;
+    }
+
+    /*check and parse BESTN*/
+    if ((strncmp(inPtr, "BESTN", 5) == 0))
+    {
+        inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
+                    &pHddSetBatchScanReq->bestNetwork, &lastArg);
+        if (TRUE == lastArg)
+        {
+            goto done;
+        }
+        else if (NULL == inPtr)
+        {
+            return -EINVAL;
+        }
+    }
+
+    /*check and parse CHANNEL*/
+    if ((strncmp(inPtr, "CHANNEL", 7) == 0))
+    {
+        inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
+        if (TRUE == lastArg)
+        {
+            goto done;
+        }
+        else if (NULL == inPtr)
+        {
+            return -EINVAL;
+        }
+        if (('A' == val) || ('a' == val))
+        {
+            pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
+        }
+        else if (('B' == val) || ('b' == val))
+        {
+            pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
+        }
+        else
+        {
+            return -EINVAL;
+        }
+    }
+
+    /*check and parse RTT*/
+    if ((strncmp(inPtr, "RTT", 3) == 0))
+    {
+        inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
+                    &pHddSetBatchScanReq->rtt, &lastArg);
+        if (TRUE == lastArg)
+        {
+            goto done;
+        }
+        if (NULL == inPtr)
+        {
+            return -EINVAL;
+        }
+    }
+
+
+done:
+
+    VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+      "Received WLS_BATCHING_SET with SCANFREQ=%d "
+      "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
+      pHddSetBatchScanReq->scanFrequency,
+      pHddSetBatchScanReq->numberOfScansToBatch,
+      pHddSetBatchScanReq->bestNetwork,
+      pHddSetBatchScanReq->rfBand,
+      pHddSetBatchScanReq->rtt);
+
+    return 0;
+}/*End of hdd_parse_set_batchscan_command*/
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_set_batch_scan_req_callback () - This function is called after
+     receiving set batch scan response from FW and it saves set batch scan
+     response data FW to HDD context and sets the completion event on
+     which hdd_ioctl is waiting
+
+  \param  - callbackContext Pointer to HDD adapter
+  \param  - pRsp Pointer to set batch scan response data received from FW
+
+  \return - nothing
+
+  --------------------------------------------------------------------------*/
+static void hdd_set_batch_scan_req_callback
+(
+    void *callbackContext,
+    tSirSetBatchScanRsp *pRsp
+)
+{
+    hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
+    tSirSetBatchScanRsp *pHddSetBatchScanRsp;
+
+    /*sanity check*/
+    if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Invalid pAdapter magic", __func__);
+        VOS_ASSERT(0);
+        return;
+    }
+    pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
+
+    /*save set batch scan response*/
+    pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
+
+    VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+      "Received set batch scan rsp from FW with nScansToBatch=%d",
+      pHddSetBatchScanRsp->nScansToBatch);
+
+    pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
+    complete(&pAdapter->hdd_set_batch_scan_req_var);
+
+    return;
+}/*End of hdd_set_batch_scan_req_callback*/
+
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
+     info in hdd batch scan response queue
+
+  \param  - pAdapter Pointer to hdd adapter
+  \param  - pAPMetaInfo Pointer to access point meta info
+  \param  - scanId scan ID of batch scan response
+  \param  - isLastAp tells whether AP is last AP in batch scan response or not
+
+  \return - nothing
+
+  --------------------------------------------------------------------------*/
+static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
+      tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
+{
+    tHddBatchScanRsp *pHead;
+    tHddBatchScanRsp *pNode;
+    tHddBatchScanRsp *pPrev;
+    tHddBatchScanRsp *pTemp;
+    tANI_U8 ssidLen;
+
+    /*head of hdd batch scan response queue*/
+    pHead = pAdapter->pBatchScanRsp;
+
+    pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
+    if (NULL == pNode)
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Could not allocate memory", __func__);
+        VOS_ASSERT(0);
+        return;
+    }
+
+    vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
+        sizeof(pNode->ApInfo.bssid));
+    ssidLen = strlen(pApMetaInfo->ssid);
+    if (SIR_MAX_SSID_SIZE < ssidLen)
+    {
+       /*invalid scan result*/
+       vos_mem_free(pNode);
+       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+          "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
+       return;
+    }
+    vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
+    /*null terminate ssid*/
+    pNode->ApInfo.ssid[ssidLen] = '\0';
+    pNode->ApInfo.ch = pApMetaInfo->ch;
+    pNode->ApInfo.rssi = pApMetaInfo->rssi;
+    pNode->ApInfo.age = pApMetaInfo->timestamp;
+    pNode->ApInfo.batchId = scanId;
+    pNode->ApInfo.isLastAp = isLastAp;
+
+    pNode->pNext = NULL;
+    if (NULL == pHead)
+    {
+         pAdapter->pBatchScanRsp = pNode;
+    }
+    else
+    {
+        pTemp = pHead;
+        while (NULL != pTemp)
+        {
+            pPrev = pTemp;
+            pTemp = pTemp->pNext;
+        }
+        pPrev->pNext = pNode;
+    }
+
+    return;
+}/*End of hdd_populate_batch_scan_rsp_queue*/
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_batch_scan_result_ind_callback () - This function is called after
+     receiving batch scan response indication from FW. It saves get batch scan
+     response data in HDD batch scan response queue. This callback sets the
+     completion event on which hdd_ioctl is waiting only after getting complete
+     batch scan response data from FW
+
+  \param  - callbackContext Pointer to HDD adapter
+  \param  - pRsp Pointer to get batch scan response data received from FW
+
+  \return - nothing
+
+  --------------------------------------------------------------------------*/
+static void hdd_batch_scan_result_ind_callback
+(
+    void *callbackContext,
+    void *pRsp
+)
+{
+    v_BOOL_t                     isLastAp;
+    tANI_U32                     numApMetaInfo;
+    tANI_U32                     numberScanList;
+    tANI_U32                     nextScanListOffset;
+    tANI_U32                     nextApMetaInfoOffset;
+    hdd_adapter_t*               pAdapter;
+    tpSirBatchScanList           pScanList;
+    tpSirBatchScanNetworkInfo    pApMetaInfo;
+    tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
+    tSirSetBatchScanReq          *pReq;
+
+    pAdapter = (hdd_adapter_t *)callbackContext;
+    /*sanity check*/
+    if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
+    {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Invalid pAdapter magic", __func__);
+        VOS_ASSERT(0);
+        return;
+    }
+
+    /*initialize locals*/
+    pReq = &pAdapter->hddSetBatchScanReq;
+    pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
+    isLastAp = FALSE;
+    numApMetaInfo = 0;
+    numberScanList = 0;
+    nextScanListOffset = 0;
+    nextApMetaInfoOffset = 0;
+    pScanList = NULL;
+    pApMetaInfo = NULL;
+
+    if ((NULL == pBatchScanRsp) || (NULL == pReq))
+    {
+         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+            "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
+            isLastAp = TRUE;
+         goto done;
+    }
+
+    pAdapter->numScanList = numberScanList =  pBatchScanRsp->numScanLists;
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+        "Batch scan rsp: numberScalList %d", numberScanList);
+
+    if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
+    {
+         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+             "%s: numberScanList %d", __func__, numberScanList);
+         isLastAp = TRUE;
+         goto done;
+    }
+
+    while (numberScanList)
+    {
+        pScanList = (tpSirBatchScanList)(pBatchScanRsp->scanResults +
+                                          nextScanListOffset);
+        if (NULL == pScanList)
+        {
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+              "%s: pScanList is %p", __func__, pScanList);
+            isLastAp = TRUE;
+           goto done;
+        }
+        numApMetaInfo = pScanList->numNetworksInScanList;
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+            "Batch scan rsp: numApMetaInfo %d", numApMetaInfo);
+
+        if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
+        {
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+              "%s: numApMetaInfo %d", __func__, numApMetaInfo);
+            isLastAp = TRUE;
+           goto done;
+        }
+
+        while (numApMetaInfo)
+        {
+            pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
+                                                nextApMetaInfoOffset);
+            if (NULL == pApMetaInfo)
+            {
+                VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
+                isLastAp = TRUE;
+                goto done;
+            }
+            /*calculate AP age*/
+            pApMetaInfo->timestamp =
+                pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
+
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+               "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
+               "ch %d rssi %d timestamp %d", __func__,
+               pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
+               pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
+               pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
+               pApMetaInfo->ch, pApMetaInfo->rssi,
+               pApMetaInfo->timestamp);
+
+            /*mark last AP in batch scan response*/
+            if ((TRUE == pBatchScanRsp->isLastResult) &&
+                (1 == numberScanList) && (1 == numApMetaInfo))
+            {
+               isLastAp = TRUE;
+            }
+
+            mutex_lock(&pAdapter->hdd_batch_scan_lock);
+            /*store batch scan repsonse in hdd queue*/
+            hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
+                pScanList->scanId, isLastAp);
+            mutex_unlock(&pAdapter->hdd_batch_scan_lock);
+
+            nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
+            numApMetaInfo--;
+        }
+
+        nextScanListOffset += (sizeof(tSirBatchScanList) - (sizeof(tANI_U8)));
+        numberScanList--;
+    }
+
+done:
+
+    /*notify hdd_ioctl only if complete batch scan rsp is received and it was
+      requested from hdd_ioctl*/
+    if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
+        (TRUE == isLastAp))
+    {
+        pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
+        complete(&pAdapter->hdd_get_batch_scan_req_var);
+    }
+
+    return;
+}/*End of hdd_batch_scan_result_ind_callback*/
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_format_batch_scan_rsp () - This function formats batch scan
+     response as per batch scan FR request format by putting proper markers
+
+  \param  - pDest pointer to destination buffer
+  \param  - cur_len current length
+  \param  - tot_len total remaining size which can be written to user space
+  \param  - pApMetaInfo Pointer to get batch scan response AP meta info
+  \param  - pAdapter Pointer to HDD adapter
+
+  \return - ret no of characters written
+
+  --------------------------------------------------------------------------*/
+static tANI_U32
+hdd_format_batch_scan_rsp
+(
+    tANI_U8 *pDest,
+    tANI_U32 cur_len,
+    tANI_U32 tot_len,
+    tHddBatchScanRsp *pApMetaInfo,
+    hdd_adapter_t* pAdapter
+)
+{
+   tANI_U32 ret = 0;
+   tANI_U32 rem_len = 0;
+   tANI_U8  temp_len = 0;
+   tANI_U8  temp_total_len = 0;
+   tANI_U8  temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
+   tANI_U8  *pTemp = temp;
+
+   /*Batch scan reponse needs to be returned to user space in
+     following format:
+     "scancount=X\n" where X is the number of scans in current batch
+     batch
+     "trunc\n" optional present if current scan truncated
+     "bssid=XX:XX:XX:XX:XX:XX\n"
+     "ssid=XXXX\n"
+     "freq=X\n" frequency in Mhz
+     "level=XX\n"
+     "age=X\n" ms
+     "dist=X\n" cm (-1 if not available)
+     "errror=X\n" (-1if not available)
+     "====\n" (end of ap marker)
+     "####\n" (end of scan marker)
+     "----\n" (end of results)*/
+     /*send scan result in above format to user space based on
+       available length*/
+   /*The GET response may have more data than the driver can return in its
+     buffer. In that case the buffer should be filled to the nearest complete
+     scan, ending with "%%%%".Subsequent callsshould return the remaining data
+     starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
+     The final buffer should end with "----\n"*/
+
+   /*sanity*/
+   if (cur_len > tot_len)
+   {
+       VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+          "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
+       return 0;
+   }
+   else
+   {
+      rem_len = (tot_len - cur_len);
+   }
+
+   /*end scan marker*/
+   if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
+   {
+       temp_len = snprintf(pTemp, sizeof(temp), "####\n");
+       pTemp += temp_len;
+       temp_total_len += temp_len;
+   }
+
+   /*bssid*/
+   temp_len = snprintf(pTemp, sizeof(temp),
+                "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
+                pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
+                pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
+                pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*ssid*/
+   temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
+                 pApMetaInfo->ApInfo.ssid);
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*freq*/
+   temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
+                 pApMetaInfo->ApInfo.ch);
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*level*/
+   temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
+                  pApMetaInfo->ApInfo.rssi);
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*age*/
+   temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%ld\n",
+                  pApMetaInfo->ApInfo.age);
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*dist*/
+   temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*error*/
+   temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*end AP marker*/
+   temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
+   pTemp += temp_len;
+   temp_total_len += temp_len;
+
+   /*last AP in batch scan response*/
+   if(TRUE == pApMetaInfo->ApInfo.isLastAp)
+   {
+       /*end scan marker*/
+       temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
+       pTemp += temp_len;
+       temp_total_len += temp_len;
+
+       /*end batch scan result marker*/
+       temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
+       pTemp += temp_len;
+       temp_total_len += temp_len;
+   }
+
+   if (temp_total_len < rem_len)
+   {
+       ret = temp_total_len + 1;
+       strlcpy(pDest, temp, ret);
+       pAdapter->isTruncated = FALSE;
+   }
+   else
+   {
+      pAdapter->isTruncated = TRUE;
+      if (rem_len >= strlen("%%%%"))
+      {
+          ret = snprintf(pDest, strlen("%%%%"), "%%%%");
+      }
+      {
+          ret = 0;
+      }
+   }
+
+   return ret;
+
+}/*End of hdd_format_batch_scan_rsp*/
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
+     buffer starting with head of hdd batch scan response queue
+
+  \param - pAdapter Pointer to HDD adapter
+  \param - pDest Pointer to user data buffer
+  \param - cur_len current offset in user buffer
+  \param - rem_len remaining  no of bytes in user buffer
+
+  \return - number of bytes written in user buffer
+
+  --------------------------------------------------------------------------*/
+
+tANI_U32 hdd_populate_user_batch_scan_rsp
+(
+    hdd_adapter_t* pAdapter,
+    tANI_U8  *pDest,
+    tANI_U32 cur_len,
+    tANI_U32 rem_len
+)
+{
+    tHddBatchScanRsp *pHead;
+    tHddBatchScanRsp *pPrev;
+    tANI_U32 len;
+
+    pAdapter->prev_batch_id = 0;
+    pAdapter->isTruncated = FALSE;
+
+    /*head of hdd batch scan response queue*/
+    pHead = pAdapter->pBatchScanRsp;
+    while (pHead)
+    {
+         len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
+                   pAdapter);
+         pDest += len;
+         cur_len += len;
+         if(TRUE == pAdapter->isTruncated)
+         {
+              /*result is truncated return rest of scan rsp in next req*/
+              cur_len = rem_len;
+              break;
+         }
+         pPrev = pHead;
+         pHead = pHead->pNext;
+         pAdapter->pBatchScanRsp  = pHead;
+         pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
+         vos_mem_free(pPrev);
+   }
+
+   return cur_len;
+}/*End of hdd_populate_user_batch_scan_rsp*/
+
+/**---------------------------------------------------------------------------
+
+  \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
+     scan response data from HDD queue to user space
+     It does following in detail:
+     a) if HDD has enough data in its queue then it 1st copies data to user
+        space and then send get batch scan indication message to FW. In this
+        case it does not wait on any event and batch scan response data will
+        be populated in HDD response queue in MC thread context after receiving
+        indication from FW
+     b) else send get batch scan indication message to FW and wait on an event
+        which will be set once HDD receives complete batch scan response from
+        FW and then this function returns batch scan response to user space
+
+  \param  - pAdapter Pointer to HDD adapter
+  \param  - pPrivData Pointer to priv_data
+
+  \return - 0 for success -EFAULT for failure
+
+  --------------------------------------------------------------------------*/
+
+int hdd_return_batch_scan_rsp_to_user
+(
+    hdd_adapter_t* pAdapter,
+    hdd_priv_data_t *pPrivData,
+    tANI_U8 *command
+)
+{
+    tANI_U8    *pDest;
+    tANI_U32   count = 0;
+    tANI_U32   len = 0;
+    tANI_U32   cur_len = 0;
+    tANI_U32   rem_len = 0;
+    eHalStatus halStatus;
+    unsigned long rc;
+    tSirTriggerBatchScanResultInd *pReq;
+
+    pReq = &pAdapter->hddTriggerBatchScanResultInd;
+    pReq->param = 0;/*batch scan client*/
+    pDest = (tANI_U8 *)(command + pPrivData->used_len);
+    pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
+
+    cur_len = pPrivData->used_len;
+    if (pPrivData->total_len > pPrivData->used_len)
+    {
+        rem_len = pPrivData->total_len - pPrivData->used_len;
+    }
+    else
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+            "%s: Invalid user data buffer total_len %d used_len %d",
+            __func__, pPrivData->total_len, pPrivData->used_len);
+        return -EFAULT;
+    }
+
+    mutex_lock(&pAdapter->hdd_batch_scan_lock);
+    len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
+                 cur_len, rem_len);
+    mutex_unlock(&pAdapter->hdd_batch_scan_lock);
+
+    /*enough scan result available in cache to return to user space or
+      scan result needs to be fetched 1st from fw and then return*/
+    if (len < rem_len)
+    {
+        pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
+        halStatus = sme_TriggerBatchScanResultInd(
+                        WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
+                        pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
+                        pAdapter);
+        if ( eHAL_STATUS_SUCCESS == halStatus )
+        {
+            if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
+            {
+                INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
+                rc = wait_for_completion_timeout(
+                     &pAdapter->hdd_get_batch_scan_req_var,
+                     msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
+                if (0 == rc)
+                {
+                    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                    "%s: Timeout waiting to fetch batch scan rsp from fw",
+                    __func__);
+                    return -EFAULT;
+                }
+            }
+
+            len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
+                      "scancount=%ld\n", pAdapter->numScanList);
+            pDest += len;
+            cur_len += len;
+
+            mutex_lock(&pAdapter->hdd_batch_scan_lock);
+            len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
+                 cur_len, rem_len);
+            mutex_unlock(&pAdapter->hdd_batch_scan_lock);
+
+            count = 0;
+            len = (len - pPrivData->used_len);
+            pDest = (command + pPrivData->used_len);
+            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+               "BATCH SCAN RESULT:");
+            while(count < len)
+            {
+                printk("%c", *(pDest + count));
+                count++;
+            }
+            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+               "%s: copy %d data to user buffer", __func__, len);
+            if (copy_to_user(pPrivData->buf, pDest, len))
+            {
+                VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                 "%s: failed to copy data to user buffer", __func__);
+                return -EFAULT;
+            }
+        }
+        else
+        {
+            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "sme_GetBatchScanScan  returned failure halStatus %d",
+                halStatus);
+             return -EINVAL;
+        }
+    }
+    else
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+           "%s: copy %d data to user buffer", __func__, len);
+        count = 0;
+        len = (len - pPrivData->used_len);
+        pDest = (command + pPrivData->used_len);
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+            "BATCH SCAN RESULT:");
+        while(count < len)
+        {
+            printk("%c", *(pDest + count));
+            count++;
+        }
+        if (copy_to_user(pPrivData->buf, pDest, len))
+        {
+            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+               "%s: failed to copy data to user buffer", __func__);
+            return -EFAULT;
+        }
+        pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
+        halStatus = sme_TriggerBatchScanResultInd(
+                        WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
+                        pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
+                        pAdapter);
+        if ( eHAL_STATUS_SUCCESS != halStatus )
+        {
+            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "sme_GetBatchScanScan  returned failure halStatus %d",
+                halStatus);
+        }
+    }
+
+   return 0;
+} /*End of hdd_return_batch_scan_rsp_to_user*/
+
+#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
+
 int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
@@ -2148,6 +3084,200 @@
                goto exit;
            }
        }
+#ifdef FEATURE_WLAN_BATCH_SCAN
+       else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
+       {
+           char    extra[32];
+           tANI_U8 len = 0;
+           tANI_U8 version = HDD_BATCH_SCAN_VERSION;
+
+           if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
+           {
+              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s: Batch scan feature is not supported by FW", __func__);
+              ret = -EINVAL;
+              goto exit;
+           }
+
+           if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
+              (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
+           {
+              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "Received WLS_BATCHING_VERSION command in invalid mode %d "
+                "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
+                " mode",
+                pAdapter->device_mode);
+              ret = -EINVAL;
+              goto exit;
+           }
+
+           len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
+                   version);
+           if (copy_to_user(priv_data.buf, &extra, len + 1))
+           {
+               VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: failed to copy data to user buffer", __func__);
+               ret = -EFAULT;
+               goto exit;
+           }
+           ret = HDD_BATCH_SCAN_VERSION;
+       }
+       else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
+       {
+          int                 status;
+          tANI_U8             *value = (command + 16);
+          eHalStatus          halStatus;
+          unsigned long       rc;
+          tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
+          tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
+
+          if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
+          {
+              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s: Batch scan feature is not supported by FW", __func__);
+              ret = -EINVAL;
+              goto exit;
+          }
+
+          if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
+              (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
+          {
+             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "Received WLS_BATCHING_SET command in invalid mode %d "
+                "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
+                pAdapter->device_mode);
+             ret = -EINVAL;
+             goto exit;
+          }
+
+          status = hdd_parse_set_batchscan_command(value, pReq);
+          if (status)
+          {
+             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "Invalid WLS_BATCHING_SET command");
+             ret = -EINVAL;
+             goto exit;
+          }
+          pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
+          halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
+                          pAdapter->sessionId, hdd_set_batch_scan_req_callback,
+                          pAdapter);
+
+          if ( eHAL_STATUS_SUCCESS == halStatus )
+          {
+             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                "sme_SetBatchScanReq  returned success halStatus %d",
+                halStatus);
+             if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
+             {
+                 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
+                 rc = wait_for_completion_timeout(
+                      &pAdapter->hdd_set_batch_scan_req_var,
+                      msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
+                 if (0 == rc)
+                 {
+                    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                    "%s: Timeout waiting for set batch scan to complete",
+                    __func__);
+                    ret = -EINVAL;
+                    goto exit;
+                 }
+             }
+             if ( !pRsp->nScansToBatch )
+             {
+                VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                    "%s: Received set batch scan failure response from FW",
+                     __func__, pRsp->nScansToBatch);
+                ret = -EINVAL;
+                goto exit;
+             }
+             /*As per the Batch Scan Framework API we should return the MIN of
+               either MSCAN or the max # of scans firmware can cache*/
+             ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
+
+             VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s: request MSCAN %d response MSCAN %d ret %d",
+                __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
+          }
+          else
+          {
+             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "sme_SetBatchScanReq  returned failure halStatus %d",
+                halStatus);
+             ret = -EINVAL;
+             goto exit;
+          }
+       }
+       else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
+       {
+          eHalStatus halStatus;
+          tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
+          pInd->param = 0;
+
+          if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
+          {
+              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s: Batch scan feature is not supported by FW", __func__);
+              ret = -EINVAL;
+              goto exit;
+          }
+
+          if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
+              (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
+          {
+              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "Received WLS_BATCHING_STOP command in invalid mode %d "
+                "WLS_BATCHING_STOP is only allowed in infra STA/P2P client"
+                " mode",
+                pAdapter->device_mode);
+              ret = -EINVAL;
+              goto exit;
+          }
+
+          halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
+                          pAdapter->sessionId);
+          if ( eHAL_STATUS_SUCCESS == halStatus )
+          {
+             ret = 0;
+             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                "sme_StopBatchScanInd  returned success halStatus %d",
+                halStatus);
+          }
+          else
+          {
+             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "sme_StopBatchScanInd  returned failure halStatus %d",
+                halStatus);
+             ret = -EINVAL;
+             goto exit;
+          }
+       }
+       else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
+       {
+          if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
+          {
+              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "%s: Batch scan feature is not supported by FW", __func__);
+              ret = -EINVAL;
+              goto exit;
+          }
+
+          if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
+              (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
+          {
+              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                "Received WLS_BATCHING_GET command in invalid mode %d "
+                "WLS_BATCHING_GET is only allowed in infra STA/P2P client"
+                " mode",
+                pAdapter->device_mode);
+              ret = -EINVAL;
+              goto exit;
+          }
+
+          priv_data.used_len = 16;
+          ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
+       }
+#endif
        else {
            hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
                    __func__, command);
@@ -3176,6 +4306,14 @@
       init_completion(&pAdapter->ula_complete);
       init_completion(&pAdapter->change_country_code);
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+      init_completion(&pAdapter->hdd_set_batch_scan_req_var);
+      init_completion(&pAdapter->hdd_get_batch_scan_req_var);
+      pAdapter->pBatchScanRsp = NULL;
+      pAdapter->numScanList = 0;
+      mutex_init(&pAdapter->hdd_batch_scan_lock);
+#endif
+
       pAdapter->isLinkUpSvcNeeded = FALSE; 
       pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
       //Init the net_device structure
@@ -3491,6 +4629,24 @@
 {
    struct net_device *pWlanDev = pAdapter->dev;
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+      tHddBatchScanRsp *pNode;
+      tHddBatchScanRsp *pPrev;
+      if (pAdapter)
+      {
+          mutex_lock(&pAdapter->hdd_batch_scan_lock);
+          pNode = pAdapter->pBatchScanRsp;
+          while (pNode)
+          {
+              pPrev = pNode;
+              pNode = pNode->pNext;
+              vos_mem_free((v_VOID_t * )pPrev);
+          }
+          pAdapter->pBatchScanRsp = NULL;
+          mutex_unlock(&pAdapter->hdd_batch_scan_lock);
+      }
+#endif
+
    if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
       if( rtnl_held )
       {
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index 1880321..94f90fa 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -150,6 +150,10 @@
 
 #define SPACE_ASCII_VALUE  32
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+#define EQUALS_TO_ASCII_VALUE (61)
+#endif
+
 // -------------------------------------------------------------------
 // Change channel generic scheme
 typedef void (*CHANGE_CHANNEL_CALLBACK)(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data,
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 4dc5945..ede6ed6 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -96,6 +96,10 @@
 #define SIR_MAX_24G_5G_CHANNEL_RANGE      166
 
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+#define SIR_MAX_SSID_SIZE (32)
+#endif
+
 
 #define SIR_NUM_11B_RATES 4   //1,2,5.5,11
 #define SIR_NUM_11A_RATES 8  //6,9,12,18,24,36,48,54
@@ -4381,4 +4385,75 @@
     tANI_U32 ucPatternIdBitmap;
 } tSirDelPeriodicTxPtrn, *tpSirDelPeriodicTxPtrn;
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+// Set batch scan resposne from FW
+typedef struct
+{
+  /*maximum number of scans which FW can cache*/
+  tANI_U32 nScansToBatch;
+} tSirSetBatchScanRsp, *tpSirSetBatchScanRsp;
+
+// Set batch scan request to FW
+typedef struct
+{
+    tANI_U32 scanFrequency;        /* how frequent to do scan - default 30Sec*/
+    tANI_U32 numberOfScansToBatch; /* number of scans to batch */
+    tANI_U32 bestNetwork;          /* best networks in terms of rssi */
+    tANI_U8  rfBand;               /* band to scan :
+                                      0 ->both Band, 1->2.4Ghz Only
+                                      and 2-> 5GHz Only */
+    tANI_U32 rtt;                  /* set if required to do RTT it is not
+                                      supported in current version */
+} tSirSetBatchScanReq, *tpSirSetBatchScanReq;
+
+
+// Stop batch scan request to FW
+typedef struct
+{
+    tANI_U32 param;
+} tSirStopBatchScanInd, *tpSirStopBatchScanInd;
+
+// Trigger batch scan result indication to FW
+typedef struct
+{
+    tANI_U32 param;
+} tSirTriggerBatchScanResultInd, *tpSirTriggerBatchScanResultInd;
+
+// Batch scan result indication from FW
+typedef PACKED_PRE struct PACKED_POST
+{
+    tANI_U8   bssid[6];     /* BSSID */
+    tANI_U8   ssid[32];     /* SSID */
+    tANI_U8   ch;           /* Channel */
+    tANI_U8   rssi;         /* RSSI or Level */
+    /*Timestamp when Network was found. Used to calculate age based on timestamp
+      in GET_RSP msg header */
+    tANI_U32  timestamp;
+} tSirBatchScanNetworkInfo, *tpSirBatchScanNetworkInfo;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+    tANI_U32   scanId; /* Scan List ID. */
+    /*No of AP in a Scan Result. Should be same as bestNetwork in SET_REQ msg*/
+    tANI_U32   numNetworksInScanList;
+    /*Variable data ptr: Number of AP in Scan List*/
+    /*Following numNetworkInScanList is data of type tSirBatchScanNetworkInfo
+     *of sizeof(tSirBatchScanNetworkInfo) * numNetworkInScanList */
+    tANI_U8    scanList[1];
+} tSirBatchScanList, *tpSirBatchScanList;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+    tANI_U32      timestamp;
+    tANI_U32      numScanLists;
+    boolean       isLastResult;
+    /* Variable Data ptr: Number of Scan Lists*/
+    /* following isLastResult is data of type tSirBatchScanList
+     * of sizeof(tSirBatchScanList) * numScanLists*/
+    tANI_U8       scanResults[1];
+}  tSirBatchScanResultIndParam, *tpSirBatchScanResultIndParam;
+
+#endif // FEATURE_WLAN_BATCH_SCAN
+
+
 #endif /* __SIR_API_H */
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index cad6c3f..25db733 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -104,6 +104,10 @@
    ADVANCE_TDLS = 29,
 #endif
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+   BATCH_SCAN = 30,
+#endif
+
    //MAX_FEATURE_SUPPORTED = 128
 } placeHolderInCapBitmap;
 
@@ -600,6 +604,14 @@
 #define SIR_HAL_ADD_PERIODIC_TX_PTRN_IND   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 208)
 #define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 209)
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+#define SIR_HAL_SET_BATCH_SCAN_REQ         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 210)
+#define SIR_HAL_SET_BATCH_SCAN_RSP         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 211)
+#define SIR_HAL_STOP_BATCH_SCAN_IND        (SIR_HAL_ITC_MSG_TYPES_BEGIN + 212)
+#define SIR_HAL_TRIGGER_BATCH_SCAN_RESULT_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 213)
+#endif
+
+
 #define SIR_HAL_MSG_TYPES_END              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 0xFF)
 // CFG message types
 #define SIR_CFG_MSG_TYPES_BEGIN        (SIR_CFG_MODULE_ID << 8)
diff --git a/CORE/SME/inc/pmc.h b/CORE/SME/inc/pmc.h
index 3a82cbb..9b0b331 100644
--- a/CORE/SME/inc/pmc.h
+++ b/CORE/SME/inc/pmc.h
@@ -221,6 +221,17 @@
     v_BOOL_t    ImpsReqTimerFailed;
     tANI_U8     ImpsReqFailCnt;
     tANI_U8     ImpsReqTimerfailCnt;
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+   /*HDD callback to be called after receiving SET BATCH SCAN RSP from FW*/
+   hddSetBatchScanReqCallback setBatchScanReqCallback;
+   void * setBatchScanReqCallbackContext;
+   /*HDD callback to be called after receiving BATCH SCAN iRESULT IND from FW*/
+   hddTriggerBatchScanResultIndCallback batchScanResultCallback;
+   void * batchScanResultCallbackContext;
+#endif
+
+
 } tPmcInfo, *tpPmcInfo;
 
 
diff --git a/CORE/SME/inc/pmcApi.h b/CORE/SME/inc/pmcApi.h
index 7e960ba..21ea575 100644
--- a/CORE/SME/inc/pmcApi.h
+++ b/CORE/SME/inc/pmcApi.h
@@ -503,5 +503,67 @@
                                    void *callbackContext, tANI_U8 sessionId);
 #endif // WLAN_FEATURE_GTK_OFFLOAD
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/*Set batch scan request Cb declaration*/
+typedef void(*hddSetBatchScanReqCallback)(void *callbackContext,
+     tSirSetBatchScanRsp *pRsp);
+
+/*Trigger batch scan result indication Cb declaration*/
+typedef void(*hddTriggerBatchScanResultIndCallback)(void *callbackContext,
+     void *pRsp);
+
+/* -----------------------------------------------------------------------------
+    \fn pmcSetBatchScanReq
+    \brief  Setting batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  sessionId - session id
+    \param  callbackRoutine - Pointer to set batch scan request callback routine
+    \param  calbackContext - callback context
+    \return eHalStatus
+             eHAL_STATUS_FAILURE  Cannot set batch scan request
+             eHAL_STATUS_SUCCESS  Request accepted.
+ -----------------------------------------------------------------------------*/
+extern eHalStatus pmcSetBatchScanReq(tHalHandle hHal, tSirSetBatchScanReq
+       *pRequest, tANI_U8 sessionId, hddSetBatchScanReqCallback callbackRoutine,
+       void *callbackContext);
+
+/* -----------------------------------------------------------------------------
+    \fn pmcTriggerBatchScanResultInd
+    \brief  API to pull batch scan result from FW
+    \param  hHal - The handle returned by macOpen.
+    \param  sessionId - session id
+    \param  callbackRoutine - Pointer to get batch scan request callback routine
+    \param  calbackContext - callback context
+    \return eHalStatus
+             eHAL_STATUS_FAILURE  Cannot set batch scan request
+             eHAL_STATUS_SUCCESS  Request accepted.
+ -----------------------------------------------------------------------------*/
+extern eHalStatus pmcTriggerBatchScanResultInd
+(
+    tHalHandle hHal, tSirTriggerBatchScanResultInd *pRequest, tANI_U8 sessionId,
+    hddTriggerBatchScanResultIndCallback callbackRoutine, void *callbackContext
+);
+
+
+/* -----------------------------------------------------------------------------
+    \fn pmcStopBatchScanInd
+    \brief  Stoping batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  pInd - Pointer to stop batch scan indication
+    \return eHalStatus
+             eHAL_STATUS_FAILURE  Cannot set batch scan request
+             eHAL_STATUS_SUCCESS  Request accepted.
+ -----------------------------------------------------------------------------*/
+
+extern eHalStatus pmcStopBatchScanInd
+(
+    tHalHandle hHal,
+    tSirStopBatchScanInd *pInd,
+    tANI_U8 sessionId
+);
+
+#endif // FEATURE_WLAN_BATCH_SCAN
+
+
 #endif
 
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 4c0a9d4..47830a7 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -2973,4 +2973,60 @@
 eHalStatus sme_RoamDelPMKIDfromCache( tHalHandle hHal, tANI_U8 sessionId, tANI_U8 *pBSSId );
 
 void smeGetCommandQStatus( tHalHandle hHal );
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/* ---------------------------------------------------------------------------
+    \fn sme_SetBatchScanReq
+    \brief  API to set batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  pRequest -  Pointer to the batch request.
+    \param  sessionId - session ID
+    \param  callbackRoutine - HDD callback which needs to be invoked after
+            getting set batch scan response from FW
+    \param  callbackContext - pAdapter context
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus
+sme_SetBatchScanReq
+(
+    tHalHandle hHal, tSirSetBatchScanReq *pRequest, tANI_U8 sessionId,
+    void (*callbackRoutine) (void *callbackCtx, tSirSetBatchScanRsp *pRsp),
+    void *callbackContext
+);
+
+/* ---------------------------------------------------------------------------
+    \fn sme_TriggerBatchScanResultInd
+    \brief  API to trigger batch scan result indications from from FW
+    \param  hHal - The handle returned by macOpen.
+    \param  pRequest -  Pointer to get batch request.
+    \param  sessionId - session ID
+    \param  callbackRoutine - HDD callback which needs to be invoked after
+            getting get batch scan response from FW
+    \param  callbackContext - pAdapter context
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus
+sme_TriggerBatchScanResultInd
+(
+    tHalHandle hHal, tSirTriggerBatchScanResultInd *pRequest, tANI_U8 sessionId,
+    void (*callbackRoutine) (void *callbackCtx, void *pRsp),
+    void *callbackContext
+);
+
+/* ---------------------------------------------------------------------------
+    \fn sme_StopBatchScanInd
+    \brief  API to stop batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  pRequest -  Pointer to stop batch indication
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus
+sme_StopBatchScanInd
+(
+    tHalHandle hHal, tSirStopBatchScanInd *pInd, tANI_U8 sessionId
+);
+
+#endif
+
+
 #endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/pmc/pmcApi.c b/CORE/SME/src/pmc/pmcApi.c
index 9150652..d031e25 100644
--- a/CORE/SME/src/pmc/pmcApi.c
+++ b/CORE/SME/src/pmc/pmcApi.c
@@ -3353,3 +3353,151 @@
     pMac->pmc.ImpsReqFailed = VOS_FALSE;
     pMac->pmc.ImpsReqTimerFailed = VOS_FALSE;
 }
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/* -----------------------------------------------------------------------------
+    \fn pmcSetBatchScanReq
+    \brief  setting batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  sessionId - session ID
+    \param  callbackRoutine - Pointer to set batch scan request callback routine
+    \param  callbackContext - Pointer to set batch scan request callback context
+    \return eHalStatus
+             eHAL_STATUS_FAILURE  Cannot set batch scan request
+             eHAL_STATUS_SUCCESS  Request accepted.
+ -----------------------------------------------------------------------------*/
+
+eHalStatus pmcSetBatchScanReq(tHalHandle hHal, tSirSetBatchScanReq *pRequest,
+    tANI_U8 sessionId, hddSetBatchScanReqCallback callbackRoutine,
+    void *callbackContext)
+{
+    tpSirSetBatchScanReq pRequestBuf;
+    vos_msg_t msg;
+    tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+    pRequestBuf = vos_mem_malloc(sizeof(tSirSetBatchScanReq));
+    if (NULL == pRequestBuf)
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+          "%s: Not able to allocate memory for SET BATCH SCAN req", __func__);
+        return eHAL_STATUS_FAILED_ALLOC;
+    }
+
+    /* Cache HDD callback information*/
+    pMac->pmc.setBatchScanReqCallback = callbackRoutine;
+    pMac->pmc.setBatchScanReqCallbackContext = callbackContext;
+
+    pRequestBuf->scanFrequency = pRequest->scanFrequency;
+    pRequestBuf->numberOfScansToBatch = pRequest->numberOfScansToBatch;
+    pRequestBuf->bestNetwork = pRequest->bestNetwork;
+    pRequestBuf->rfBand = pRequest->rfBand;
+    pRequestBuf->rtt = pRequest->rtt;
+
+    msg.type     = WDA_SET_BATCH_SCAN_REQ;
+    msg.reserved = 0;
+    msg.bodyptr  = pRequestBuf;
+    if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+          "%s: Not able to post WDA_SET_BATCH_SCAN_REQ message to WDA",
+          __func__);
+        vos_mem_free(pRequestBuf);
+        return eHAL_STATUS_FAILURE;
+    }
+
+    return eHAL_STATUS_SUCCESS;
+}
+
+/* -----------------------------------------------------------------------------
+    \fn pmcTriggerBatchScanResultInd
+    \brief  API to trigger batch scan results indications from FW
+    \param  hHal - The handle returned by macOpen.
+    \param  sessionId - session ID
+    \param  callbackRoutine - Pointer to get batch scan request callback routine
+    \param  callbackContext - Pointer to get batch scan request callback context
+    \return eHalStatus
+             eHAL_STATUS_FAILURE  Cannot set batch scan request
+             eHAL_STATUS_SUCCESS  Request accepted.
+ -----------------------------------------------------------------------------*/
+
+eHalStatus pmcTriggerBatchScanResultInd
+(
+    tHalHandle hHal, tSirTriggerBatchScanResultInd *pRequest, tANI_U8 sessionId,
+    hddTriggerBatchScanResultIndCallback callbackRoutine, void *callbackContext
+)
+{
+    tpSirTriggerBatchScanResultInd pRequestBuf;
+    vos_msg_t msg;
+    tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+    pRequestBuf = vos_mem_malloc(sizeof(tSirTriggerBatchScanResultInd));
+    if (NULL == pRequestBuf)
+    {
+       VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+        "%s: Not able to allocate memory for WDA_TRIGGER_BATCH_SCAN_RESULT_IND",
+        __func__);
+        return eHAL_STATUS_FAILED_ALLOC;
+    }
+
+    /*HDD callback to be called after getting batch scan result ind from FW*/
+    pMac->pmc.batchScanResultCallback = callbackRoutine;
+    pMac->pmc.batchScanResultCallbackContext = callbackContext;
+
+    pRequestBuf->param = pRequest->param;
+
+    msg.type     = WDA_TRIGGER_BATCH_SCAN_RESULT_IND;
+    msg.reserved = 0;
+    msg.bodyptr  = pRequestBuf;
+    if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+          "%s: Not able to post WDA_TRIGGER_BATCH_SCAN_RESULT_IND message"
+          " to WDA", __func__);
+        vos_mem_free(pRequestBuf);
+        return eHAL_STATUS_FAILURE;
+    }
+
+    return eHAL_STATUS_SUCCESS;
+}
+
+/* -----------------------------------------------------------------------------
+    \fn pmcStopBatchScanInd
+    \brief  Stoping batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  callbackRoutine - Pointer to stop batch scan request callback routine
+    \return eHalStatus
+             eHAL_STATUS_FAILURE  Cannot set batch scan request
+             eHAL_STATUS_SUCCESS  Request accepted.
+ -----------------------------------------------------------------------------*/
+
+eHalStatus pmcStopBatchScanInd(tHalHandle hHal, tSirStopBatchScanInd *pRequest,
+    tANI_U8 sessionId)
+{
+    tSirStopBatchScanInd *pRequestBuf;
+    vos_msg_t msg;
+
+    pRequestBuf = vos_mem_malloc(sizeof(tSirStopBatchScanInd));
+    if (NULL == pRequestBuf)
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+          "%s: Not able to allocate memory for STOP BATCH SCAN IND", __func__);
+        return eHAL_STATUS_FAILED_ALLOC;
+    }
+
+    pRequestBuf->param = pRequest->param;
+
+    msg.type     = WDA_STOP_BATCH_SCAN_IND;
+    msg.reserved = 0;
+    msg.bodyptr  = pRequestBuf;
+    if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+          "%s: Not able to post WDA_TOP_BATCH_SCAN_IND message to WDA", __func__);
+        vos_mem_free(pRequestBuf);
+        return eHAL_STATUS_FAILURE;
+    }
+
+    return eHAL_STATUS_SUCCESS;
+}
+
+#endif
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 7c8c729..14437f9 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -9129,3 +9129,94 @@
 
     return;
 }
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/* ---------------------------------------------------------------------------
+    \fn sme_SetBatchScanReq
+    \brief  API to set batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  pRequest -  Pointer to the batch request.
+    \param  sessionId - session ID
+    \param  callbackRoutine - HDD callback which needs to be invoked after
+            getting set batch scan response from FW
+    \param  callbackContext - pAdapter context
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus sme_SetBatchScanReq
+(
+    tHalHandle hHal, tSirSetBatchScanReq *pRequest, tANI_U8 sessionId,
+    void (*callbackRoutine) (void *callbackCtx, tSirSetBatchScanRsp *pRsp),
+    void *callbackContext
+)
+{
+    tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+    eHalStatus status;
+
+    if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme )))
+    {
+       status = pmcSetBatchScanReq(hHal, pRequest, sessionId, callbackRoutine,
+                  callbackContext);
+       sme_ReleaseGlobalLock( &pMac->sme );
+    }
+
+    return status;
+}
+
+/* ---------------------------------------------------------------------------
+    \fn sme_TriggerBatchScanResultInd
+    \brief  API to trigger batch scan result indications from FW
+    \param  hHal - The handle returned by macOpen.
+    \param  pRequest -  Pointer to get batch request.
+    \param  sessionId - session ID
+    \param  callbackRoutine - HDD callback which needs to be invoked after
+            getting batch scan result indication from FW
+    \param  callbackContext - pAdapter context
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus sme_TriggerBatchScanResultInd
+(
+    tHalHandle hHal, tSirTriggerBatchScanResultInd *pRequest, tANI_U8 sessionId,
+    void (*callbackRoutine) (void *callbackCtx, void *pRsp),
+    void *callbackContext
+)
+{
+    tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+    eHalStatus status;
+
+    if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme )))
+    {
+       status = pmcTriggerBatchScanResultInd(hHal, pRequest, sessionId,
+                   callbackRoutine, callbackContext);
+       sme_ReleaseGlobalLock( &pMac->sme );
+    }
+
+    return status;
+}
+
+
+/* ---------------------------------------------------------------------------
+    \fn sme_StopBatchScanInd
+    \brief  API to stop batch scan request in FW
+    \param  hHal - The handle returned by macOpen.
+    \param  pRequest -  Pointer to the batch request.
+    \param  sessionId - session ID
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus sme_StopBatchScanInd
+(
+    tHalHandle hHal, tSirStopBatchScanInd *pRequest, tANI_U8 sessionId
+)
+{
+    tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+    eHalStatus status;
+
+    if ( eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock( &pMac->sme )))
+    {
+       status = pmcStopBatchScanInd(hHal, pRequest, sessionId);
+       sme_ReleaseGlobalLock( &pMac->sme );
+    }
+
+    return status;
+}
+
+#endif
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index 394ebe1..f1c82ec 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -789,6 +789,10 @@
 #ifdef WLAN_FEATURE_11AC
         CASE_RETURN_STRING(WDA_UPDATE_OP_MODE);
 #endif
+#ifdef FEATURE_WLAN_BATCH_SCAN
+        CASE_RETURN_STRING(WDA_SET_BATCH_SCAN_REQ);
+        CASE_RETURN_STRING(WDA_TRIGGER_BATCH_SCAN_RESULT_IND);
+#endif
         default:
             return((tANI_U8*) "UNKNOWN" );
             break;
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index f2bd11e..dde480e 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1106,6 +1106,13 @@
 #define WDA_ADD_PERIODIC_TX_PTRN_IND    SIR_HAL_ADD_PERIODIC_TX_PTRN_IND
 #define WDA_DEL_PERIODIC_TX_PTRN_IND    SIR_HAL_DEL_PERIODIC_TX_PTRN_IND
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+#define WDA_SET_BATCH_SCAN_REQ            SIR_HAL_SET_BATCH_SCAN_REQ
+#define WDA_SET_BATCH_SCAN_RSP            SIR_HAL_SET_BATCH_SCAN_RSP
+#define WDA_STOP_BATCH_SCAN_IND           SIR_HAL_STOP_BATCH_SCAN_IND
+#define WDA_TRIGGER_BATCH_SCAN_RESULT_IND SIR_HAL_TRIGGER_BATCH_SCAN_RESULT_IND
+#endif
+
 tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg);
 
 eHalStatus WDA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId);
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 0486098..cabe5b0 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -10538,6 +10538,240 @@
    return CONVERT_WDI2VOS_STATUS(wdiStatus);
 }
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/*
+ * FUNCTION: WDA_ProcessStopBatchScanInd
+ *
+ * DESCRIPTION: This function sends stop batch scan inidcation message to WDI
+ *
+ * PARAM:
+ * pWDA: pointer to WDA context
+ * pReq: pointer to stop batch scan request
+ */
+VOS_STATUS WDA_ProcessStopBatchScanInd(tWDA_CbContext *pWDA,
+                               tSirStopBatchScanInd *pReq)
+{
+   WDI_Status wdiStatus;
+   WDI_StopBatchScanIndType wdiReq;
+
+   wdiReq.param = pReq->param;
+
+   wdiStatus = WDI_StopBatchScanInd(&wdiReq);
+
+   if (WDI_STATUS_SUCCESS_SYNC != wdiStatus)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "Stop batch scan ind failed %s:%d", __func__, wdiStatus);
+   }
+
+   vos_mem_free(pReq);
+
+   return CONVERT_WDI2VOS_STATUS(wdiStatus);
+}
+/*==========================================================================
+  FUNCTION WDA_ProcessTriggerBatchScanResultInd
+
+  DESCRIPTION
+    API to pull batch scan result from FW
+
+  PARAMETERS
+    pWDA: Pointer to WDA context
+    pGetBatchScanReq: Pointer to get batch scan result indication
+
+  RETURN VALUE
+    NONE
+
+===========================================================================*/
+VOS_STATUS WDA_ProcessTriggerBatchScanResultInd(tWDA_CbContext *pWDA,
+       tSirTriggerBatchScanResultInd *pReq)
+{
+   WDI_Status wdiStatus;
+   WDI_TriggerBatchScanResultIndType wdiReq;
+
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH,
+                                          "------> %s " ,__func__);
+
+   wdiReq.param = pReq->param;
+
+   wdiStatus = WDI_TriggerBatchScanResultInd(&wdiReq);
+
+   if (WDI_STATUS_SUCCESS_SYNC != wdiStatus)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+          "Trigger batch scan result ind failed %s:%d",
+          __func__, wdiStatus);
+   }
+
+   vos_mem_free(pReq);
+
+   return CONVERT_WDI2VOS_STATUS(wdiStatus);
+}
+
+/*==========================================================================
+  FUNCTION WDA_SetBatchScanRespCallback
+
+  DESCRIPTION
+    API to process set batch scan response from FW
+
+  PARAMETERS
+    pRsp: Pointer to set batch scan response
+    pUserData: Pointer to user data
+
+  RETURN VALUE
+    NONE
+
+===========================================================================*/
+void WDA_SetBatchScanRespCallback
+(
+    WDI_SetBatchScanRspType *pRsp,
+    void* pUserData
+)
+{
+   tSirSetBatchScanRsp *pHddSetBatchScanRsp;
+   tpAniSirGlobal pMac;
+   void *pCallbackContext;
+   tWDA_CbContext *pWDA = NULL ;
+   tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData;
+
+
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH,
+                                          "<------ %s " ,__func__);
+   if (NULL == pWdaParams)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s: pWdaParams received NULL", __func__);
+      VOS_ASSERT(0) ;
+      return ;
+   }
+
+   /*extract WDA context*/
+   pWDA = pWdaParams->pWdaContext;
+   if (NULL == pWDA)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+          "%s:pWDA is NULL can't invole HDD callback",
+           __func__);
+      vos_mem_free(pWdaParams->wdaWdiApiMsgParam);
+      vos_mem_free(pWdaParams->wdaMsgParam);
+      vos_mem_free(pWdaParams);
+      VOS_ASSERT(0);
+      return;
+   }
+
+   vos_mem_free(pWdaParams->wdaWdiApiMsgParam);
+   vos_mem_free(pWdaParams->wdaMsgParam);
+   vos_mem_free(pWdaParams);
+
+   pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pWDA->pVosContext);
+   if (NULL == pMac)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+          "%s:pMac is NULL", __func__);
+      VOS_ASSERT(0);
+      return;
+   }
+
+   pHddSetBatchScanRsp =
+     (tSirSetBatchScanRsp *)vos_mem_malloc(sizeof(tSirSetBatchScanRsp));
+   if (NULL == pHddSetBatchScanRsp)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+          "%s: VOS MEM Alloc Failure can't invoke HDD callback", __func__);
+      VOS_ASSERT(0);
+      return;
+   }
+
+   pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
+
+   pCallbackContext = pMac->pmc.setBatchScanReqCallbackContext;
+   /*call hdd callback with set batch scan response data*/
+   if(pMac->pmc.setBatchScanReqCallback)
+   {
+       pMac->pmc.setBatchScanReqCallback(pCallbackContext, pHddSetBatchScanRsp);
+   }
+   else
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+          "%s:HDD callback is null", __func__);
+      VOS_ASSERT(0);
+   }
+
+   vos_mem_free(pHddSetBatchScanRsp);
+   return ;
+}
+
+/*==========================================================================
+  FUNCTION WDA_ProcessSetBatchScanReq
+
+  DESCRIPTION
+    API to send set batch scan request to WDI
+
+  PARAMETERS
+    pWDA: Pointer to WDA context
+    pSetBatchScanReq: Pointer to set batch scan req
+
+  RETURN VALUE
+    NONE
+
+===========================================================================*/
+VOS_STATUS WDA_ProcessSetBatchScanReq(tWDA_CbContext *pWDA,
+       tSirSetBatchScanReq *pSetBatchScanReq)
+{
+   WDI_Status status;
+   tWDA_ReqParams *pWdaParams ;
+   WDI_SetBatchScanReqType *pWdiSetBatchScanReq;
+
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH,
+                                          "------> %s " ,__func__);
+
+   pWdiSetBatchScanReq =
+     (WDI_SetBatchScanReqType *)vos_mem_malloc(sizeof(WDI_SetBatchScanReqType));
+   if (NULL == pWdiSetBatchScanReq)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: VOS MEM Alloc Failure", __func__);
+      vos_mem_free(pSetBatchScanReq);
+      VOS_ASSERT(0);
+      return VOS_STATUS_E_NOMEM;
+   }
+
+   pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams));
+   if (NULL == pWdaParams)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: VOS MEM Alloc Failure", __func__);
+      VOS_ASSERT(0);
+      vos_mem_free(pSetBatchScanReq);
+      vos_mem_free(pWdiSetBatchScanReq);
+      return VOS_STATUS_E_NOMEM;
+   }
+
+   pWdiSetBatchScanReq->scanFrequency = pSetBatchScanReq->scanFrequency;
+   pWdiSetBatchScanReq->numberOfScansToBatch =
+               pSetBatchScanReq->numberOfScansToBatch;
+   pWdiSetBatchScanReq->bestNetwork = pSetBatchScanReq->bestNetwork;
+   pWdiSetBatchScanReq->rfBand = pSetBatchScanReq->rfBand;
+   pWdiSetBatchScanReq->rtt = pSetBatchScanReq->rtt;
+
+   pWdaParams->wdaWdiApiMsgParam = pWdiSetBatchScanReq;
+   pWdaParams->pWdaContext = pWDA;
+   pWdaParams->wdaMsgParam = pSetBatchScanReq;
+
+   status = WDI_SetBatchScanReq(pWdiSetBatchScanReq, pWdaParams,
+                (WDI_SetBatchScanCb)WDA_SetBatchScanRespCallback);
+   if (IS_WDI_STATUS_FAILURE(status))
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "Failure in Set Batch Scan REQ WDI API, free all the memory " );
+      vos_mem_free(pWdaParams->wdaWdiApiMsgParam);
+      vos_mem_free(pWdaParams->wdaMsgParam);
+      vos_mem_free(pWdaParams);
+   }
+   return CONVERT_WDI2VOS_STATUS(status);
+}
+
+#endif
+
 /*
  * -------------------------------------------------------------------------
  * DATA interface with WDI for Mgmt Frames
@@ -11559,6 +11793,27 @@
          break;
       }
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+      case WDA_SET_BATCH_SCAN_REQ:
+      {
+          WDA_ProcessSetBatchScanReq(pWDA,
+            (tSirSetBatchScanReq *)pMsg->bodyptr);
+          break;
+      }
+      case WDA_TRIGGER_BATCH_SCAN_RESULT_IND:
+      {
+          WDA_ProcessTriggerBatchScanResultInd(pWDA,
+            (tSirTriggerBatchScanResultInd *)pMsg->bodyptr);
+          break;
+      }
+      case WDA_STOP_BATCH_SCAN_IND:
+      {
+          WDA_ProcessStopBatchScanInd(pWDA,
+            (tSirStopBatchScanInd *)pMsg->bodyptr);
+          break;
+      }
+#endif
+
       default:
       {
          VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
@@ -12095,6 +12350,62 @@
          break;
       }
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+     case  WDI_BATCH_SCAN_RESULT_IND:
+     {
+         void *pBatchScanResult;
+         void *pCallbackContext;
+         tpAniSirGlobal pMac;
+
+         VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH,
+                   "Received WDI_BATCHSCAN_RESULT_IND from FW");
+
+         /*sanity check*/
+         if(NULL == pWDA)
+         {
+            VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s:pWDA is NULL", __func__);
+            VOS_ASSERT(0);
+            return;
+         }
+
+         pBatchScanResult =
+            (void *)wdiLowLevelInd->wdiIndicationData.pBatchScanResult;
+         if (NULL == pBatchScanResult)
+         {
+            VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s:Batch scan result from FW is null can't invoke HDD callback",
+              __func__);
+            VOS_ASSERT(0);
+            return;
+         }
+
+         pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pWDA->pVosContext);
+         if (NULL == pMac)
+         {
+            VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s:pMac is NULL", __func__);
+            VOS_ASSERT(0);
+            return;
+         }
+
+         pCallbackContext = pMac->pmc.batchScanResultCallbackContext;
+         /*call hdd callback with set batch scan response data*/
+         if(pMac->pmc.batchScanResultCallback)
+         {
+            pMac->pmc.batchScanResultCallback(pCallbackContext,
+               pBatchScanResult);
+         }
+         else
+         {
+            VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+               "%s:HDD callback is null", __func__);
+            VOS_ASSERT(0);
+         }
+         break;
+     }
+#endif
+
       default:
       {
          /* TODO error */
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index b9ccff5..12ba8f9 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -406,6 +406,11 @@
   /* Periodic Tx Pattern FW Indication */
   WDI_PERIODIC_TX_PTRN_FW_IND,
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  /*Batch scan result indication from FW*/
+  WDI_BATCH_SCAN_RESULT_IND,
+#endif
+
   WDI_MAX_IND
 }WDI_LowLevelIndEnumType;
 
@@ -638,6 +643,84 @@
     wpt_uint32 patternIdBitmap;
 } WDI_PeriodicTxPtrnFwIndType;
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/*---------------------------------------------------------------------------
+  WDI_SetBatchScanReqType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+    wpt_uint32 scanFrequency;        /* how frequent to do scan default 30Sec*/
+    wpt_uint32 numberOfScansToBatch; /* number of scans to batch */
+    wpt_uint32 bestNetwork;          /* best networks in terms of rssi */
+    wpt_uint8  rfBand;               /* band to scan :
+                                      0 ->both Band, 1->2.4Ghz Only
+                                      and 2-> 5GHz Only */
+    wpt_uint32 rtt;                  /* set if required to do RTT it is not
+                                      supported in current version */
+}WDI_SetBatchScanReqType;
+
+/*---------------------------------------------------------------------------
+  WDI_SetBatchScanRspType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+  /*max number of scans which FW can cache*/
+  wpt_uint32 nScansToBatch;
+}WDI_SetBatchScanRspType;
+
+/*---------------------------------------------------------------------------
+  WDI_TriggerBatchScanResultIndType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+    wpt_uint32 param;
+}WDI_TriggerBatchScanResultIndType;
+
+/*---------------------------------------------------------------------------
+  WDI_StopBatchScanIndType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+  /*max number of scans which FW can cache*/
+  wpt_uint32 param;
+}WDI_StopBatchScanIndType;
+
+
+/*---------------------------------------------------------------------------
+ * WDI_BatchScanResultIndType
+ *--------------------------------------------------------------------------*/
+typedef struct
+{
+    wpt_uint32   bssid[6];     /* BSSID */
+    wpt_uint32   ssid[32];     /* SSID */
+    wpt_uint32   ch;           /* Channel */
+    wpt_uint32   rssi;         /* RSSI or Level */
+    /* Timestamp when Network was found. Used to calculate age based on
+       timestamp in GET_RSP msg header */
+    wpt_uint32  timestamp;
+} tWDIBatchScanNetworkInfo, *tpWDIBatchScanNetworkInfo;
+
+typedef struct
+{
+    wpt_uint32   scanId; /*Scan List ID*/
+    /*No of AP in a Scan Result. Should be same as bestNetwork in SET_REQ msg*/
+    wpt_uint32   numNetworksInScanList;
+    /*Variable data ptr: Number of AP in Scan List*/
+    wpt_uint32    scanList[1];
+} tWDIBatchScanList, *tpWDIBatchScanList;
+
+typedef struct
+{
+    wpt_uint32      timestamp;
+    wpt_uint32      numScanLists;
+    wpt_boolean     isLastResult;
+    /* Variable Data ptr: Number of Scan Lists*/
+    wpt_uint32      scanResults[1];
+}  tWDIBatchScanResultParam, *tpWDIBatchScanResultParam;
+
+#endif
+
+
 /*---------------------------------------------------------------------------
  WDI_IbssPeerInactivityIndType
 -----------------------------------------------------------------------------*/
@@ -707,6 +790,12 @@
 
     /* Periodic TX Pattern FW Indication */
     WDI_PeriodicTxPtrnFwIndType  wdiPeriodicTxPtrnFwInd;
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+    /*batch scan result indication from FW*/
+    void *pBatchScanResult;
+#endif
+
   }  wdiIndicationData;
 }WDI_LowLevelIndType;
 
@@ -6998,6 +7087,31 @@
                                 void*        pUserData);
 #endif /* FEATURE_WLAN_LPHB */
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/*---------------------------------------------------------------------------
+   WDI_SetBatchScanCb
+
+   DESCRIPTION
+
+   This callback is invoked by DAL when it has received a get batch scan
+   response from the underlying device.
+
+   PARAMETERS
+
+    IN
+    wdiStatus:  response status received from HAL
+    pUserData:  user data
+
+
+
+  RETURN VALUE
+    The result code associated with performing the operation
+---------------------------------------------------------------------------*/
+typedef void (*WDI_SetBatchScanCb)(void *pData, WDI_SetBatchScanRspType *pRsp);
+
+#endif
+
+
 /*========================================================================
  *     Function Declarations and Documentation
  ==========================================================================*/
@@ -9956,6 +10070,53 @@
    WDI_LphbCfgCb lphbCfgCb
 );
 #endif /* FEATURE_WLAN_LPHB */
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/**
+ @brief WDI_SetBatchScanReq
+    This API is called to set batch scan request in FW
+
+ @param pBatchScanReqParam : pointer to set batch scan re param
+        usrData : Client context
+        setBatchScanRspCb : set batch scan resp callback
+ @see
+ @return SUCCESS or FAIL
+*/
+WDI_Status WDI_SetBatchScanReq
+(
+   void *pBatchScanReqParam,
+   void *usrData,
+   WDI_SetBatchScanCb setBatchScanRspCb
+);
+
+/**
+ @brief WDI_StopBatchScanInd
+
+ @param none
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_StopBatchScanInd(WDI_StopBatchScanIndType *pWdiReq);
+
+/**
+ @brief WDI_TriggerBatchScanResultInd
+    This API is called to pull batch scan result from FW
+
+ @param pBatchScanReqParam : pointer to trigger batch scan ind param
+        usrData : Client context
+        setBatchScanRspCb : get batch scan resp callback
+ @see
+ @return SUCCESS or FAIL
+*/
+WDI_Status
+WDI_TriggerBatchScanResultInd(WDI_TriggerBatchScanResultIndType *pWdiReq);
+
+
+#endif /*FEATURE_WLAN_BATCH_SCAN*/
+
 #ifdef __cplusplus
  }
 #endif 
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index e59025e..188061b 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -452,6 +452,11 @@
   /* WLAN FW LPHB config request */
   WDI_LPHB_CFG_REQ                              = 85,
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  /* WLAN FW set batch scan request */
+  WDI_SET_BATCH_SCAN_REQ                        = 88,
+#endif
+
   WDI_MAX_REQ,
 
   /*Send a suspend Indication down to HAL*/
@@ -478,6 +483,13 @@
   /*Keep adding the indications to the max request
     such that we keep them sepparate */
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  /*Send stop batch scan indication to FW*/
+  WDI_STOP_BATCH_SCAN_IND,
+  /*Send stop batch scan indication to FW*/
+  WDI_TRIGGER_BATCH_SCAN_RESULT_IND,
+#endif
+
   WDI_MAX_UMAC_IND
 }WDI_RequestEnumType; 
 
@@ -736,6 +748,10 @@
   /* WLAN FW LPHB Config response */
   WDI_LPHB_CFG_RESP                             = 84,
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  WDI_SET_BATCH_SCAN_RESP                        = 85,
+#endif
+
   /*-------------------------------------------------------------------------
     Indications
      !! Keep these last in the enum if possible
@@ -795,6 +811,12 @@
   /* Periodic Tx Pattern Indication from FW to Host */
   WDI_HAL_PERIODIC_TX_PTRN_FW_IND     = WDI_HAL_IND_MIN + 16,
 
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  WDI_BATCHSCAN_RESULT_IND           =  WDI_HAL_IND_MIN + 17,
+#endif
+
+
   WDI_MAX_RESP
 }WDI_ResponseEnumType; 
 
@@ -2768,6 +2790,41 @@
 );
 #endif /* FEATURE_WLAN_LPHB */
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/**
+ @brief WDI_ProcessSetBatchScanReq -
+    Send set batch scan configuration request to FW
+
+ @param  pWDICtx : wdi context
+         pEventData : indication data
+
+ @see
+ @return success or failure
+*/
+WDI_Status WDI_ProcessSetBatchScanReq
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
+/**
+ @brief WDI_ProcessGetBatchScanReq -
+    Send get batch scan request to FW
+
+ @param  pWDICtx : wdi context
+         pEventData : indication data
+
+ @see
+ @return success or failure
+*/
+WDI_Status WDI_ProcessGetBatchScanReq
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+#endif /* FEATURE_WLAN_BATCH_SCAN */
+
+
 /*=========================================================================
                              Indications
 =========================================================================*/
@@ -2890,6 +2947,43 @@
   WDI_EventInfoType*     pEventData
 );
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/**
+  @brief Process stop batch scan indications function
+         It is called when Main FSM allows it
+
+  @param  pWDICtx:         pointer to the WLAN DAL context
+          pEventData:      pointer to the event information structure
+
+  @see
+  @return Result of the function call
+ */
+ WDI_Status
+ WDI_ProcessStopBatchScanInd
+ (
+   WDI_ControlBlockType*  pWDICtx,
+   WDI_EventInfoType*     pEventData
+ );
+
+/**
+  @brief This API is called to trigger batch scan results from FW
+         It is called when Main FSM allows it
+
+  @param  pWDICtx:         pointer to the WLAN DAL context
+          pEventData:      pointer to the event information structure
+
+  @see
+  @return Result of the function call
+ */
+ WDI_Status
+ WDI_ProcessTriggerBatchScanResultInd
+ (
+   WDI_ControlBlockType*  pWDICtx,
+   WDI_EventInfoType*     pEventData
+ );
+
+#endif
+
 /*========================================================================
           Main DAL Control Path Response Processing API 
 ========================================================================*/
@@ -5429,5 +5523,40 @@
 );
 #endif /* FEATURE_WLAN_LPHB */
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+/**
+ @brief WDI_ProcessSetBatchScanRsp -
+     Process set batch scan response from FW
+
+ @param  pWDICtx : wdi context
+         pEventData : indication data
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status WDI_ProcessSetBatchScanRsp
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
+/**
+ @brief Process batch scan response from FW
+
+ @param  pWDICtx:        pointer to the WLAN DAL context
+         pEventData:     pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessBatchScanResultInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
+#endif /* FEATURE_WLAN_BATCH_SCAN */
+
 #endif /*WLAN_QCT_WDI_I_H*/
 
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index d7affd4..cc5e6ff 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -394,6 +394,13 @@
 #else
   NULL,
 #endif /* FEATURE_WLAN_LPHB */
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  WDI_ProcessSetBatchScanReq,               /* WDI_SET_BATCH_SCAN_REQ */
+#else
+  NULL,
+#endif /* FEATURE_WLAN_BATCH_SCAN */
+
   /*-------------------------------------------------------------------------
     Indications
   -------------------------------------------------------------------------*/
@@ -408,6 +415,13 @@
 #endif
   WDI_ProcessAddPeriodicTxPtrnInd,      /* WDI_ADD_PERIODIC_TX_PATTERN_IND */
   WDI_ProcessDelPeriodicTxPtrnInd,      /* WDI_DEL_PERIODIC_TX_PATTERN_IND */
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  WDI_ProcessStopBatchScanInd,          /* WDI_STOP_BATCH_SCAN_IND */
+  WDI_ProcessTriggerBatchScanResultInd, /* WDI_TRIGGER_BATCH_SCAN_RESULT_IND */
+#else
+  NULL,
+  NULL,
+#endif /* FEATURE_WLAN_BATCH_SCAN */
 };
 
 
@@ -591,6 +605,13 @@
 #else
     NULL,
 #endif /* FEATURE_WLAN_LPHB */
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+    WDI_ProcessSetBatchScanRsp,        /* WDI_SET_BATCH_SCAN_RESP */
+#else
+    NULL,
+#endif /*FEATURE_WLAN_BATCH_SCAN*/
+
   /*---------------------------------------------------------------------
     Indications
   ---------------------------------------------------------------------*/
@@ -637,6 +658,13 @@
   WDI_ProcessIbssPeerInactivityInd,     /* WDI_HAL_IBSS_PEER_INACTIVITY_IND */
 
   WDI_ProcessPeriodicTxPtrnFwInd,   /* WDI_HAL_PERIODIC_TX_PTRN_FW_IND */
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  WDI_ProcessBatchScanResultInd,     /* WDI_BATCHSCAN_RESULT_IND */
+#else
+  NULL,
+#endif
+
 };
 
 
@@ -946,6 +974,11 @@
 #ifdef WLAN_FEATURE_11W
     CASE_RETURN_STRING( WDI_EXCLUDE_UNENCRYPTED_IND );
 #endif
+#ifdef FEATURE_WLAN_BATCH_SCAN
+    CASE_RETURN_STRING( WDI_SET_BATCH_SCAN_REQ);
+    CASE_RETURN_STRING( WDI_STOP_BATCH_SCAN_IND );
+    CASE_RETURN_STRING( WDI_TRIGGER_BATCH_SCAN_RESULT_IND);
+#endif
     default:
         return "Unknown WDI MessageId";
   }
@@ -1049,6 +1082,9 @@
     CASE_RETURN_STRING( WDI_SHUTDOWN_RESP );
     CASE_RETURN_STRING( WDI_SET_POWER_PARAMS_RESP );
     CASE_RETURN_STRING( WDI_GET_ROAM_RSSI_RESP );
+#ifdef FEATURE_WLAN_BATCH_SCAN
+    CASE_RETURN_STRING( WDI_SET_BATCH_SCAN_RESP);
+#endif
     default:
         return "Unknown WDI MessageId";
   }
@@ -22630,6 +22666,15 @@
   case WDI_DEL_PERIODIC_TX_PATTERN_IND:
     return WLAN_HAL_DEL_PERIODIC_TX_PTRN_IND;
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  case WDI_SET_BATCH_SCAN_REQ:
+       return WLAN_HAL_BATCHSCAN_SET_REQ;
+  case WDI_STOP_BATCH_SCAN_IND:
+       return WLAN_HAL_BATCHSCAN_STOP_IND;
+  case WDI_TRIGGER_BATCH_SCAN_RESULT_IND:
+       return WLAN_HAL_BATCHSCAN_TRIGGER_RESULT_IND;
+#endif
+
   default:
     return WLAN_HAL_MSG_MAX;
   }
@@ -22878,6 +22923,13 @@
   case WLAN_HAL_PERIODIC_TX_PTRN_FW_IND:
     return WDI_HAL_PERIODIC_TX_PTRN_FW_IND;
 
+#ifdef FEATURE_WLAN_BATCH_SCAN
+  case WLAN_HAL_BATCHSCAN_SET_RSP:
+    return WDI_SET_BATCH_SCAN_RESP;
+  case WLAN_HAL_BATCHSCAN_RESULT_IND:
+    return WDI_BATCHSCAN_RESULT_IND;
+#endif // FEATURE_WLAN_BATCH_SCAN
+
   default:
     return eDRIVER_TYPE_MAX;
   }
@@ -28345,3 +28397,449 @@
    return WDI_STATUS_SUCCESS;
 
 } /*WDI_ProcessIbssPeerInactivityInd*/
+
+#ifdef FEATURE_WLAN_BATCH_SCAN
+
+/**
+ @brief Process stop batch indication from WDA
+
+ @param pWDICtx:         pointer to the WLAN DAL context
+        pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessStopBatchScanInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  wpt_uint8*                pSendBuffer        = NULL;
+  wpt_uint16                usDataOffset       = 0;
+  wpt_uint16                usSendSize         = 0;
+  WDI_Status                wdiStatus;
+  tHalBatchScanStopIndParam *pHalInd           = NULL;
+  WDI_StopBatchScanIndType  *pWdiInd           = NULL;
+
+
+  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+  WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+         "%s", __func__);
+
+  /*-------------------------------------------------------------------------
+    Sanity check
+  -------------------------------------------------------------------------*/
+
+  if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ))
+  {
+     WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL,
+                 "%s: Invalid parameters", __func__);
+     WDI_ASSERT(0);
+     return WDI_STATUS_E_FAILURE;
+  }
+  pWdiInd = (WDI_StopBatchScanIndType *)pEventData->pEventData;
+  /*-----------------------------------------------------------------------
+    Get message buffer
+  -----------------------------------------------------------------------*/
+
+  if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx,
+                        WDI_STOP_BATCH_SCAN_IND,
+                        sizeof(tHalBatchScanStopIndParam),
+                        &pSendBuffer, &usDataOffset, &usSendSize))||
+      ( usSendSize < (usDataOffset + sizeof(tHalBatchScanStopIndParam))))
+  {
+     WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_FATAL,
+              "Unable to get send buffer in stop batch scan ind %p ",
+                pEventData);
+     WDI_ASSERT(0);
+     return WDI_STATUS_E_FAILURE;
+  }
+
+  pHalInd = (tHalBatchScanStopIndParam *)(pSendBuffer + usDataOffset);
+  pHalInd->param = pWdiInd->param;
+
+  pWDICtx->pReqStatusUserData = NULL;
+  pWDICtx->pfncRspCB = NULL;
+  /*-------------------------------------------------------------------------
+    Send Stop batch scan indication to HAL
+  -------------------------------------------------------------------------*/
+  wdiStatus =  WDI_SendIndication( pWDICtx, pSendBuffer, usSendSize);
+  return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus:WDI_STATUS_SUCCESS_SYNC;
+}
+
+/**
+ @brief This API is called to trigger batch scan results from FW
+
+ @param pWDICtx:         pointer to the WLAN DAL context
+        pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessTriggerBatchScanResultInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  WDI_Status                        wdiStatus;
+  wpt_uint8*                        pSendBuffer        = NULL;
+  wpt_uint16                        usDataOffset       = 0;
+  wpt_uint16                        usSendSize         = 0;
+  tHalBatchScanTriggerResultParam   *pHalInd           = NULL;
+  WDI_TriggerBatchScanResultIndType *pWdiInd           = NULL;
+
+
+  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+  WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+         "%s", __func__);
+
+  /*-------------------------------------------------------------------------
+    Sanity check
+  -------------------------------------------------------------------------*/
+
+  if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ))
+  {
+     WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL,
+                 "%s: Invalid parameters", __func__);
+     WDI_ASSERT(0);
+     return WDI_STATUS_E_FAILURE;
+  }
+  pWdiInd = (WDI_TriggerBatchScanResultIndType *)pEventData->pEventData;
+  /*-----------------------------------------------------------------------
+    Get message buffer
+  -----------------------------------------------------------------------*/
+
+  if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx,
+                        WDI_TRIGGER_BATCH_SCAN_RESULT_IND,
+                        sizeof(tHalBatchScanTriggerResultParam),
+                        &pSendBuffer, &usDataOffset, &usSendSize))||
+      ( usSendSize < (usDataOffset + sizeof(tHalBatchScanTriggerResultParam))))
+  {
+     WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_FATAL,
+              "Unable to get send buffer in stop batch scan ind %p ",
+                pEventData);
+     WDI_ASSERT(0);
+     return WDI_STATUS_E_FAILURE;
+  }
+
+  pHalInd = (tHalBatchScanTriggerResultParam *)(pSendBuffer + usDataOffset);
+  pHalInd->param = pWdiInd->param;
+
+  pWDICtx->pReqStatusUserData = NULL;
+  pWDICtx->pfncRspCB = NULL;
+  /*-------------------------------------------------------------------------
+    Send trigger batch scan result indication to HAL
+  -------------------------------------------------------------------------*/
+  wdiStatus =  WDI_SendIndication( pWDICtx, pSendBuffer, usSendSize);
+  return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus:WDI_STATUS_SUCCESS_SYNC;
+}
+
+
+/**
+ @brief Process set batch scan response from FW
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+         pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessSetBatchScanRsp
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+    WDI_SetBatchScanCb   wdiSetBatchScanCb;
+    WDI_SetBatchScanRspType *pSetBatchScanRsp;
+
+    tHalBatchScanSetRspParam *pHalSetBatchScanRsp;
+    /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    /*sanity check*/
+    if (( NULL == pWDICtx ) || ( NULL == pEventData ) ||
+      ( NULL == pEventData->pEventData))
+    {
+        WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                 "%s: Invalid parameters", __func__);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    wdiSetBatchScanCb = (WDI_SetBatchScanCb)pWDICtx->pfncRspCB;
+    if ( NULL == wdiSetBatchScanCb)
+    {
+        WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL,
+            "%s: call back function is NULL", __func__);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    pSetBatchScanRsp = wpalMemoryAllocate(sizeof(WDI_SetBatchScanRspType));
+
+    if (NULL == pSetBatchScanRsp)
+    {
+        WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+            "Failed to allocate memory in set batch scan response %x %x %x ",
+            pWDICtx, pEventData, pEventData->pEventData);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    /*extract response and send it to UMAC*/
+    pHalSetBatchScanRsp = (tHalBatchScanSetRspParam *)pEventData->pEventData;
+
+    pSetBatchScanRsp->nScansToBatch = pHalSetBatchScanRsp->supportedMscan;
+
+    /*Notify UMAC*/
+    wdiSetBatchScanCb(pSetBatchScanRsp, pWDICtx->pRspCBUserData);
+
+    wpalMemoryFree(pSetBatchScanRsp);
+
+    return WDI_STATUS_SUCCESS;
+}/*WDI_ProcessSetBatchScanRsp*/
+
+/**
+ @brief Process batch scan result indication from FW
+
+ @param  pWDICtx:         pointer to the WLAN DAL context
+         pEventData:      pointer to the event information structure
+
+ @see
+ @return Result of the function call
+*/
+WDI_Status
+WDI_ProcessBatchScanResultInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+    void *pBatchScanResultInd;
+    WDI_LowLevelIndType wdiInd;
+    /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    /*sanity check*/
+    if (( NULL == pWDICtx ) || ( NULL == pEventData ) ||
+      ( NULL == pEventData->pEventData))
+    {
+        WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                 "%s: Invalid parameters", __func__);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    /*extract response and send it to UMAC*/
+    pBatchScanResultInd = (void *)pEventData->pEventData;
+
+    /*Fill in the indication parameters*/
+    wdiInd.wdiIndicationType = WDI_BATCH_SCAN_RESULT_IND;
+
+    wdiInd.wdiIndicationData.pBatchScanResult = pBatchScanResultInd;
+
+    /*Notify UMAC*/
+    if (pWDICtx->wdiLowLevelIndCB)
+    {
+        pWDICtx->wdiLowLevelIndCB( &wdiInd, pWDICtx->pIndUserData );
+    }
+    else
+    {
+        WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                 "%s: WDILowLevelIndCb is null", __func__);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    return WDI_STATUS_SUCCESS;
+} /*End of WDI_ProcessBatchScanResultInd*/
+
+/**
+ @brief WDI_ProcessSetBatchScanReq -
+    Set batch scan request to FW
+
+ @param  pWDICtx : wdi context
+         pEventData : indication data
+
+ @see
+ @return none
+*/
+WDI_Status WDI_ProcessSetBatchScanReq
+(
+    WDI_ControlBlockType*  pWDICtx,
+    WDI_EventInfoType*     pEventData
+)
+{
+    WDI_SetBatchScanReqType *pWdiReq;
+    WDI_Status               wdiStatus;
+    wpt_uint8*               pSendBuffer        = NULL;
+    wpt_uint16               usDataOffset       = 0;
+    wpt_uint16               usSendSize         = 0;
+    tHalBatchScanSetParams  *pHalReq;
+    /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+    /*sanity check*/
+    if ((NULL == pEventData) || (NULL == pEventData->pEventData))
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+            "%s: Invalid parameters in set batch scan request", __func__);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+
+    pWdiReq = (WDI_SetBatchScanReqType *)pEventData->pEventData;
+
+
+    /*get message buffer*/
+    if ((WDI_STATUS_SUCCESS != WDI_GetMessageBuffer(pWDICtx,
+                              WDI_SET_BATCH_SCAN_REQ,
+                              sizeof(tHalBatchScanSetParams),
+                              &pSendBuffer, &usDataOffset, &usSendSize))||
+      (usSendSize < (usDataOffset + sizeof(tHalBatchScanSetParams))))
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_ERROR,
+            "Unable to get send buffer for SET_BATCH_SCAN_REQ ");
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    pHalReq = (tHalBatchScanSetParams *)(pSendBuffer + usDataOffset);
+
+    pHalReq->rtt = pWdiReq->rtt;
+    pHalReq->rfBand = pWdiReq->rfBand;
+    pHalReq->bestNetworks = pWdiReq->bestNetwork;
+    pHalReq->scanInterval = pWdiReq->scanFrequency;
+    pHalReq->numScan2Batch = pWdiReq->numberOfScansToBatch;
+
+    /*send set batch scan request to fw*/
+    pWDICtx->pfncRspCB          = pEventData->pCBfnc;
+    pWDICtx->pReqStatusUserData = pEventData->pUserData;
+
+    wdiStatus = WDI_SendMsg(pWDICtx, pSendBuffer,
+                          usSendSize, pWDICtx->pfncRspCB,
+                          pWDICtx->pReqStatusUserData,
+                          WDI_SET_BATCH_SCAN_RESP);
+
+    return wdiStatus;
+}
+
+/**
+ @brief WDI_SetBatchScanReq
+    This API is called to set batch scan request in FW
+
+ @param pBatchScanReqParam : pointer to set batch scan re param
+        usrData : Client context
+        setBatchScanRspCb : set batch scan resp callback
+ @see
+ @return SUCCESS or FAIL
+*/
+WDI_Status WDI_SetBatchScanReq
+(
+    void *pBatchScanReqParam,
+    void *usrData,
+    WDI_SetBatchScanCb setBatchScanRspCb
+)
+{
+    WDI_EventInfoType      wdiEventData;
+
+    /*sanity check*/
+    if (eWLAN_PAL_FALSE == gWDIInitialized)
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+            "WDI API call before module is initialized - Fail request");
+
+        return WDI_STATUS_E_NOT_ALLOWED;
+    }
+
+    /* fill in event data and post to the main FSM */
+    wdiEventData.wdiRequest      = WDI_SET_BATCH_SCAN_REQ;
+    wdiEventData.pEventData      = pBatchScanReqParam;
+    wdiEventData.uEventDataSize  = sizeof(WDI_SetBatchScanReqType);
+    wdiEventData.pCBfnc          = setBatchScanRspCb;
+    wdiEventData.pUserData       = usrData;
+
+    return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+/**
+ @brief WDI_StopbatchScanInd: Send stop batch scan indication to FW
+
+ @param None
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_StopBatchScanInd(WDI_StopBatchScanIndType *pWdiReq)
+{
+  WDI_EventInfoType      wdiEventData;
+
+  /*-------------------------------------------------------------------------
+    Sanity Check
+   ------------------------------------------------------------------------*/
+  if (eWLAN_PAL_FALSE == gWDIInitialized)
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+               "WDI API call before module is initialized - Fail request!");
+
+    return WDI_STATUS_E_NOT_ALLOWED;
+  }
+
+  /*-------------------------------------------------------------------------
+    Fill in Event data and post to the Main FSM
+   ------------------------------------------------------------------------*/
+  wdiEventData.wdiRequest      = WDI_STOP_BATCH_SCAN_IND;
+  wdiEventData.pEventData      = pWdiReq;
+  wdiEventData.uEventDataSize  = sizeof(WDI_StopBatchScanIndType);
+  wdiEventData.pCBfnc          = NULL;
+  wdiEventData.pUserData       = NULL;
+
+  return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+/**
+ @brief WDI_TriggerBatchScanResultInd
+    This API is called to pull batch scan result from FW
+
+ @param pWdiReq : pointer to get batch scan ind param
+ @see
+ @return SUCCESS or FAIL
+*/
+WDI_Status WDI_TriggerBatchScanResultInd
+(
+    WDI_TriggerBatchScanResultIndType *pWdiReq
+)
+{
+    WDI_EventInfoType      wdiEventData;
+    /*-------------------------------------------------------------------------
+      Sanity Check
+    ------------------------------------------------------------------------*/
+    if (eWLAN_PAL_FALSE == gWDIInitialized)
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+             "WDI API call before module is initialized - Fail request!");
+
+        return WDI_STATUS_E_NOT_ALLOWED;
+    }
+
+    /*-------------------------------------------------------------------------
+      Fill in Event data and post to the Main FSM
+     ------------------------------------------------------------------------*/
+    wdiEventData.wdiRequest      = WDI_TRIGGER_BATCH_SCAN_RESULT_IND;
+    wdiEventData.pEventData      = pWdiReq;
+    wdiEventData.uEventDataSize  = sizeof(WDI_TriggerBatchScanResultIndType);
+    wdiEventData.pCBfnc          = NULL;
+    wdiEventData.pUserData       = NULL;
+
+    return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+#endif /*FEATURE_WLAN_BATCH_SCAN*/
diff --git a/Kbuild b/Kbuild
index 5771d94..b50ab80 100644
--- a/Kbuild
+++ b/Kbuild
@@ -533,6 +533,7 @@
 		-DWLAN_WAKEUP_EVENTS \
 	        -DWLAN_KD_READY_NOTIFIER \
 		-DWLAN_NL80211_TESTMODE \
+		-DFEATURE_WLAN_BATCH_SCAN \
 		-DFEATURE_WLAN_LPHB
 
 ifneq ($(CONFIG_PRONTO_WLAN),)