wlan: Switch to new channel once ECSA is indicated in beacon

Once ECSA is indicated in beacon Swith to new channel and update the
beacon on new channel.

Change-Id: I8f9b1dd5d6b3fe7a9b41d3dc8cfa6016d28b18e6
CRs-Fixed: 2143138
diff --git a/CORE/SME/src/csr/csrApiRoam.c b/CORE/SME/src/csr/csrApiRoam.c
index e897126..b06ffb4 100644
--- a/CORE/SME/src/csr/csrApiRoam.c
+++ b/CORE/SME/src/csr/csrApiRoam.c
@@ -2837,7 +2837,10 @@
          * failure, decrement bRefAssocStartCnt.
          */
         pSession->bRefAssocStartCnt--;
-    }
+    } else if (u1 == eCSR_ROAM_ECSA_CHAN_CHANGE_RSP && u2 ==
+               eCSR_ROAM_RESULT_NONE)
+        pSession->connectedProfile.operationChannel =
+               pRoamInfo->ap_chan_change_rsp->new_channel;
 
     if(NULL != pSession->callback)
     {
@@ -19670,7 +19673,49 @@
    status = palSendMBMessage(mac_ctx->hHdd, msg);
    if (!VOS_IS_STATUS_SUCCESS(status))
          smsLog(mac_ctx, LOGE,
-                FL(" channel switch req fauiled status %d "), status);
+                FL(" channel switch IE req failed status %d "), status);
    return status;
 }
 
+VOS_STATUS csr_roam_channel_change_req(tpAniSirGlobal mac_ctx,
+   tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode, tCsrRoamProfile *profile)
+{
+   VOS_STATUS status = VOS_STATUS_SUCCESS;
+   struct sir_channel_chanege_req *msg;
+   tCsrRoamStartBssParams param;
+
+   vos_mem_zero(&param, sizeof(tCsrRoamStartBssParams));
+
+   csrRoamGetBssStartParms(mac_ctx, profile, &param);
+
+   msg = vos_mem_malloc(sizeof(*msg));
+   if (!msg) {
+        smsLog(mac_ctx, LOGE, FL(" Memory alloc failed "));
+        return VOS_STATUS_E_NOMEM;
+   }
+
+   msg->type = eWNI_SME_ECSA_CHAN_CHANGE_REQ;
+   msg->len = sizeof(*msg);
+
+   msg->new_chan = new_chan;
+   msg->cb_mode = cb_mode;
+   vos_mem_copy(msg->bssid, bssid, VOS_MAC_ADDR_SIZE);
+   msg->dot11mode = csrTranslateToWNICfgDot11Mode(mac_ctx,
+                        mac_ctx->roam.configParam.uCfgDot11Mode);
+   if (IS_24G_CH(msg->new_chan) &&
+      (false == mac_ctx->roam.configParam.enableVhtFor24GHz) &&
+      (WNI_CFG_DOT11_MODE_11AC == msg->dot11mode ||
+       WNI_CFG_DOT11_MODE_11AC_ONLY == msg->dot11mode))
+        msg->dot11mode = WNI_CFG_DOT11_MODE_11N;
+
+   vos_mem_copy(&msg->operational_rateset,
+            &param.operationalRateSet, sizeof(msg->operational_rateset));
+   vos_mem_copy(&msg->extended_rateset,
+           &param.extendedRateSet, sizeof(msg->extended_rateset));
+
+   status = palSendMBMessage(mac_ctx->hHdd, msg);
+   if (!VOS_IS_STATUS_SUCCESS(status))
+         smsLog(mac_ctx, LOGE,
+                FL(" channel switch req fauiled status %d "), status);
+   return status;
+}
diff --git a/CORE/SME/src/csr/csrUtil.c b/CORE/SME/src/csr/csrUtil.c
index 52687fe..4f4d524 100644
--- a/CORE/SME/src/csr/csrUtil.c
+++ b/CORE/SME/src/csr/csrUtil.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -1304,6 +1304,8 @@
 #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
         CASE_RETURN_STR(eCSR_ROAM_UPDATE_MAX_RATE_IND);
         CASE_RETURN_STR(eCSR_ROAM_LOST_LINK_PARAMS_IND);
+        CASE_RETURN_STR(eCSR_ROAM_ECSA_BCN_TX_IND);
+        CASE_RETURN_STR(eCSR_ROAM_ECSA_CHAN_CHANGE_RSP);
     default:
         return "unknown";
     }
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 76d943b..6d523a3 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -2384,6 +2384,72 @@
     return status;
 }
 
+/**
+ * sme_ecsa_msg_processor() - Handle ECSA indication and resp from LIM
+ * @mac_ctx: A pointer to Global MAC structure
+ * @msg_type: Indication/resp type
+ * @msg_buf: Indication/resp buffer
+ *
+ * Return VOS_STATUS
+ */
+static VOS_STATUS sme_ecsa_msg_processor(tpAniSirGlobal mac_ctx,
+   uint16_t msg_type, void *msg_buf)
+{
+   tCsrRoamInfo roam_info = { 0 };
+   struct sir_ecsa_ie_complete_ind *ecsa_ie_cmp_ind;
+   struct sir_channel_chanege_rsp *chan_params;
+   uint32_t session_id = 0;
+   eRoamCmdStatus roamStatus;
+   eCsrRoamResult roamResult;
+
+   switch (msg_type) {
+   case eWNI_SME_ECSA_IE_BEACON_COMP_IND:
+       ecsa_ie_cmp_ind =
+              (struct sir_ecsa_ie_complete_ind *) msg_buf;
+       if (!ecsa_ie_cmp_ind) {
+            smsLog(mac_ctx, LOGE, FL("pMsg is NULL for eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND"));
+            return VOS_STATUS_E_FAILURE;
+       }
+       session_id = ecsa_ie_cmp_ind->session_id;
+       roamStatus = eCSR_ROAM_ECSA_BCN_TX_IND;
+       roamResult = eCSR_ROAM_RESULT_NONE;
+       smsLog(mac_ctx, LOG1, FL("sapdfs: Received eWNI_SME_ECSA_IE_BEACON_COMP_IND for session id [%d]"),
+              session_id);
+       break;
+   case eWNI_SME_ECSA_CHAN_CHANGE_RSP:
+       chan_params = (struct sir_channel_chanege_rsp *)msg_buf;
+       roam_info.ap_chan_change_rsp =
+              vos_mem_malloc(sizeof(struct sir_channel_chanege_rsp));
+       if (!roam_info.ap_chan_change_rsp) {
+            smsLog(mac_ctx, LOGE, FL("failed to allocate ap_chan_change_rsp"));
+            return VOS_STATUS_E_FAILURE;
+       }
+       session_id = chan_params->sme_session_id;
+       roam_info.ap_chan_change_rsp->sme_session_id = session_id;
+       roam_info.ap_chan_change_rsp->new_channel = chan_params->new_channel;
+       if (chan_params->status == VOS_STATUS_SUCCESS) {
+           roam_info.ap_chan_change_rsp->status = VOS_STATUS_SUCCESS;
+           roamResult = eCSR_ROAM_RESULT_NONE;
+       } else {
+           roam_info.ap_chan_change_rsp->status = VOS_STATUS_E_FAILURE;
+           roamResult = eCSR_ROAM_RESULT_FAILURE;
+       }
+       roamStatus = eCSR_ROAM_ECSA_CHAN_CHANGE_RSP;
+       break;
+   default:
+       smsLog(mac_ctx, LOGE, FL("Invalid ECSA message: 0x%x"), msg_type);
+       return VOS_STATUS_E_FAILURE;
+   }
+
+   /* Indicate Radar Event to SAP */
+   csrRoamCallCallback(mac_ctx, session_id, &roam_info, 0,
+                       roamStatus, roamResult);
+   if (roam_info.ap_chan_change_rsp)
+       vos_mem_free(roam_info.ap_chan_change_rsp);
+
+   return VOS_STATUS_SUCCESS;
+}
+
 /*--------------------------------------------------------------------------
 
   \brief sme_ProcessMsg() - The main message processor for SME.
@@ -2873,6 +2939,21 @@
                           " nothing to process");
               }
               break;
+          case eWNI_SME_ECSA_IE_BEACON_COMP_IND:
+          case eWNI_SME_ECSA_CHAN_CHANGE_RSP:
+              MTRACE(vos_trace(VOS_MODULE_ID_SME,
+                     TRACE_CODE_SME_RX_WDA_MSG, NO_SESSION, pMsg->type));
+              if (pMsg->bodyptr)
+              {
+                  sme_ecsa_msg_processor(pMac, pMsg->type, pMsg->bodyptr);
+                  vos_mem_free(pMsg->bodyptr);
+              }
+              else
+              {
+                  smsLog(pMac, LOGE,
+                         FL("Empty message for (eWNI_SME_ECSA_IE_BEACON_COMP_IND)"));
+              }
+              break;
 
           default:
 
@@ -15111,3 +15192,24 @@
    return status;
 }
 
+
+VOS_STATUS sme_roam_channel_change_req(tHalHandle hal, tCsrBssid bssid,
+                                   uint8_t new_chan, tCsrRoamProfile *profile)
+{
+   VOS_STATUS status;
+   tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+   uint8_t cb_mode = 0;
+
+   status = sme_AcquireGlobalLock(&mac_ctx->sme);
+   if (VOS_IS_STATUS_SUCCESS(status)) {
+       if (CSR_IS_CHANNEL_5GHZ(new_chan)) {
+           sme_SelectCBMode(hal, profile->phyMode, new_chan);
+           cb_mode = mac_ctx->roam.configParam.channelBondingMode5GHz;
+       }
+       status = csr_roam_channel_change_req(mac_ctx, bssid, new_chan, cb_mode,
+                                            profile);
+       sme_ReleaseGlobalLock(&mac_ctx->sme);
+   }
+   return status;
+}
+