wlan: Process user hints for regulatory change in driver

In SAP to set country from hostapd.conf we give regulatory hint
to NL80211 which should set country in nl80211 and driver.
Regulatory hints by user were ignored by nl80211(ignore till
wiphy->regd is null as WIPHY_FLAG_STRICT_REGULATORY is set)
and by driver.

In change interface to SAP we will again give regulatory hint
from driver to allocate wiphy->regd so that nl80211 will
process hints by user.
And in wlan_hdd_crda_reg_notifier we will set country
and update the regd in driver.

These changes are for NV.bin solution only.

Change-Id: I1a0bbc14cb47c9c12cd48c66ac40cd217dd7dfaa
CRs-fixed: 570018
diff --git a/CORE/VOSS/src/vos_nvitem.c b/CORE/VOSS/src/vos_nvitem.c
index f22f43c..a664c76 100644
--- a/CORE/VOSS/src/vos_nvitem.c
+++ b/CORE/VOSS/src/vos_nvitem.c
@@ -78,6 +78,11 @@
 static char linux_reg_cc[2] = {0, 0};
 static v_REGDOMAIN_t temp_reg_domain = REGDOMAIN_COUNT;
 
+#else
+
+/* Cant access pAdapter in this file so defining a new variable to wait when changing country*/
+static struct completion change_country_code;
+
 #endif
 
 static char crda_alpha2[2] = {0, 0}; /* country code from initial crda req */
@@ -86,7 +91,6 @@
 static v_BOOL_t crda_regulatory_run_time_entry_valid = VOS_FALSE;
 
 
-
 /*----------------------------------------------------------------------------
  * Preprocessor Definitions and Constants
  * -------------------------------------------------------------------------*/
@@ -2525,10 +2529,12 @@
   \brief vos_nv_setRegDomain -
   \param clientCtxt  - Client Context, Not used for PRIMA
               regId  - Regulatory Domain ID
+              sendRegHint - send hint to nl80211
   \return status set REG domain operation
   \sa
   -------------------------------------------------------------------------*/
-VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId)
+VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId,
+                                                v_BOOL_t sendRegHint)
 {
 
     if (regId >= REGDOMAIN_COUNT)
@@ -3311,10 +3317,12 @@
   \brief vos_nv_setRegDomain -
   \param clientCtxt  - Client Context, Not used for PRIMA
               regId  - Regulatory Domain ID
+              sendRegHint - send hint to nl80211
   \return status set REG domain operation
   \sa
   -------------------------------------------------------------------------*/
-VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId)
+VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId,
+                                                  v_BOOL_t sendRegHint)
 {
     v_CONTEXT_t pVosContext = NULL;
     hdd_context_t *pHddCtx = NULL;
@@ -3338,7 +3346,7 @@
    /* when CRDA is not running then we are world roaming.
       In this case if 11d is enabled, then country code should
       be update on basis of world roaming */
-   if (NULL != pHddCtx)
+   if (NULL != pHddCtx && sendRegHint)
    {
       wiphy = pHddCtx->wiphy;
       regulatory_hint(wiphy, "00");
@@ -3482,7 +3490,15 @@
       return VOS_STATUS_E_EXISTS;
    }
 }
-
+/* FUNCTION: vos_nv_change_country_code_cb
+*  to wait for contry code completion
+*/
+void* vos_nv_change_country_code_cb(void *pAdapter)
+{
+   struct completion *change_code_cng = pAdapter;
+   complete(change_code_cng);
+   return NULL;
+}
 
 /*
  * Function: wlan_hdd_crda_reg_notifier
@@ -3510,13 +3526,47 @@
                      " %c%c\n", request->alpha2[0], request->alpha2[1]);
     if (request->initiator == NL80211_REGDOM_SET_BY_USER)
     {
+       int status;
        wiphy_dbg(wiphy, "info: set by user\n");
-       if (create_crda_regulatory_entry(wiphy, request, pHddCtx->cfg_ini->nBandCapability) != 0)
+       init_completion(&change_country_code);
+       /* We will process hints by user from nl80211 in driver.
+       * sme_ChangeCountryCode will set the country to driver
+       * and update the regdomain.
+       * when we return back to nl80211 from this callback, the nl80211 will
+       * send NL80211_CMD_REG_CHANGE event to the hostapd waking it up to
+       * query channel list from nl80211. Thus we need to update the channels
+       * according to reg domain set by user before returning to nl80211 so
+       * that hostapd will gets the updated channels.
+       * The argument sendRegHint in sme_ChangeCountryCode is
+       * set to eSIR_FALSE (hint is from nl80211 and thus
+       * no need to notify nl80211 back)*/
+       status = sme_ChangeCountryCode(pHddCtx->hHal,
+                                   (void *)(tSmeChangeCountryCallback)
+                                   vos_nv_change_country_code_cb,
+                                   request->alpha2,
+                                   &change_country_code,
+                                   pHddCtx->pvosContext,
+                                   eSIR_FALSE,
+                                   eSIR_FALSE);
+       if (eHAL_STATUS_SUCCESS == status)
+       {
+          status = wait_for_completion_interruptible_timeout(
+                                       &change_country_code,
+                                       msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
+          if(status <= 0)
+          {
+             wiphy_dbg(wiphy, "info: set country timed out\n");
+          }
+       }
+       else
+       {
+          wiphy_dbg(wiphy, "info: unable to set country by user\n");
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0))
           return;
 #else
           return 0;
 #endif
+       }
        // ToDo
        /* Don't change default country code to CRDA country code by user req */
        /* Shouldcall sme_ChangeCountryCode to send a message to trigger read
@@ -3524,7 +3574,8 @@
        //sme_ChangeCountryCode(pHddCtx->hHal, NULL,
        //    &country_code[0], pAdapter, pHddCtx->pvosContext);
     }
-    else if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
+
+    if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
     {
        wiphy_dbg(wiphy, "info: set by country IE\n");
        if (create_crda_regulatory_entry(wiphy, request, pHddCtx->cfg_ini->nBandCapability) != 0)
@@ -3543,7 +3594,8 @@
        //    &country_code[0], pAdapter, pHddCtx->pvosContext);
     }
     else if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
-             (request->initiator == NL80211_REGDOM_SET_BY_CORE))
+             (request->initiator == NL80211_REGDOM_SET_BY_CORE)||
+                (request->initiator == NL80211_REGDOM_SET_BY_USER))
     {
          if ( eHAL_STATUS_SUCCESS !=  sme_GetCountryCode(pHddCtx->hHal, ccode, &uBufLen))
          {