wlan: add update channel list request support

Add capability to support dynamic updation of scan channel list based
on the change in country code.

Change-Id: I5d898617932fe07026f1e6423c676a6838ee5405
CRs-Fixed: 605330
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 2c20a44..358a5f7 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -79,6 +79,7 @@
 #include "wlan_qct_sys.h"
 /* Used MACRO's */
 /* Get WDA context from vOSS module */
+#define WDA_2_4_GHZ_MAX_FREQ  3000
 #define VOS_GET_WDA_CTXT(a)            vos_get_context(VOS_MODULE_ID_WDA, a)
 #define VOS_GET_MAC_CTXT(a)            vos_get_context(VOS_MODULE_ID_PE, a)
 #define OFFSET_OF(structType,fldName)   (&((structType*)0)->fldName)
@@ -5886,6 +5887,172 @@
    }
    return CONVERT_WDI2VOS_STATUS(status) ;
 }
+
+/*
+ * FUNCTION: WDA_UpdateChReqCallback
+ *
+ */
+void WDA_UpdateChReqCallback(WDI_Status status, void* pUserData)
+{
+   tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData;
+   WDI_UpdateChReqParamsType *pwdiUpdateChReqParam =
+       (WDI_UpdateChReqParamsType *)pWdaParams->wdaWdiApiMsgParam;
+   WDI_UpdateChannelReqType *pwdiUpdateChanReqType =
+      &pwdiUpdateChReqParam->wdiUpdateChanParams;
+   WDI_UpdateChannelReqinfoType *pChanInfoType =
+       pwdiUpdateChanReqType->pchanParam;
+   tSirUpdateChanList *pChanList =
+       (tSirUpdateChanList *)pWdaParams->wdaMsgParam;
+
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                                          "<------ %s " ,__func__);
+   if(NULL == pWdaParams)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s: pWdaParams received NULL", __func__);
+      VOS_ASSERT(0);
+      return;
+   }
+
+   /*
+    * currently there is no response message is expected between PE and
+    * WDA, Failure return from WDI is a ASSERT condition
+    */
+   vos_mem_free(pChanInfoType);
+   vos_mem_free(pChanList);
+   vos_mem_free(pWdaParams->wdaWdiApiMsgParam);
+   vos_mem_free(pWdaParams);
+
+   return;
+}
+
+/*
+ * FUNCTION: WDA_ProcessUpdateChannelList
+ * Request to WDI to Update the ChannelList params.
+ */
+VOS_STATUS WDA_ProcessUpdateChannelList(tWDA_CbContext *pWDA,
+        tSirUpdateChanList *pChanList)
+{
+   WDI_Status status = WDI_STATUS_SUCCESS;
+   WDI_UpdateChReqParamsType *pwdiUpdateChReqParam;
+   WDI_UpdateChannelReqType *pwdiUpdateChanReqType;
+   WDI_UpdateChannelReqinfoType *pChanInfoType;
+   tWDA_ReqParams *pWdaParams;
+   wpt_uint8 i;
+
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                                          "------> %s " ,__func__);
+   if(NULL == pChanList)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s: NULL pChanList", __func__);
+      VOS_ASSERT(0);
+      return VOS_STATUS_E_INVAL;
+   }
+
+   if(!WDA_getFwWlanFeatCaps(UPDATE_CHANNEL_LIST))
+   {
+       VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+               "Update channel list capability Not Supported");
+       vos_mem_free(pChanList);
+       return VOS_STATUS_E_INVAL;
+   }
+
+   pwdiUpdateChReqParam = (WDI_UpdateChReqParamsType *)vos_mem_malloc(
+           sizeof(WDI_UpdateChReqParamsType));
+   if(NULL == pwdiUpdateChReqParam)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s: VOS MEM Alloc Failed for WDI_UpdateChReqParamsType",
+              __func__);
+      VOS_ASSERT(0);
+      vos_mem_free(pChanList);
+      return VOS_STATUS_E_NOMEM;
+   }
+   pwdiUpdateChanReqType = &pwdiUpdateChReqParam->wdiUpdateChanParams;
+   pChanInfoType = (WDI_UpdateChannelReqinfoType *)
+       vos_mem_malloc(sizeof(WDI_UpdateChannelReqinfoType) *
+               pChanList->numChan);
+   if(NULL == pChanInfoType)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: VOS MEM Alloc Failure", __func__);
+      VOS_ASSERT(0);
+      vos_mem_free(pChanList);
+      vos_mem_free(pwdiUpdateChReqParam);
+      return VOS_STATUS_E_NOMEM;
+   }
+   vos_mem_zero(pChanInfoType, sizeof(WDI_UpdateChannelReqinfoType)
+           * pChanList->numChan);
+   pwdiUpdateChanReqType->pchanParam = pChanInfoType;
+
+   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(pChanList);
+      vos_mem_free(pChanInfoType);
+      vos_mem_free(pwdiUpdateChReqParam);
+      return VOS_STATUS_E_NOMEM;
+   }
+   pwdiUpdateChanReqType->numchan = pChanList->numChan;
+
+   for(i = 0; i < pwdiUpdateChanReqType->numchan; i++)
+   {
+       pChanInfoType->mhz =
+           vos_chan_to_freq(pChanList->chanParam[i].chanId);
+
+       pChanInfoType->band_center_freq1 = pChanInfoType->mhz;
+       pChanInfoType->band_center_freq2 = 0;
+
+       VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+               "chan[%d] = %u", i, pChanInfoType->mhz);
+       if (pChanList->chanParam[i].dfsSet)
+       {
+           WDA_SET_CHANNEL_FLAG(pChanInfoType, WLAN_HAL_CHAN_FLAG_PASSIVE);
+           VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                   "chan[%d] DFS[%d]", pChanList->chanParam[i].chanId,
+                   pChanList->chanParam[i].dfsSet);
+       }
+
+       if (pChanInfoType->mhz < WDA_2_4_GHZ_MAX_FREQ)
+       {
+           WDA_SET_CHANNEL_MODE(pChanInfoType, MODE_11G);
+       }
+       else
+       {
+           WDA_SET_CHANNEL_MODE(pChanInfoType, MODE_11A);
+           WDA_SET_CHANNEL_FLAG(pChanInfoType, WLAN_HAL_CHAN_FLAG_ALLOW_HT);
+           WDA_SET_CHANNEL_FLAG(pChanInfoType, WLAN_HAL_CHAN_FLAG_ALLOW_VHT);
+       }
+
+       WDA_SET_CHANNEL_MAX_POWER(pChanInfoType, pChanList->chanParam[i].pwr);
+       WDA_SET_CHANNEL_REG_POWER(pChanInfoType, pChanList->chanParam[i].pwr);
+
+       pChanInfoType++;
+   }
+
+   pwdiUpdateChReqParam->wdiReqStatusCB = NULL;
+   pWdaParams->pWdaContext = pWDA;
+   pWdaParams->wdaMsgParam = (void *)pChanList;
+   /* store Params pass it to WDI */
+   pWdaParams->wdaWdiApiMsgParam = (void *)pwdiUpdateChReqParam;
+   status = WDI_UpdateChannelReq(pwdiUpdateChReqParam,
+           (WDI_UpdateChannelRspCb)WDA_UpdateChReqCallback, pWdaParams);
+   if(IS_WDI_STATUS_FAILURE(status))
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "Failure in Update Channel REQ Params WDI API, free all the memory");
+      vos_mem_free(pwdiUpdateChanReqType->pchanParam);
+      vos_mem_free(pwdiUpdateChReqParam);
+      vos_mem_free(pWdaParams->wdaMsgParam);
+      vos_mem_free(pWdaParams);
+   }
+   return CONVERT_WDI2VOS_STATUS(status);
+}
+
 /*
  * FUNCTION: WDA_AddTSReqCallback
  * send ADD TS RSP back to PE
@@ -11776,6 +11943,12 @@
          WDA_ProcessDelBAReq(pWDA, (tDelBAParams *)pMsg->bodyptr);
          break;
       }
+      case WDA_UPDATE_CHAN_LIST_REQ:
+      {
+         WDA_ProcessUpdateChannelList(pWDA,
+                 (tSirUpdateChanList *)pMsg->bodyptr);
+         break;
+      }
       case WDA_SET_LINK_STATE:
       {
          WDA_ProcessSetLinkState(pWDA, (tLinkStateParams *)pMsg->bodyptr);