From 40d4eeed507ed937b29062607f40e04bb4727d13 Mon Sep 17 00:00:00 2001
From: sudheer <s-doredla@ti.com>
Date: Wed, 8 Mar 2023 17:17:22 +0530
Subject: [PATCH] Facing the race conditions between multiple MailboxP_post
 requests for EnetMcm_serverTask. Two or more client tasks were posting
 Mailbox with MCM commands for EnetMcm_serverTask and then pending on the
 response. As we had only one response queue, the response was pulled in by
 the wrong client task followed by Assertion.

This condition is not easily reproducible, it happens only when server
task is processing one client task and simultaneously another client
task posted on the server Mailbox.

Now, we will have a queue of response mailbox per client in order to
handle MCM commands for EnetMcm_serverTask so that each client have
its own response mailbox for its requested MCM command.

Signed-off-by: sudheer <s-doredla@ti.com>
---
 ethfw/ethfw/src/ethfw.c                       |   1 +
 .../src/ethfw_callbacks_lwipif.c              |   1 +
 ethfw/utils/ethfw_stats/src/app_ethfw_stats.c |   2 +
 ethfw/utils/intervlan/src/eth_swintervlan.c   |   1 +
 .../enet/examples/enet_lwip_example/main.c    |   1 +
 .../ti/drv/enet/examples/utils/enet_mcm.c     | 390 +++++++++++++-----
 .../enet/examples/utils/include/enet_mcm.h    |   3 +
 .../ti/osal/src/freertos/QueueP_freertos.c    |  13 +-
 .../timeSync/v2/src/ip/cpsw/timeSync_cpsw.c   |   1 +
 .../timeSync/v2/src/ip/icssg/timeSync_icssg.c |   1 +
 10 files changed, 299 insertions(+), 115 deletions(-)

diff --git a/ethfw/ethfw/src/ethfw.c b/ethfw/ethfw/src/ethfw.c
index ffa5c60c..f9940d73 100644
--- a/ethfw/ethfw/src/ethfw.c
+++ b/ethfw/ethfw/src/ethfw.c
@@ -1133,6 +1133,7 @@ static void EthFw_deinitMcm(void)
 {
     /* Release MCM handle - CPSW should close if we're last client */
     EnetMcm_releaseHandleInfo(&gEthFwObj.mcmCmdIf);
+    EnetMcm_releaseCmdIf(gEthFwObj.enetType, &gEthFwObj.mcmCmdIf);
 
     /* De-initialize CPSW MCM */
     EnetMcm_deInit(gEthFwObj.enetType);
diff --git a/ethfw/utils/ethfw_callbacks/src/ethfw_callbacks_lwipif.c b/ethfw/utils/ethfw_callbacks/src/ethfw_callbacks_lwipif.c
index f133083b..b38d4499 100644
--- a/ethfw/utils/ethfw_callbacks/src/ethfw_callbacks_lwipif.c
+++ b/ethfw/utils/ethfw_callbacks/src/ethfw_callbacks_lwipif.c
@@ -379,6 +379,7 @@ void EthFwCallbacks_lwipifCpswReleaseHandle(LwipifEnetAppIf_ReleaseHandleInfo *r
 
     EnetMcm_coreDetach(&mcmCmdIf, releaseInfo->coreId, releaseInfo->coreKey);
     EnetMcm_releaseHandleInfo(&mcmCmdIf);
+    EnetMcm_releaseCmdIf(enetType, &mcmCmdIf);
 }
 
 #if defined(ETHFW_PROXY_ARP_HANDLING)
diff --git a/ethfw/utils/ethfw_stats/src/app_ethfw_stats.c b/ethfw/utils/ethfw_stats/src/app_ethfw_stats.c
index a0908d0c..af280407 100644
--- a/ethfw/utils/ethfw_stats/src/app_ethfw_stats.c
+++ b/ethfw/utils/ethfw_stats/src/app_ethfw_stats.c
@@ -314,6 +314,8 @@ int32_t appEthfwStatsInit(Enet_Type enetType, uint32_t instId)
         obj->ethfwStatsShutdown = false;
     }
 
+    EnetMcm_releaseCmdIf(obj->enetType, &cmdIf);
+
     return status;
 }
 
diff --git a/ethfw/utils/intervlan/src/eth_swintervlan.c b/ethfw/utils/intervlan/src/eth_swintervlan.c
index 56ca0d8d..63cca588 100644
--- a/ethfw/utils/intervlan/src/eth_swintervlan.c
+++ b/ethfw/utils/intervlan/src/eth_swintervlan.c
@@ -273,6 +273,7 @@ static void CpswApp_InterVlanRouting(void* a0,
     EnetAppUtils_freePktInfoQ(&cqPktInfoQ);
 
     EnetMcm_releaseHandleInfo(&cmdIf);
+    EnetMcm_releaseCmdIf(gCpswInterVlanAppObj.enetType, &cmdIf);
 }
 
 void CpswApp_ingRxIsrFxn(void *appData)
diff --git a/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/enet_lwip_example/main.c b/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/enet_lwip_example/main.c
index 20eecd43..93693a99 100644
--- a/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/enet_lwip_example/main.c
+++ b/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/enet_lwip_example/main.c
@@ -1210,6 +1210,7 @@ void LwipifEnetAppCb_releaseHandle(LwipifEnetAppIf_ReleaseHandleInfo *releaseInf
 
     EnetMcm_coreDetach(pMcmCmdIf, releaseInfo->coreId, releaseInfo->coreKey);
     EnetMcm_releaseHandleInfo(pMcmCmdIf);
+    EnetMcm_releaseCmdIf(gEnetAppCfg.enetType, pMcmCmdIf);
 }
 
 static void EnetApp_deinit(void)
diff --git a/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/enet_mcm.c b/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/enet_mcm.c
index f302d6b0..89e11e11 100644
--- a/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/enet_mcm.c
+++ b/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/enet_mcm.c
@@ -66,6 +66,17 @@
 #define ENETMCM_TSK_PRIORITY                (2U)
 #define ENETMCM_PERIODICTSK_PRIORITY        (7U)
 #define ENETMCM_ASYNCIOCTLTASK_PRIORITY     (9U)
+#define ENETMCM_MAX_CLIENTS                 (8U)
+#define ENETMCM_INTERNAL_CLIENT_IDX         (ENETMCM_MAX_CLIENTS)
+
+/*! \brief Get the index of the given element within an array */
+#define ENETMCM_UTILS_GETARRAYINDEX(member, array)   (member - &array[0])
+
+/*! \brief Macro to determine if a member is part of an array */
+#define ENETMCM_UTILS_ARRAYISMEMBER(member, array)                              \
+    (((((uintptr_t)member - (uintptr_t) & array[0]) % sizeof(array[0])) == 0)   \
+     && (member >= &array[0])                                                   \
+     && (ENETMCM_UTILS_GETARRAYINDEX(member, array) < ENET_ARRAYSIZE(array)))
 
 /* ========================================================================== */
 /*                         Structure Declarations                             */
@@ -90,6 +101,76 @@ typedef struct EnetMcm_CoreAttachTable_s
     EnetMcm_CoreAttachTableEntry entry[ENET_CFG_REMOTE_CLIENT_CORES_MAX];
 }  EnetMcm_CoreAttachTable;
 
+typedef enum EnetMcm_Command_e
+{
+    /*! GET CPSW & UDMA HANDLE */
+    MCM_GET_HANDLE,
+
+    /*! RELEASE HANDLE */
+    MCM_RELEASE_HANDLE,
+
+    /*! ATTACH core */
+    MCM_CORE_ATTACH,
+
+    /*! DETACH core */
+    MCM_CORE_DETACH,
+
+    /*! Run IOCTL. Mainly useful for asynchronous IOCTLs */
+    MCM_IOCTL,
+
+    /*! SHUTDOWN MCM */
+    MCM_SHUTDOWN,
+
+    /*! Disconnecting client */
+    MCM_CLIENT_DISCONNECT,
+
+    /*! Response to MCM_GET_HANDLE command */
+    MCM_RESPONSE_GET_HANDLE,
+
+    /*! Response to MCM_RELEASE_HANDLE command */
+    MCM_RESPONSE_RELEASE_HANDLE,
+
+    /*! Response to MCM_CORE_ATTACH command */
+    MCM_RESPONSE_CORE_ATTACH,
+
+    /*! Response to MCM_CORE_DETACH command */
+    MCM_RESPONSE_CORE_DETACH,
+
+    /*! Response to MCM_IOCL command */
+    MCM_RESPONSE_IOCTL,
+
+    /*! Response to SHUTDOWN MCM */
+    MCM_RESPONSE_SHUTDOWN,
+
+    /*! Response to Client Disconnect */
+    MCM_RESPONSE_CLIENT_DISCONNECT,
+}
+EnetMcm_Command;
+
+typedef struct EnetMcm_mailboxObj_s
+{
+    EnetMcm_Command cmd;
+    MailboxP_Handle response;
+
+    struct EnetMcm_mailboxMsgs_s
+    {
+        uint32_t coreId;
+        uint32_t coreKey;
+        uint32_t ioctlStatus;
+        uint32_t ioctlCmd;
+        Enet_IoctlPrms *ioctlPrms;
+        EnetMcm_HandleInfo handleInfo;
+        EnetPer_AttachCoreOutArgs attachInfo;
+    } msgBody;
+}EnetMcm_mailboxObj;
+
+typedef struct EnetMcm_RespMboxObj_s
+{
+    QueueP_Elem qElem;
+    bool isValidClient;
+    MailboxP_Handle hMbox;
+} EnetMcm_RespMboxObj;
+
 typedef struct EnetMcm_Obj_s
 {
     bool isInitDone;
@@ -130,7 +211,11 @@ typedef struct EnetMcm_Obj_s
 
     MailboxP_Handle hMboxCmd;
 
-    MailboxP_Handle hMboxResponse;
+    EnetMcm_RespMboxObj *hInternalClientRespMbox;
+
+    QueueP_Handle hMboxRespFreeQ;
+
+    EnetMcm_RespMboxObj respMbox[(ENETMCM_MAX_CLIENTS + 1)];
 
     ClockP_Handle hTimer;
 
@@ -165,63 +250,17 @@ typedef struct EnetMcm_Obj_s
     /*! Semaphore used to wait for async IOCTL completion. It's posted from
      *  async IOCTL callback which is called from Enet_poll() */
     SemaphoreP_Handle asyncIoctlSem;
-}EnetMcm_Obj;
 
-typedef enum EnetMcm_Command_e
-{
-    /*! GET CPSW & UDMA HANDLE */
-    MCM_GET_HANDLE,
+    uint8_t mcmMainTaskStack[ENETMCM_TSK_STACK_MAIN] __attribute__ ((aligned(32)));
 
-    /*! RELEASE HANDLE */
-    MCM_RELEASE_HANDLE,
+    uint8_t mcmPrdTaskStack[ENETMCM_TSK_STACK_MAIN] __attribute__ ((aligned(32)));
 
-    /*! ATTACH core */
-    MCM_CORE_ATTACH,
-
-    /*! DETACH core */
-    MCM_CORE_DETACH,
+    uint8_t asyncIoctlTaskStack[ENETMCM_TSK_STACK_MAIN] __attribute__ ((aligned(32)));            
 
-    /*! Run IOCTL. Mainly useful for asynchronous IOCTLs */
-    MCM_IOCTL,
-
-    /*! SHUTDOWN MCM */
-    MCM_SHUTDOWN,
-
-    /*! Response to MCM_GET_HANDLE command */
-    MCM_RESPONSE_GET_HANDLE,
-
-    /*! Response to MCM_RELEASE_HANDLE command */
-    MCM_RESPONSE_RELEASE_HANDLE,
-
-    /*! Response to MCM_CORE_ATTACH command */
-    MCM_RESPONSE_CORE_ATTACH,
-
-    /*! Response to MCM_CORE_DETACH command */
-    MCM_RESPONSE_CORE_DETACH,
-
-    /*! Response to MCM_IOCL command */
-    MCM_RESPONSE_IOCTL,
-
-    /*! Response to SHUTDOWN MCM */
-    MCM_RESPONSE_SHUTDOWN,
-}
-EnetMcm_Command;
-
-typedef struct EnetMcm_mailboxObj_s
-{
-    EnetMcm_Command cmd;
+    uint8_t mcmRequestMbxBuf[sizeof(EnetMcm_mailboxObj) * ENETMCM_MBOX_MSG_COUNT] __attribute__ ((aligned(32)));
 
-    struct EnetMcm_mailboxMsgs_s
-    {
-        uint32_t coreId;
-        uint32_t coreKey;
-        uint32_t ioctlStatus;
-        uint32_t ioctlCmd;
-        Enet_IoctlPrms *ioctlPrms;
-        EnetMcm_HandleInfo handleInfo;
-        EnetPer_AttachCoreOutArgs attachInfo;
-    } msgBody;
-}EnetMcm_mailboxObj;
+    uint8_t mcmResponseMbxBuf[(ENETMCM_MAX_CLIENTS + 1)][sizeof(EnetMcm_mailboxObj) * ENETMCM_MBOX_MSG_COUNT] __attribute__ ((aligned(32)));
+}EnetMcm_Obj;
 
 /* ========================================================================== */
 /*                          Function Declarations                             */
@@ -235,6 +274,12 @@ static void     EnetMcm_serverTask(void * hMcm);
 
 static int32_t  EnetMcm_enablePorts(EnetMcm_Handle hMcm);
 
+static void EnetMcm_shutdown(Enet_Type enetType,
+                             EnetMcm_CmdIf *hMcmCmdIf);
+
+static EnetMcm_RespMboxObj* EnetMcm_getRespMbox(EnetMcm_Handle hMcm,
+                                                MailboxP_Handle hMboxResp);
+
 /* ========================================================================== */
 /*                            Global Variables                                */
 /* ========================================================================== */
@@ -248,7 +293,7 @@ static EnetMcm_Obj gMcmObj[] =
         .hMutex                 = NULL,
         .task                   = NULL,
         .hMboxCmd               = NULL,
-        .hMboxResponse          = NULL,
+        .hInternalClientRespMbox = NULL,
         .hTimer                 = NULL,
         .task_periodicTick      = NULL,
         .timerSem               = NULL,
@@ -265,7 +310,7 @@ static EnetMcm_Obj gMcmObj[] =
         .hMutex                 = NULL,
         .task                   = NULL,
         .hMboxCmd               = NULL,
-        .hMboxResponse          = NULL,
+        .hInternalClientRespMbox = NULL,
         .hTimer                 = NULL,
         .task_periodicTick      = NULL,
         .timerSem               = NULL,
@@ -283,7 +328,7 @@ static EnetMcm_Obj gMcmObj[] =
         .hMutex                 = NULL,
         .task                   = NULL,
         .hMboxCmd               = NULL,
-        .hMboxResponse          = NULL,
+        .hInternalClientRespMbox = NULL,
         .hTimer                 = NULL,
         .task_periodicTick      = NULL,
         .timerSem               = NULL,
@@ -301,7 +346,7 @@ static EnetMcm_Obj gMcmObj[] =
         .hMutex                 = NULL,
         .task                   = NULL,
         .hMboxCmd               = NULL,
-        .hMboxResponse          = NULL,
+        .hInternalClientRespMbox = NULL,
         .hTimer                 = NULL,
         .task_periodicTick      = NULL,
         .timerSem               = NULL,
@@ -312,16 +357,6 @@ static EnetMcm_Obj gMcmObj[] =
     },
 };
 
-uint8_t mcmMainTaskStack[ENETMCM_TSK_STACK_MAIN] __attribute__ ((aligned(32)));
-
-uint8_t mcmPrdTaskStack[ENETMCM_TSK_STACK_MAIN] __attribute__ ((aligned(32)));
-
-uint8_t asyncIoctlTaskStack[ENETMCM_TSK_STACK_MAIN] __attribute__ ((aligned(32)));
-
-uint8_t mcmRequestMbxBuf[sizeof(EnetMcm_mailboxObj) * ENETMCM_MBOX_MSG_COUNT] __attribute__ ((aligned(32)));
-
-uint8_t mcmResponseMbxBuf[sizeof(EnetMcm_mailboxObj) * ENETMCM_MBOX_MSG_COUNT] __attribute__ ((aligned(32)));
-
 /* ========================================================================== */
 /*                          Function Definitions                              */
 /* ========================================================================== */
@@ -446,35 +481,56 @@ static void EnetMcm_delCoreAttachEntry(EnetMcm_CoreAttachTable *attachTbl,
 
 static void EnetMcm_initMbox(EnetMcm_Handle hMcm)
 {
-    TaskP_Params params;
-
+    TaskP_Params params;    
+    EnetMcm_RespMboxObj *respMbox;
+    QueueP_Params qPrms;
     MailboxP_Params mboxParams;
+    uint32_t i;
+
+    QueueP_Params_init(&qPrms);
+
+    hMcm->hMboxRespFreeQ = QueueP_create(&qPrms);
+    EnetAppUtils_assert(hMcm->hMboxRespFreeQ != NULL);
 
     MailboxP_Params_init(&mboxParams);
     mboxParams.name = (uint8_t *)"MCM Request MBX";
     mboxParams.size =  sizeof(EnetMcm_mailboxObj);
     mboxParams.count = ENETMCM_MBOX_MSG_COUNT;
-    mboxParams.buf = (void *)mcmRequestMbxBuf;
-    mboxParams.bufsize = sizeof(EnetMcm_mailboxObj) * ENETMCM_MBOX_MSG_COUNT;
+    mboxParams.buf = (void *)hMcm->mcmRequestMbxBuf;
+    mboxParams.bufsize = sizeof(hMcm->mcmRequestMbxBuf);
 
     hMcm->hMboxCmd = MailboxP_create(&mboxParams);
     EnetAppUtils_assert(hMcm->hMboxCmd != NULL);
 
-    MailboxP_Params_init(&mboxParams);
-    mboxParams.name = (uint8_t *)"MCM Response MBX";
-    mboxParams.size =  sizeof(EnetMcm_mailboxObj);
-    mboxParams.count = ENETMCM_MBOX_MSG_COUNT;
-    mboxParams.buf = (void *)mcmResponseMbxBuf;
-    mboxParams.bufsize = sizeof(EnetMcm_mailboxObj) * ENETMCM_MBOX_MSG_COUNT;
-
-    hMcm->hMboxResponse = MailboxP_create(&mboxParams);
-    EnetAppUtils_assert(hMcm->hMboxResponse != NULL);
+    for (i = 0U; i < ENET_ARRAYSIZE(hMcm->respMbox); i++)
+    {
+        MailboxP_Params_init(&mboxParams);
+        mboxParams.name = (uint8_t *)"MCM Response MBX";
+        mboxParams.size =  sizeof(EnetMcm_mailboxObj);
+        mboxParams.count = ENETMCM_MBOX_MSG_COUNT;
+        mboxParams.buf = (void *)&hMcm->mcmResponseMbxBuf[i][0];
+        mboxParams.bufsize = sizeof(hMcm->mcmResponseMbxBuf[i]);
+
+        respMbox = &hMcm->respMbox[i];
+        respMbox->hMbox = MailboxP_create(&mboxParams);
+        respMbox->isValidClient = false;
+        EnetAppUtils_assert(respMbox->hMbox != NULL);
+        if (i != ENETMCM_INTERNAL_CLIENT_IDX)
+        {
+            QueueP_put(hMcm->hMboxRespFreeQ, &respMbox->qElem);
+        }
+        else
+        {
+            respMbox->isValidClient = true;
+            hMcm->hInternalClientRespMbox = respMbox;
+        }
+    }
 
     TaskP_Params_init(&params);
 
     params.priority  = ENETMCM_TSK_PRIORITY;
-    params.stack     = &mcmMainTaskStack[0];
-    params.stacksize = ENETMCM_TSK_STACK_MAIN;
+    params.stack     = &hMcm->mcmMainTaskStack[0];
+    params.stacksize = sizeof(hMcm->mcmMainTaskStack);
     params.arg0      = hMcm;
 
     switch (hMcm->enetType)
@@ -665,6 +721,8 @@ void  EnetMcm_getCmdIf(Enet_Type enetType,
                        EnetMcm_CmdIf *hMcmCmdIf)
 {
     EnetMcm_Handle hMcm = &gMcmObj[enetType];
+    EnetMcm_RespMboxObj *respMbox;
+    QueueP_Elem *elem;
 
     EnetAppUtils_assert(hMcmCmdIf != NULL);
     EnetAppUtils_assert(hMcm->hMutex != NULL);
@@ -672,8 +730,15 @@ void  EnetMcm_getCmdIf(Enet_Type enetType,
     MutexP_lock(hMcm->hMutex, MutexP_WAIT_FOREVER);
     EnetAppUtils_assert(hMcm->isInitDone == true);
 
+    elem = QueueP_get(hMcm->hMboxRespFreeQ);
+    EnetAppUtils_assert(elem != NULL);
+    respMbox = container_of(elem, EnetMcm_RespMboxObj, qElem);
+
     hMcmCmdIf->hMboxCmd      = hMcm->hMboxCmd;
-    hMcmCmdIf->hMboxResponse = hMcm->hMboxResponse;
+    hMcmCmdIf->hMboxResponse = respMbox->hMbox;
+
+    EnetAppUtils_assert(respMbox->isValidClient == false);
+    respMbox->isValidClient = true;
 
     MutexP_unlock(hMcm->hMutex);
 
@@ -681,10 +746,55 @@ void  EnetMcm_getCmdIf(Enet_Type enetType,
     EnetAppUtils_assert(hMcmCmdIf->hMboxResponse != NULL);
 }
 
+void EnetMcm_releaseCmdIf(Enet_Type enetType,
+                          EnetMcm_CmdIf *hMcmCmdIf)
+{
+    EnetMcm_Handle hMcm = &gMcmObj[enetType];
+    EnetMcm_RespMboxObj *respMbox = NULL;
+    EnetMcm_mailboxObj msg;
+
+    EnetAppUtils_assert(hMcmCmdIf != NULL);
+    EnetAppUtils_assert(hMcm->hMutex != NULL);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.cmd = MCM_CLIENT_DISCONNECT;
+    msg.response = hMcmCmdIf->hMboxResponse;
+
+    MailboxP_post(hMcmCmdIf->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
+    MailboxP_pend(hMcmCmdIf->hMboxResponse, &msg, SemaphoreP_WAIT_FOREVER);
+    EnetAppUtils_assert(msg.cmd == MCM_RESPONSE_CLIENT_DISCONNECT);
+    EnetAppUtils_assert(MailboxP_getNumPendingMsgs(hMcmCmdIf->hMboxResponse) == 0);
+
+    respMbox = EnetMcm_getRespMbox(hMcm, hMcmCmdIf->hMboxResponse);
+    /* The mcm server should have cleared the isValidClient on receiving the disconnect command */
+    EnetAppUtils_assert(respMbox->isValidClient == false);
+
+    QueueP_put(hMcm->hMboxRespFreeQ, &respMbox->qElem);
+}
+
+static void EnetMcm_releaseInternalRespMbox(EnetMcm_Handle hMcm)
+{
+    EnetMcm_mailboxObj msg;
+
+    memset(&msg, 0, sizeof(msg));
+    msg.cmd = MCM_CLIENT_DISCONNECT;
+    EnetAppUtils_assert(hMcm->hInternalClientRespMbox != NULL);
+    msg.response = hMcm->hInternalClientRespMbox->hMbox;
+
+    MailboxP_post(hMcm->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
+    MailboxP_pend(hMcm->hInternalClientRespMbox->hMbox, &msg, SemaphoreP_WAIT_FOREVER);
+    EnetAppUtils_assert(msg.cmd == MCM_RESPONSE_CLIENT_DISCONNECT);
+    EnetAppUtils_assert(MailboxP_getNumPendingMsgs(hMcm->hInternalClientRespMbox->hMbox) == 0);
+
+    EnetAppUtils_assert(hMcm->hInternalClientRespMbox->isValidClient == false);
+}
+
 void EnetMcm_deInit(Enet_Type enetType)
 {
     EnetMcm_Handle hMcm = &gMcmObj[enetType];
     uint32_t numPendingmsgs;
+    uint32_t i;
+    EnetMcm_CmdIf mcmCmdIf;
 
     EnetAppUtils_assert(hMcm->hMutex != NULL);
 
@@ -692,39 +802,44 @@ void EnetMcm_deInit(Enet_Type enetType)
 
     if (hMcm->isInitDone == true)
     {
-        EnetMcm_mailboxObj msg;
-
-        msg.cmd = MCM_SHUTDOWN;
-
-        MailboxP_post(hMcm->hMboxCmd, &msg, MailboxP_WAIT_FOREVER);
-        MailboxP_pend(hMcm->hMboxResponse, &msg, MailboxP_WAIT_FOREVER);
-        EnetAppUtils_assert(msg.cmd == MCM_RESPONSE_SHUTDOWN);
-
-        while (TaskP_isTerminated(hMcm->task) != 1)
+        /*! Releasing response queue mailbox per client */
+        for (i = 0U; i < ENETMCM_MAX_CLIENTS; i++)
         {
-            TaskP_sleep(10);
-        }
-        TaskP_delete(&hMcm->task);
-
-        numPendingmsgs = MailboxP_getNumPendingMsgs(hMcm->hMboxCmd);
-        while (numPendingmsgs != 0U)
-        {
-            MailboxP_pend(hMcm->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
-            numPendingmsgs = MailboxP_getNumPendingMsgs(hMcm->hMboxCmd);
+            if ((i != ENETMCM_INTERNAL_CLIENT_IDX) && (hMcm->respMbox[i].isValidClient == true))
+            {
+                mcmCmdIf.hMboxCmd = hMcm->hMboxCmd;
+                mcmCmdIf.hMboxResponse = hMcm->respMbox[i].hMbox;
+                EnetMcm_releaseCmdIf(enetType, &mcmCmdIf);
+            }
         }
-
+        /* For shutting down MCM*/
+        EnetMcm_releaseInternalRespMbox(hMcm);
+        mcmCmdIf.hMboxCmd = hMcm->hMboxCmd;
+        EnetAppUtils_assert(hMcm->hInternalClientRespMbox != NULL);
+        mcmCmdIf.hMboxResponse = hMcm->hInternalClientRespMbox->hMbox;
+        EnetMcm_shutdown(enetType, &mcmCmdIf);
+ 
+        /* Deleting hMboxCmd Mailbox*/
+        EnetAppUtils_assert(MailboxP_getNumPendingMsgs(hMcm->hMboxCmd) == 0);
         MailboxP_delete(hMcm->hMboxCmd);
+        hMcm->hMboxCmd = NULL;
 
-        numPendingmsgs = MailboxP_getNumPendingMsgs(hMcm->hMboxResponse);
-        while (numPendingmsgs != 0U)
+        /* Deleting all hMboxResp Mailboxes */
+        for (i = 0U; i < ENET_ARRAYSIZE(hMcm->respMbox); i++)
         {
-            MailboxP_pend(hMcm->hMboxResponse, &msg, SemaphoreP_WAIT_FOREVER);
-            numPendingmsgs = MailboxP_getNumPendingMsgs(hMcm->hMboxResponse);
+            EnetAppUtils_assert(MailboxP_getNumPendingMsgs(hMcm->respMbox[i].hMbox) == 0);
+            MailboxP_delete(hMcm->respMbox[i].hMbox);
         }
+        hMcm->hInternalClientRespMbox = NULL;
 
-        MailboxP_delete(hMcm->hMboxResponse);
+        QueueP_delete(hMcm->hMboxRespFreeQ);
 
         EnetMcm_initAttachTable(&hMcm->coreAttachTable);
+        while (TaskP_isTerminated(hMcm->task) != 1)
+        {
+            TaskP_sleep(10);
+        }
+        TaskP_delete(&hMcm->task);
         hMcm->isInitDone = false;
     }
 
@@ -914,8 +1029,8 @@ static void EnetMcm_createClock(EnetMcm_Handle hMcm)
      * default priority (1) */
     TaskP_Params_init(&params);
     params.priority       = ENETMCM_PERIODICTSK_PRIORITY;
-    params.stack          = &mcmPrdTaskStack[0];
-    params.stacksize      = ENETMCM_TSK_STACK_MAIN;
+    params.stack          = &hMcm->mcmPrdTaskStack[0];
+    params.stacksize      = sizeof(hMcm->mcmPrdTaskStack);
     params.arg0           = hMcm->timerSem;
     params.arg1           = hMcm;
     params.name           = (uint8_t *)"Enet_PeriodicTickTask";
@@ -1014,8 +1129,8 @@ static int32_t EnetMcm_open(EnetMcm_Handle hMcm)
     params.arg0           = hMcm;
     params.arg1           = hMcm->asyncIoctlSem;
     params.name           = (uint8_t *)"EnetMcm_AsyncIoctlTask";
-    params.stack          =  &asyncIoctlTaskStack[0];
-    params.stacksize      =  sizeof(asyncIoctlTaskStack);
+    params.stack          = &hMcm->asyncIoctlTaskStack[0];
+    params.stacksize      = sizeof(hMcm->asyncIoctlTaskStack);
 
     hMcm->asyncIoctlTaskShutdown = false;
 
@@ -1158,9 +1273,16 @@ static void EnetMcm_serverTask(void * McmHandle)
     {
         int32_t status = ENET_SOK;
         EnetMcm_mailboxObj msg;
+        EnetMcm_RespMboxObj *respMbox;
+        uint32_t idx;
 
         MailboxP_pend(hMcm->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
 
+        respMbox = EnetMcm_getRespMbox(hMcm, msg.response);
+        /* For MCM_SHUTDOWN the cmd is sent by internal MCM client at deInit time.
+         * This client should have isValidClient set to false */
+        EnetAppUtils_assert((respMbox->isValidClient == true) || (msg.cmd == MCM_SHUTDOWN));
+
         switch (msg.cmd)
         {
             case MCM_GET_HANDLE:
@@ -1215,6 +1337,15 @@ static void EnetMcm_serverTask(void * McmHandle)
             case MCM_SHUTDOWN:
                 isShutdownMcm = true;
                 msg.cmd       = MCM_RESPONSE_SHUTDOWN;
+                EnetAppUtils_assert(ENETMCM_UTILS_ARRAYISMEMBER(respMbox, hMcm->respMbox) == true);
+                idx = ENETMCM_UTILS_GETARRAYINDEX(respMbox, hMcm->respMbox);
+                EnetAppUtils_assert(idx == ENETMCM_INTERNAL_CLIENT_IDX);
+                break;
+
+            case MCM_CLIENT_DISCONNECT:
+                msg.cmd = MCM_RESPONSE_CLIENT_DISCONNECT;
+                /* Clear client valid flag on receiving disconnect message */
+                respMbox->isValidClient = false;
                 break;
 
             default:
@@ -1222,7 +1353,7 @@ static void EnetMcm_serverTask(void * McmHandle)
                 EnetAppUtils_assert(false);
         }
 
-        MailboxP_post(hMcm->hMboxResponse, &msg, SemaphoreP_WAIT_FOREVER);
+        MailboxP_post(msg.response, &msg, SemaphoreP_WAIT_FOREVER);
     }
 }
 
@@ -1327,6 +1458,7 @@ void EnetMcm_acquireHandleInfo(const EnetMcm_CmdIf *hMcmCmdIf,
 
     memset(&msg, 0, sizeof(msg));
     msg.cmd = MCM_GET_HANDLE;
+    msg.response = hMcmCmdIf->hMboxResponse;
     if ((hMcmCmdIf != NULL) && (handleInfo != NULL))
     {
         MailboxP_post(hMcmCmdIf->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
@@ -1347,6 +1479,7 @@ void EnetMcm_releaseHandleInfo(const EnetMcm_CmdIf *hMcmCmdIf)
 
     memset(&msg, 0, sizeof(msg));
     msg.cmd = MCM_RELEASE_HANDLE;
+    msg.response = hMcmCmdIf->hMboxResponse;
     EnetAppUtils_assert(hMcmCmdIf != NULL);
 
     MailboxP_post(hMcmCmdIf->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
@@ -1364,6 +1497,7 @@ void EnetMcm_coreAttach(const EnetMcm_CmdIf *hMcmCmdIf,
     if ((hMcmCmdIf != NULL) && (attachInfo != NULL))
     {
         msg.cmd            = MCM_CORE_ATTACH;
+        msg.response       = hMcmCmdIf->hMboxResponse;
         msg.msgBody.coreId = coreId;
 
         MailboxP_post(hMcmCmdIf->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
@@ -1386,6 +1520,7 @@ void     EnetMcm_coreDetach(const EnetMcm_CmdIf *hMcmCmdIf,
     memset(&msg, 0, sizeof(msg));
     EnetAppUtils_assert(hMcmCmdIf != NULL);
     msg.cmd             = MCM_CORE_DETACH;
+    msg.response        = hMcmCmdIf->hMboxResponse;
     msg.msgBody.coreId  = coreId;
     msg.msgBody.coreKey = coreKey;
 
@@ -1406,6 +1541,7 @@ int32_t EnetMcm_ioctl(const EnetMcm_CmdIf *hMcmCmdIf,
     if ((hMcmCmdIf != NULL) && (prms != NULL))
     {
         msg.cmd = MCM_IOCTL;
+        msg.response          = hMcmCmdIf->hMboxResponse;
         msg.msgBody.ioctlCmd  = cmd;
         msg.msgBody.ioctlPrms = prms;
 
@@ -1422,3 +1558,33 @@ int32_t EnetMcm_ioctl(const EnetMcm_CmdIf *hMcmCmdIf,
 
     return status;
 }
+
+static void EnetMcm_shutdown(Enet_Type enetType, EnetMcm_CmdIf *hMcmCmdIf)
+{
+    EnetMcm_mailboxObj msg;
+
+    msg.cmd = MCM_SHUTDOWN;
+    msg.response = hMcmCmdIf->hMboxResponse;
+
+    MailboxP_post(hMcmCmdIf->hMboxCmd, &msg, SemaphoreP_WAIT_FOREVER);
+    MailboxP_pend(hMcmCmdIf->hMboxResponse, &msg, SemaphoreP_WAIT_FOREVER);
+    EnetAppUtils_assert(msg.cmd == MCM_RESPONSE_SHUTDOWN);
+}
+
+static EnetMcm_RespMboxObj* EnetMcm_getRespMbox(EnetMcm_Handle hMcm, MailboxP_Handle hMboxResp)
+{
+    EnetMcm_RespMboxObj *respMbox;
+    uint32_t i;
+
+    for (i = 0U; i < ENET_ARRAYSIZE(hMcm->respMbox); i++)
+    {
+        if(hMboxResp == hMcm->respMbox[i].hMbox)
+        {
+            respMbox = &hMcm->respMbox[i];
+            break;
+        }
+    }
+    EnetAppUtils_assert(respMbox != NULL);
+
+    return respMbox;
+}
diff --git a/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/include/enet_mcm.h b/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/include/enet_mcm.h
index 6af5b142..5e8d1019 100644
--- a/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/include/enet_mcm.h
+++ b/pdk_jacinto_08_02_00_21/packages/ti/drv/enet/examples/utils/include/enet_mcm.h
@@ -117,6 +117,9 @@ int32_t  EnetMcm_init(const EnetMcm_InitConfig *pMcmInitCfg);
 void  EnetMcm_getCmdIf(Enet_Type enetType,
                        EnetMcm_CmdIf *hMcmCmdIf);
 
+void  EnetMcm_releaseCmdIf(Enet_Type enetType,
+                           EnetMcm_CmdIf *hMcmCmdIf);
+
 void     EnetMcm_acquireHandleInfo(const EnetMcm_CmdIf *hMcmCmdIf,
                                    EnetMcm_HandleInfo *handleInfo);
 
diff --git a/pdk_jacinto_08_02_00_21/packages/ti/osal/src/freertos/QueueP_freertos.c b/pdk_jacinto_08_02_00_21/packages/ti/osal/src/freertos/QueueP_freertos.c
index 8a6d37af..66411759 100644
--- a/pdk_jacinto_08_02_00_21/packages/ti/osal/src/freertos/QueueP_freertos.c
+++ b/pdk_jacinto_08_02_00_21/packages/ti/osal/src/freertos/QueueP_freertos.c
@@ -202,10 +202,17 @@ void * QueueP_get(QueueP_Handle handle)
     { 
         q = &queue->queueHndl;
 
-        pElem = q->next;
+        if (QueueP_isEmpty(handle) != true)
+        {
+            pElem = q->next;
 
-        q->next = pElem->next;
-        pElem->next->prev = q;
+            q->next = pElem->next;
+            pElem->next->prev = q;
+        }
+        else
+        {
+           pElem = NULL;
+        }
     }
     
     HwiP_restore(key);
diff --git a/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/cpsw/timeSync_cpsw.c b/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/cpsw/timeSync_cpsw.c
index c8b1de81..46353666 100644
--- a/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/cpsw/timeSync_cpsw.c
+++ b/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/cpsw/timeSync_cpsw.c
@@ -926,6 +926,7 @@ void TimeSync_close(TimeSync_Handle timeSyncHandle)
                            timeSyncHandle->coreKey);
         /* Release handle info */
         EnetMcm_releaseHandleInfo(&timeSyncHandle->hMcmCmdIf);
+        EnetMcm_releaseCmdIf(timeSyncHandle->enetType, &timeSyncHandle->hMcmCmdIf);
 
     }
 }
diff --git a/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/icssg/timeSync_icssg.c b/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/icssg/timeSync_icssg.c
index 01a89103..8dd93afd 100644
--- a/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/icssg/timeSync_icssg.c
+++ b/pdk_jacinto_08_02_00_21/packages/ti/transport/timeSync/v2/src/ip/icssg/timeSync_icssg.c
@@ -780,6 +780,7 @@ void TimeSync_close(TimeSync_Handle timeSyncHandle)
                            timeSyncHandle->coreKey);
         /* Release handle info */
         EnetMcm_releaseHandleInfo(&timeSyncHandle->hMcmCmdIf);
+        EnetMcm_releaseCmdIf(timeSyncHandle->enetType, &timeSyncHandle->hMcmCmdIf);
 
     }
 }
-- 
2.17.1

