Prima: Add Support for firmware memory dump

 Common API for fw mem dump request cfg80211 and wext(ioctl)
 WLAN HAL API changes
 Creation of procfs and reading through it
 Simple state machine to synchronize fw dump writes and reads

Change-Id: Ifdf90e77b8d9011f664d3f776207069e11038a7e
CRs-Fixed: 916853
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 5315338..5a27bdc 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -2528,6 +2528,11 @@
 #define CFG_OPTIMIZE_CA_EVENT_ENABLE     ( 1 )
 #define CFG_OPTIMIZE_CA_EVENT_DEFAULT    ( 0 )
 
+#define CFG_FWR_MEM_DUMP_NAME       "gEnableFwrMemDump"
+#define CFG_FWR_MEM_DUMP_MAX        ( 1 )
+#define CFG_FWR_MEM_DUMP_MIN        ( 0 )
+#define CFG_FWR_MEM_DUMP_DEF        ( 1 )
+
 /*--------------------------------------------------------------------------- 
   Type declarations
   -------------------------------------------------------------------------*/ 
@@ -3041,6 +3046,7 @@
    v_U32_t                     linkFailTxCnt;
    v_BOOL_t                    ignorePeerHTopMode;
    v_U8_t                      gOptimizeCAevent;
+   v_BOOL_t                    enableFwrMemDump;
 } hdd_config_t;
 
 /*--------------------------------------------------------------------------- 
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index 4a8ecfe..68aed06 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -167,11 +167,12 @@
 
     /* Get Wifi Specific Info */
     QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO = 61,
+    /* Start Wifi Memory Dump */
+    QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP = 63,
     QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST = 65,
     QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST = 66,
     QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND = 67,
     QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST = 68,
-
     QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
 };
 
@@ -199,6 +200,7 @@
     /*EXT TDLS*/
     QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX,
     QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX,
+    QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX,
 
     QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX,
     QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX,
@@ -1188,4 +1190,26 @@
 #define cfg80211_vendor_event_alloc backported_cfg80211_vendor_event_alloc
 #endif
 
+/**
+ * enum qca_wlan_vendor_attr_memory_dump - values for memory dump attributes
+ * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_INVALID - Invalid
+ * @QCA_WLAN_VENDOR_ATTR_REQUEST_ID - Indicate request ID
+ * @QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE - Indicate size of the memory dump
+ * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST - To keep track of the last enum
+ * @QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_MAX - max value possible for this type
+ *
+ * enum values are used for NL attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP sub command.
+ */
+enum qca_wlan_vendor_attr_memory_dump {
+    QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_INVALID = 0,
+    QCA_WLAN_VENDOR_ATTR_REQUEST_ID = 1,
+    QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE = 2,
+
+    QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST,
+    QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_MAX =
+    QCA_WLAN_VENDOR_ATTR_MEMORY_DUMP_AFTER_LAST - 1,
+};
+
+
 #endif
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index caef24e..eb5901a 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -63,6 +63,8 @@
 #endif
 #include "wlan_hdd_cfg80211.h"
 
+#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
+#include <linux/fs.h>
 /*--------------------------------------------------------------------------- 
   Preprocessor definitions and constants
   -------------------------------------------------------------------------*/
@@ -1217,6 +1219,17 @@
 
 #define WLAN_WAIT_TIME_LL_STATS 5000
 
+/* FW memory dump feature
+@TODO : Move this code to a separate file later */
+#define PROCFS_MEMDUMP_DIR  "debug"
+#define PROCFS_MEMDUMP_NAME "fwdump"
+#define FW_MEM_DUMP_REQ_ID 1
+
+int memdump_init(void);
+int memdump_deinit(void);
+void wlan_hdd_fw_mem_dump_cb(void *,tAniFwrDumpRsp *);
+int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx);
+
 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
 /**
  * struct hdd_ll_stats_context - hdd link layer stats context
@@ -1533,6 +1546,7 @@
    WLAN_BMUHW_TRACE_LOG_EN = 1<<1,
    WLAN_QXDM_LOG_EN = 1<<2,
    WLAN_DPU_TXP_LOG_EN = 1<<3,
+   WLAN_FW_MEM_DUMP_EN = 1<<6,
 } WLAN_ENABLE_HW_FW_LOG_TYPE;
 
 /*--------------------------------------------------------------------------- 
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 356b658..ac17690 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -3396,6 +3396,13 @@
                  CFG_OPTIMIZE_CA_EVENT_DISABLE,
                  CFG_OPTIMIZE_CA_EVENT_ENABLE ),
 
+   REG_VARIABLE(CFG_FWR_MEM_DUMP_NAME, WLAN_PARAM_Integer,
+                 hdd_config_t,enableFwrMemDump,
+                 VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+                 CFG_FWR_MEM_DUMP_DEF,
+                 CFG_FWR_MEM_DUMP_MIN,
+                 CFG_FWR_MEM_DUMP_MAX),
+
 };
 
 /*
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index fab6be0..4cb9e0d 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -96,6 +96,7 @@
 #include "wlan_nv.h"
 #include "wlan_hdd_dev_pwr.h"
 #include "qwlan_version.h"
+#include "wlan_logging_sock_svc.h"
 
 
 #define g_mode_rates_size (12)
@@ -5691,6 +5692,66 @@
     return ret;
 }
 
+
+static int
+__wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy,
+                                    struct wireless_dev *wdev,
+                                    const void *data, int data_len)
+{
+    hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+    int ret;
+    ENTER();
+
+    ret = wlan_hdd_validate_context(pHddCtx);
+    if (0 != ret)
+    {
+        return ret;
+    }
+
+    if( !pHddCtx->cfg_ini->enableFwrMemDump ||
+       (FALSE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
+    {
+       hddLog(VOS_TRACE_LEVEL_INFO, FL("FW dump Logging not supported"));
+       return -EINVAL;
+    }
+    /*call common API for FW mem dump req*/
+    ret = wlan_hdd_fw_mem_dump_req(pHddCtx);
+
+    EXIT();
+    return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_get_fw_mem_dump() - Get FW memory dump
+ * @wiphy:   pointer to wireless wiphy structure.
+ * @wdev:    pointer to wireless_dev structure.
+ * @data:    Pointer to the NL data.
+ * @data_len:Length of @data
+ *
+ * This is called when wlan driver needs to get the firmware memory dump
+ * via vendor specific command.
+ *
+ * Return:   0 on success, error number otherwise.
+ */
+
+static int
+wlan_hdd_cfg80211_get_fw_mem_dump(struct wiphy *wiphy,
+                                              struct wireless_dev *wdev,
+                                         const void *data, int data_len)
+
+{
+    int ret = 0;
+
+    vos_ssr_protect(__func__);
+    ret = __wlan_hdd_cfg80211_get_fw_mem_dump(wiphy, wdev, data,
+                                              data_len);
+    vos_ssr_unprotect(__func__);
+
+    return ret;
+
+}
+
+
 static const struct nla_policy
 wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
  +1] =
@@ -6081,6 +6142,14 @@
     },
     {
         .info.vendor_id = QCA_NL80211_VENDOR_ID,
+        .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
+        .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+                 WIPHY_VENDOR_CMD_NEED_NETDEV |
+                 WIPHY_VENDOR_CMD_NEED_RUNNING,
+        .doit = wlan_hdd_cfg80211_get_fw_mem_dump
+    },
+    {
+        .info.vendor_id = QCA_NL80211_VENDOR_ID,
         .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
         .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
             WIPHY_VENDOR_CMD_NEED_NETDEV |
@@ -6194,6 +6263,11 @@
         .vendor_id = QCA_NL80211_VENDOR_ID,
         .subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
     },
+    [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
+        .vendor_id = QCA_NL80211_VENDOR_ID,
+        .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
+    },
+
 
     {
         .vendor_id = QCA_NL80211_VENDOR_ID,
diff --git a/CORE/HDD/src/wlan_hdd_early_suspend.c b/CORE/HDD/src/wlan_hdd_early_suspend.c
index 9c4f047..06be08b 100644
--- a/CORE/HDD/src/wlan_hdd_early_suspend.c
+++ b/CORE/HDD/src/wlan_hdd_early_suspend.c
@@ -2040,6 +2040,9 @@
    vos_sched_flush_rx_mqs(vosSchedContext);
 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
    wlan_logging_flush_pkt_queue();
+   /*Free fw dump mem in case of SSR/Shutdown */
+   wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
+   wlan_free_fwr_mem_dump_buffer();
 #endif
 
    /* Deinit all the TX and MC queues */
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index c2739c9..d45b07d 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8859,6 +8859,9 @@
    //Clean up HDD Nlink Service
    send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
 
+   wlan_free_fwr_mem_dump_buffer();
+   memdump_deinit();
+
 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
    if (pHddCtx->cfg_ini->wlanLoggingEnable)
    {
@@ -9436,7 +9439,7 @@
   \return -  None
 
   --------------------------------------------------------------------------*/
-void hdd_init_frame_logging_done(void *fwlogInitCbContext, VOS_STATUS status)
+void hdd_init_frame_logging_done(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp)
 {
    hdd_context_t* pHddCtx = (hdd_context_t*)fwlogInitCbContext;
 
@@ -9447,7 +9450,7 @@
       return;
    }
 
-   if ((VOS_STATUS_SUCCESS == status) &&
+   if ((pRsp->status == VOS_STATUS_SUCCESS) &&
        (TRUE == pHddCtx->cfg_ini->enableMgmtLogging))
    {
       hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init successful"));
@@ -9457,9 +9460,21 @@
    {
       hddLog(VOS_TRACE_LEVEL_INFO, FL("Mgmt Frame Logging init not success"));
       pHddCtx->mgmt_frame_logging = FALSE;
+      return;
    }
 
-   return;
+   /*Check feature supported by FW*/
+   if(TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED))
+   {
+      //Store fwr mem dump size given by firmware.
+      wlan_store_fwr_mem_dump_size(pRsp->fw_mem_dump_max_size);
+   }
+   else
+   {
+      wlan_store_fwr_mem_dump_size(0);
+   }
+
+
 }
 /**---------------------------------------------------------------------------
 
@@ -9492,10 +9507,11 @@
 
    vos_mem_set(wlanFWLoggingInitParam, sizeof(tSirFWLoggingInitParam), 0);
 
-   hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s Logging",__func__,
+   hddLog(VOS_TRACE_LEVEL_INFO, "%s: Configuring %s %s %s %s Logging",__func__,
                pHddCtx->cfg_ini->enableFWLogging?"FW Log,":"",
                pHddCtx->cfg_ini->enableContFWLogging ? "Cont FW log,":"",
-               pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"");
+               pHddCtx->cfg_ini->enableMgmtLogging ? "Mgmt Pkt Log":"",
+               pHddCtx->cfg_ini->enableFwrMemDump ? "Fw Mem dump":"");
 
    if (pHddCtx->cfg_ini->enableFWLogging ||
                  pHddCtx->cfg_ini->enableContFWLogging)
@@ -9511,7 +9527,16 @@
    {
       wlanFWLoggingInitParam->enableFlag |= WLAN_BMUHW_TRACE_LOG_EN;
    }
-
+   if(pHddCtx->cfg_ini->enableFwrMemDump &&
+      (TRUE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
+   {
+      wlanFWLoggingInitParam->enableFlag |= WLAN_FW_MEM_DUMP_EN;
+   }
+   if( wlanFWLoggingInitParam->enableFlag == 0 )
+   {
+      hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Logging not enabled", __func__);
+      return;
+   }
    wlanFWLoggingInitParam->frameType = WLAN_FRAME_LOGGING_FRAMETYPE_MGMT;
    wlanFWLoggingInitParam->frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;
    wlanFWLoggingInitParam->bufferMode = WLAN_FRAME_LOGGING_BUFFERMODE_CIRCULAR;
@@ -10284,7 +10309,9 @@
    if (pHddCtx->cfg_ini->wlanLoggingEnable &&
                (pHddCtx->cfg_ini->enableFWLogging ||
                 pHddCtx->cfg_ini->enableMgmtLogging ||
-                pHddCtx->cfg_ini->enableContFWLogging))
+                pHddCtx->cfg_ini->enableContFWLogging ||
+                pHddCtx->cfg_ini->enableFwrMemDump )
+                )
    {
        hdd_init_frame_logging(pHddCtx);
    }
@@ -10392,6 +10419,8 @@
    {
       hddLog(VOS_TRACE_LEVEL_INFO, FL("Registered IPv4 notifier"));
    }
+   /*Fw mem dump procfs initialization*/
+   memdump_init();
 
    goto success;
 
@@ -12023,6 +12052,272 @@
     return sta_id;
 }
 
+/*FW memory dump feature*/
+/**
+ * This structure hold information about the /proc file
+ *
+ */
+static struct proc_dir_entry *proc_file, *proc_dir;
+
+/**
+ * memdump_read() - perform read operation in memory dump proc file
+ *
+ * @file  - handle for the proc file.
+ * @buf   - pointer to user space buffer.
+ * @count - number of bytes to be read.
+ * @pos   - offset in the from buffer.
+ *
+ * This function performs read operation for the memory dump proc file.
+ *
+ * Return: number of bytes read on success, error code otherwise.
+ */
+static ssize_t memdump_read(struct file *file, char __user *buf,
+                    size_t count, loff_t *pos)
+{
+    int status;
+    hdd_context_t *hdd_ctx = (hdd_context_t *)PDE_DATA(file_inode(file));
+    size_t ret_count;
+    ENTER();
+
+    hddLog(LOG1, FL("Read req for size:%zu pos:%llu"), count, *pos);
+    status = wlan_hdd_validate_context(hdd_ctx);
+    if (0 != status) {
+        return -EINVAL;
+    }
+
+    if (!wlan_fwr_mem_dump_test_and_set_read_allowed_bit()) {
+        hddLog(LOGE, FL("Current mem dump request timed out/failed"));
+        return -EINVAL;
+    }
+
+    /* run fs_read_handler in an atomic context*/
+    vos_ssr_protect(__func__);
+    ret_count = wlan_fwr_mem_dump_fsread_handler( buf, count, pos);
+    if(ret_count == 0)
+    {
+        /*Free the fwr mem dump buffer */
+        wlan_free_fwr_mem_dump_buffer();
+        wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
+    }
+    /*if SSR/unload code is waiting for memdump_read to finish,signal it*/
+    vos_ssr_unprotect(__func__);
+    EXIT();
+    return ret_count;
+}
+
+/**
+ * struct memdump_fops - file operations for memory dump feature
+ * @read - read function for memory dump operation.
+ *
+ * This structure initialize the file operation handle for memory
+ * dump feature
+ */
+static const struct file_operations memdump_fops = {
+    read: memdump_read
+};
+
+/*
+* wlan_hdd_fw_mem_dump_cb : callback for Fw mem dump request
+* To be passed by HDD to WDA and called upon receiving of response
+* from firmware
+* @fwMemDumpReqContext : memory dump request context
+* @dump_rsp : dump response from HAL
+* Returns none
+*/
+void wlan_hdd_fw_mem_dump_cb(void *fwMemDumpReqContext,
+                         tAniFwrDumpRsp *dump_rsp)
+{
+    hdd_context_t *pHddCtx = (hdd_context_t *)fwMemDumpReqContext;
+    int status;
+    ENTER();
+    status = wlan_hdd_validate_context(pHddCtx);
+    if (0 != status) {
+        return;
+    }
+
+    if (dump_rsp->dump_status != eHAL_STATUS_SUCCESS) {
+        hddLog(LOGE, FL("fw dump request declined by fwr"));
+       //report failure to user space
+       wlan_indicate_mem_dump_complete(false);
+       //Free the allocated fwr dump
+       wlan_free_fwr_mem_dump_buffer();
+       wlan_set_fwr_mem_dump_state(FW_MEM_DUMP_IDLE);
+       return;
+    }
+    else
+        hddLog(LOG1, FL("fw dump request accepted by fwr"));
+    EXIT();
+
+}
+
+/**
+ * memdump_procfs_remove() - Remove file/dir under procfs for memory dump
+ *
+ * This function removes file/dir under proc file system that was
+ * processing firmware memory dump
+ *
+ * Return:  None
+ */
+static void memdump_procfs_remove(void)
+{
+    remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
+    hddLog(LOG1 , FL("/proc/%s/%s removed\n"),
+           PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
+    remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
+    hddLog(LOG1 , FL("/proc/%s removed\n"), PROCFS_MEMDUMP_DIR);
+}
+
+/**
+ * memdump_procfs_init() - Initialize procfs for memory dump
+ *
+ * @vos_ctx - Global vos context.
+ *
+ * This function create file under proc file system to be used later for
+ * processing firmware memory dump
+ *
+ * Return:   0 on success, error code otherwise.
+ */
+static int memdump_procfs_init(void *vos_ctx)
+{
+    hdd_context_t *hdd_ctx;
+
+    hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
+    if (!hdd_ctx) {
+        hddLog(LOGE , FL("Invalid HDD context"));
+        return -EINVAL;
+    }
+
+    proc_dir = proc_mkdir(PROCFS_MEMDUMP_DIR, NULL);
+    if (proc_dir == NULL) {
+        remove_proc_entry(PROCFS_MEMDUMP_DIR, NULL);
+        hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
+               PROCFS_MEMDUMP_DIR);
+        return -ENOMEM;
+    }
+
+    proc_file = proc_create_data(PROCFS_MEMDUMP_NAME,
+                                 S_IRUSR | S_IWUSR, proc_dir,
+                                 &memdump_fops, hdd_ctx);
+    if (proc_file == NULL) {
+        remove_proc_entry(PROCFS_MEMDUMP_NAME, proc_dir);
+        hddLog(LOGE , FL("Error: Could not initialize /proc/%s"),
+               PROCFS_MEMDUMP_NAME);
+        return -ENOMEM;
+    }
+
+    hddLog(LOG1 , FL("/proc/%s/%s created"),
+           PROCFS_MEMDUMP_DIR, PROCFS_MEMDUMP_NAME);
+
+    return 0;
+}
+
+/**
+ * memdump_init() - Initialization function for memory dump feature
+ *
+ * This function creates proc file for memdump feature and registers
+ * HDD callback function with SME.
+ *
+ * Return - 0 on success, error otherwise
+ */
+int memdump_init(void)
+{
+    hdd_context_t *hdd_ctx;
+    void *vos_ctx;
+    int status = 0;
+
+    vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+    if (!vos_ctx) {
+        hddLog(LOGE, FL("Invalid VOS context"));
+        return -EINVAL;
+    }
+
+    hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
+    if (!hdd_ctx) {
+        hddLog(LOGE , FL("Invalid HDD context"));
+        return -EINVAL;
+    }
+
+    status = memdump_procfs_init(vos_ctx);
+    if (status) {
+        hddLog(LOGE , FL("Failed to create proc file"));
+        return status;
+    }
+
+    return 0;
+}
+
+/**
+ * memdump_deinit() - De initialize memdump feature
+ *
+ * This function removes proc file created for memdump feature.
+ *
+ * Return: None
+ */
+int memdump_deinit(void)
+{
+    hdd_context_t *hdd_ctx;
+    void *vos_ctx;
+
+    vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+    if (!vos_ctx) {
+        hddLog(LOGE, FL("Invalid VOS context"));
+        return -EINVAL;
+    }
+
+    hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
+    if(!hdd_ctx) {
+        hddLog(LOGE , FL("Invalid HDD context"));
+        return -EINVAL;
+    }
+
+    memdump_procfs_remove();
+    return 0;
+}
+
+/**
+ * wlan_hdd_fw_mem_dump_req(pHddCtx) - common API(cfg80211/ioctl) for requesting fw mem dump to SME
+ * Return: HAL status
+ */
+
+int wlan_hdd_fw_mem_dump_req(hdd_context_t * pHddCtx)
+{
+   tAniFwrDumpReq fw_mem_dump_req={0};
+   eHalStatus status = eHAL_STATUS_FAILURE;
+   int ret=0;
+   ENTER();
+   /*Check whether a dump request is already going on
+    *Caution this function will free previously held memory if new dump request is allowed*/
+   if (!wlan_fwr_mem_dump_test_and_set_write_allowed_bit()) {
+       hddLog(LOGE, FL("Fw memdump already in progress"));
+       return -EBUSY;
+   }
+   //Allocate memory for fw mem dump buffer
+   ret = wlan_fwr_mem_dump_buffer_allocation();
+   if(ret == -EFAULT)
+   {
+      hddLog(LOGE, FL("Fwr mem dump not supported by FW"));
+      return ret;
+   }
+   if (0 != ret) {
+       hddLog(LOGE, FL("Fwr mem Allocation failed"));
+       return -ENOMEM;
+   }
+   fw_mem_dump_req.fwMemDumpReqCallback = wlan_hdd_fw_mem_dump_cb;
+   fw_mem_dump_req.fwMemDumpReqContext = pHddCtx;
+   status = sme_FwMemDumpReq(pHddCtx->hHal, &fw_mem_dump_req);
+   if(eHAL_STATUS_SUCCESS != status)
+   {
+       hddLog(VOS_TRACE_LEVEL_ERROR,
+          "%s: fw_mem_dump_req failed ", __func__);
+       wlan_free_fwr_mem_dump_buffer();
+   }
+   EXIT();
+
+   return status;
+}
+
+
+
 //Register the module init/exit functions
 module_init(hdd_module_init);
 module_exit(hdd_module_exit);
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 3462628..4e676d9 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -241,6 +241,7 @@
 #define WE_DUMP_ROAM_TIMER_LOG     12
 #define WE_RESET_ROAM_TIMER_LOG    13
 #define WE_GET_FW_LOGS             14
+#define WE_GET_FW_MEMDUMP          15
 
 /* Private ioctls and their sub-ioctls */
 #define WLAN_PRIV_SET_VAR_INT_GET_NONE   (SIOCIWFIRSTPRIV + 7)
@@ -398,7 +399,9 @@
 int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest,
                            v_U8_t sessionId);
 #endif
-
+static int get_fwr_memdump(struct net_device *,
+                            struct iw_request_info *,
+                            union iwreq_data *, char *);
 /**---------------------------------------------------------------------------
 
   \brief mem_alloc_copy_from_user_helper -
@@ -7056,6 +7059,13 @@
                      TRUE);
             break;
         }
+        case WE_GET_FW_MEMDUMP:
+        {
+            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                     "FW_MEM_DUMP requested ");
+            get_fwr_memdump(dev,info,wrqu,extra);
+            break;
+        }
         default:
         {
             hddLog(LOGE, "%s: unknown ioctl %d", __func__, sub_cmd);
@@ -9714,6 +9724,32 @@
     return ret;
 }
 
+static int get_fwr_memdump(struct net_device *dev,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu, char *extra)
+{
+    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+    int ret;
+    ENTER();
+   // HddCtx sanity
+   ret = wlan_hdd_validate_context(pHddCtx);
+   if (0 != ret)
+   {
+      return ret;
+   }
+   if( !pHddCtx->cfg_ini->enableFwrMemDump ||
+      (FALSE == sme_IsFeatureSupportedByFW(MEMORY_DUMP_SUPPORTED)))
+   {
+      hddLog(VOS_TRACE_LEVEL_INFO, FL("FW dump Logging not supported"));
+      return -EINVAL;
+   }
+   ret = wlan_hdd_fw_mem_dump_req(pHddCtx);
+
+   EXIT();
+   return ret;
+}
+
 static int __iw_set_power_params_priv(struct net_device *dev,
                                       struct iw_request_info *info,
                                       union iwreq_data *wrqu, char *extra)
@@ -10541,6 +10577,11 @@
         0,
         0,
         "getFwLogs" },
+    {
+        WE_GET_FW_MEMDUMP,
+        0,
+        0,
+        "getFwMemDump" },
     /* handlers for main ioctl */
     {   WLAN_PRIV_SET_VAR_INT_GET_NONE,
         IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 3128e70..5477b24 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -3730,7 +3730,23 @@
     tANI_U8 setMcstBcstFilter;
 }tSirWlanSetRxpFilters,*tpSirWlanSetRxpFilters;
 
-typedef void(*FWLoggingInitReqCb)(void *fwlogInitCbContext, VOS_STATUS status);
+typedef struct
+{
+  //FW mail box address
+  uint64 logMailBoxAddr;
+  tANI_U32 status;
+  //Logging mail box version
+  tANI_U8 logMailBoxVer;
+  //Qshrink is enabled
+  tANI_U8 logCompressEnabled;
+  /* used to tell fwr mem dump size */
+  tANI_U32 fw_mem_dump_max_size;
+  //Reserved for future purpose
+  tANI_U32 reserved1;
+  tANI_U32 reserved2;
+}tAniLoggingInitRsp, *tpAniLoggingInitRsp;
+
+typedef void(*FWLoggingInitReqCb)(void *fwlogInitCbContext, tAniLoggingInitRsp *pRsp);
 typedef void ( *tGetFrameLogCallback) (void *pContext);
 
 typedef struct sAniGetFrameLogReq
@@ -5647,4 +5663,34 @@
     void *data;
     tSirMonModeCb callback;
 }tSirMonModeReq, *ptSirMonModeReq;
+
+/**
+ * struct tAniFwrDumpRsp - firmware dump response details.
+ *
+ * This structure is used to store the firmware dump
+ * response from the firmware.
+ */
+typedef struct
+{
+    tANI_U32 dump_status;
+}tAniFwrDumpRsp, *tpAniFwrDumpRsp;
+
+typedef void (*FWMemDumpReqCb)(void *fwMemDumpReqContext, tAniFwrDumpRsp *dump_rsp);
+
+/**
+ * struct tAniFwrDumpReq - firmware memory dump request details.
+.*.@FWMemDumpReqCb - Associated Callback
+ *.@fwMemDumpReqContext - Callback context
+ * @reserved - reserved field 1.
+ *
+ * This structure carries information about the firmware
+ * memory dump request.
+ */
+typedef struct
+{
+    FWMemDumpReqCb  fwMemDumpReqCallback;
+    void *          fwMemDumpReqContext;
+    tANI_U32        reserved1;
+}tAniFwrDumpReq, *tpAniFwrDumpReq;
+
 #endif /* __SIR_API_H */
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 4933df2..9a54ecf 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -130,6 +130,7 @@
    MGMT_FRAME_LOGGING    = 53,
    ENHANCED_TXBD_COMPLETION = 54,
    LOGGING_ENHANCEMENT   = 55,
+   MEMORY_DUMP_SUPPORTED = 57,
    //MAX_FEATURE_SUPPORTED = 128
 } placeHolderInCapBitmap;
 
@@ -719,7 +720,10 @@
 #define SIR_HAL_LOST_LINK_PARAMS_IND         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 274)
 #define SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND  (SIR_HAL_ITC_MSG_TYPES_BEGIN + 275)
 
+#define SIR_HAL_FW_MEM_DUMP_REQ           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 275)
+
 #define SIR_HAL_MSG_TYPES_END              (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
+
 // CFG message types
 #define SIR_CFG_MSG_TYPES_BEGIN        (SIR_CFG_MODULE_ID << 8)
 #define SIR_CFG_ITC_MSG_TYPES_BEGIN    (SIR_CFG_MSG_TYPES_BEGIN+0xB0)
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index ef237dc..ea20757 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -3214,6 +3214,8 @@
 eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, v_BOOL_t nRoamScanOffloadEnabled);
 #endif
 
+eHalStatus sme_FwMemDumpReq(tHalHandle hHal, tAniFwrDumpReq *recv_req);
+
 
 /* ---------------------------------------------------------------------------
     \fn sme_IsFeatureSupportedByFW
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index b2ccf8f..fa12f38 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -13161,3 +13161,56 @@
     status = palSendMBMessage( pMac->hHdd, pMsg );
     return status;
 }
+
+
+/**
+ * sme_FwMemDumpReq() - Send Fwr mem Dump Request
+ * @hal: HAL pointer
+ *
+ * Return: eHalStatus
+ */
+
+eHalStatus sme_FwMemDumpReq(tHalHandle hHal, tAniFwrDumpReq *recv_req)
+{
+
+    eHalStatus status = eHAL_STATUS_SUCCESS;
+    tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+    vos_msg_t msg;
+    tAniFwrDumpReq * send_req;
+
+    send_req = vos_mem_malloc(sizeof(*send_req));
+    if(!send_req) {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+            FL("Mem allo failed for FW_MEM_DUMP"));
+        return eHAL_STATUS_FAILURE;
+    }
+
+    send_req->fwMemDumpReqCallback = recv_req->fwMemDumpReqCallback;
+    send_req->fwMemDumpReqContext = recv_req->fwMemDumpReqContext;
+
+    if (eHAL_STATUS_SUCCESS == sme_AcquireGlobalLock(&pMac->sme))
+    {
+        msg.bodyptr = send_req;
+        msg.type = WDA_FW_MEM_DUMP_REQ;
+        msg.reserved = 0;
+
+        if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))
+        {
+            VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+            FL("Not able to post WDA_FW_MEM_DUMP"));
+            vos_mem_free(send_req);
+            status = eHAL_STATUS_FAILURE;
+        }
+        sme_ReleaseGlobalLock(&pMac->sme);
+    }
+    else
+    {
+        VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+        FL("Failed to acquire SME Global Lock"));
+        vos_mem_free(send_req);
+        status = eHAL_STATUS_FAILURE;
+    }
+
+    return status;
+}
+
diff --git a/CORE/SVC/inc/wlan_logging_sock_svc.h b/CORE/SVC/inc/wlan_logging_sock_svc.h
index 80ac7c5..34745c5 100644
--- a/CORE/SVC/inc/wlan_logging_sock_svc.h
+++ b/CORE/SVC/inc/wlan_logging_sock_svc.h
@@ -63,6 +63,21 @@
 
 void wlan_logging_set_log_level(void);
 
+enum FW_MEM_DUMP_STATE{
+       FW_MEM_DUMP_IDLE,
+       FW_MEM_DUMP_READ_IN_PROGRESS,
+       FW_MEM_DUMP_WRITE_IN_PROGRESS,
+       FW_MEM_DUMP_WRITE_DONE,
+};
+int wlan_fwr_mem_dump_buffer_allocation(void);
+bool wlan_fwr_mem_dump_test_and_set_write_allowed_bit(void);
+bool wlan_fwr_mem_dump_test_and_set_read_allowed_bit(void);
+void wlan_set_fwr_mem_dump_state(enum FW_MEM_DUMP_STATE fw_mem_dump_state);
+size_t wlan_fwr_mem_dump_fsread_handler(char __user *buf, size_t count, loff_t *pos);
+void wlan_indicate_mem_dump_complete(bool );
+void wlan_store_fwr_mem_dump_size(uint32 dump_size);
+void wlan_free_fwr_mem_dump_buffer(void);
+
 bool wlan_is_logger_thread(int threadId);
 void wlan_logging_reset_thread_stuck_count(int threadId);
 #endif /* WLAN_LOGGING_SOCK_SVC_H */
diff --git a/CORE/SVC/src/logging/wlan_logging_sock_svc.c b/CORE/SVC/src/logging/wlan_logging_sock_svc.c
index 9e68ba9..1d8b829 100644
--- a/CORE/SVC/src/logging/wlan_logging_sock_svc.c
+++ b/CORE/SVC/src/logging/wlan_logging_sock_svc.c
@@ -60,9 +60,14 @@
 #define HOST_LOG_POST_MASK   0x002
 #define LOGGER_FW_LOG_PKT_POST_MASK   0x003
 #define LOGGER_FATAL_EVENT_POST_MASK  0x004
+#define LOGGER_FW_MEM_DUMP_PKT_POST_MASK   0x005
+#define LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK 0x006
+
 
 #define LOGGER_MAX_DATA_MGMT_PKT_Q_LEN   (8)
 #define LOGGER_MAX_FW_LOG_PKT_Q_LEN   (16)
+#define LOGGER_MAX_FW_MEM_DUMP_PKT_Q_LEN   (32)
+
 
 #define NL_BDCAST_RATELIMIT_INTERVAL (5*HZ)
 #define NL_BDCAST_RATELIMIT_BURST    1
@@ -98,6 +103,26 @@
 	bool is_flush_complete;
 };
 
+struct fw_mem_dump_logging{
+	//It will hold the starting point of mem dump buffer
+	uint8 *fw_dump_start_loc;
+	//It will hold the current loc to tell how much data filled
+	uint8 *fw_dump_current_loc;
+	uint32 fw_dump_max_size;
+	vos_pkt_t *fw_mem_dump_queue;
+	/* Holds number of pkts in fw log vos pkt queue */
+	unsigned int fw_mem_dump_pkt_qcnt;
+	/* Number of dropped pkts for fw dump */
+	unsigned int fw_mem_dump_pkt_drop_cnt;
+	/* Lock to synchronize of queue/dequeue of pkts in fw log pkt queue */
+	spinlock_t fw_mem_dump_lock;
+	/* Fw memory dump state */
+	enum FW_MEM_DUMP_STATE fw_mem_dump_status;
+	/* Completion variable for handling SSR/unload during copy_to_user */
+	struct completion fw_mem_copy_to_user_completion;
+};
+
+
 struct wlan_logging {
 	/* Log Fatal and ERROR to console */
 	bool log_fe_to_console;
@@ -152,6 +177,7 @@
 	/* data structure for log complete event*/
 	struct logger_log_complete log_complete;
 	spinlock_t bug_report_lock;
+	struct fw_mem_dump_logging fw_mem_dump_ctx;
 };
 
 static struct wlan_logging gwlan_logging;
@@ -636,6 +662,83 @@
 	return ret;
 }
 
+static int fill_fw_mem_dump_buffer(void)
+{
+	struct sk_buff *skb = NULL;
+	vos_pkt_t *current_pkt;
+	vos_pkt_t *next_pkt;
+	VOS_STATUS status = VOS_STATUS_E_FAILURE;
+	unsigned long flags;
+	int  byte_left = 0;
+
+	do {
+		spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+
+		if (!gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue) {
+			spin_unlock_irqrestore(
+				&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+			return -EIO;
+		}
+
+		/* pick first pkt from queued chain */
+		current_pkt = gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue;
+
+		/* get the pointer to the next packet in the chain */
+		status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
+							TRUE);
+
+		/* both "success" and "empty" are acceptable results */
+		if (!((status == VOS_STATUS_SUCCESS) ||
+					(status == VOS_STATUS_E_EMPTY))) {
+			spin_unlock_irqrestore(
+				&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+			pr_err("%s: Failure walking packet chain", __func__);
+			return -EIO;
+		}
+
+		/* update queue head with next pkt ptr which could be NULL */
+		gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue = next_pkt;
+		--gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt;
+		spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+
+		status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
+						VOS_FALSE);
+		if (!VOS_IS_STATUS_SUCCESS(status)) {
+			pr_err("%s: Failure extracting skb from vos pkt",
+				__func__);
+			return -EIO;
+		}
+
+		//Copy data from SKB to mem dump buffer
+		spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+		if((skb) && (skb->len != 0))
+		{
+			// Prevent buffer overflow
+			byte_left = ((int)gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size -
+					(int)(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc - gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc));
+			if(skb->len > byte_left)
+			{
+				vos_mem_copy(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc, &skb->data, byte_left);
+				//Update the current location ptr
+				gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc +=  byte_left;
+			}
+			else
+			{
+				vos_mem_copy(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc, &skb->data, skb->len);
+				//Update the current location ptr
+				gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc +=  skb->len;
+			}
+		}
+		spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+		//if(skb)
+		//	pr_err("Mem dump buffer overflow byte_left %d skb->len %d", byte_left, skb->len);
+		/*return vos pkt since skb is already detached */
+		vos_pkt_return_packet(current_pkt);
+	} while (next_pkt);
+
+	return 0;
+}
+
 static int send_filled_buffers_to_user(void)
 {
 	int ret = -1;
@@ -650,7 +753,7 @@
 	static int rate_limit;
 
 	while (!list_empty(&gwlan_logging.filled_list)
-		&& !gwlan_logging.exit) {
+			&& !gwlan_logging.exit) {
 
 		skb = dev_alloc_skb(MAX_LOGMSG_LENGTH);
 		if (skb == NULL) {
@@ -813,7 +916,10 @@
 		   test_bit(LOGGER_FW_LOG_PKT_POST_MASK,
 						&gwlan_logging.event_flag) ||
 		   test_bit(LOGGER_FATAL_EVENT_POST_MASK,
-						&gwlan_logging.event_flag)));
+						&gwlan_logging.event_flag) ||
+		   test_bit(LOGGER_FW_MEM_DUMP_PKT_POST_MASK,&gwlan_logging.event_flag) ||
+		   test_bit(LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK, &gwlan_logging.event_flag)));
+
 
 		if (ret_wait_status == -ERESTARTSYS) {
 			pr_err("%s: wait_event return -ERESTARTSYS", __func__);
@@ -856,6 +962,17 @@
 				wake_up_interruptible(&gwlan_logging.wait_queue);
 			}
 		}
+
+		if (test_and_clear_bit(LOGGER_FW_MEM_DUMP_PKT_POST_MASK,
+			&gwlan_logging.event_flag)) {
+			fill_fw_mem_dump_buffer();
+		}
+		if(test_and_clear_bit(LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK,&gwlan_logging.event_flag)){
+				/*indicate to user space that mem dump is complete */
+				fill_fw_mem_dump_buffer();
+				wlan_indicate_mem_dump_complete(true);
+		}
+
 	}
 
 	vos_timer_destroy(&gwlan_logging.threadStuckTimer);
@@ -1046,7 +1163,6 @@
 {
 	vos_pkt_t *pkt_queue_head;
 	unsigned long flags;
-
 	spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);
 	if (NULL != gwlan_logging.data_mgmt_pkt_queue) {
 		pkt_queue_head = gwlan_logging.data_mgmt_pkt_queue;
@@ -1074,7 +1190,17 @@
 		spin_unlock_irqrestore(&gwlan_logging.fw_log_pkt_lock,
 					flags);
 	}
-
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	if (NULL != gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue) {
+		pkt_queue_head = gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue;
+		spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
+					flags);
+		vos_pkt_return_packet(pkt_queue_head);
+		wlan_free_fwr_mem_dump_buffer();
+	} else {
+		spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
+					flags);
+	}
 	return 0;
 }
 
@@ -1112,6 +1238,7 @@
 	spin_lock_init(&gwlan_logging.spin_lock);
 	spin_lock_init(&gwlan_logging.data_mgmt_pkt_lock);
 	spin_lock_init(&gwlan_logging.fw_log_pkt_lock);
+	spin_lock_init(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock);
 	gapp_pid = INVALID_PID;
 	gwlan_logging.pcur_node = NULL;
 
@@ -1247,6 +1374,60 @@
 	return VOS_STATUS_SUCCESS;
 }
 
+int wlan_queue_fw_mem_dump_for_app(vos_pkt_t *pPacket)
+{
+	unsigned long flags;
+	vos_pkt_t *next_pkt;
+	vos_pkt_t *free_pkt;
+	VOS_STATUS status = VOS_STATUS_E_FAILURE;
+
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	if (gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt >= LOGGER_MAX_FW_MEM_DUMP_PKT_Q_LEN) {
+		status = vos_pkt_walk_packet_chain(
+			gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue, &next_pkt, TRUE);
+		/*both "success" and "empty" are acceptable results*/
+		if (!((status == VOS_STATUS_SUCCESS) ||
+				(status == VOS_STATUS_E_EMPTY))) {
+			spin_unlock_irqrestore(
+				&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+			pr_err("%s: Failure walking packet chain", __func__);
+			/*keep returning pkts to avoid low resource cond*/
+			vos_pkt_return_packet(pPacket);
+			return VOS_STATUS_E_FAILURE;
+		}
+
+		free_pkt = gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue;
+		gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue = next_pkt;
+		/*returning head of pkt queue. latest pkts are important*/
+		--gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt;
+                ++gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_drop_cnt ;
+		spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
+					flags);
+                pr_info("%s : fw mem_dump pkt cnt --> %d\n" ,__func__, gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_drop_cnt);
+		vos_pkt_return_packet(free_pkt);
+	} else {
+		spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock,
+					flags);
+	}
+
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+
+	if (gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue) {
+		vos_pkt_chain_packet(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue,
+					pPacket, TRUE);
+	} else {
+		gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_queue = pPacket;
+	}
+	++gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_qcnt;
+
+	spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+
+	set_bit(LOGGER_FW_MEM_DUMP_PKT_POST_MASK, &gwlan_logging.event_flag);
+	wake_up_interruptible(&gwlan_logging.wait_queue);
+
+	return VOS_STATUS_SUCCESS;
+}
+
 int wlan_queue_logpkt_for_app(vos_pkt_t *pPacket, uint32 pkt_type)
 {
 	VOS_STATUS status = VOS_STATUS_E_FAILURE;
@@ -1274,6 +1455,9 @@
 	case WLAN_FW_LOGS:
 		status = wlan_queue_fw_log_pkt_for_app(pPacket);
 		break;
+	case WLAN_FW_MEMORY_DUMP:
+		status = wlan_queue_fw_mem_dump_for_app(pPacket);
+		break;
 
 	default:
 		pr_info("%s: Unknown pkt received %d", __func__, pkt_type);
@@ -1290,8 +1474,15 @@
     {
         pr_info("%s: Setting LOGGER_FATAL_EVENT\n", __func__);
         set_bit(LOGGER_FATAL_EVENT_POST_MASK, &gwlan_logging.event_flag);
-        wake_up_interruptible(&gwlan_logging.wait_queue);
+	wake_up_interruptible(&gwlan_logging.wait_queue);
     }
+    if(type == WLAN_FW_MEMORY_DUMP)
+    {
+	    pr_info("%s: Setting FW MEM DUMP LOGGER event\n", __func__);
+	    set_bit(LOGGER_FW_MEM_DUMP_PKT_POST_DONE_MASK, &gwlan_logging.event_flag);
+	    wake_up_interruptible(&gwlan_logging.wait_queue);
+    }
+
 }
 
 /**
@@ -1337,4 +1528,202 @@
 	spin_unlock_irqrestore(&gwlan_logging.thread_stuck_lock, flags);
 }
 
+int wlan_fwr_mem_dump_buffer_allocation(void)
+{
+	/*Allocate the dump memory as reported by fw.
+	  or if feature not supported just report to the user */
+	if(gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size <= 0)
+	{
+	   pr_err("%s: fw_mem_dump_req not supported by firmware", __func__);
+	   return -EFAULT;
+	}
+	gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc =
+		(uint8 *)vos_mem_vmalloc(gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size);
+	gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc = gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc;
+	if(NULL == gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc)
+	{
+		pr_err("%s: fw_mem_dump_req alloc failed for size %d bytes", __func__,gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+/*set the current fw mem dump state*/
+void wlan_set_fwr_mem_dump_state(enum FW_MEM_DUMP_STATE fw_mem_dump_state)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = fw_mem_dump_state;
+	spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+}
+/*check for new request validity and free memory if present from previous request */
+bool wlan_fwr_mem_dump_test_and_set_write_allowed_bit(){
+	unsigned long flags;
+	bool ret = false;
+	bool write_done = false;
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+
+	if(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_IDLE){
+		ret = true;
+		gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_WRITE_IN_PROGRESS;
+	}
+	else if(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_WRITE_DONE){
+		ret = true;
+		write_done =  true;
+		gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_WRITE_IN_PROGRESS;
+	}
+	spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	pr_info("%s:fw mem dump state --> %d ", __func__,gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status);
+
+	if(write_done)
+		wlan_free_fwr_mem_dump_buffer();
+	return ret;
+}
+
+bool wlan_fwr_mem_dump_test_and_set_read_allowed_bit(){
+	unsigned long flags;
+	bool ret=false;
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	if(gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_WRITE_DONE ||
+          gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status == FW_MEM_DUMP_READ_IN_PROGRESS ){
+          ret = true;
+          gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_READ_IN_PROGRESS;
+	}
+	spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	pr_info("%s:fw mem dump state --> %d ", __func__,gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status);
+
+	return ret;
+}
+size_t wlan_fwr_mem_dump_fsread_handler(char __user *buf,
+		size_t count, loff_t *pos)
+{
+	if (buf == NULL || gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc == NULL)
+	{
+		pr_err("%s : start loc : %p buf : %p ",__func__,gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc,buf);
+		return 0;
+	}
+
+	if (*pos < 0) {
+		pr_err("Invalid start offset for memdump read");
+		return 0;
+	} else if (*pos >= gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size || !count) {
+		pr_err("No more data to copy");
+		return 0;
+	} else if (count > gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size - *pos) {
+		count = gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size - *pos;
+	}
+	if (copy_to_user(buf, gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc, count)) {
+		pr_err("copy to user space failed");
+		return 0;
+	}
+
+	/* offset(pos) should be updated here based on the copy done*/
+	*pos += count;
+
+	return count;
+}
+
+void wlan_free_fwr_mem_dump_buffer (void )
+{
+	unsigned long flags;
+	void * tmp = NULL;
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	tmp = gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc;
+	gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc = NULL;
+	gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc = NULL;
+	spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	// Don't set fw_dump_max_size to 0, only free the buffera
+	if(tmp != NULL)
+		vos_mem_vfree((void *)tmp);
+}
+
+void wlan_store_fwr_mem_dump_size(uint32 dump_size)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	//Store the dump size
+	gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size = dump_size;
+	spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+}
+/**
+ * wlan_indicate_mem_dump_complete() -  When H2H for mem
+ * dump finish invoke the handler.
+ *
+ * This is a handler used to indicate user space about the
+ * availability for firmware memory dump via vendor event.
+ *
+ * Return: None
+ */
+void wlan_indicate_mem_dump_complete(bool status )
+{
+	hdd_context_t *hdd_ctx;
+	void *vos_ctx;
+	int ret;
+	struct sk_buff *skb = NULL;
+	unsigned long flags;
+
+	vos_ctx = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
+	if (!vos_ctx) {
+		pr_err("Invalid VOS context");
+		return;
+	}
+
+	hdd_ctx = vos_get_context(VOS_MODULE_ID_HDD, vos_ctx);
+	if(!hdd_ctx) {
+		pr_err("Invalid HDD context");
+		return;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (0 != ret) {
+		pr_err("HDD context is not valid");
+		return;
+	}
+
+	spin_lock_irqsave(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+	/*Chnage fw memory dump to indicate write done*/
+	gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_status = FW_MEM_DUMP_WRITE_DONE;
+        /*reset dropped packet count upon completion of this request*/
+        gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_pkt_drop_cnt = 0;
+	spin_unlock_irqrestore(&gwlan_logging.fw_mem_dump_ctx.fw_mem_dump_lock, flags);
+
+	skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+		NULL,
+#endif
+		sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN,
+		QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX,
+		GFP_KERNEL);
+
+	if (!skb) {
+		pr_err("cfg80211_vendor_event_alloc failed");
+		return;
+	}
+	if(status)
+	{
+		if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE,
+				gwlan_logging.fw_mem_dump_ctx.fw_dump_max_size)) {
+			pr_err("nla put fail");
+			goto nla_put_failure;
+		}
+	}
+	else
+	{
+		pr_err("memdump failed.Returning size 0 to user");
+		if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MEMDUMP_SIZE,
+				0)) {
+			pr_err("nla put fail");
+			goto nla_put_failure;
+		}
+	}
+
+	cfg80211_vendor_event(skb, GFP_KERNEL);
+	pr_info("Memdump event sent successfully to user space : recvd size %d",(int)(gwlan_logging.fw_mem_dump_ctx.fw_dump_current_loc - gwlan_logging.fw_mem_dump_ctx.fw_dump_start_loc));
+	return;
+
+nla_put_failure:
+	kfree_skb(skb);
+	return;
+}
+
 #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index c66b092..1ade7a3 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1291,6 +1291,8 @@
 #define WDA_SEND_FREQ_RANGE_CONTROL_IND        SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND
 
 
+#define WDA_FW_MEM_DUMP_REQ                  SIR_HAL_FW_MEM_DUMP_REQ
+
 #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 // Bit 6 will be used to control BD rate for Management frames
 
 #define halTxFrame(hHal, pFrmBuf, frmLen, frmType, txDir, tid, pCompFunc, pData, txFlag) \
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index e35a088..d6e3804 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -260,6 +260,9 @@
 WDA_ProcessSetRtsCtsHTVhtInd(tWDA_CbContext *pWDA,
                          tANI_U32 val);
 
+VOS_STATUS
+WDA_ProcessFwrMemDumpReq(tWDA_CbContext *pWDA,
+                                tAniFwrDumpReq* pFwrMemDumpReq);
 
 VOS_STATUS WDA_ProcessMonStartReq( tWDA_CbContext *pWDA, void* wdaRequest);
 VOS_STATUS WDA_ProcessMonStopReq( tWDA_CbContext *pWDA, void* wdaRequest);
@@ -5494,6 +5497,7 @@
 {
    tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData;
    tSirFWLoggingInitParam *pFWLoggingInitParams;
+   tAniLoggingInitRsp *pLoggingInitRsp;
 
    VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
                                           "<------ %s " ,__func__);
@@ -5515,13 +5519,24 @@
       return ;
    }
 
+   pLoggingInitRsp = (tAniLoggingInitRsp *)vos_mem_malloc(sizeof(tAniLoggingInitRsp)) ;
+   if(NULL == pWdaParams)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                 "%s: VOS MEM Alloc Failure for pLoggingInitRsp", __func__);
+      VOS_ASSERT(0);
+      vos_mem_free(pWdaParams);
+      return;
+   }
+
    pFWLoggingInitParams = (tSirFWLoggingInitParam *)pWdaParams->wdaMsgParam;
+   vos_mem_copy(pLoggingInitRsp, wdiRsp, sizeof(tAniLoggingInitRsp));
 
    if(pFWLoggingInitParams->fwlogInitCallback)
    {
       pFWLoggingInitParams->fwlogInitCallback(
                                pFWLoggingInitParams->fwlogInitCbContext,
-                               CONVERT_WDI2VOS_STATUS(wdiRsp->status));
+                               pLoggingInitRsp);
    }
    else
    {
@@ -5529,6 +5544,7 @@
               "%s: pFWLoggingInitParams callback is NULL", __func__);
    }
 
+   vos_mem_free(pLoggingInitRsp);
    vos_mem_free(pWdaParams->wdaWdiApiMsgParam);
    vos_mem_free(pWdaParams->wdaMsgParam);
    vos_mem_free(pWdaParams);
@@ -13703,6 +13719,136 @@
     return CONVERT_WDI2VOS_STATUS(wdiStatus) ;
 }
 
+
+/*
+ * FUNCTION: WDA_FwrMemDumpRespCallback
+ * recieves Mgmt Logging init response from FW
+ */
+ void WDA_FwrMemDumpRespCallback(WDI_FwrMemDumpRsp* wdiRsp,
+                                                            void* pUserData)
+{
+   tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData;
+   tAniFwrDumpReq *pFwrMemDumpReq;
+   tAniFwrDumpRsp  *pFwrMemDumpRsp;
+   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 ;
+   }
+
+   if(NULL == pWdaParams->wdaMsgParam)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s: pWdaParams->wdaMsgParam is NULL", __func__);
+      VOS_ASSERT(0);
+      vos_mem_free(pWdaParams);
+      return ;
+   }
+
+   pFwrMemDumpRsp = (tAniFwrDumpRsp *)vos_mem_malloc(sizeof(tAniFwrDumpRsp));
+   if(pFwrMemDumpRsp == NULL)
+   {
+       VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+               "%s: pFwrMemDumpRsp is NULL", __func__);
+       VOS_ASSERT(0);
+       vos_mem_free(pWdaParams);
+       return ;
+   }
+
+   pFwrMemDumpRsp->dump_status  = wdiRsp->dump_status;
+   pFwrMemDumpReq = (tAniFwrDumpReq *)pWdaParams->wdaMsgParam;
+
+   if(pFwrMemDumpReq->fwMemDumpReqCallback)
+   {
+      pFwrMemDumpReq->fwMemDumpReqCallback(
+                               pFwrMemDumpReq->fwMemDumpReqContext,
+                               pFwrMemDumpRsp);
+   }
+   else
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+              "%s: FwrMemDump callback is NULL", __func__);
+   }
+
+   vos_mem_free(pWdaParams->wdaWdiApiMsgParam);
+   vos_mem_free(pWdaParams->wdaMsgParam);
+   vos_mem_free(pWdaParams);
+   vos_mem_free(pFwrMemDumpRsp);
+
+   return ;
+}
+
+VOS_STATUS WDA_ProcessFwrMemDumpReq(tWDA_CbContext * pWDA,
+                         tAniFwrDumpReq* pFwrMemDumpReq)
+{
+   VOS_STATUS status = VOS_STATUS_SUCCESS;
+   WDI_Status wstatus;
+   WDI_FwrMemDumpReqType * pWdiFwrMemDumpReq;
+   tWDA_ReqParams *pWdaParams ;
+
+   VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                                          "------> %s " ,__func__);
+   /* Sanity Check*/
+   if(NULL == pFwrMemDumpReq)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: pFwrMemDumpReq received NULL", __func__);
+      VOS_ASSERT(0) ;
+      return VOS_STATUS_E_FAULT;
+   }
+
+   pWdiFwrMemDumpReq = (WDI_FwrMemDumpReqType *)vos_mem_malloc(sizeof(WDI_FwrMemDumpReqType));
+   if(NULL == pWdiFwrMemDumpReq)
+   {
+      VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                           "%s: pWdiFwrMemDumpReq Alloc Failure", __func__);
+      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: pWdaParams Alloc Failure", __func__);
+      VOS_ASSERT(0);
+      vos_mem_free(pWdiFwrMemDumpReq);
+      return VOS_STATUS_E_NOMEM;
+   }
+
+   /* Store Params pass it to WDI */
+   pWdaParams->wdaWdiApiMsgParam = (void *)pWdiFwrMemDumpReq;
+   pWdaParams->pWdaContext = pWDA;
+   /* Store param pointer as passed in by caller */
+   pWdaParams->wdaMsgParam = pFwrMemDumpReq;
+
+   status = WDI_FwrMemDumpReq(pWdiFwrMemDumpReq,
+                              (WDI_FwrMemDumpCb)WDA_FwrMemDumpRespCallback,
+                              pWdaParams);
+
+   if(IS_WDI_STATUS_FAILURE(wstatus))
+   {
+       VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                 FL("Fwr Mem Dump Req failed, free all the memory"));
+       status = CONVERT_WDI2VOS_STATUS(wstatus);
+       vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ;
+       vos_mem_free(pWdaParams->wdaMsgParam);
+       vos_mem_free(pWdaParams);
+       pWdaParams->wdaWdiApiMsgParam = NULL;
+       pWdaParams->wdaMsgParam = NULL;
+   }
+
+    return status;
+
+}
+
+
+
 /*
  * FUNCTION: WDA_McProcessMsg
  * Trigger DAL-AL to start CFG download 
@@ -14408,6 +14554,12 @@
          WDA_ProcessSetPowerParamsReq(pWDA, (tSirSetPowerParamsReq *)pMsg->bodyptr);
          break;
       }
+      case WDA_FW_MEM_DUMP_REQ:
+      {
+          WDA_ProcessFwrMemDumpReq(pWDA, (tAniFwrDumpReq*)pMsg->bodyptr);
+          break;
+      }
+
 #ifdef WLAN_FEATURE_GTK_OFFLOAD
       case WDA_GTK_OFFLOAD_REQ:
       {
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index 1f78693..20ee417 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -2703,8 +2703,9 @@
   wpt_uint8 logMailBoxVer;
   //Qshrink is enabled
   wpt_boolean logCompressEnabled;
+  /* store the size of fw mem dump */
+  wpt_uint32 fw_mem_dump_max_size;
   //Reserved for future purpose
-  wpt_uint32 reserved0;
   wpt_uint32 reserved1;
   wpt_uint32 reserved2;
 }WDI_FWLoggingInitRspParamType;
@@ -6145,6 +6146,32 @@
 
 }WDI_MonStartReqType;
 
+/**
+ * struct WDI_FwrMemDumpReqType - firmware memory dump request details.
+.*.@FWMemDumpReqCb - Associated Callback
+ *.@fwMemDumpReqContext - Callback context
+ * @reserved - reserved field 1.
+ *
+ * This structure carries information about the firmware
+ * memory dump request.
+ */
+typedef struct
+{
+    wpt_uint32        reserved1;
+}WDI_FwrMemDumpReqType;
+
+/**
+ * struct WDI_FwrMemDumpRsp - firmware dump response details.
+ *
+ * This structure is used to store the firmware dump
+ * response from the firmware.
+ */
+typedef struct
+{
+    wpt_uint32 dump_status;
+}WDI_FwrMemDumpRsp;
+
+
 /*----------------------------------------------------------------------------
  *   WDI callback types
  *--------------------------------------------------------------------------*/
@@ -7896,6 +7923,25 @@
 typedef void  (*WDI_SetPowerParamsCb)(WDI_Status  wdiStatus,
                                       void*       pUserData);
 
+
+/*---------------------------------------------------------------------------
+   WDA_FwrMemDumpRespCallback
+
+   DESCRIPTION
+
+   This callback is invoked by DAL when it has received a Fwr Mem dump
+   response from the underlying device.
+
+   PARAMETERS
+
+    IN
+    wdiStatus:  response status received from HAL
+    pUserData:  user data
+ ---------------------------------------------------------------------------*/
+typedef void (* WDI_FwrMemDumpCb) (WDI_FwrMemDumpRsp* wdiRsp,
+                                        void*       pUserData);
+
+
 #ifdef WLAN_FEATURE_GTK_OFFLOAD
 /*---------------------------------------------------------------------------
    WDI_GtkOffloadCb
@@ -8068,6 +8114,9 @@
 
 typedef void  (*WDI_MonModeRspCb)(void *pEventData,void *pUserData);
 
+typedef void  (*WDI_FwrMemDumpRspCb)(WDI_FwrMemDumpRsp *wdiRsp, void *pUserData);
+
+
 /*========================================================================
  *     Function Declarations and Documentation
  ==========================================================================*/
@@ -11550,6 +11599,16 @@
         void*                   pUserData
         );
 
+WDI_Status
+WDI_FwrMemDumpReq
+
+(
+   WDI_FwrMemDumpReqType          *pwdiFwrMemDumpReqInfo,
+   WDI_FwrMemDumpCb                wdiFwrMemDumpRspCb,
+   void*                           pUserData
+);
+
+
 /**
  @brief WDI_NanRequest
         NAN request
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index a8e9ccf..a968b61 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -479,6 +479,7 @@
   WDI_MON_START_REQ                              = 107,
   WDI_MON_STOP_REQ                               = 108,
   WDI_FATAL_EVENT_LOGGING_REQ                    = 109,
+  WDI_FWR_MEM_DUMP_REQ                           = 110,
 
   WDI_MAX_REQ,
 
@@ -821,6 +822,7 @@
   WDI_MON_START_RSP                              = 107,
   WDI_MON_STOP_RSP                               = 108,
   WDI_FATAL_EVENT_LOGGING_RSP                    = 109,
+  WDI_FWR_MEM_DUMP_RSP                           = 110,
 
   /*-------------------------------------------------------------------------
     Indications
@@ -6316,5 +6318,19 @@
   WDI_EventInfoType*     pEventData
 );
 
+WDI_Status
+WDI_ProcessFwrMemDumpReq
+(
+    WDI_ControlBlockType*  pWDICtx,
+    WDI_EventInfoType*     pEventData
+);
+
+WDI_Status
+    WDI_ProcessFwrMemDumpRsp
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
 #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 110e67f..d8007e6 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -204,6 +204,7 @@
    ,MGMT_FRAME_LOGGING             //53
    ,ENHANCED_TXBD_COMPLETION       //54
    ,LOGGING_ENHANCEMENT            //55
+   ,MEMORY_DUMP_SUPPORTED          //57
 };
 
 /*-------------------------------------------------------------------------- 
@@ -480,6 +481,8 @@
   WDI_ProcessMonStartReq,          /* WDI_MON_START_REQ */
   WDI_ProcessMonStopReq,           /* WDI_MON_STOP_REQ */
   WDI_ProcessFatalEventLogsReq,     /*WDI_FATAL_EVENT_LOGGING_REQ*/
+  WDI_ProcessFwrMemDumpReq,           /* WDI_FWR_MEM_DUMP_REQ*/
+
   /*-------------------------------------------------------------------------
     Indications
   -------------------------------------------------------------------------*/
@@ -753,6 +756,7 @@
     WDI_ProcessMonStartRsp,                    /* WDI_MON_START_RSP*/
     WDI_ProcessMonStopRsp,                    /* WDI_MON_STOP_RSP*/
     WDI_ProcessFatalEventLogsRsp,              /*WDI_FATAL_EVENT_LOGGING_RSP*/
+    WDI_ProcessFwrMemDumpRsp,                 /* WDI_FWR_MEM_DUMP_RSP */
   /*---------------------------------------------------------------------
     Indications
   ---------------------------------------------------------------------*/
@@ -1183,6 +1187,7 @@
     CASE_RETURN_STRING( WDI_MON_STOP_REQ );
     CASE_RETURN_STRING( WDI_FATAL_EVENT_LOGGING_REQ );
     CASE_RETURN_STRING( WDI_SEND_FREQ_RANGE_CONTROL_IND );
+    CASE_RETURN_STRING( WDI_FWR_MEM_DUMP_REQ);
     default:
         return "Unknown WDI MessageId";
   }
@@ -1319,6 +1324,7 @@
     CASE_RETURN_STRING( WDI_FW_LOGGING_INIT_RSP);
     CASE_RETURN_STRING( WDI_GET_FRAME_LOG_RSP);
     CASE_RETURN_STRING (WDI_FATAL_EVENT_LOGGING_RSP);
+    CASE_RETURN_STRING( WDI_FWR_MEM_DUMP_RSP);
     default:
         return "Unknown WDI MessageId";
   }
@@ -1484,8 +1490,9 @@
                      case LOGGING_ENHANCEMENT: snprintf(pCapStr, sizeof("LOGGING_ENHANCEMENT"), "%s", "LOGGING_ENHANCEMENT");
                           pCapStr += strlen("LOGGING_ENHANCEMENT");
                           break;
-
-
+                     case MEMORY_DUMP_SUPPORTED:snprintf(pCapStr, sizeof("FW_MEM_DUMP_LOGGING"), "%s", "FW_MEM_DUMP_LOGGING");
+                          pCapStr += strlen("FW_MEM_DUMP_LOGGING");
+                          break;
                  }
                  *pCapStr++ = ',';
                  *pCapStr++ = ' ';
@@ -4448,6 +4455,67 @@
    return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
 }
 
+
+/**
+ @brief WDI_FwrMemDumpReq will be called when the upper
+        MAC wants to get fwr mem dump. Upon the call of
+        this API the WLAN DAL will pack and send a HAL
+        Frame logging init request message to
+        the lower RIVA sub-system.
+
+        In state BUSY this request will be queued. Request won't
+        be allowed in any other state.
+
+
+ @param pWdiFwrMemDumpReq: the fwr mem dump req params
+                      as specified by the Device Interface
+
+        wdiFWLoggingInitReqCb: callback for passing back the
+        response of the frame logging init operation received
+        from the device
+
+        pUserData: user data will be passed back with the
+        callback
+
+ @return Result of the function call
+*/
+
+WDI_Status
+WDI_FwrMemDumpReq
+
+(
+   WDI_FwrMemDumpReqType          *pwdiFwrMemDumpReqInfo,
+   WDI_FwrMemDumpCb                wdiFwrMemDumpRspCb,
+   void*                           pUserData
+)
+{
+   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_FWR_MEM_DUMP_REQ;
+   wdiEventData.pEventData      = pwdiFwrMemDumpReqInfo;
+   wdiEventData.uEventDataSize  = sizeof(WDI_FwrMemDumpReqType);
+   wdiEventData.pCBfnc          = wdiFwrMemDumpRspCb;
+   wdiEventData.pUserData       = pUserData;
+
+   return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+
+
 /**
  @brief WDI_ConfigureRxpFilterReq will be called when the upper
         MAC wants to set/reset the RXP filters for received pkts
@@ -24278,6 +24346,9 @@
        return WLAN_HAL_FATAL_EVENT_LOGGING_REQ;
   case WDI_SEND_FREQ_RANGE_CONTROL_IND:
        return WLAN_HAL_SEND_FREQ_RANGE_CONTROL_IND;
+  case WDI_FWR_MEM_DUMP_REQ:
+       return WLAN_HAL_FW_MEMORY_DUMP_REQ;
+
   default:
     return WLAN_HAL_MSG_MAX;
   }
@@ -24612,6 +24683,8 @@
        return WDI_MON_STOP_RSP;
   case WLAN_HAL_FATAL_EVENT_LOGGING_RSP:
        return WDI_FATAL_EVENT_LOGGING_RSP;
+  case WLAN_HAL_FW_MEMORY_DUMP_RSP:
+       return WDI_FWR_MEM_DUMP_RSP;
   default:
     return eDRIVER_TYPE_MAX;
   }
@@ -34567,6 +34640,7 @@
   wpalMemoryCopy( &halRsp, pEventData->pEventData, sizeof(halRsp));
 
   wdiFWLogginginitRsp.status = WDI_HAL_2_WDI_STATUS(halRsp.status);
+  wdiFWLogginginitRsp.fw_mem_dump_max_size = halRsp.fw_dump_max_size;
 
   /*Notify UMAC*/
   wdiFWFrameLoggingInitRspCb( &wdiFWLogginginitRsp, pWDICtx->pRspCBUserData);
@@ -34574,6 +34648,57 @@
   return WDI_STATUS_SUCCESS;
 }
 
+/**
+ @brief Process Fwr Mem Dump Rsp function
+        (called when a response is being received over the bus from HAL)
+
+ @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_ProcessFwrMemDumpRsp
+
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  tHalFwMemoryDumpRespMsg      halRsp;
+  WDI_FwrMemDumpRspCb          wdiFwrMemDumpRspCb;
+  WDI_FwrMemDumpRsp            wdiFwrMemDumpRsp;
+
+  VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+                  "%s: %d Enter",__func__, __LINE__);
+
+  /*-------------------------------------------------------------------------
+    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;
+  }
+  wdiFwrMemDumpRspCb = (WDI_FwrMemDumpRspCb)pWDICtx->pfncRspCB;
+
+  /*-------------------------------------------------------------------------
+    Extract response and send it to UMAC
+  -------------------------------------------------------------------------*/
+  wpalMemoryCopy( &halRsp.tFwMemoryDumpResp, pEventData->pEventData, sizeof(halRsp));
+
+  wdiFwrMemDumpRsp.dump_status = WDI_HAL_2_WDI_STATUS(halRsp.tFwMemoryDumpResp.status);
+
+  /*Notify UMAC*/
+  wdiFwrMemDumpRspCb( &wdiFwrMemDumpRsp, pWDICtx->pRspCBUserData);
+
+  return WDI_STATUS_SUCCESS;
+}
+
 WDI_Status
 WDI_ProcessFWLoggingDXEdoneInd
 (
@@ -34877,6 +35002,78 @@
 }
 
 /**
+ @brief Process FwrMemDumpReq Request
+
+ @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_ProcessFwrMemDumpReq
+
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+    WDI_FwrMemDumpReqType *            wdiFwrMemDumpReq;
+    wpt_uint8*                         pSendBuffer  = NULL;
+    wpt_uint16                         usDataOffset = 0;
+    wpt_uint16                         usSendSize   = 0;
+    WDI_Status                         wdiStatus;
+    tHalFwMemoryDumpReqMsg             halFwrMemDumpReq;
+    WDI_FwrMemDumpRspCb                wdiFwrMemDumpRspCb;
+
+    VOS_TRACE( VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+            "%s: %d Enter",__func__, __LINE__);
+
+    /*-------------------------------------------------------------------------
+      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;
+    }
+
+    wdiFwrMemDumpReq = (WDI_FwrMemDumpReqType *)pEventData->pEventData;
+
+    /*-----------------------------------------------------------------------
+      Get message buffer
+      -----------------------------------------------------------------------*/
+    if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx,
+                    WDI_FWR_MEM_DUMP_REQ,
+                    sizeof(halFwrMemDumpReq.tFwMemoryDumpReqParam),
+                    &pSendBuffer, &usDataOffset, &usSendSize))||
+            (usSendSize < (usDataOffset +
+            sizeof(halFwrMemDumpReq.tFwMemoryDumpReqParam))))
+    {
+        WPAL_TRACE( eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_FATAL,
+                "Unable to get send buffer in Process Fwr Mem Dump Req");
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    wdiFwrMemDumpRspCb   = (WDI_FwrMemDumpRspCb)pEventData->pCBfnc;
+    wpalMemoryCopy( pSendBuffer+usDataOffset,
+                    &halFwrMemDumpReq.tFwMemoryDumpReqParam,
+                    sizeof(halFwrMemDumpReq.tFwMemoryDumpReqParam));
+
+    /*-------------------------------------------------------------------------
+        Send Fwr Mem Dump Request to HAL
+      ------------------------------------------------------------------------*/
+    wdiStatus = WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize,
+                             wdiFwrMemDumpRspCb, pEventData->pUserData,
+                             WDI_FWR_MEM_DUMP_RSP);
+    return  wdiStatus;
+}
+
+/**
  @brief WDI_EncryptMsgReq
 
  @param pwdiEncryptMsgParams: Req parameter for the FW
diff --git a/riva/inc/wlan_hal_msg.h b/riva/inc/wlan_hal_msg.h
index fb02291..a55950e 100644
--- a/riva/inc/wlan_hal_msg.h
+++ b/riva/inc/wlan_hal_msg.h
@@ -6782,6 +6782,7 @@
     MGMT_FRAME_LOGGING     = 53,
     ENHANCED_TXBD_COMPLETION = 54,
     LOGGING_ENHANCEMENT    = 55,
+    MEMORY_DUMP_SUPPORTED  = 57,
     MAX_FEATURE_SUPPORTED  = 128,
 } placeHolderInCapBitmap;
 
@@ -8665,8 +8666,9 @@
     tANI_U8 logMailBoxVer;
     /* Qshrink is enabled */
     tANI_BOOLEAN logCompressEnabled;
+    /* fw_dump_max_size is used to tell fwr mem dump size */
+    tANI_U32 fw_dump_max_size;
     /* Reserved for future purpose */
-    tANI_U32 reserved0;
     tANI_U32 reserved1;
     tANI_U32 reserved2;
 } tFWLoggingInitResp, * tpFWLoggingInitResp;
@@ -8717,6 +8719,35 @@
 }tLoggingMailBox, *tpLoggingMailBox;
 
 /*---------------------------------------------------------------------------
+ *WLAN_HAL_FW_MEMORY_DUMP_REQ
+ *--------------------------------------------------------------------------*/
+typedef PACKED_PRE struct PACKED_POST
+{
+    tANI_U32        reserved;
+}tHalFwMemoryDumpReqType, * tpHalFwMemoryDumpReqType;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+    tHalMsgHeader           header;
+    tHalFwMemoryDumpReqType tFwMemoryDumpReqParam;
+} tHalFwMemoryDumpReqMsg,   * tpHalFwMemoryDumpReqMsg;
+
+/*---------------------------------------------------------------------------
+ * WLAN_HAL_FW_MEMORY_DUMP_RSP
+ *-------------------------------------------------------------------------*/
+typedef PACKED_PRE struct PACKED_POST
+{
+    tANI_U32   status;
+} tHalFwMemoryDumpRespType, * tpHalFwMemoryDumpRespType;
+
+typedef PACKED_PRE struct PACKED_POST
+{
+    tHalMsgHeader             header;
+    tHalFwMemoryDumpRespType  tFwMemoryDumpResp;
+}  tHalFwMemoryDumpRespMsg,   * tpHalFwMemoryDumpRespMsg;
+
+
+/*---------------------------------------------------------------------------
 * WLAN_HAL_ENABLE_MONITOR_MODE_REQ
 *-------------------------------------------------------------------------*/