wlan: Add Dhcp server offload feature

Add support to set the dhcp server offload.
dhcp info such as DHCP enable, server ip address,
number of clients, and start address of dhcp pool
will be sent to firmware.

Change-Id: Id24c355820287d77b0e4200b86b42fe80e6cd4f8
CRs-Fixed: 1091422
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 7d06c2e..8bcbee0 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -47,6 +47,12 @@
 #include <vos_types.h>
 #include <csrApi.h>
 
+#ifdef DHCP_SERVER_OFFLOAD
+#define IPADDR_NUM_ENTRIES     (4)
+#define IPADDR_STRING_LENGTH   (16)
+#define DHCP_START_POOL_ADDRESS 100
+#endif /* DHCP_SERVER_OFFLOAD */
+
 //Number of items that can be configured
 #define MAX_CFG_INI_ITEMS   512
 
@@ -2743,6 +2749,32 @@
 #define CFG_DISABLE_BAR_WAKEUP_HOST_MAX         1
 #define CFG_DISABLE_BAR_WAKEUP_HOST_DEFAULT     0
 
+#ifdef DHCP_SERVER_OFFLOAD
+/*
+ * Enable/Disable DHCP Server Offload
+ * Default: Disable
+ */
+#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_NAME      "gDHCPServerOffloadEnable"
+#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MIN       ( 0 )
+#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MAX       ( 1 )
+#define CFG_DHCP_SERVER_OFFLOAD_SUPPORT_DEFAULT   ( 1 )
+
+/* Max number of DHCP clients to be supported */
+#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_NAME     "gDHCPMaxNumClients"
+#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MIN      ( 1 )
+#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MAX      ( 8 )
+#define CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_DEFAULT  ( 8 )
+
+/* Start address of the pool */
+#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_NAME     "gDHCPStartLsb"
+#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_MIN      ( 100 )
+#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_MAX      ( 255 )
+#define CFG_DHCP_SERVER_OFFLOAD_START_LSB_DEFAULT  ( 100 )
+
+/* DHCP Server IP*/
+#define CFG_DHCP_SERVER_IP_NAME     "gDHCPServerIP"
+#define CFG_DHCP_SERVER_IP_DEFAULT  "192,168,1,2"
+#endif /* DHCP_SERVER_OFFLOAD */
 
 /*
  * gExtScanConcMode is used to manage EXT Scan during concurrency
@@ -3465,6 +3497,12 @@
    v_U8_t                      max_chan_for_dwell_time_cfg;
    v_U16_t                     tdls_enable_defer_time;
    v_U8_t                      boffset_correction_enable;
+#ifdef DHCP_SERVER_OFFLOAD
+   v_BOOL_t                    enable_dhcp_srv_offload;
+   v_U32_t                     dhcp_max_num_clients;
+   v_U8_t                      dhcp_srv_ip[IPADDR_STRING_LENGTH];
+   v_U8_t                      dhcp_start_lsb;
+#endif  /* DHCP_SERVER_OFFLOAD */
    uint32_t                    enable_edca_params;
    uint32_t                    edca_vo_cwmin;
    uint32_t                    edca_vi_cwmin;
@@ -3499,6 +3537,9 @@
 VOS_STATUS hdd_execute_config_command(hdd_context_t *pHddCtx, char *command);
 tANI_BOOLEAN hdd_is_okc_mode_enabled(hdd_context_t *pHddCtx);
 
+VOS_STATUS hdd_string_to_u8_array(char *str, tANI_U8 *intArray, tANI_U8 *len,
+				  tANI_U8 intArrayMaxLen);
+
 #define VAR_OFFSET( _Struct, _Var ) (offsetof(_Struct, _Var))
 #define VAR_SIZE( _Struct, _Var ) (sizeof(((_Struct *)0)->_Var))
 
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 966f6f2..5b9f38d 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -774,6 +774,14 @@
 
 } hdd_hostapd_state_t;
 
+#ifdef DHCP_SERVER_OFFLOAD
+typedef struct hdd_dhcp_state_s
+{
+    VOS_STATUS dhcp_offload_status;
+    vos_event_t vos_event;
+} hdd_dhcp_state_t;
+#endif /* DHCP_SERVER_OFFLOAD */
+
 
 /*
  * Per station structure kept in HDD for multiple station support for SoftAP
@@ -1210,6 +1218,9 @@
 
    /* Currently used antenna Index*/
    int antennaIndex;
+#ifdef DHCP_SERVER_OFFLOAD
+   hdd_dhcp_state_t dhcp_status;
+#endif /* DHCP_SERVER_OFFLOAD */
 };
 
 #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index f2f7cf9..aedea63 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -3631,6 +3631,7 @@
                CFG_SAR_BOFFSET_SET_CORRECTION_MIN,
                CFG_SAR_BOFFSET_SET_CORRECTION_MAX),
 
+
   REG_VARIABLE(CFG_ENABLE_EDCA_INI_NAME, WLAN_PARAM_Integer,
                hdd_config_t, enable_edca_params,
                VAR_FLAGS_OPTIONAL |
@@ -3775,6 +3776,33 @@
                       VAR_FLAGS_OPTIONAL,
                       (void *) CFG_SAP_AUTH_OFL_KEY_DEFAULT ),
 #endif
+#ifdef DHCP_SERVER_OFFLOAD
+  REG_VARIABLE(CFG_DHCP_SERVER_OFFLOAD_SUPPORT_NAME, WLAN_PARAM_Integer,
+               hdd_config_t, enable_dhcp_srv_offload,
+               VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+               CFG_DHCP_SERVER_OFFLOAD_SUPPORT_DEFAULT,
+               CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MIN,
+               CFG_DHCP_SERVER_OFFLOAD_SUPPORT_MAX),
+
+  REG_VARIABLE(CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_NAME, WLAN_PARAM_Integer,
+               hdd_config_t, dhcp_max_num_clients,
+               VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+               CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_DEFAULT,
+               CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MIN,
+               CFG_DHCP_SERVER_OFFLOAD_NUM_CLIENT_MAX),
+
+  REG_VARIABLE_STRING(CFG_DHCP_SERVER_IP_NAME, WLAN_PARAM_String,
+               hdd_config_t, dhcp_srv_ip,
+               VAR_FLAGS_OPTIONAL,
+               (void *) CFG_DHCP_SERVER_IP_DEFAULT),
+
+  REG_VARIABLE(CFG_DHCP_SERVER_OFFLOAD_START_LSB_NAME, WLAN_PARAM_Integer,
+               hdd_config_t, dhcp_start_lsb,
+               VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+               CFG_DHCP_SERVER_OFFLOAD_START_LSB_DEFAULT,
+               CFG_DHCP_SERVER_OFFLOAD_START_LSB_MIN,
+               CFG_DHCP_SERVER_OFFLOAD_START_LSB_MAX),
+#endif /* DHCP_SERVER_OFFLOAD */
 };
 
 /*
@@ -4312,6 +4340,21 @@
           "Name = [gPERRoamCCAEnabled] Value = [%u] ",
           pHddCtx->cfg_ini->isPERRoamCCAEnabled);
 
+#ifdef DHCP_SERVER_OFFLOAD
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+           "Name = [gDHCPServerOffloadEnable] Value = [%u]",
+                   pHddCtx->cfg_ini->enable_dhcp_srv_offload);
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+           "Name = [gDHCPMaxNumClients] Value = [%u]",
+                   pHddCtx->cfg_ini->dhcp_max_num_clients);
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+           "Name = [gDHCPServerIP] Value = [%s]",
+                   pHddCtx->cfg_ini->dhcp_srv_ip);
+  VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+           "Name = [gDHCPStartLsb] Value = [%u]",
+                   pHddCtx->cfg_ini->dhcp_start_lsb);
+#endif /* DHCP_SERVER_OFFLOAD */
+
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
           "Name = [gPERRoamFullScanThreshold] Value = [%u] ",
           pHddCtx->cfg_ini->PERRoamFullScanThreshold);
@@ -4865,8 +4908,8 @@
 
 }
 
-#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
-static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len, tANI_U8 intArrayMaxLen )
+VOS_STATUS hdd_string_to_u8_array(char *str, tANI_U8 *intArray,
+				   tANI_U8 *len, tANI_U8 intArrayMaxLen)
 {
    char *s = str;
 
@@ -4894,7 +4937,6 @@
    return VOS_STATUS_SUCCESS;
 
 }
-#endif
 
 
 v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx )
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 39e1b2c..39c3303 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -9173,6 +9173,114 @@
     return ret;
 }
 
+#ifdef DHCP_SERVER_OFFLOAD
+void hdd_dhcp_server_offload_done(void *fw_dhcp_srv_offload_cb_context,
+				  VOS_STATUS status)
+{
+	hdd_adapter_t* adapter = (hdd_adapter_t*)fw_dhcp_srv_offload_cb_context;
+
+	ENTER();
+
+	if (NULL == adapter)
+	{
+		hddLog(VOS_TRACE_LEVEL_ERROR,
+		       "%s: adapter is NULL",__func__);
+		return;
+	}
+
+	adapter->dhcp_status.dhcp_offload_status = status;
+	vos_event_set(&adapter->dhcp_status.vos_event);
+	return;
+}
+
+/**
+ * wlan_hdd_set_dhcp_server_offload() - set dhcp server offload
+ * @hostapd_adapter: pointer to hostapd adapter.
+ *
+ * Return: None
+ */
+static VOS_STATUS wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *hostapd_adapter)
+{
+	hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(hostapd_adapter);
+	sir_dhcp_srv_offload_info dhcp_srv_info;
+	tANI_U8 num_entries = 0;
+	tANI_U8 srv_ip[IPADDR_NUM_ENTRIES];
+	tANI_U8 num;
+	tANI_U32 temp;
+	VOS_STATUS ret;
+
+	ENTER();
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (0 != ret)
+		return VOS_STATUS_E_INVAL;
+
+	/* Prepare the request to send to SME */
+	dhcp_srv_info = vos_mem_malloc(sizeof(*dhcp_srv_info));
+	if (NULL == dhcp_srv_info) {
+		hddLog(VOS_TRACE_LEVEL_ERROR,
+		       "%s: could not allocate tDhcpSrvOffloadInfo!", __func__);
+		return VOS_STATUS_E_NOMEM;
+	}
+
+	vos_mem_zero(dhcp_srv_info, sizeof(*dhcp_srv_info));
+
+	dhcp_srv_info->bssidx = hostapd_adapter->sessionId;
+	dhcp_srv_info->dhcp_srv_offload_enabled = TRUE;
+	dhcp_srv_info->dhcp_client_num = hdd_ctx->cfg_ini->dhcp_max_num_clients;
+	dhcp_srv_info->start_lsb = hdd_ctx->cfg_ini->dhcp_start_lsb;
+	dhcp_srv_info->dhcp_offload_callback = hdd_dhcp_server_offload_done;
+	dhcp_srv_info->dhcp_server_offload_cb_context = hostapd_adapter;
+
+	hdd_string_to_u8_array(hdd_ctx->cfg_ini->dhcp_srv_ip,
+			       srv_ip,
+			       &num_entries,
+			       IPADDR_NUM_ENTRIES);
+	if (num_entries != IPADDR_NUM_ENTRIES) {
+		hddLog(VOS_TRACE_LEVEL_ERROR,
+		       "%s: incorrect IP address (%s) assigned for DHCP server!",
+		       __func__, hdd_ctx->cfg_ini->dhcp_srv_ip);
+		vos_mem_free(dhcp_srv_info);
+		return VOS_STATUS_E_FAILURE;
+	}
+
+	if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
+		hddLog(VOS_TRACE_LEVEL_ERROR,
+		       "%s: invalid IP address (%s)! It could NOT be multicast IP address!",
+		       __func__, hdd_ctx->cfg_ini->dhcp_srv_ip);
+		vos_mem_free(dhcp_srv_info);
+		return VOS_STATUS_E_FAILURE;
+	}
+
+	if (srv_ip[IPADDR_NUM_ENTRIES-1] >= DHCP_START_POOL_ADDRESS) {
+		hddLog(VOS_TRACE_LEVEL_ERROR,
+		       "%s: invalid IP address (%s)! The last field must be less than 100!",
+		       __func__, hdd_ctx->cfg_ini->dhcp_srv_ip);
+		vos_mem_free(dhcp_srv_info);
+		return VOS_STATUS_E_FAILURE;
+	}
+
+	for (num = 0; num < num_entries; num++) {
+		temp = srv_ip[num];
+		dhcp_srv_info->dhcp_srv_ip |= (temp << (8 * num));
+	}
+
+	if (eHAL_STATUS_SUCCESS !=
+	    sme_set_dhcp_srv_offload(hdd_ctx->hHal, dhcp_srv_info)) {
+		hddLog(VOS_TRACE_LEVEL_ERROR,
+		       "%s: sme_set_dhcp_srv_offload fail!", __func__);
+		vos_mem_free(dhcp_srv_info);
+		return VOS_STATUS_E_FAILURE;
+	}
+
+	hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+	       "%s: enable DHCP Server offload successfully!", __func__);
+
+	vos_mem_free(dhcp_srv_info);
+	return 0;
+}
+#endif /* DHCP_SERVER_OFFLOAD */
+
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0))
 static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter,
                             struct beacon_parameters *params)
@@ -9659,6 +9767,29 @@
     hdd_wmm_init(pHostapdAdapter);
     wlan_hdd_incr_active_session(pHddCtx, pHostapdAdapter->device_mode);
 
+#ifdef DHCP_SERVER_OFFLOAD
+    /* set dhcp server offload */
+    if (iniConfig->enable_dhcp_srv_offload &&
+        sme_IsFeatureSupportedByFW(SAP_OFFLOADS)) {
+        status = wlan_hdd_set_dhcp_server_offload(pHostapdAdapter);
+        if (!VOS_IS_STATUS_SUCCESS(status))
+        {
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                      ("HDD DHCP Server Offload Failed!!"));
+            return -EINVAL;
+        }
+        vos_event_reset(&pHostapdAdapter->dhcp_status.vos_event);
+        status = vos_wait_single_event(&pHostapdAdapter->dhcp_status.vos_event, 2000);
+        if (!VOS_IS_STATUS_SUCCESS(status) || pHostapdAdapter->dhcp_status.dhcp_offload_status)
+        {
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                     ("ERROR: DHCP HDD vos wait for single_event failed!! %d"),
+                     pHostapdAdapter->dhcp_status.dhcp_offload_status);
+            return -EINVAL;
+        }
+    }
+#endif /* DHCP_SERVER_OFFLOAD */
+
 #ifdef WLAN_FEATURE_P2P_DEBUG
     if (pHostapdAdapter->device_mode == WLAN_HDD_P2P_GO)
     {
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 5913fec..16d9058 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -4818,6 +4818,9 @@
 VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter )
 {
     hdd_hostapd_state_t * phostapdBuf;
+#ifdef DHCP_SERVER_OFFLOAD
+    hdd_dhcp_state_t *dhcp_status;
+#endif /* DHCP_SERVER_OFFLOAD */
     struct net_device *dev = pAdapter->dev;
     hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
     VOS_STATUS status;
@@ -4841,6 +4844,9 @@
 
     // Allocate the Wireless Extensions state structure
     phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter );
+#ifdef DHCP_SERVER_OFFLOAD
+    dhcp_status = &pAdapter->dhcp_status;
+#endif /* DHCP_SERVER_OFFLOAD */
 
     spin_lock_init(&pAdapter->sta_hash_lock);
     pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
@@ -4862,7 +4868,10 @@
 
     // Zero the memory.  This zeros the profile structure.
     memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t));
-    
+#ifdef DHCP_SERVER_OFFLOAD
+    memset(dhcp_status, 0,sizeof(*dhcp_status));
+#endif /* DHCP_SERVER_OFFLOAD */
+
     // Set up the pointer to the Wireless Extensions state structure
     // NOP
     status = hdd_set_hostapd(pAdapter);
@@ -4877,8 +4886,13 @@
          VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: Hostapd HDD vos event init failed!!"));
          return status;
     }
-    
-
+#ifdef DHCP_SERVER_OFFLOAD
+    status = vos_event_init(&dhcp_status->vos_event);
+    if (!VOS_IS_STATUS_SUCCESS(status)) {
+         VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: Hostapd HDD vos event init failed!!"));
+         return status;
+    }
+#endif /* DHCP_SERVER_OFFLOAD */
     sema_init(&(WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->semWpsPBCOverlapInd, 1);
  
      // Register as a wireless device
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index f356ded..237daca 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8964,6 +8964,15 @@
     }
 }
 
+VOS_STATUS hdd_cleanup_ap_events(hdd_adapter_t *adapter)
+{
+#ifdef DHCP_SERVER_OFFLOAD
+    vos_event_destroy(&adapter->dhcp_status.vos_event);
+#endif
+    return VOS_STATUS_SUCCESS;
+}
+
+
 VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
                              const v_BOOL_t bCloseSession )
 {
@@ -9134,6 +9143,7 @@
           }
 
          //Any softap specific cleanup here...
+         hdd_cleanup_ap_events(pAdapter);
          if (pAdapter->device_mode == WLAN_HDD_P2P_GO) {
             while (pAdapter->is_roc_inprogress) {
                VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 74856ae..bc1427b 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -3793,6 +3793,9 @@
 typedef void ( *tGetFrameLogCallback) (void *pContext);
 typedef void(*RssiMonitorReqCb)(void *rssiMonitorCbContext, VOS_STATUS status);
 typedef void(*pktFilterReqCb)(void *data, tANI_U32 status);
+typedef void(*dhcp_offload_req_cb)(void *rssiMonitorCbContext,
+				   VOS_STATUS status);
+
 
 typedef struct sAniGetFrameLogReq
 {
@@ -5566,6 +5569,26 @@
     tSirWifiScanResult   bssHotlist[1];
 } tSirEXTScanHotlistMatch, *tpSirEXTScanHotlistMatch;
 
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * sir_dhcp_srv_offload_info_t - dhcp server offload info
+ * @bssidx: bss index
+ * @dhcp_srv_offload_enabled: enable or disable
+ * @dhcp_client_num: number of clients supported
+ * @dhcp_srv_ip: server ip address
+ * @start_lsb: lsb of start address of dhcp pool
+ */
+typedef struct
+{
+    tANI_U8 bssidx;
+    tANI_U32 dhcp_srv_offload_enabled;
+    tANI_U32 dhcp_client_num;
+    tANI_U32 dhcp_srv_ip;
+    tANI_U32 start_lsb;
+    dhcp_offload_req_cb    dhcp_offload_callback;
+    void                   *dhcp_server_offload_cb_context;
+} sir_dhcp_srv_offload_info_t, *sir_dhcp_srv_offload_info;
+#endif /* DHCP_SERVER_OFFLOAD */
 
 typedef PACKED_PRE struct PACKED_POST
 {
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 7e35c02..203dbb0 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -777,7 +777,9 @@
 #define SIR_HAL_SAP_OFL_ADD_STA            (SIR_HAL_ITC_MSG_TYPES_BEGIN + 292)
 #define SIR_HAL_SAP_OFL_DEL_STA            (SIR_HAL_ITC_MSG_TYPES_BEGIN + 293)
 #endif
-
+#ifdef DHCP_SERVER_OFFLOAD
+#define SIR_HAL_SET_DHCP_SERVER_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 294)
+#endif /* DHCP_SERVER_OFFLOAD */
 #define SIR_HAL_MSG_TYPES_END              (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 // CFG message types
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index e1e50db..48e19fd 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -3980,4 +3980,9 @@
         struct tSirSapOffloadInfo *sap_auth_offload_info);
 
 #endif /* SAP_AUTH_OFFLOAD */
+#ifdef DHCP_SERVER_OFFLOAD
+eHalStatus sme_set_dhcp_srv_offload(tHalHandle hal,
+				    sir_dhcp_srv_offload_info_t *dhcp_srv_info);
+#endif /* DHCP_SERVER_OFFLOAD */
+
 #endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 2d9b957..2567b25 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -14607,3 +14607,57 @@
     return (status);
 }
 #endif
+
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * sme_set_dhcp_srv_offload() - sme api to set dhcp server offload info
+ * @hal: handle to hal
+ * @dhcp_srv_info: pointer to dhcp server info
+ *
+ * Return: eHalStatus
+ *	eHAL_STATUS_SUCCESS - success or else failure code
+ */
+eHalStatus sme_set_dhcp_srv_offload(tHalHandle hal,
+				    sir_dhcp_srv_offload_info_t *dhcp_srv_info)
+{
+	vos_msg_t vos_msg;
+	eHalStatus status = eHAL_STATUS_SUCCESS;
+	tpAniSirGlobal mac = PMAC_STRUCT(hal);
+	sir_dhcp_srv_offload_info_t *dhcp_serv_info = NULL;
+
+	dhcp_serv_info =
+		vos_mem_malloc(sizeof(*dhcp_serv_info));
+	if (NULL == dhcp_serv_info) {
+		VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+			  "Failed to alloc memory");
+		return VOS_STATUS_E_NOMEM;
+	}
+
+	vos_mem_copy(dhcp_serv_info, dhcp_srv_info,
+		     sizeof(*dhcp_serv_info));
+
+	status = sme_AcquireGlobalLock(&mac->sme);
+	if (eHAL_STATUS_SUCCESS == status) {
+		/* serialize the req through MC thread */
+		vos_msg.type = WDA_SET_DHCP_SERVER_OFFLOAD_REQ;
+		vos_msg.bodyptr = dhcp_serv_info;
+
+		if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message
+					   (VOS_MODULE_ID_WDA, &vos_msg))) {
+			VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+				  "%s: Not able to post WDA_SET_DHCP_SERVER_OFFLOAD_REQ to WDA!",
+				  __func__);
+			vos_mem_free(dhcp_serv_info);
+			status = eHAL_STATUS_FAILURE;
+		}
+		sme_ReleaseGlobalLock(&mac->sme);
+	} else {
+		VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+			   "%s: sme_AcquireGlobalLock error!",
+			   __func__);
+		vos_mem_free(dhcp_serv_info);
+	}
+
+	return status;
+}
+#endif /* DHCP_SERVER_OFFLOAD */
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index 12a8a6b..db5ce8d 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -906,6 +906,9 @@
         CASE_RETURN_STRING(WDA_MON_STOP_REQ);
         CASE_RETURN_STRING(WDA_SPOOF_MAC_ADDR_REQ);
         CASE_RETURN_STRING(WDA_LOST_LINK_PARAMS_IND);
+#ifdef DHCP_SERVER_OFFLOAD
+        CASE_RETURN_STRING(WDA_SET_DHCP_SERVER_OFFLOAD_REQ);
+#endif /* DHCP_SERVER_OFFLOAD */
         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 503f460..06cbaf8 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1296,6 +1296,10 @@
 #define WDA_START_RSSI_MONITOR_REQ             SIR_HAL_RSSI_MON_START_REQ
 #define WDA_STOP_RSSI_MONITOR_REQ              SIR_HAL_RSSI_MON_STOP_REQ
 
+#ifdef DHCP_SERVER_OFFLOAD
+#define WDA_SET_DHCP_SERVER_OFFLOAD_REQ     SIR_HAL_SET_DHCP_SERVER_OFFLOAD_REQ
+#endif /* DHCP_SERVER_OFFLOAD */
+
 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 6cb743b..da7c8c2 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -2491,6 +2491,74 @@
    vos_mem_free(configParam);
    return VOS_STATUS_E_FAILURE;
 }
+
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * wda_dhcp_server_offload_rsp_callback() - response to the dhcp server offload
+ * @wdi_rsp: pointer to the dhcp server offload response
+ * @user_data: pointer to user data
+ *
+ * Return: None
+ */
+void wda_dhcp_server_offload_rsp_callback(wdi_dhcp_server_offload_rsp_param_t*
+					  wdi_rsp,
+					  void* user_data)
+{
+	tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data;
+	sir_dhcp_srv_offload_info_t *dhcp_srv_offload_info;
+	VOS_STATUS status;
+
+	VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+		   "<------ %s " ,__func__);
+
+	if(NULL == wda_params)
+	{
+		VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+			  "%s: pWdaParams received NULL", __func__);
+		VOS_ASSERT(0);
+		return;
+	}
+
+	if(NULL == wda_params->wdaMsgParam)
+	{
+		VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+			  "%s: pWdaParams->wdaMsgParam is NULL", __func__);
+		VOS_ASSERT(0);
+		vos_mem_free(wda_params->wdaWdiApiMsgParam);
+		vos_mem_free(wda_params);
+		return;
+	}
+
+	dhcp_srv_offload_info = (sir_dhcp_srv_offload_info_t *)
+		wda_params->wdaMsgParam;
+
+	if(dhcp_srv_offload_info->dhcp_offload_callback)
+	{
+	   dhcp_srv_offload_info->dhcp_offload_callback(
+				    dhcp_srv_offload_info->dhcp_server_offload_cb_context,
+				    CONVERT_WDI2VOS_STATUS(wdi_rsp->status));
+	}
+	else
+	{
+	   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+		   "%s: pFWLoggingInitParams callback is NULL", __func__);
+	}
+
+	status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status);
+	if (status)
+	{
+		VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+			  "%s: DHCP server offload failed with status=%d", __func__, status);
+		VOS_ASSERT(0);
+	}
+
+	vos_mem_free(wda_params->wdaWdiApiMsgParam);
+	vos_mem_free(wda_params->wdaMsgParam);
+	vos_mem_free(wda_params);
+	return;
+}
+#endif /* DHCP_SERVER_OFFLOAD */
+
 /*
  * FUNCTION: WDA_wdiCompleteCB
  * call the voss call back function
@@ -15506,6 +15574,90 @@
     return WLANTL_SuspendDataTx(pWDA->pVosContext, &staId, NULL);
 }
 
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * wda_process_dhcpserver_offload_req() - wda api to set dhcp server offload
+ * @wda_handle: pointer to wda handle
+ * @dhcp_server_offload_info: dhcp server offload info
+ *
+ * Return: status
+ *	0 - success or else failure
+ */
+static int wda_process_dhcpserver_offload_req(tWDA_CbContext *wda_handle,
+					  sir_dhcp_srv_offload_info_t
+					  *dhcp_server_offload_info)
+{
+	wdi_set_dhcp_server_offload_t *dhcp_info;
+	tWDA_ReqParams *wda_params;
+	WDI_Status wstatus;
+	VOS_STATUS status = VOS_STATUS_SUCCESS;
+
+	VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+		  FL("---> %s"), __func__);
+
+	if(NULL == dhcp_server_offload_info)
+	{
+		VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+			  "%s: dhcp_server_offload_info received NULL",
+			  __func__);
+		VOS_ASSERT(0) ;
+		return VOS_STATUS_E_FAULT;
+	}
+
+	dhcp_info = (wdi_set_dhcp_server_offload_t *)
+		vos_mem_malloc(sizeof(*dhcp_info));
+	if (!dhcp_info) {
+		VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+			  "Failed to allocate buffer to send "
+			  "set_dhcp_server_offload cmd");
+		vos_mem_free(dhcp_server_offload_info);
+		return VOS_STATUS_E_NOMEM;
+	}
+
+	vos_mem_zero(dhcp_info, sizeof(*dhcp_info));
+
+	wda_params = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ;
+	if(NULL == wda_params)
+	{
+		VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+			  "%s: VOS MEM Alloc Failure", __func__);
+		VOS_ASSERT(0);
+		vos_mem_free(dhcp_info);
+		vos_mem_free(dhcp_server_offload_info);
+		return VOS_STATUS_E_NOMEM;
+	}
+
+	dhcp_info->bssidx = dhcp_server_offload_info->bssidx;
+	dhcp_info->enable = dhcp_server_offload_info->dhcp_srv_offload_enabled;
+	dhcp_info->num_client = dhcp_server_offload_info->dhcp_client_num;
+	dhcp_info->srv_ipv4 = dhcp_server_offload_info->dhcp_srv_ip;
+	dhcp_info->start_lsb = dhcp_server_offload_info->start_lsb;
+
+	wda_params->pWdaContext = wda_handle;
+	wda_params->wdaMsgParam = dhcp_server_offload_info;
+	wda_params->wdaWdiApiMsgParam = (void *)dhcp_info;
+
+	wstatus = wdi_process_dhcpserver_offload_req(dhcp_info,
+					(wdi_dhcp_srv_offload_rsp_cb)
+					 wda_dhcp_server_offload_rsp_callback,
+					 wda_params);
+	if(IS_WDI_STATUS_FAILURE(wstatus))
+	{
+		VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+			   "Failed to send set_dhcp_server_offload cmd" );
+		status = CONVERT_WDI2VOS_STATUS(wstatus);
+		vos_mem_free(wda_params->wdaWdiApiMsgParam) ;
+		vos_mem_free(wda_params->wdaMsgParam);
+		vos_mem_free(wda_params);
+	}
+
+	VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+		  "Set dhcp server offload");
+	return status;
+}
+#endif /* DHCP_SERVER_OFFLOAD */
+
+
 /*
  * FUNCTION: WDA_McProcessMsg
  * Trigger DAL-AL to start CFG download 
@@ -16431,6 +16583,15 @@
          WDA_ProcessEncryptMsgReq(pWDA, (u8 *)pMsg->bodyptr);
          break;
       }
+#ifdef DHCP_SERVER_OFFLOAD
+      case WDA_SET_DHCP_SERVER_OFFLOAD_REQ:
+      {
+         wda_process_dhcpserver_offload_req(pWDA,
+              (sir_dhcp_srv_offload_info_t *)pMsg->bodyptr);
+         break;
+      }
+#endif /* DHCP_SERVER_OFFLOAD */
+
 
       case WDA_NAN_REQUEST:
       {
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index 694f33c..782f704 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -6441,6 +6441,34 @@
    wpt_macAddr  bssId;
 }WDI_WifiConfigSetReqType;
 
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * wdi_set_dhcp_server_offload_t - dhcp server offload info
+ * @bssidx: bss index
+ * @enable: enable od disable
+ * @srv_ipv4: server ip address
+ * @start_lsb: starting lsb addredd of pool
+ * @num_client: number of clients supported
+ */
+typedef struct {
+   wpt_uint8 bssidx;
+   wpt_uint32 enable;
+   wpt_uint32 srv_ipv4; /* server IP */
+   wpt_uint32 start_lsb; /* starting address assigned to client */
+   wpt_uint32 num_client; /* number of clients we support */
+} wdi_set_dhcp_server_offload_t;
+
+/**
+ * wdi_dhcp_server_offload_rsp_param_t - dhcp server offload response
+ * @status: status for the command success or failure
+ */
+typedef struct
+{
+   /* wdi status */
+   wpt_uint32   status;
+} wdi_dhcp_server_offload_rsp_param_t;
+#endif /* DHCP_SERVER_OFFLOAD */
+
 /**
  * struct WDI_FwrMemDumpReqType - firmware memory dump request details.
 .*.@FWMemDumpReqCb - Associated Callback
@@ -8471,6 +8499,10 @@
 typedef void (*WDI_AntennaDivSelRspCb)(WDI_Status status,
               void *resp, void *pUserData);
 
+#ifdef DHCP_SERVER_OFFLOAD
+typedef void (*wdi_dhcp_srv_offload_rsp_cb)(void *event_data,void *user_data);
+#endif /* DHCP_SERVER_OFFLOAD */
+
 /*========================================================================
  *     Function Declarations and Documentation
  ==========================================================================*/
@@ -12264,4 +12296,14 @@
    struct WDI_sap_ofl_enable_params *sap_ofl_enable_cmd
 );
 
+#ifdef DHCP_SERVER_OFFLOAD
+WDI_Status
+wdi_process_dhcpserver_offload_req
+(
+   wdi_set_dhcp_server_offload_t *dhcp_info,
+   wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback,
+   void *user_data
+);
+#endif /* DHCP_SERVER_OFFLOAD */
+
 #endif /* #ifndef WLAN_QCT_WDI_H */
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index 81c80fa..3455220 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -494,6 +494,8 @@
   WDI_PER_ROAM_SCAN_TRIGGER_REQ                  = 117,
 #endif
 
+  WDI_DHCP_SERVER_OFFLOAD_REQ                    = 118,
+
   WDI_MAX_REQ,
 
   /*Send a suspend Indication down to HAL*/
@@ -873,6 +875,7 @@
   WDI_PER_ROAM_SCAN_OFFLOAD_RSP                  = 116,
   WDI_PER_ROAM_SCAN_TRIGGER_RSP                  = 117,
 #endif
+  WDI_DHCP_SERVER_OFFLOAD_RSP                    = 118,
 
   /*-------------------------------------------------------------------------
     Indications
@@ -6695,5 +6698,22 @@
   WDI_EventInfoType*     pEventData
  );
 #endif
+
+#ifdef DHCP_SERVER_OFFLOAD
+WDI_Status
+wdi_dhcp_server_offload_req
+(
+  WDI_ControlBlockType *wdi_ctx,
+  WDI_EventInfoType *event_data
+);
+
+WDI_Status
+wdi_dhcp_server_offload_rsp
+(
+  WDI_ControlBlockType *wdi_ctx,
+  WDI_EventInfoType *event_data
+);
+#endif /* DHCP_SERVER_OFFLOAD */
+
 #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 3c81622..b2c3017 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -518,6 +518,12 @@
   NULL,
   NULL,
 #endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */
+#ifdef DHCP_SERVER_OFFLOAD
+  wdi_dhcp_server_offload_req,   /* WDI_DHCP_SERVER_OFFLOAD_REQ */
+#else
+  NULL,
+#endif /* DHCP_SERVER_OFFLOAD */
+
   /*-------------------------------------------------------------------------
     Indications
   -------------------------------------------------------------------------*/
@@ -842,6 +848,11 @@
     NULL,
     NULL,
 #endif
+#ifdef DHCP_SERVER_OFFLOAD
+    wdi_dhcp_server_offload_rsp, /* WDI_DHCP_SERVER_OFFLOAD_RSP */
+#else
+    NULL,
+#endif /* DHCP_SERVER_OFFLOAD */
   /*---------------------------------------------------------------------
     Indications
   ---------------------------------------------------------------------*/
@@ -1305,12 +1316,53 @@
 #ifdef SAP_AUTH_OFFLOAD
     CASE_RETURN_STRING( WDI_PROCESS_SAP_AUTH_OFFLOAD_IND);
 #endif
+#ifdef DHCP_SERVER_OFFLOAD
+    CASE_RETURN_STRING( WDI_DHCP_SERVER_OFFLOAD_REQ );
+#endif /* DHCP_SERVER_OFFLOAD */
     default:
         return "Unknown WDI MessageId";
   }
 }
 
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * wdi_process_dhcpserver_offload_req() - wdi api to set dhcp server offload
+ * @dhcp_info: pointer to dhcp server offload
+ * @wdi_dhcp_srv_offload_rsp_callback: response callback
+ * @user_data: pointer to user data
+ *
+ * Return: WDI_Status
+ *	WDI_STATUS_SUCCESS - success or else failure status
+ */
+WDI_Status
+wdi_process_dhcpserver_offload_req
+(
+ wdi_set_dhcp_server_offload_t *dhcp_info,
+ wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback,
+ void *user_data
+)
+{
+	WDI_EventInfoType wdi_event_data;
 
+	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
+	  -----------------------------------------------------------------*/
+	wdi_event_data.wdiRequest      = WDI_DHCP_SERVER_OFFLOAD_REQ;
+	wdi_event_data.pEventData      = dhcp_info;
+	wdi_event_data.uEventDataSize  = sizeof(*dhcp_info);
+	wdi_event_data.pCBfnc          = wdi_dhcp_srv_offload_rsp_callback;
+	wdi_event_data.pUserData       = user_data;
+
+	return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdi_event_data);
+}
+#endif /* DHCP_SERVER_OFFLOAD */
 
 /**
  @brief WDI_getRespMsgString prints the WDI resonse message in string.
@@ -1458,6 +1510,9 @@
     CASE_RETURN_STRING (WDI_PER_ROAM_SCAN_OFFLOAD_RSP);
     CASE_RETURN_STRING (WDI_PER_ROAM_SCAN_TRIGGER_RSP);
 #endif
+#ifdef DHCP_SERVER_OFFLOAD
+    CASE_RETURN_STRING (WDI_DHCP_SERVER_OFFLOAD_RSP);
+#endif /* DHCP_SERVER_OFFLOAD */
     default:
         return "Unknown WDI MessageId";
   }
@@ -24765,6 +24820,10 @@
   case WDI_PROCESS_SAP_AUTH_OFFLOAD_IND:
       return WLAN_HAL_SAP_AUTH_OFFLOAD_IND;
 #endif
+#ifdef DHCP_SERVER_OFFLOAD
+  case WDI_DHCP_SERVER_OFFLOAD_REQ:
+      return WLAN_HAL_DHCP_SERVER_OFFLOAD_REQ;
+#endif /* DHCP_SERVER_OFFLOAD */
   default:
     return WLAN_HAL_MSG_MAX;
   }
@@ -25134,6 +25193,10 @@
   case WLAN_HAL_PER_ROAM_SCAN_TRIGGER_RSP:
        return WDI_PER_ROAM_SCAN_TRIGGER_RSP;
 #endif
+#ifdef DHCP_SERVER_OFFLOAD
+  case WLAN_HAL_DHCP_SERVER_OFFLOAD_RSP:
+       return WDI_DHCP_SERVER_OFFLOAD_RSP;
+#endif /* DHCP_SERVER_OFFLOAD */
   default:
     return eDRIVER_TYPE_MAX;
   }
@@ -33788,6 +33851,48 @@
                       WDI_MON_START_RSP);
 }
 
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * wdi_dhcp_server_offload_rsp() - wdi api for the dhcp server response
+ * @wdi_ctx: pointer to the wdi context
+ * @event_data: pointer to the event data
+ *
+ * Return: WDI_Status
+ *	WDI_STATUS_SUCCESS - success or else failure status
+ */
+WDI_Status
+wdi_dhcp_server_offload_rsp
+(
+    WDI_ControlBlockType *wdi_ctx,
+    WDI_EventInfoType *event_data
+)
+{
+	wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback;
+
+	WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+		   "%s: Enter ", __func__);
+	/*-------------------------------------------------------------------
+	  Sanity check
+	  -----------------------------------------------------------------*/
+	if ((NULL == wdi_ctx) || (NULL == event_data) ||
+	    (NULL == event_data->pEventData))
+	{
+		WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+			   "%s: Invalid parameters", __func__);
+		WDI_ASSERT(0);
+		return WDI_STATUS_E_FAILURE;
+	}
+
+	wdi_dhcp_srv_offload_rsp_callback =
+		(wdi_dhcp_srv_offload_rsp_cb)wdi_ctx->pfncRspCB;
+
+	wdi_dhcp_srv_offload_rsp_callback((void *) event_data->pEventData,
+					  wdi_ctx->pRspCBUserData);
+
+	return WDI_STATUS_SUCCESS;
+}
+#endif /* DHCP_SERVER_OFFLOAD */
+
 WDI_Status
 WDI_ProcessMonStartRsp
 (
@@ -36719,6 +36824,98 @@
 
 }
 
+#ifdef DHCP_SERVER_OFFLOAD
+/**
+ * wdi_dhcp_server_offload_req() - wdi api for dhcp server offload
+ * @wdi_ctx: pointer to wdi context
+ * @event_data: pointer to event data
+ *
+ * Return: WDI_Status
+ *	WDI_STATUS_SUCCESS - success or else failure status
+ */
+WDI_Status
+wdi_dhcp_server_offload_req
+(
+    WDI_ControlBlockType *wdi_ctx,
+    WDI_EventInfoType *event_data
+)
+{
+	wdi_set_dhcp_server_offload_t *wdi_dhcp_server_info;
+	wpt_uint8 *buff  = NULL;
+	wpt_uint16 data_offset = 0;
+	wpt_uint16 size = 0;
+	WDI_Status wdi_status;
+	hal_dhcp_srv_offload_req_msg_t dhcp_srv_offload_req;
+	wdi_dhcp_srv_offload_rsp_cb wdi_dhcp_srv_offload_rsp_callback;
+
+	VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+		  "%s: %d Enter",__func__, __LINE__);
+
+	/*------------------------------------------------------------------
+	  Sanity check
+	  ------------------------------------------------------------------*/
+	if ((NULL == wdi_ctx) || (NULL == event_data) ||
+	    (NULL == event_data->pEventData))
+	{
+		WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+			   "%s: Invalid parameters", __func__);
+		WDI_ASSERT(0);
+		return WDI_STATUS_E_FAILURE;
+	}
+
+	wdi_dhcp_server_info = (wdi_set_dhcp_server_offload_t *)
+		event_data->pEventData;
+
+	/*-------------------------------------------------------------------
+	  Get message buffer
+	  -----------------------------------------------------------------*/
+	if (( WDI_STATUS_SUCCESS !=
+	      WDI_GetMessageBuffer(wdi_ctx,
+				   WDI_DHCP_SERVER_OFFLOAD_REQ,
+				   sizeof(dhcp_srv_offload_req.
+					  dhcp_srv_offload_req_params),
+				   &buff, &data_offset, &size))||
+	    (size < (data_offset +
+		     sizeof(dhcp_srv_offload_req.dhcp_srv_offload_req_params))))
+	{
+		WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_FATAL,
+			   "Unable to get send buffer in GetFrameLog Req");
+		WDI_ASSERT(0);
+		return WDI_STATUS_E_FAILURE;
+	}
+
+	dhcp_srv_offload_req.dhcp_srv_offload_req_params.bss_idx =
+		wdi_dhcp_server_info->bssidx;
+	dhcp_srv_offload_req.dhcp_srv_offload_req_params.enable =
+		wdi_dhcp_server_info->enable;
+	dhcp_srv_offload_req.dhcp_srv_offload_req_params.srv_ipv4 =
+		wdi_dhcp_server_info->srv_ipv4;
+	dhcp_srv_offload_req.dhcp_srv_offload_req_params.start_lsb =
+		wdi_dhcp_server_info->start_lsb;
+	dhcp_srv_offload_req.dhcp_srv_offload_req_params.num_client =
+		wdi_dhcp_server_info->num_client;
+
+	wdi_dhcp_srv_offload_rsp_callback = (wdi_dhcp_srv_offload_rsp_cb)
+		event_data->pCBfnc;
+
+	wpalMemoryCopy(buff+data_offset,
+		       &dhcp_srv_offload_req.dhcp_srv_offload_req_params,
+		       sizeof(dhcp_srv_offload_req.
+			      dhcp_srv_offload_req_params));
+
+	/*-------------------------------------------------------------------
+	  Send Suspend Request to HAL
+	  -----------------------------------------------------------------*/
+	wdi_status = WDI_SendMsg(wdi_ctx, buff, size,
+				 wdi_dhcp_srv_offload_rsp_callback,
+				 event_data->pUserData,
+				 WDI_DHCP_SERVER_OFFLOAD_RSP);
+	VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+		  "%s: %d Exit",__func__, __LINE__);
+	return wdi_status;
+}
+#endif /* DHCP_SERVER_OFFLOAD */
+
 
 /**
  @brief Process FWLoggingInit Request
diff --git a/Kbuild b/Kbuild
index 06f553b..c2a7ea0 100644
--- a/Kbuild
+++ b/Kbuild
@@ -567,7 +567,8 @@
                 -DWLAN_FEATURE_LINK_LAYER_STATS \
                 -DWLAN_FEATURE_EXTSCAN \
                 -DFEATURE_EXT_LL_STAT \
-                -DWLAN_VOWIFI_DEBUG
+                -DWLAN_VOWIFI_DEBUG \
+		-DDHCP_SERVER_OFFLOAD
 
 ifneq ($(CONFIG_PRONTO_WLAN),)
 CDEFINES += -DWCN_PRONTO
diff --git a/firmware_bin/WCNSS_qcom_cfg.ini b/firmware_bin/WCNSS_qcom_cfg.ini
index 97b61e9..7c9b10a 100644
--- a/firmware_bin/WCNSS_qcom_cfg.ini
+++ b/firmware_bin/WCNSS_qcom_cfg.ini
@@ -477,6 +477,24 @@
 #Delack set lower limit
 gTcpDelAckThresholdLow=12000
 
+# Enable or Disable DHCP Server offload
+# 1=Enable, 0=Disable (default)
+gDHCPServerOffloadEnable=0
+
+# Set max number of DHCP Clients
+# Its value could not be greater than 2(default)
+#gDHCPMaxNumClients=2
+
+# Set DHCP server IP
+# 4th field could not be greater than 99, that is xxx,xxx,xxx,0 ~ xxx,xxx,xxx,99
+# 1st field could not be within the range of 224 ~ 239 (multicast IP address)
+# 192,168,1,2(default)
+#gDHCPServerIP=192,168,1,2
+
+# Set DHCP pool start Lsb
+# min 100 (default)
+# max 255
+gDHCPStartLsb=100
 END
 
 # Note: Configuration parser would not read anything past the END marker