wlan: Add Periodic TX Packet Offload feature through debugfs

This feature is to add support in host driver/FW to transmit specific
packet periodically without waking up host. Application can program the
content of the data packet, and the content is transparent to host
driver/FW.

Change-Id: I77f07a8de23804bfe340486105263b9257a1e6b0
CRs-Fixed: 528870
diff --git a/CORE/HDD/inc/wlan_hdd_debugfs.h b/CORE/HDD/inc/wlan_hdd_debugfs.h
index 7b912c8..c7f00af 100644
--- a/CORE/HDD/inc/wlan_hdd_debugfs.h
+++ b/CORE/HDD/inc/wlan_hdd_debugfs.h
@@ -18,7 +18,6 @@
 inline void hdd_debugfs_exit(hdd_context_t *pHddCtx)
 {
 }
-#endif
-
+#endif /* #ifdef WLAN_OPEN_SOURCE */
 #endif /* #ifndef _WLAN_HDD_DEBUGFS_H */
 
diff --git a/CORE/HDD/src/wlan_hdd_debugfs.c b/CORE/HDD/src/wlan_hdd_debugfs.c
index 0337b4a..ef1f252 100644
--- a/CORE/HDD/src/wlan_hdd_debugfs.c
+++ b/CORE/HDD/src/wlan_hdd_debugfs.c
@@ -24,6 +24,7 @@
 #include <wlan_hdd_wowl.h>
 
 #define MAX_USER_COMMAND_SIZE_WOWL_PATTERN 512
+#define MAX_USER_COMMAND_SIZE_FRAME 4096
 
 static ssize_t wcnss_wowpattern_write(struct file *file,
                const char __user *buf, size_t count, loff_t *ppos)
@@ -95,6 +96,173 @@
     return count;
 }
 
+static ssize_t wcnss_patterngen_write(struct file *file,
+               const char __user *buf, size_t count, loff_t *ppos)
+{
+    hdd_adapter_t *pAdapter = (hdd_adapter_t *)file->private_data;
+    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
+    tSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams;
+    tSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams;
+
+    char *cmd, *sptr, *token;
+    v_U8_t pattern_idx = 0;
+    v_U8_t pattern_duration = 0;
+    char *pattern_buf;
+    v_U16_t pattern_len = 0;
+    v_U16_t i = 0;
+
+    if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
+                   "%s: Invalid adapter or adapter has invalid magic.",
+                   __func__);
+
+        return -EINVAL;
+    }
+
+    if (!hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Not in Connected state!", __func__);
+
+        return -EINVAL;
+    }
+
+    /* Get command from user */
+    if (count <= MAX_USER_COMMAND_SIZE_FRAME)
+        cmd = vos_mem_malloc(count);
+    else
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Command length is larger than d% bytes.",
+                   __func__, MAX_USER_COMMAND_SIZE_FRAME);
+
+        return -EINVAL;
+    }
+
+    if (copy_from_user(cmd, buf, count))
+    {
+        vos_mem_free(cmd);
+        return -EFAULT;
+    }
+    cmd[count] = '\0';
+    sptr = cmd;
+
+    /* Get pattern idx */
+    token = strsep(&sptr, " ");
+    if (!token)
+        goto failure;
+    if (kstrtou8(token, 0, &pattern_idx))
+        goto failure;
+
+    if (pattern_idx > (MAXNUM_PERIODIC_TX_PTRNS - 1))
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Pattern index %d is not in the range (0 ~ %d).",
+                   __func__, pattern_idx, MAXNUM_PERIODIC_TX_PTRNS - 1);
+
+        goto failure;
+    }
+
+    /* Get pattern duration */
+    token = strsep(&sptr, " ");
+    if (!token)
+        goto failure;
+    if (kstrtou8(token, 0, &pattern_duration))
+        goto failure;
+
+    /* Delete pattern using index if duration is 0*/
+    if (!pattern_duration)
+    {
+        delPeriodicTxPtrnParams =
+            vos_mem_malloc(sizeof(tSirDelPeriodicTxPtrn));
+
+        delPeriodicTxPtrnParams->ucPatternIdBitmap = 1 << pattern_idx;
+        vos_mem_copy(delPeriodicTxPtrnParams->macAddress,
+                     pAdapter->macAddressCurrent.bytes, 6);
+
+        /* Delete pattern */
+        if (eHAL_STATUS_SUCCESS != sme_DelPeriodicTxPtrn(pHddCtx->hHal,
+                                                delPeriodicTxPtrnParams))
+        {
+            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                       "%s: sme_DelPeriodicTxPtrn() failed!", __func__);
+
+            vos_mem_free(delPeriodicTxPtrnParams);
+            goto failure;
+        }
+
+        vos_mem_free(delPeriodicTxPtrnParams);
+        vos_mem_free(cmd);
+        return count;
+    }
+
+    /* Get pattern */
+    token = strsep(&sptr, " ");
+    if (!token)
+        goto failure;
+
+    pattern_buf = token;
+    pattern_buf[strlen(pattern_buf) - 1] = '\0';
+    pattern_len = strlen(pattern_buf);
+
+    /* Since the pattern is a hex string, 2 characters represent 1 byte. */
+    if (pattern_len % 2)
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Malformed pattern!", __func__);
+
+        goto failure;
+    }
+    else
+        pattern_len >>= 1;
+
+    if (pattern_len < 14 || pattern_len > PERIODIC_TX_PTRN_MAX_SIZE)
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Not an 802.3 frame!", __func__);
+
+        goto failure;
+    }
+
+    addPeriodicTxPtrnParams = vos_mem_malloc(sizeof(tSirAddPeriodicTxPtrn));
+
+    addPeriodicTxPtrnParams->ucPtrnId = pattern_idx;
+    addPeriodicTxPtrnParams->usPtrnIntervalMs = pattern_duration * 500;
+    addPeriodicTxPtrnParams->ucPtrnSize = pattern_len;
+    vos_mem_copy(addPeriodicTxPtrnParams->macAddress,
+                 pAdapter->macAddressCurrent.bytes, 6);
+
+    /* Extract the pattern */
+    for(i = 0; i < addPeriodicTxPtrnParams->ucPtrnSize; i++)
+    {
+        addPeriodicTxPtrnParams->ucPattern[i] =
+        (hdd_parse_hex(pattern_buf[0]) << 4) + hdd_parse_hex(pattern_buf[1]);
+
+        /* Skip to next byte */
+        pattern_buf += 2;
+    }
+
+    /* Add pattern */
+    if (eHAL_STATUS_SUCCESS != sme_AddPeriodicTxPtrn(pHddCtx->hHal,
+                                            addPeriodicTxPtrnParams))
+    {
+        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                   "%s: sme_AddPeriodicTxPtrn() failed!", __func__);
+
+        vos_mem_free(addPeriodicTxPtrnParams);
+        goto failure;
+    }
+
+    vos_mem_free(addPeriodicTxPtrnParams);
+    vos_mem_free(cmd);
+    return count;
+
+failure:
+    vos_mem_free(cmd);
+    return EINVAL;
+}
+
 static int wcnss_debugfs_open(struct inode *inode, struct file *file)
 {
     if (inode->i_private)
@@ -112,6 +280,13 @@
     .llseek = default_llseek,
 };
 
+static const struct file_operations fops_patterngen = {
+    .write = wcnss_patterngen_write,
+    .open = wcnss_debugfs_open,
+    .owner = THIS_MODULE,
+    .llseek = default_llseek,
+};
+
 VOS_STATUS hdd_debugfs_init(hdd_adapter_t *pAdapter)
 {
     hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
@@ -124,6 +299,10 @@
         pHddCtx->debugfs_phy, pAdapter, &fops_wowpattern))
         return VOS_STATUS_E_FAILURE;
 
+    if (NULL == debugfs_create_file("pattern_gen", S_IRUSR | S_IWUSR,
+        pHddCtx->debugfs_phy, pAdapter, &fops_patterngen))
+        return VOS_STATUS_E_FAILURE;
+
     return VOS_STATUS_SUCCESS;
 }
 
@@ -131,5 +310,5 @@
 {
     debugfs_remove_recursive(pHddCtx->debugfs_phy);
 }
-#endif //#ifdef WLAN_OPEN_SOURCE
+#endif /* #ifdef WLAN_OPEN_SOURCE */
 
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 972bd31..d144631 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -139,6 +139,10 @@
 #define SIR_VERSION_STRING_LEN 64
 typedef tANI_U8 tSirVersionString[SIR_VERSION_STRING_LEN];
 
+/* Periodic Tx pattern offload feature */
+#define PERIODIC_TX_PTRN_MAX_SIZE 1536
+#define MAXNUM_PERIODIC_TX_PTRNS 6
+
 enum eSirHostMsgTypes
 {
     SIR_HAL_APP_SETUP_NTF = SIR_HAL_HOST_MSG_START,
@@ -4338,4 +4342,24 @@
 } tSirLPHBTimeoutInd;
 #endif /* FEATURE_WLAN_LPHB */
 
+typedef struct sSirAddPeriodicTxPtrn
+{
+    /* MAC Address for the adapter */
+    tSirMacAddr macAddress;
+
+    tANI_U8  ucPtrnId;           // Pattern ID
+    tANI_U16 ucPtrnSize;         // Pattern size
+    tANI_U32 usPtrnIntervalMs;   // In msec
+    tANI_U8  ucPattern[PERIODIC_TX_PTRN_MAX_SIZE]; // Pattern buffer
+} tSirAddPeriodicTxPtrn, *tpSirAddPeriodicTxPtrn;
+
+typedef struct sSirDelPeriodicTxPtrn
+{
+    /* MAC Address for the adapter */
+    tSirMacAddr macAddress;
+
+    /* Bitmap of pattern IDs that need to be deleted */
+    tANI_U32 ucPatternIdBitmap;
+} tSirDelPeriodicTxPtrn, *tpSirDelPeriodicTxPtrn;
+
 #endif /* __SIR_API_H */
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index e072f5d..a5b763e 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -591,6 +591,9 @@
 #define SIR_HAL_LPHB_CONF_IND              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 206)
 #define SIR_HAL_LPHB_WAIT_EXPIRE_IND       (SIR_HAL_ITC_MSG_TYPES_BEGIN + 207)
 
+#define SIR_HAL_ADD_PERIODIC_TX_PTRN_IND   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 208)
+#define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 209)
+
 #define SIR_HAL_MSG_TYPES_END              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 0xFF)
 // CFG message types
 #define SIR_CFG_MSG_TYPES_BEGIN        (SIR_CFG_MODULE_ID << 8)
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 2bbdcd6..778dcc5 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -2933,4 +2933,24 @@
                       tSirLPHBReq *lphdReq,
                       void (*pCallbackfn)(void *pAdapter, void *indParam));
 #endif /* FEATURE_WLAN_LPHB */
+
+/* ---------------------------------------------------------------------------
+    \fn sme_AddPeriodicTxPtrn
+    \brief  API to Periodic TX Pattern Offload feature
+    \param  hHal - The handle returned by macOpen
+    \param  addPeriodicTxPtrnParams -  Pointer to the add pattern structure
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus sme_AddPeriodicTxPtrn(tHalHandle hHal, tSirAddPeriodicTxPtrn
+                                 *addPeriodicTxPtrnParams);
+
+/* ---------------------------------------------------------------------------
+    \fn sme_DelPeriodicTxPtrn
+    \brief  API to Periodic TX Pattern Offload feature
+    \param  hHal - The handle returned by macOpen
+    \param  delPeriodicTxPtrnParams -  Pointer to the deleting pattern structure
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus sme_DelPeriodicTxPtrn(tHalHandle hHal, tSirDelPeriodicTxPtrn
+                                 *delPeriodicTxPtrnParams);
 #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 e936f24..f09f7f6 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -8757,3 +8757,75 @@
 }
 #endif /* FEATURE_WLAN_LPHB */
 
+/* ---------------------------------------------------------------------------
+    \fn sme_AddPeriodicTxPtrn
+    \brief  API to Periodic TX Pattern Offload feature
+    \param  hHal - The handle returned by macOpen
+    \param  addPeriodicTxPtrnParams - Pointer to the add pattern structure
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus sme_AddPeriodicTxPtrn(tHalHandle hHal, tSirAddPeriodicTxPtrn
+                                 *addPeriodicTxPtrnParams)
+{
+    tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+    eHalStatus status;
+    vos_msg_t msg;
+
+    if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme)))
+    {
+        msg.type     = WDA_ADD_PERIODIC_TX_PTRN_IND;
+        msg.bodyptr  = addPeriodicTxPtrnParams;
+
+        if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
+        {
+            VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,"%s: Not able "
+                       "to post WDA_ADD_PERIODIC_TX_PTRN_IND to WDA!",
+                       __func__);
+
+            sme_ReleaseGlobalLock(&pMac->sme);
+            return eHAL_STATUS_FAILURE;
+        }
+
+        sme_ReleaseGlobalLock(&pMac->sme);
+        return eHAL_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
+/* ---------------------------------------------------------------------------
+    \fn sme_DelPeriodicTxPtrn
+    \brief  API to Periodic TX Pattern Offload feature
+    \param  hHal - The handle returned by macOpen
+    \param  delPeriodicTxPtrnParams - Pointer to the delete pattern structure
+    \return eHalStatus
+  ---------------------------------------------------------------------------*/
+eHalStatus sme_DelPeriodicTxPtrn(tHalHandle hHal, tSirDelPeriodicTxPtrn
+                                 *delPeriodicTxPtrnParams)
+{
+    tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+    eHalStatus status;
+    vos_msg_t msg;
+
+    if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme)))
+    {
+        msg.type     = WDA_DEL_PERIODIC_TX_PTRN_IND;
+        msg.bodyptr  = delPeriodicTxPtrnParams;
+
+        if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
+        {
+            VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,"%s: Not able "
+                       "to post WDA_DEL_PERIODIC_TX_PTRN_IND to WDA!",
+                       __func__);
+
+            sme_ReleaseGlobalLock(&pMac->sme);
+            return eHAL_STATUS_FAILURE;
+        }
+
+        sme_ReleaseGlobalLock(&pMac->sme);
+        return eHAL_STATUS_SUCCESS;
+    }
+
+    return status;
+}
+
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 44fa9e9..72d458a 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1094,6 +1094,9 @@
 #define WDA_LPHB_WAIT_EXPIRE_IND   SIR_HAL_LPHB_WAIT_EXPIRE_IND
 #endif /* FEATURE_WLAN_LPHB */
 
+#define WDA_ADD_PERIODIC_TX_PTRN_IND    SIR_HAL_ADD_PERIODIC_TX_PTRN_IND
+#define WDA_DEL_PERIODIC_TX_PTRN_IND    SIR_HAL_DEL_PERIODIC_TX_PTRN_IND
+
 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 31260b2..f5e8992 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -10337,6 +10337,98 @@
 #endif // WLAN_FEATURE_GTK_OFFLOAD
 
 /*
+ * FUNCTION: WDA_ProcessAddPeriodicTxPtrnInd
+ *
+ */
+VOS_STATUS WDA_ProcessAddPeriodicTxPtrnInd(tWDA_CbContext *pWDA,
+                               tSirAddPeriodicTxPtrn *pAddPeriodicTxPtrnParams)
+{
+   WDI_Status wdiStatus;
+   WDI_AddPeriodicTxPtrnParamsType *addPeriodicTxPtrnParams;
+
+   addPeriodicTxPtrnParams =
+      vos_mem_malloc(sizeof(WDI_AddPeriodicTxPtrnParamsType));
+
+   if (NULL == addPeriodicTxPtrnParams)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "%s: Not able to allocate memory for addPeriodicTxPtrnParams!",
+                __func__);
+
+      return VOS_STATUS_E_NOMEM;
+   }
+
+   vos_mem_copy(&(addPeriodicTxPtrnParams->wdiAddPeriodicTxPtrnParams),
+                pAddPeriodicTxPtrnParams, sizeof(tSirAddPeriodicTxPtrn));
+
+   addPeriodicTxPtrnParams->wdiReqStatusCB = WDA_WdiIndicationCallback;
+   addPeriodicTxPtrnParams->pUserData = pWDA;
+
+   wdiStatus = WDI_AddPeriodicTxPtrnInd(addPeriodicTxPtrnParams);
+
+   if (WDI_STATUS_PENDING == wdiStatus)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                "Pending received for %s:%d", __func__, __LINE__ );
+   }
+   else if (WDI_STATUS_SUCCESS_SYNC != wdiStatus)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "Failure in %s:%d", __func__, __LINE__ );
+   }
+
+   vos_mem_free(addPeriodicTxPtrnParams);
+
+   return CONVERT_WDI2VOS_STATUS(wdiStatus);
+}
+
+/*
+ * FUNCTION: WDA_ProcessDelPeriodicTxPtrnInd
+ *
+ */
+VOS_STATUS WDA_ProcessDelPeriodicTxPtrnInd(tWDA_CbContext *pWDA,
+                               tSirDelPeriodicTxPtrn *pDelPeriodicTxPtrnParams)
+{
+   WDI_Status wdiStatus;
+   WDI_DelPeriodicTxPtrnParamsType *delPeriodicTxPtrnParams;
+
+   delPeriodicTxPtrnParams =
+      vos_mem_malloc(sizeof(WDI_DelPeriodicTxPtrnParamsType));
+
+   if (NULL == delPeriodicTxPtrnParams)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "%s: Not able to allocate memory for delPeriodicTxPtrnParams!",
+                __func__);
+
+      return VOS_STATUS_E_NOMEM;
+   }
+
+   vos_mem_copy(&(delPeriodicTxPtrnParams->wdiDelPeriodicTxPtrnParams),
+                pDelPeriodicTxPtrnParams, sizeof(tSirDelPeriodicTxPtrn));
+
+   delPeriodicTxPtrnParams->wdiReqStatusCB = WDA_WdiIndicationCallback;
+   delPeriodicTxPtrnParams->pUserData = pWDA;
+
+   wdiStatus = WDI_DelPeriodicTxPtrnInd(delPeriodicTxPtrnParams);
+
+   if (WDI_STATUS_PENDING == wdiStatus)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                "Pending received for %s:%d", __func__, __LINE__ );
+   }
+   else if (WDI_STATUS_SUCCESS_SYNC != wdiStatus)
+   {
+      VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "Failure in %s:%d", __func__, __LINE__ );
+   }
+
+   vos_mem_free(delPeriodicTxPtrnParams);
+
+   return CONVERT_WDI2VOS_STATUS(wdiStatus);
+}
+
+/*
  * -------------------------------------------------------------------------
  * DATA interface with WDI for Mgmt Frames
  * ------------------------------------------------------------------------- 
@@ -11344,6 +11436,19 @@
          break;
       }
 #endif
+      case WDA_ADD_PERIODIC_TX_PTRN_IND:
+      {
+         WDA_ProcessAddPeriodicTxPtrnInd(pWDA,
+            (tSirAddPeriodicTxPtrn *)pMsg->bodyptr);
+         break;
+      }
+      case WDA_DEL_PERIODIC_TX_PTRN_IND:
+      {
+         WDA_ProcessDelPeriodicTxPtrnInd(pWDA,
+            (tSirDelPeriodicTxPtrn *)pMsg->bodyptr);
+         break;
+      }
+
       default:
       {
          VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
@@ -11842,6 +11947,18 @@
          break;
       }
 #endif /* FEATURE_WLAN_LPHB */
+      case WDI_PERIODIC_TX_PTRN_FW_IND:
+      {
+         VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+            "%s: WDI_PERIODIC_TX_PTRN_FW_IND received, bssIdx: %d, "
+            "selfStaIdx: %d, status: %d, patternIdBitmap: %d", __func__,
+            (int)wdiLowLevelInd->wdiIndicationData.wdiPeriodicTxPtrnFwInd.bssIdx,
+            (int)wdiLowLevelInd->wdiIndicationData.wdiPeriodicTxPtrnFwInd.selfStaIdx,
+            (int)wdiLowLevelInd->wdiIndicationData.wdiPeriodicTxPtrnFwInd.status,
+            (int)wdiLowLevelInd->wdiIndicationData.wdiPeriodicTxPtrnFwInd.patternIdBitmap);
+
+         break;
+      }
 
       case WDI_IBSS_PEER_INACTIVITY_IND:
       {
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index 659875f..a8add0d 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -162,6 +162,10 @@
 
 #define WDI_SET_POWER_STATE_TIMEOUT  10000 /* in msec a very high upper limit */
 
+/* Periodic Tx pattern offload feature */
+#define PERIODIC_TX_PTRN_MAX_SIZE 1536
+#define MAXNUM_PERIODIC_TX_PTRNS 6
+
 /*============================================================================
  *     GENERIC STRUCTURES 
   
@@ -399,6 +403,9 @@
   /* IBSS Peer Inactivity Indication */
   WDI_IBSS_PEER_INACTIVITY_IND,
 
+  /* Periodic Tx Pattern FW Indication */
+  WDI_PERIODIC_TX_PTRN_FW_IND,
+
   WDI_MAX_IND
 }WDI_LowLevelIndEnumType;
 
@@ -620,6 +627,17 @@
 } WDI_LPHBTimeoutIndData;
 #endif /* FEATURE_WLAN_LPHB */
 
+/*-----------------------------------------------------------------------------
+WDI_PeriodicTxPtrnFwIndType
+-----------------------------------------------------------------------------*/
+typedef struct
+{
+    wpt_uint8  bssIdx;
+    wpt_uint32 selfStaIdx;
+    wpt_uint32 status;
+    wpt_uint32 patternIdBitmap;
+} WDI_PeriodicTxPtrnFwIndType;
+
 /*---------------------------------------------------------------------------
  WDI_IbssPeerInactivityIndType
 -----------------------------------------------------------------------------*/
@@ -687,6 +705,8 @@
     /* IBSS Peer Inactivity Indication */
     WDI_IbssPeerInactivityIndType   wdiIbssPeerInactivityInd;
 
+    /* Periodic TX Pattern FW Indication */
+    WDI_PeriodicTxPtrnFwIndType  wdiPeriodicTxPtrnFwInd;
   }  wdiIndicationData;
 }WDI_LowLevelIndType;
 
@@ -5112,6 +5132,66 @@
 }WDI_LPHBConfigParamsType;
 #endif /* FEATURE_WLAN_LPHB */
 
+/*---------------------------------------------------------------------------
+  WDI_AddPeriodicTxPtrnInfoType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+  /* MAC Address for the adapter  */
+  wpt_macAddr macAddr;
+
+  wpt_uint8  ucPtrnId;           // Pattern ID
+  wpt_uint16 ucPtrnSize;         // Pattern size
+  wpt_uint32 usPtrnIntervalMs;   // In msec
+  wpt_uint8  ucPattern[PERIODIC_TX_PTRN_MAX_SIZE]; // Pattern buffer
+} WDI_AddPeriodicTxPtrnInfoType;
+
+/*---------------------------------------------------------------------------
+  WDI_DelPeriodicTxPtrnInfoType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+  /* MAC Address for the adapter  */
+  wpt_macAddr macAddr;
+
+  /* Bitmap of pattern IDs that needs to be deleted */
+  wpt_uint32 ucPatternIdBitmap;
+} WDI_DelPeriodicTxPtrnInfoType;
+
+/*---------------------------------------------------------------------------
+  WDI_AddPeriodicTxPtrnParamsType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+  WDI_AddPeriodicTxPtrnInfoType wdiAddPeriodicTxPtrnParams;
+
+  /*Request status callback offered by UMAC - it is called if the current
+    req has returned PENDING as status; it delivers the status of sending
+    the message over the BUS */
+  WDI_ReqStatusCb   wdiReqStatusCB;
+
+  /*The user data passed in by UMAC, it will be sent back when the above
+    function pointer will be called */
+  void*             pUserData;
+} WDI_AddPeriodicTxPtrnParamsType;
+
+/*---------------------------------------------------------------------------
+  WDI_DelPeriodicTxPtrnParamsType
+---------------------------------------------------------------------------*/
+typedef struct
+{
+  WDI_DelPeriodicTxPtrnInfoType wdiDelPeriodicTxPtrnParams;
+
+  /*Request status callback offered by UMAC - it is called if the current
+    req has returned PENDING as status; it delivers the status of sending
+    the message over the BUS */
+  WDI_ReqStatusCb   wdiReqStatusCB;
+
+  /*The user data passed in by UMAC, it will be sent back when the above
+    function pointer will be called */
+  void*             pUserData;
+} WDI_DelPeriodicTxPtrnParamsType;
+
 /*----------------------------------------------------------------------------
  *   WDI callback types
  *--------------------------------------------------------------------------*/
@@ -9287,6 +9367,36 @@
 );
 #endif
 
+/**
+ @brief WDI_AddPeriodicTxPtrnInd
+
+ @param WDI_AddPeriodicTxPtrnParamsType
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_AddPeriodicTxPtrnInd
+(
+  WDI_AddPeriodicTxPtrnParamsType *addPeriodicTxPtrnParams
+);
+
+/**
+ @brief WDI_DelPeriodicTxPtrnInd
+
+ @param WDI_DelPeriodicTxPtrnParamsType
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_DelPeriodicTxPtrnInd
+(
+  WDI_DelPeriodicTxPtrnParamsType *delPeriodicTxPtrnParams
+);
+
 #ifdef FEATURE_WLAN_SCAN_PNO
 /**
  @brief WDI_SetPreferredNetworkList
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index 32de8f3..aad1de2 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -469,6 +469,12 @@
   /* Drop/Receive unencrypted frames indication to HAL */
   WDI_EXCLUDE_UNENCRYPTED_IND,
 
+  /* Send an add periodic Tx pattern indication to HAL */
+  WDI_ADD_PERIODIC_TX_PATTERN_IND,
+
+  /* Send a delete periodic Tx pattern indicationto HAL */
+  WDI_DEL_PERIODIC_TX_PATTERN_IND,
+
   /*Keep adding the indications to the max request
     such that we keep them sepparate */
 
@@ -786,6 +792,9 @@
   /* IBSS Peer Inactivity Indication from FW to Host */
   WDI_HAL_IBSS_PEER_INACTIVITY_IND     = WDI_HAL_IND_MIN + 15,
 
+  /* Periodic Tx Pattern Indication from FW to Host */
+  WDI_HAL_PERIODIC_TX_PTRN_FW_IND     = WDI_HAL_IND_MIN + 16,
+
   WDI_MAX_RESP
 }WDI_ResponseEnumType; 
 
@@ -2847,6 +2856,40 @@
 );
 #endif
 
+/**
+ @brief Process Add Periodic Tx Pattern Indication function (called when
+           Main FSM allows it)
+
+ @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_ProcessAddPeriodicTxPtrnInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
+/**
+ @brief Process Delete Periodic Tx Pattern Indication function (called when
+           Main FSM allows it)
+
+ @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_ProcessDelPeriodicTxPtrnInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
 /*========================================================================
           Main DAL Control Path Response Processing API 
 ========================================================================*/
@@ -4272,6 +4315,22 @@
 );
 #endif /* FEATURE_WLAN_LPHB */
 
+/**
+ @brief Process Periodic Tx Pattern Fw Indication function
+
+ @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_ProcessPeriodicTxPtrnFwInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
 #ifdef WLAN_FEATURE_VOWIFI_11R
 /**
  @brief Process Aggrgated Add TSpec Request function (called when Main FSM
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index a2e57e8..54c6d07 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -398,6 +398,8 @@
 #else
   NULL,
 #endif
+  WDI_ProcessAddPeriodicTxPtrnInd,      /* WDI_ADD_PERIODIC_TX_PATTERN_IND */
+  WDI_ProcessDelPeriodicTxPtrnInd,      /* WDI_DEL_PERIODIC_TX_PATTERN_IND */
 };
 
 
@@ -625,6 +627,8 @@
 #endif /* FEATURE_WLAN_LPHB */
 
   WDI_ProcessIbssPeerInactivityInd,     /* WDI_HAL_IBSS_PEER_INACTIVITY_IND */
+
+  WDI_ProcessPeriodicTxPtrnFwInd,   /* WDI_HAL_PERIODIC_TX_PTRN_FW_IND */
 };
 
 
@@ -5997,6 +6001,86 @@
 #endif
 
 /**
+ @brief WDI_AddPeriodicTxPtrnInd: Add Periodic TX Pattern Indication to FW
+
+ @param addPeriodicTxPtrnParams: Add Pattern parameters
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_AddPeriodicTxPtrnInd
+(
+  WDI_AddPeriodicTxPtrnParamsType*    addPeriodicTxPtrnParams
+)
+{
+  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_ADD_PERIODIC_TX_PATTERN_IND;
+  wdiEventData.pEventData      = addPeriodicTxPtrnParams;
+  wdiEventData.uEventDataSize  = sizeof(WDI_AddPeriodicTxPtrnParamsType);
+  wdiEventData.pCBfnc          = NULL;
+  wdiEventData.pUserData       = NULL;
+
+  return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+/**
+ @brief WDI_DelPeriodicTxPtrnInd: Delete Periodic TX Pattern Indication to FW
+
+ @param delPeriodicTxPtrnParams: Delete Pattern parameters
+
+ @see
+
+ @return Status of the request
+*/
+WDI_Status
+WDI_DelPeriodicTxPtrnInd
+(
+  WDI_DelPeriodicTxPtrnParamsType*    delPeriodicTxPtrnParams
+)
+{
+  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_DEL_PERIODIC_TX_PATTERN_IND;
+  wdiEventData.pEventData      = delPeriodicTxPtrnParams;
+  wdiEventData.uEventDataSize  = sizeof(WDI_DelPeriodicTxPtrnParamsType);
+  wdiEventData.pCBfnc          = NULL;
+  wdiEventData.pUserData       = NULL;
+
+  return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+/**
  @brief WDI_HALDumpCmdReq
         Post HAL DUMP Command Event
 
@@ -10883,6 +10967,182 @@
 }/*WDI_ProcessExcludeUnencryptInd*/
 #endif
 
+/**
+ @brief Process Add Periodic Tx Pattern Indication function (called when
+           Main FSM allows it)
+
+ @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_ProcessAddPeriodicTxPtrnInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  WDI_AddPeriodicTxPtrnParamsType   *pAddPeriodicTxPtrnParams;
+  wpt_uint8*                     pSendBuffer         = NULL;
+  wpt_uint16                     usDataOffset        = 0;
+  wpt_uint16                     usSendSize          = 0;
+  WDI_Status                     wdiStatus;
+  tHalAddPeriodicTxPtrn          *halAddPeriodicTxPtrn;
+  wpt_uint8                      selfStaIdx          = 0;
+
+  /*-------------------------------------------------------------------------
+     Sanity check
+  -------------------------------------------------------------------------*/
+  if ((NULL == pEventData) || (NULL == pEventData->pEventData))
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+               "%s: Invalid parameters in AddPeriodicTxPtrnInd!", __func__);
+    WDI_ASSERT(0);
+    return WDI_STATUS_E_FAILURE;
+  }
+
+  pAddPeriodicTxPtrnParams =
+    (WDI_AddPeriodicTxPtrnParamsType *)pEventData->pEventData;
+
+   /*------------------------------------------------------------------------
+     Get message buffer
+   ------------------------------------------------------------------------*/
+  if ((WDI_STATUS_SUCCESS != WDI_GetMessageBuffer(pWDICtx,
+       WDI_ADD_PERIODIC_TX_PATTERN_IND, sizeof(tHalAddPeriodicTxPtrn),
+       &pSendBuffer, &usDataOffset, &usSendSize))||
+       (usSendSize < (usDataOffset + sizeof(tHalAddPeriodicTxPtrn))))
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+               "%s: Unable to get send buffer in AddPeriodicTxPtrnInd!",
+               __func__);
+    WDI_ASSERT(0);
+    return WDI_STATUS_E_FAILURE;
+  }
+
+  halAddPeriodicTxPtrn = (tHalAddPeriodicTxPtrn *)(pSendBuffer + usDataOffset);
+
+  if (WDI_STATUS_SUCCESS != WDI_STATableFindStaidByAddr(pWDICtx,
+      pAddPeriodicTxPtrnParams->wdiAddPeriodicTxPtrnParams.macAddr,
+      &selfStaIdx))
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+               "%s: Failed to get selfStaIdx!", __func__);
+
+    return WDI_STATUS_E_FAILURE;
+  }
+
+  halAddPeriodicTxPtrn->selfStaIdx = selfStaIdx;
+  halAddPeriodicTxPtrn->ucPtrnId =
+    pAddPeriodicTxPtrnParams->wdiAddPeriodicTxPtrnParams.ucPtrnId;
+  halAddPeriodicTxPtrn->usPtrnSize =
+    pAddPeriodicTxPtrnParams->wdiAddPeriodicTxPtrnParams.ucPtrnSize;
+  halAddPeriodicTxPtrn->uPtrnIntervalMs =
+    pAddPeriodicTxPtrnParams->wdiAddPeriodicTxPtrnParams.usPtrnIntervalMs;
+
+  wpalMemoryCopy(halAddPeriodicTxPtrn->ucPattern,
+    pAddPeriodicTxPtrnParams->wdiAddPeriodicTxPtrnParams.ucPattern,
+    pAddPeriodicTxPtrnParams->wdiAddPeriodicTxPtrnParams.ucPtrnSize);
+
+  /*-------------------------------------------------------------------------
+    Send Indication to HAL
+  -------------------------------------------------------------------------*/
+  pWDICtx->wdiReqStatusCB     = pAddPeriodicTxPtrnParams->wdiReqStatusCB;
+  pWDICtx->pReqStatusUserData = pAddPeriodicTxPtrnParams->pUserData;
+
+  wdiStatus = WDI_SendIndication(pWDICtx, pSendBuffer, usSendSize);
+
+  WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+             "%s: Sent WLAN_HAL_ADD_PERIODIC_TX_PTRN_IND to HAL.", __func__);
+
+  return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus : WDI_STATUS_SUCCESS_SYNC;
+} /* WDI_ProcessAddPeriodicTxPtrnInd */
+
+/**
+ @brief Process Delete Periodic Tx Pattern Indication function (called when
+           Main FSM allows it)
+
+ @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_ProcessDelPeriodicTxPtrnInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  WDI_DelPeriodicTxPtrnParamsType   *pDelPeriodicTxPtrnParams;
+  wpt_uint8*                     pSendBuffer         = NULL;
+  wpt_uint16                     usDataOffset        = 0;
+  wpt_uint16                     usSendSize          = 0;
+  WDI_Status                     wdiStatus;
+  tHalDelPeriodicTxPtrn          *halDelPeriodicTxPtrn;
+  wpt_uint8                      selfStaIdx          = 0;
+
+  /*-------------------------------------------------------------------------
+     Sanity check
+  -------------------------------------------------------------------------*/
+  if ((NULL == pEventData) || (NULL == pEventData->pEventData))
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+               "%s: Invalid parameters in DelPeriodicTxPtrnInd!", __func__);
+    WDI_ASSERT(0);
+    return WDI_STATUS_E_FAILURE;
+  }
+
+  pDelPeriodicTxPtrnParams =
+    (WDI_DelPeriodicTxPtrnParamsType *)pEventData->pEventData;
+
+   /*------------------------------------------------------------------------
+     Get message buffer
+   ------------------------------------------------------------------------*/
+  if ((WDI_STATUS_SUCCESS != WDI_GetMessageBuffer(pWDICtx,
+       WDI_DEL_PERIODIC_TX_PATTERN_IND, sizeof(tHalDelPeriodicTxPtrn),
+       &pSendBuffer, &usDataOffset, &usSendSize))||
+       (usSendSize < (usDataOffset + sizeof(tHalDelPeriodicTxPtrn))))
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_WARN,
+               "%s: Unable to get send buffer in DelPeriodicTxPtrnInd!",
+               __func__);
+    WDI_ASSERT(0);
+    return WDI_STATUS_E_FAILURE;
+  }
+
+  halDelPeriodicTxPtrn = (tHalDelPeriodicTxPtrn *)(pSendBuffer + usDataOffset);
+
+  if (WDI_STATUS_SUCCESS != WDI_STATableFindStaidByAddr(pWDICtx,
+      pDelPeriodicTxPtrnParams->wdiDelPeriodicTxPtrnParams.macAddr,
+      &selfStaIdx))
+  {
+    WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+               "%s: Failed to get selfStaIdx!", __func__);
+
+    return WDI_STATUS_E_FAILURE;
+  }
+
+  halDelPeriodicTxPtrn->selfStaIdx = selfStaIdx;
+  halDelPeriodicTxPtrn->uPatternIdBitmap =
+    pDelPeriodicTxPtrnParams->wdiDelPeriodicTxPtrnParams.ucPatternIdBitmap;
+
+  /*-------------------------------------------------------------------------
+    Send Indication to HAL
+  -------------------------------------------------------------------------*/
+  pWDICtx->wdiReqStatusCB     = pDelPeriodicTxPtrnParams->wdiReqStatusCB;
+  pWDICtx->pReqStatusUserData = pDelPeriodicTxPtrnParams->pUserData;
+
+  wdiStatus = WDI_SendIndication(pWDICtx, pSendBuffer, usSendSize);
+
+  WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+             "%s: Sent WLAN_HAL_DEL_PERIODIC_TX_PTRN_IND to HAL.", __func__);
+
+  return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus : WDI_STATUS_SUCCESS_SYNC;
+} /* WDI_ProcessDelPeriodicTxPtrnInd */
+
 /*==========================================================================
                   MISC CONTROL PROCESSING REQUEST API
 ==========================================================================*/
@@ -20021,6 +20281,52 @@
 }/*WDI_ProcessTxPerHitInd*/
 
 /**
+ @brief Process Periodic Tx Pattern Fw Indication function
+
+ @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_ProcessPeriodicTxPtrnFwInd
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+)
+{
+  WDI_LowLevelIndType  wdiInd;
+
+  /*-------------------------------------------------------------------------
+    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;
+  }
+
+  /*-------------------------------------------------------------------------
+    Extract indication and send it to UMAC
+  -------------------------------------------------------------------------*/
+  wpalMemoryCopy(&(wdiInd.wdiIndicationData.wdiPeriodicTxPtrnFwInd),
+                 (tHalPeriodicTxPtrnFwInd *)pEventData->pEventData,
+                 sizeof(tHalPeriodicTxPtrnFwInd));
+
+  if (pWDICtx->wdiLowLevelIndCB)
+  {
+    /*Notify UMAC*/
+    pWDICtx->wdiLowLevelIndCB(&wdiInd, pWDICtx->pIndUserData);
+  }
+
+  return WDI_STATUS_SUCCESS;
+}
+
+/**
  @brief WDI_ProcessFTMCommandReq
         Process FTM Command, simply route to HAL
 
@@ -22310,6 +22616,11 @@
    case WDI_LPHB_CFG_REQ:
       return WLAN_HAL_LPHB_CFG_REQ;
 #endif /* FEATURE_WLAN_LPHB */
+  case WDI_ADD_PERIODIC_TX_PATTERN_IND:
+    return WLAN_HAL_ADD_PERIODIC_TX_PTRN_IND;
+  case WDI_DEL_PERIODIC_TX_PATTERN_IND:
+    return WLAN_HAL_DEL_PERIODIC_TX_PTRN_IND;
+
   default:
     return WLAN_HAL_MSG_MAX;
   }
@@ -22555,6 +22866,8 @@
 
   case WLAN_HAL_IBSS_PEER_INACTIVITY_IND:
     return WDI_HAL_IBSS_PEER_INACTIVITY_IND;
+  case WLAN_HAL_PERIODIC_TX_PTRN_FW_IND:
+    return WDI_HAL_PERIODIC_TX_PTRN_FW_IND;
 
   default:
     return eDRIVER_TYPE_MAX;