prima: Add timer related messages at the top of PE queue

Currently when PE queue is full, timer message gets queued at the
end of PE queue even when timer gets expired in time. This causes
delay in processing timer messages. This delay can be maximum if
timer message is the last message in PE queue. This can take substantial
amount of time to process timer message as timer message will be
processed only after processing of other messages. For instance,
if timer message processing takes substantial amount of time during
scan, it can delay sending max channel timeout and may result in
scan timeout. So, add timer related messages at
the top of PE queue to process those messages immediately.

Change-Id: Iccaf0075c97a7edd2c1de1d168f1a4e7d01381c2
CRs-Fixed: 936179
diff --git a/CORE/MAC/src/pe/include/limApi.h b/CORE/MAC/src/pe/include/limApi.h
index 51a910f..5b869d3 100644
--- a/CORE/MAC/src/pe/include/limApi.h
+++ b/CORE/MAC/src/pe/include/limApi.h
@@ -127,6 +127,8 @@
 extern void limCleanup(tpAniSirGlobal);
 /// Function to post messages to LIM thread
 extern tANI_U32  limPostMsgApi(tpAniSirGlobal, tSirMsgQ *);
+tANI_U32  limPostMsgApiHighPri(tpAniSirGlobal, tSirMsgQ *);
+
 /**
  * Function to process messages posted to LIM thread
  * and dispatch to various sub modules within LIM module.
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index f465af7..87d921d 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -1266,6 +1266,35 @@
 
 } /*** end limPostMsgApi() ***/
 
+/**
+ * limPostMsgApiHighPri()
+ *
+ * FUNCTION:
+ * This function is called from other thread while posting a
+ * message to LIM message Queue gSirLimMsgQ.
+ *
+ * LOGIC:
+ * NA
+ *
+ * ASSUMPTIONS:
+ * NA
+ *
+ * NOTE:
+ * NA
+ *
+ * @param  pMac - Pointer to Global MAC structure
+ * @param  pMsg - Pointer to the message structure
+ * @return None
+ */
+
+tANI_U32
+limPostMsgApiHighPri(tpAniSirGlobal pMac, tSirMsgQ *pMsg)
+{
+    return  vos_mq_post_message_high_pri(VOS_MQ_ID_PE, (vos_msg_t *) pMsg);
+
+
+} /*** end limPostMsgApi() ***/
+
 
 /*--------------------------------------------------------------------------
 
diff --git a/CORE/MAC/src/pe/lim/limTimerUtils.c b/CORE/MAC/src/pe/lim/limTimerUtils.c
index ee1f6b0..1e3d522 100644
--- a/CORE/MAC/src/pe/lim/limTimerUtils.c
+++ b/CORE/MAC/src/pe/lim/limTimerUtils.c
@@ -40,7 +40,7 @@
 #include "limAssocUtils.h"
 #include "limSecurityUtils.h"
 #include "pmmApi.h"
-
+#include "limApi.h"
 
 // default value 5000 ms for background scan period when it is disabled
 #define LIM_BACKGROUND_SCAN_PERIOD_DEFAULT_MS    5000
@@ -788,7 +788,7 @@
     msg.bodyptr = NULL;
     msg.bodyval = 0;
 
-    if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS)
+    if ((statusCode = limPostMsgApiHighPri(pMac, &msg)) != eSIR_SUCCESS)
         limLog(pMac, LOGE,
                FL("posting message %X to LIM failed, reason=%d"),
                msg.type, statusCode);
diff --git a/CORE/VOSS/inc/vos_mq.h b/CORE/VOSS/inc/vos_mq.h
index 7194e35..e82dd00 100644
--- a/CORE/VOSS/inc/vos_mq.h
+++ b/CORE/VOSS/inc/vos_mq.h
@@ -156,6 +156,43 @@
   --------------------------------------------------------------------------*/
 VOS_STATUS vos_mq_post_message( VOS_MQ_ID msgQueueId, vos_msg_t *message );
 
+/**--------------------------------------------------------------------------
+  \brief vos_mq_post_message_high_pri() - posts a high priority message to
+           a message queue
+
+  This API allows messages to be posted to the head of a specific message
+  queue. Messages  can be posted to the following message queues:
+
+  <ul>
+    <li> SME
+    <li> PE
+    <li> HAL
+    <li> TL
+  </ul>
+
+  \param msgQueueId - identifies the message queue upon which the message
+         will be posted.
+
+  \param message - a pointer to a message buffer.  Memory for this message
+         buffer is allocated by the caller and free'd by the vOSS after the
+         message is posted to the message queue.  If the consumer of the
+         message needs anything in this message, it needs to copy the contents
+         before returning from the message queue handler.
+
+  \return VOS_STATUS_SUCCESS - the message has been successfully posted
+          to the message queue.
+
+          VOS_STATUS_E_INVAL - The value specified by msgQueueId does not
+          refer to a valid Message Queue Id.
+
+          VOS_STATUS_E_FAULT  - message is an invalid pointer.
+
+          VOS_STATUS_E_FAILURE - the message queue handler has reported
+          an unknown failure.
+  --------------------------------------------------------------------------*/
+
+VOS_STATUS vos_mq_post_message_high_pri(VOS_MQ_ID msgQueueId, vos_msg_t *message);
+
 
 /**---------------------------------------------------------------------------
   
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index b7d4fae..0278a1f 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -2117,6 +2117,151 @@
 } /* vos_mq_post_message()*/
 
 
+/**--------------------------------------------------------------------------
+  \brief vos_mq_post_message_high_pri() - posts a high priority message to
+           a message queue
+
+  This API allows messages to be posted to the head of a specific message
+  queue. Messages  can be posted to the following message queues:
+
+  <ul>
+    <li> SME
+    <li> PE
+    <li> HAL
+    <li> TL
+  </ul>
+
+  \param msgQueueId - identifies the message queue upon which the message
+         will be posted.
+
+  \param message - a pointer to a message buffer.  Memory for this message
+         buffer is allocated by the caller and free'd by the vOSS after the
+         message is posted to the message queue.  If the consumer of the
+         message needs anything in this message, it needs to copy the contents
+         before returning from the message queue handler.
+
+  \return VOS_STATUS_SUCCESS - the message has been successfully posted
+          to the message queue.
+
+          VOS_STATUS_E_INVAL - The value specified by msgQueueId does not
+          refer to a valid Message Queue Id.
+
+          VOS_STATUS_E_FAULT  - message is an invalid pointer.
+
+          VOS_STATUS_E_FAILURE - the message queue handler has reported
+          an unknown failure.
+  --------------------------------------------------------------------------*/
+VOS_STATUS vos_mq_post_message_high_pri(VOS_MQ_ID msgQueueId, vos_msg_t *pMsg)
+{
+  pVosMqType      pTargetMq   = NULL;
+  pVosMsgWrapper  pMsgWrapper = NULL;
+
+  if ((gpVosContext == NULL) || (pMsg == NULL))
+  {
+    VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+        "%s: Null params or global vos context is null", __func__);
+    VOS_ASSERT(0);
+    return VOS_STATUS_E_FAILURE;
+  }
+
+  switch (msgQueueId)
+  {
+    /// Message Queue ID for messages bound for SME
+    case  VOS_MQ_ID_SME:
+    {
+       pTargetMq = &(gpVosContext->vosSched.smeMcMq);
+       break;
+    }
+
+    /// Message Queue ID for messages bound for PE
+    case VOS_MQ_ID_PE:
+    {
+       pTargetMq = &(gpVosContext->vosSched.peMcMq);
+       break;
+    }
+
+    /// Message Queue ID for messages bound for WDA
+    case VOS_MQ_ID_WDA:
+    {
+       pTargetMq = &(gpVosContext->vosSched.wdaMcMq);
+       break;
+    }
+
+    /// Message Queue ID for messages bound for WDI
+    case VOS_MQ_ID_WDI:
+    {
+       pTargetMq = &(gpVosContext->vosSched.wdiMcMq);
+       break;
+    }
+
+    /// Message Queue ID for messages bound for TL
+    case VOS_MQ_ID_TL:
+    {
+       pTargetMq = &(gpVosContext->vosSched.tlMcMq);
+       break;
+    }
+
+    /// Message Queue ID for messages bound for the SYS module
+    case VOS_MQ_ID_SYS:
+    {
+       pTargetMq = &(gpVosContext->vosSched.sysMcMq);
+       break;
+    }
+
+    default:
+
+    VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+              ("%s: Trying to queue msg into unknown MC Msg queue ID %d"),
+              __func__, msgQueueId);
+
+    return VOS_STATUS_E_FAILURE;
+  }
+
+  VOS_ASSERT(NULL !=pTargetMq);
+  if (pTargetMq == NULL)
+  {
+     VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+         "%s: pTargetMq == NULL", __func__);
+     return VOS_STATUS_E_FAILURE;
+  }
+
+  /*
+  ** Try and get a free Msg wrapper
+  */
+  pMsgWrapper = vos_mq_get(&gpVosContext->freeVosMq);
+
+  if (NULL == pMsgWrapper)
+  {
+    VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+              "%s: VOS Core run out of message wrapper", __func__);
+    if (!gpVosContext->vosWrapperFullReported)
+    {
+      gpVosContext->vosWrapperFullReported = 1;
+      vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
+                      WLAN_LOG_INDICATOR_HOST_ONLY,
+                      WLAN_LOG_REASON_VOS_MSG_UNDER_RUN,
+                      FALSE, TRUE);
+    }
+    return VOS_STATUS_E_RESOURCES;
+  }
+
+  /*
+  ** Copy the message now
+  */
+  vos_mem_copy( (v_VOID_t*)pMsgWrapper->pVosMsg,
+                (v_VOID_t*)pMsg, sizeof(vos_msg_t));
+
+  vos_mq_put_front(pTargetMq, pMsgWrapper);
+
+  set_bit(MC_POST_EVENT_MASK, &gpVosContext->vosSched.mcEventFlag);
+  wake_up_interruptible(&gpVosContext->vosSched.mcWaitQueue);
+
+  return VOS_STATUS_SUCCESS;
+
+} /* vos_mq_post_message_high_pri()*/
+
+
+
 /**---------------------------------------------------------------------------
   
   \brief vos_tx_mq_serialize() - serialize a message to the Tx execution flow
diff --git a/CORE/VOSS/src/vos_mq.c b/CORE/VOSS/src/vos_mq.c
index b428189..91ed206 100644
--- a/CORE/VOSS/src/vos_mq.c
+++ b/CORE/VOSS/src/vos_mq.c
@@ -163,6 +163,42 @@
 
 } /* vos_mq_put() */
 
+/*---------------------------------------------------------------------------
+
+  \brief vos_mq_put_front() - Add a message to the head of message queue
+
+  The \a vos_mq_put_front() function add a message to the head of Message queue.
+
+  \param  pMq - pointer to the message queue
+
+  \param  pMsgWrapper - Msg Wrapper containing the message
+
+  \return None
+
+  \sa vos_mq_put()
+
+---------------------------------------------------------------------------*/
+void vos_mq_put_front(pVosMqType pMq, pVosMsgWrapper pMsgWrapper)
+{
+  unsigned long flags;
+
+  /*
+  ** Some quick sanity check
+  */
+  if ((pMq == NULL) || (pMsgWrapper == NULL)) {
+     VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
+         "%s: NULL pointer passed",__func__);
+     return ;
+  }
+
+  spin_lock_irqsave(&pMq->mqLock, flags);
+
+  list_add(&pMsgWrapper->msgNode, &pMq->mqList);
+
+  spin_unlock_irqrestore(&pMq->mqLock, flags);
+
+} /* vos_mq_put_front() */
+
 
 /*---------------------------------------------------------------------------
   
diff --git a/CORE/VOSS/src/vos_sched.h b/CORE/VOSS/src/vos_sched.h
index 7ed3ed6..1a8731b 100644
--- a/CORE/VOSS/src/vos_sched.h
+++ b/CORE/VOSS/src/vos_sched.h
@@ -492,6 +492,7 @@
 VOS_STATUS vos_mq_init(pVosMqType pMq);
 void vos_mq_deinit(pVosMqType pMq);
 void vos_mq_put(pVosMqType pMq, pVosMsgWrapper pMsgWrapper);
+void vos_mq_put_front(pVosMqType pMq, pVosMsgWrapper pMsgWrapper);
 pVosMsgWrapper vos_mq_get(pVosMqType pMq);
 v_BOOL_t vos_is_mq_empty(pVosMqType pMq);
 pVosSchedContext get_vos_sched_ctxt(void);