/****************************************************************************** © 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. All rights reserved. This is proprietary source code of Freescale Semiconductor Inc., and its use is subject to the NetComm Device Drivers EULA. The copyright notice above does not evidence any actual or intended publication of such source code. ALTERNATIVELY, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Freescale Semiconductor nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /****************************************************************************** @File qm.c @Description QM & Portal implementation *//***************************************************************************/ #include #include #include #include "error_ext.h" #include "std_ext.h" #include "string_ext.h" #include "sprint_ext.h" #include "mm_ext.h" #include "core_ext.h" #include "debug_ext.h" #include "qm.h" static volatile bool blockingFlag = FALSE; static void QmIpcMsgCompletionCB(t_Handle h_Module, uint8_t *p_Msg, uint8_t *p_Reply, uint32_t replyLength, t_Error status) { SANITY_CHECK_RETURN(h_Module, E_INVALID_HANDLE); UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);UNUSED(h_Module); blockingFlag = FALSE; } static t_Error QmHandleIpcMsgCB(t_Handle h_Qm, uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply, uint32_t *p_ReplyLength) { t_Qm *p_Qm = (t_Qm*)h_Qm; t_QmIpcMsg *p_IpcMsg = (t_QmIpcMsg*)p_Msg; t_QmIpcReply *p_IpcReply = (t_QmIpcReply *)p_Reply; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE); #ifdef DISABLE_SANITY_CHECKS UNUSED(msgLength); #endif /* DISABLE_SANITY_CHECKS */ ASSERT_COND(p_IpcMsg); memset(p_IpcReply, 0, (sizeof(uint8_t) * QM_IPC_MAX_REPLY_SIZE)); *p_ReplyLength = 0; switch(p_IpcMsg->msgId) { case (QM_MASTER_IS_ALIVE): *(uint8_t*)p_IpcReply->replyBody = 1; *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); break; case (QM_FORCE_FQID): { t_QmIpcFqidParams ipcFqid; uint32_t fqid; memcpy((uint8_t*)&ipcFqid, p_IpcMsg->msgBody, sizeof(t_QmIpcFqidParams)); fqid = QmFqidGet(p_Qm, ipcFqid.size, 1, TRUE, ipcFqid.fqid); memcpy(p_IpcReply->replyBody, (uint8_t*)&fqid, sizeof(uint32_t)); *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); break; } case (QM_PUT_FQID): { t_Error err; t_QmIpcFqidParams ipcFqid; memcpy((uint8_t*)&ipcFqid, p_IpcMsg->msgBody, sizeof(t_QmIpcFqidParams)); if ((err = QmFqidPut(p_Qm, ipcFqid.fqid)) != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); break; } case (QM_GET_COUNTER): { t_QmIpcGetCounter ipcCounter; uint32_t count; memcpy((uint8_t*)&ipcCounter, p_IpcMsg->msgBody, sizeof(t_QmIpcGetCounter)); count = QmGetCounter(p_Qm, (e_QmInterModuleCounters)ipcCounter.enumId); memcpy(p_IpcReply->replyBody, (uint8_t*)&count, sizeof(uint32_t)); *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); break; } case (QM_GET_SET_PORTAL_PARAMS): { t_Error err; t_QmIpcPortalInitParams ipcPortalInitParams; t_QmInterModulePortalInitParams portalInitParams; memcpy((uint8_t*)&ipcPortalInitParams, p_IpcMsg->msgBody, sizeof(t_QmIpcPortalInitParams)); portalInitParams.portalId = ipcPortalInitParams.portalId; portalInitParams.stashDestQueue = ipcPortalInitParams.stashDestQueue; portalInitParams.liodn = ipcPortalInitParams.liodn; portalInitParams.dqrrLiodn = ipcPortalInitParams.dqrrLiodn; portalInitParams.fdFqLiodn = ipcPortalInitParams.fdFqLiodn; if ((err = QmGetSetPortalParams(p_Qm, &portalInitParams)) != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); break; } case (QM_GET_REVISION): { t_QmRevisionInfo revInfo; t_QmIpcRevisionInfo ipcRevInfo; p_IpcReply->error = (uint32_t)QmGetRevision(h_Qm, &revInfo); ipcRevInfo.majorRev = revInfo.majorRev; ipcRevInfo.minorRev = revInfo.minorRev; memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_QmIpcRevisionInfo)); *p_ReplyLength = sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo); break; } default: *p_ReplyLength = 0; RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); } return E_OK; } static t_Error CheckQmParameters(t_Qm *p_Qm) { if ((p_Qm->p_QmDriverParams->partFqidBase + p_Qm->p_QmDriverParams->partNumOfFqids) > QM_MAX_NUM_OF_FQIDS) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partFqidBase+partNumOfFqids out of range!!!")); if ((p_Qm->partCgsBase + p_Qm->partNumOfCgs) > QM_MAX_NUM_OF_CGS) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partCgsBase+partNumOfCgs out of range!!!")); if (p_Qm->guestId == NCSW_MASTER_ID) { uint64_t phyAddr; phyAddr = XX_VirtToPhys(UINT_TO_PTR(p_Qm->p_QmDriverParams->swPortalsBaseAddress)); if (phyAddr & 0x00000000001fffffLL) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("swPortalsBaseAddress isn't properly aligned")); if (!p_Qm->p_QmDriverParams->rtFramesDepth) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rtFramesDepth must be larger than '0'!!!")); if (p_Qm->p_QmDriverParams->rtFramesDepth > ((16*MEGABYTE)*3)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rtFramesDepth must be equal or smaller than 48MB!!!")); if (!p_Qm->p_QmDriverParams->totalNumOfFqids) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfFqids must be larger than '0'!!!")); if (p_Qm->p_QmDriverParams->totalNumOfFqids > (16*MEGABYTE)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfFqids must be equal or smaller than 16MB!!!")); if(!p_Qm->f_Exception) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); } return E_OK; } static t_Error QmInitPfdr(t_Qm *p_Qm, uint32_t pfdr_start, uint32_t num) { uint8_t rslt; uint32_t timeout = 100000; ASSERT_COND(p_Qm); ASSERT_COND(pfdr_start && !(pfdr_start & 7) && !(num & 7) && num); /* Make sure te command interface is 'idle' */ rslt = MCR_get_rslt(GET_UINT32(p_Qm->p_QmRegs->mcr)); if (!MCR_rslt_idle(rslt)) RETURN_ERROR(CRITICAL,E_INVALID_STATE,("QMAN_MCR isn't idle")); /* Write the MCR command params then the verb */ WRITE_UINT32(p_Qm->p_QmRegs->mcp0, pfdr_start); /* TODO: remove this - it's a workaround for a model bug that is * corrected in more recent versions. We use the workaround until * everyone has upgraded. */ WRITE_UINT32(p_Qm->p_QmRegs->mcp1, (pfdr_start + num - 16)); WRITE_UINT32(p_Qm->p_QmRegs->mcp1, (pfdr_start + num - 1)); mb(); WRITE_UINT32(p_Qm->p_QmRegs->mcr, MCR_INIT_PFDR); /* Poll for the result */ do { XX_UDelay(1); rslt = MCR_get_rslt(GET_UINT32(p_Qm->p_QmRegs->mcr)); } while(!MCR_rslt_idle(rslt) && --timeout); if (MCR_rslt_ok(rslt)) return E_OK; WRITE_UINT32(p_Qm->p_QmRegs->mcr, 0); if (!timeout) RETURN_ERROR(MAJOR, E_TIMEOUT, NO_MSG); if (MCR_rslt_eaccess(rslt)) RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); if (MCR_rslt_inval(rslt)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unexpected result from MCR_INIT_PFDR: %02x\n", rslt)); } static __inline__ void QmSetWqScheduling(t_Qm *p_Qm, e_QmWqClass wqClass, uint8_t csElev, uint8_t csw2, uint8_t csw3, uint8_t csw4, uint8_t csw5, uint8_t csw6, uint8_t csw7) { ASSERT_COND(p_Qm); WRITE_UINT32(p_Qm->p_QmRegs->wq_cs_cfg[wqClass], (uint32_t)(((csElev & 0xff) << 24) | ((csw2 & 0x7) << 20) | ((csw3 & 0x7) << 16) | ((csw4 & 0x7) << 12) | ((csw5 & 0x7) << 8) | ((csw6 & 0x7) << 4) | (csw7 & 0x7))); } static uint32_t ReserveFqids(t_Qm *p_Qm, uint32_t size, uint32_t alignment, bool force, uint32_t base) { uint64_t ans; uint32_t intFlags; intFlags = XX_LockIntrSpinlock(p_Qm->lock); if (force) ans = MM_GetForce(p_Qm->h_FqidMm, (uint64_t)base, (uint64_t)size, "QM FQID MEM"); else ans = MM_Get(p_Qm->h_FqidMm, (uint64_t)size, alignment, "QM FQID MEM"); if (ans == ILLEGAL_BASE) { XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); return (uint32_t)ans; } base = (uint32_t)ans; ans = MM_GetForce(p_Qm->h_RsrvFqidMm, (uint64_t)base, (uint64_t)size, "QM rsrv FQID MEM"); if (ans == ILLEGAL_BASE) { MM_Put(p_Qm->h_FqidMm, (uint64_t)base); XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); return (uint32_t)ans; } XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); return (uint32_t)base; } static void FreeInitResources(t_Qm *p_Qm) { if (p_Qm->p_FqdBase) XX_FreeSmart(p_Qm->p_FqdBase); if (p_Qm->p_PfdrBase) XX_FreeSmart(p_Qm->p_PfdrBase); if (p_Qm->h_Session) XX_IpcFreeSession(p_Qm->h_Session); if (p_Qm->h_RsrvFqidMm) MM_Free(p_Qm->h_RsrvFqidMm); if (p_Qm->h_FqidMm) MM_Free(p_Qm->h_FqidMm); } /****************************************/ /* Inter-Module functions */ /****************************************/ uint32_t QmGetCounter(t_Handle h_Qm, e_QmInterModuleCounters counter) { t_Qm *p_Qm = (t_Qm*)h_Qm; SANITY_CHECK_RETURN_VALUE(p_Qm, E_INVALID_HANDLE, 0); SANITY_CHECK_RETURN_VALUE((((p_Qm->guestId == NCSW_MASTER_ID) && p_Qm->p_QmRegs) || (p_Qm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE, 0); if ((p_Qm->guestId == NCSW_MASTER_ID) || (!p_Qm->h_Session && p_Qm->p_QmRegs)) { switch(counter) { case(e_QM_IM_COUNTERS_SFDR_IN_USE): return GET_UINT32(p_Qm->p_QmRegs->sfdr_in_use); case(e_QM_IM_COUNTERS_PFDR_IN_USE): return (p_Qm->numOfPfdr - GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc)); case(e_QM_IM_COUNTERS_PFDR_FREE_POOL): return (GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc) - GET_UINT32(p_Qm->p_QmRegs->pfdr_cfg)); default: break; } /* should never get here */ ASSERT_COND(FALSE); } else if (p_Qm->h_Session) { t_QmIpcMsg msg; t_QmIpcReply reply; t_QmIpcGetCounter ipcCounter; uint32_t replyLength, count; t_Error errCode = E_OK; memset(&msg, 0, sizeof(t_QmIpcMsg)); memset(&reply, 0, sizeof(t_QmIpcReply)); ipcCounter.enumId = (uint32_t)counter; msg.msgId = QM_GET_COUNTER; memcpy(msg.msgBody, &ipcCounter, sizeof(t_QmIpcGetCounter)); replyLength = sizeof(uint32_t) + sizeof(uint32_t); if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(t_QmIpcGetCounter), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) REPORT_ERROR(MAJOR, errCode, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); if ((errCode == E_OK) && (replyLength == (sizeof(uint32_t) + sizeof(uint32_t)))) { memcpy((uint8_t*)&count, reply.replyBody, sizeof(uint32_t)); return count; } } else REPORT_ERROR(WARNING, E_NOT_SUPPORTED, ("In 'guest', either IPC or 'baseAddress' is required!")); return 0; } t_Error QmGetRevision(t_Handle h_Qm, t_QmRevisionInfo *p_QmRevisionInfo) { t_Qm *p_Qm = (t_Qm *)h_Qm; uint32_t tmpReg; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_QmRevisionInfo, E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR((((p_Qm->guestId == NCSW_MASTER_ID) && p_Qm->p_QmRegs) || (p_Qm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE); if ((p_Qm->guestId == NCSW_MASTER_ID) || (!p_Qm->h_Session && p_Qm->p_QmRegs)) { /* read revision register 1 */ tmpReg = GET_UINT32(p_Qm->p_QmRegs->ip_rev_1); p_QmRevisionInfo->majorRev = (uint8_t)((tmpReg & REV1_MAJOR_MASK) >> REV1_MAJOR_SHIFT); p_QmRevisionInfo->minorRev = (uint8_t)((tmpReg & REV1_MINOR_MASK) >> REV1_MINOR_SHIFT); } else if (p_Qm->h_Session) { t_QmIpcMsg msg; t_QmIpcReply reply; t_QmIpcRevisionInfo ipcRevInfo; uint32_t replyLength; t_Error errCode = E_OK; memset(&msg, 0, sizeof(t_QmIpcMsg)); memset(&reply, 0, sizeof(reply)); msg.msgId = QM_GET_REVISION; replyLength = sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo); if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MAJOR, errCode, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo))) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_QmIpcRevisionInfo)); p_QmRevisionInfo->majorRev = ipcRevInfo.majorRev; p_QmRevisionInfo->minorRev = ipcRevInfo.minorRev; return (t_Error)(reply.error); } else RETURN_ERROR(WARNING, E_NOT_SUPPORTED, ("In 'guest', either IPC or 'baseAddress' is required!")); return E_OK; } t_Error QmGetSetPortalParams(t_Handle h_Qm, t_QmInterModulePortalInitParams *p_PortalParams) { t_Qm *p_Qm = (t_Qm *)h_Qm; t_QmRevisionInfo revInfo; uint32_t lioReg,ioReg; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_PortalParams, E_NULL_POINTER); if (p_Qm->guestId == NCSW_MASTER_ID) { QmGetRevision(p_Qm, &revInfo); if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) { lioReg = (uint32_t)(p_PortalParams->stashDestQueue << 24) | (p_PortalParams->liodn << 16) | (p_PortalParams->dqrrLiodn); ioReg = (p_PortalParams->fdFqLiodn); } else { lioReg = (uint32_t)(p_PortalParams->liodn << 16) | (p_PortalParams->dqrrLiodn); ioReg = (uint32_t)(p_PortalParams->stashDestQueue << 16) | (p_PortalParams->fdFqLiodn); } WRITE_UINT32(p_Qm->p_QmRegs->swpConfRegs[p_PortalParams->portalId].lio_cfg, lioReg); WRITE_UINT32(p_Qm->p_QmRegs->swpConfRegs[p_PortalParams->portalId].io_cfg, ioReg); } else if (p_Qm->h_Session) { t_QmIpcMsg msg; t_QmIpcPortalInitParams portalParams; t_Error errCode; memset(&msg, 0, sizeof(t_QmIpcMsg)); portalParams.portalId = p_PortalParams->portalId; portalParams.stashDestQueue = p_PortalParams->stashDestQueue; portalParams.liodn = p_PortalParams->liodn; portalParams.dqrrLiodn = p_PortalParams->dqrrLiodn; portalParams.fdFqLiodn = p_PortalParams->fdFqLiodn; msg.msgId = QM_GET_SET_PORTAL_PARAMS; memcpy(msg.msgBody, &portalParams, sizeof(t_QmIpcPortalInitParams)); XX_LockSpinlock(p_Qm->lock); if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(t_QmIpcPortalInitParams), NULL, NULL, NULL, NULL)) != E_OK) { XX_UnlockSpinlock(p_Qm->lock); RETURN_ERROR(MAJOR, errCode, NO_MSG); } XX_UnlockSpinlock(p_Qm->lock); } else DBG(WARNING, ("Can't set portal parameters (e.g. liodns). " \ "probably QM is running in guest-mode with no IPC!")); return E_OK; } uint32_t QmFqidGet(t_Qm *p_Qm, uint32_t size, uint32_t alignment, bool force, uint32_t base) { uint64_t ans; uint32_t intFlags; intFlags = XX_LockIntrSpinlock(p_Qm->lock); if (force) { ans = MM_GetForce(p_Qm->h_FqidMm, (uint64_t)base, (uint64_t)size, "QM FQID MEM"); if (ans == ILLEGAL_BASE) { ans = MM_GetForce(p_Qm->h_RsrvFqidMm, (uint64_t)base, (uint64_t)size, "QM rsrv FQID MEM"); if (ans == ILLEGAL_BASE) ans = base; else if (p_Qm->h_Session) { t_QmIpcMsg msg; t_QmIpcReply reply; uint32_t replyLength; t_QmIpcFqidParams ipcFqid; t_Error errCode = E_OK; memset(&msg, 0, sizeof(t_QmIpcMsg)); memset(&reply, 0, sizeof(t_QmIpcReply)); ipcFqid.fqid = base; ipcFqid.size = size; msg.msgId = QM_FORCE_FQID; memcpy(msg.msgBody, &ipcFqid, sizeof(t_QmIpcFqidParams)); replyLength = sizeof(uint32_t) + sizeof(uint32_t); if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(t_QmIpcFqidParams), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) REPORT_ERROR(MAJOR, errCode, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); if ((errCode != E_OK) || (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))) ans = ILLEGAL_BASE; else memcpy((uint8_t*)&ans, reply.replyBody, sizeof(uint32_t)); } else { DBG(WARNING, ("No Ipc - can't validate fqid.")); ans = base; } } } else ans = MM_Get(p_Qm->h_FqidMm, size, alignment, "QM FQID MEM"); XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); KASSERT(ans < UINT32_MAX, ("Oops, %jx > UINT32_MAX!\n", (uintmax_t)ans)); return (uint32_t)ans; } t_Error QmFqidPut(t_Qm *p_Qm, uint32_t base) { uint32_t intFlags; intFlags = XX_LockIntrSpinlock(p_Qm->lock); /* Check maybe this fqid was reserved in the past */ if (MM_GetForce(p_Qm->h_RsrvFqidMm, (uint64_t)base, (uint64_t)1, "QM rsrv FQID MEM") == ILLEGAL_BASE) { XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); return E_OK; } else MM_PutForce(p_Qm->h_RsrvFqidMm, (uint64_t)base, (uint64_t)1); if (MM_InRange(p_Qm->h_FqidMm, (uint64_t)base)) { if (MM_Put(p_Qm->h_FqidMm, (uint64_t)base) != 0) { XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); return E_OK; } else { XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); return ERROR_CODE(E_NOT_FOUND); } } else if (p_Qm->h_Session) { t_QmIpcMsg msg; t_QmIpcFqidParams ipcFqid; t_Error errCode = E_OK; memset(&msg, 0, sizeof(t_QmIpcMsg)); ipcFqid.fqid = (uint8_t)base; ipcFqid.size = 0; msg.msgId = QM_PUT_FQID; memcpy(msg.msgBody, &ipcFqid, sizeof(t_QmIpcFqidParams)); if ((errCode = XX_IpcSendMessage(p_Qm->h_Session, (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(t_QmIpcFqidParams), NULL, NULL, NULL, NULL)) != E_OK) { XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); RETURN_ERROR(MAJOR, errCode, NO_MSG); } } else DBG(WARNING, ("No Ipc - can't validate fqid.")); XX_UnlockIntrSpinlock(p_Qm->lock, intFlags); return E_OK; } t_Error QmGetCgId(t_Handle h_Qm, uint8_t *p_CgId) { t_Qm *p_Qm = (t_Qm *)h_Qm; uint16_t i; for(i = p_Qm->partCgsBase;ipartCgsBase+p_Qm->partNumOfCgs;i++) if (!p_Qm->cgsUsed[i]) { p_Qm->cgsUsed[i] = (uint8_t)TRUE; *p_CgId = (uint8_t)i; break; } if(i == (p_Qm->partCgsBase+p_Qm->partNumOfCgs)) RETURN_ERROR(MINOR, E_BUSY, ("No available CG")); else return E_OK; } t_Error QmFreeCgId(t_Handle h_Qm, uint8_t cgId) { t_Qm *p_Qm = (t_Qm *)h_Qm; if (!p_Qm->cgsUsed[cgId]) RETURN_ERROR(MINOR, E_INVALID_STATE, ("CG is not in use")); else p_Qm->cgsUsed[cgId] = (uint8_t)FALSE; return E_OK; } /****************************************/ /* API Init unit functions */ /****************************************/ t_Handle QM_Config(t_QmParam *p_QmParam) { t_Qm *p_Qm; uint8_t i; SANITY_CHECK_RETURN_VALUE(p_QmParam, E_INVALID_HANDLE, NULL); p_Qm = (t_Qm *)XX_Malloc(sizeof(t_Qm)); if (!p_Qm) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM obj!!!")); return NULL; } memset(p_Qm, 0, sizeof(t_Qm)); p_Qm->p_QmDriverParams = (t_QmDriverParams *)XX_Malloc(sizeof(t_QmDriverParams)); if (!p_Qm->p_QmDriverParams) { XX_Free(p_Qm); REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm driver parameters")); return NULL; } memset(p_Qm->p_QmDriverParams, 0, sizeof(t_QmDriverParams)); p_Qm->guestId = p_QmParam->guestId; p_Qm->p_QmDriverParams->partFqidBase = p_QmParam->partFqidBase; p_Qm->p_QmDriverParams->partNumOfFqids = p_QmParam->partNumOfFqids; p_Qm->partCgsBase = p_QmParam->partCgsBase; p_Qm->partNumOfCgs = p_QmParam->partNumOfCgs; p_Qm->p_QmRegs = (t_QmRegs *)UINT_TO_PTR(p_QmParam->baseAddress); if (p_Qm->guestId == NCSW_MASTER_ID) { p_Qm->exceptions = DEFAULT_exceptions; p_Qm->f_Exception = p_QmParam->f_Exception; p_Qm->h_App = p_QmParam->h_App; p_Qm->errIrq = p_QmParam->errIrq; p_Qm->p_QmDriverParams->liodn = p_QmParam->liodn; p_Qm->p_QmDriverParams->rtFramesDepth = DEFAULT_rtFramesDepth; p_Qm->p_QmDriverParams->fqdMemPartitionId = p_QmParam->fqdMemPartitionId; p_Qm->p_QmDriverParams->pfdrMemPartitionId = p_QmParam->pfdrMemPartitionId; p_Qm->p_QmDriverParams->swPortalsBaseAddress = p_QmParam->swPortalsBaseAddress; p_Qm->p_QmDriverParams->totalNumOfFqids = p_QmParam->totalNumOfFqids; p_Qm->p_QmDriverParams->pfdrThreshold = DEFAULT_pfdrThreshold; p_Qm->p_QmDriverParams->sfdrThreshold = DEFAULT_sfdrThreshold; p_Qm->p_QmDriverParams->pfdrBaseConstant = DEFAULT_pfdrBaseConstant; for(i= 0;ip_QmDriverParams->dcPortalsParams[i].sendToSw = (bool)((i < e_DPAA_DCPORTAL2) ? FALSE : TRUE); #ifdef QMAN_SFDR_LEAK_ERRATA_QMAN5 { #define WORKAROUND_TMP_VAL 0x00000003 t_QmRevisionInfo revInfo; QmGetRevision(p_Qm, &revInfo); if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) { uint32_t *tmp = (uint32_t *)UINT_TO_PTR(p_QmParam->baseAddress + 0xbf0); uint32_t tmpReg = WORKAROUND_TMP_VAL; WRITE_UINT32(*tmp, tmpReg); while ((tmpReg = GET_UINT32(*tmp)) != WORKAROUND_TMP_VAL) ; } } #endif /* QMAN_SFDR_LEAK_ERRATA_QMAN5 */ } /* build the QM partition IPC address */ memset(p_Qm->moduleName, 0, MODULE_NAME_SIZE); if(Sprint (p_Qm->moduleName, "QM_0_%d",p_Qm->guestId) != (p_Qm->guestId<10 ? 6:7)) { XX_Free(p_Qm->p_QmDriverParams); XX_Free(p_Qm); REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); return NULL; } return p_Qm; } t_Error QM_Init(t_Handle h_Qm) { t_Qm *p_Qm = (t_Qm *)h_Qm; t_QmDriverParams *p_QmDriverParams; t_Error err; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); CHECK_INIT_PARAMETERS(p_Qm, CheckQmParameters); p_QmDriverParams = p_Qm->p_QmDriverParams; if (p_QmDriverParams->partNumOfFqids) { if (MM_Init(&p_Qm->h_FqidMm, p_QmDriverParams->partFqidBase, p_QmDriverParams->partNumOfFqids) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("QM-FQIDS-MEM partition!!!")); if (MM_Init(&p_Qm->h_RsrvFqidMm, p_QmDriverParams->partFqidBase, p_QmDriverParams->partNumOfFqids) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("QM-Reserve-FQIDS-MEM partition!!!")); } if (p_Qm->guestId == NCSW_MASTER_ID) { uint64_t phyAddr; t_QmRevisionInfo revInfo; uint32_t dsSize, exp, i; QmGetRevision(p_Qm, &revInfo); DBG(TRACE, ("Qman ver:%02x,%02x", revInfo.majorRev, revInfo.minorRev)); phyAddr = XX_VirtToPhys(UINT_TO_PTR(p_QmDriverParams->swPortalsBaseAddress)); WRITE_UINT32(p_Qm->p_QmRegs->qcsp_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff)); WRITE_UINT32(p_Qm->p_QmRegs->qcsp_bar, (uint32_t)phyAddr); WRITE_UINT32(p_Qm->p_QmRegs->liodnr, (uint16_t)p_QmDriverParams->liodn); /* FQD memory */ dsSize = (uint32_t)(p_QmDriverParams->totalNumOfFqids * FQD_ENTRY_SIZE); LOG2(dsSize, exp); if (!POWER_OF_2(dsSize)) (exp++); dsSize = (uint32_t)(1 << exp); if (dsSize < (4*KILOBYTE)) { dsSize = (4*KILOBYTE); LOG2(dsSize, exp); } p_Qm->p_FqdBase = XX_MallocSmart(dsSize, (int)p_QmDriverParams->fqdMemPartitionId, dsSize); if (!p_Qm->p_FqdBase) { RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQD obj!!!")); } memset(p_Qm->p_FqdBase, 0, dsSize); mb(); for (i=0; ip_FqdBase, i)); mb(); phyAddr = XX_VirtToPhys(p_Qm->p_FqdBase); WRITE_UINT32(p_Qm->p_QmRegs->fqd_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff)); WRITE_UINT32(p_Qm->p_QmRegs->fqd_bar, (uint32_t)phyAddr); WRITE_UINT32(p_Qm->p_QmRegs->fqd_ar, AR_ENABLE | (exp - 1)); /* PFDR memory */ dsSize = (uint32_t)(p_QmDriverParams->rtFramesDepth * (PFDR_ENTRY_SIZE/3)); LOG2(dsSize, exp); if (!POWER_OF_2(dsSize)) (exp++); dsSize = (uint32_t)(1 << exp); if (dsSize < (4*KILOBYTE)) { dsSize = (4*KILOBYTE); LOG2(dsSize, exp); } p_Qm->p_PfdrBase = XX_MallocSmart(dsSize, (int)p_QmDriverParams->pfdrMemPartitionId, dsSize); if (!p_Qm->p_PfdrBase) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("PFDR obj!!!")); phyAddr = XX_VirtToPhys(p_Qm->p_PfdrBase); WRITE_UINT32(p_Qm->p_QmRegs->pfdr_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff)); WRITE_UINT32(p_Qm->p_QmRegs->pfdr_bar, (uint32_t)phyAddr); WRITE_UINT32(p_Qm->p_QmRegs->pfdr_ar, AR_ENABLE | (exp - 1)); if (QmInitPfdr(p_Qm, 8, dsSize / 64 - 8) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PFDR init failed!!!")); /* thresholds */ WRITE_UINT32(p_Qm->p_QmRegs->pfdr_fp_lwit, (p_Qm->p_QmDriverParams->pfdrThreshold & 0xffffff)); WRITE_UINT32(p_Qm->p_QmRegs->pfdr_cfg, p_Qm->p_QmDriverParams->pfdrBaseConstant); WRITE_UINT32(p_Qm->p_QmRegs->sfdr_cfg, (p_Qm->p_QmDriverParams->sfdrThreshold & 0x3ff)); p_Qm->numOfPfdr = GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc); /* corenet initiator settings */ WRITE_UINT32(p_Qm->p_QmRegs->ci_sched_cfg, (CI_SCHED_CFG_EN | (DEFAULT_initiatorSrcciv << CI_SCHED_CFG_SRCCIV_SHIFT) | (DEFAULT_initiatorSrqW << CI_SCHED_CFG_SRQ_W_SHIFT) | (DEFAULT_initiatorRwW << CI_SCHED_CFG_RW_W_SHIFT) | (DEFAULT_initiatorBmanW << CI_SCHED_CFG_BMAN_W_SHIFT))); /* HID settings */ if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) /* offset 0x0bf0 */ WRITE_UINT32(p_Qm->p_QmRegs->res23[144], 0x3); else WRITE_UINT32(p_Qm->p_QmRegs->res23[144], 0x0); for(i=0;ip_QmDriverParams->dcPortalsParams[i].sendToSw) WRITE_UINT32(p_Qm->p_QmRegs->dcpConfRegs[i].cfg, p_Qm->p_QmDriverParams->dcPortalsParams[i].swPortalId); else WRITE_UINT32(p_Qm->p_QmRegs->dcpConfRegs[i].cfg, QM_DCP_CFG_ED); } #ifdef QMAN_WQ_CS_CFG_ERRATA_QMAN4 { t_QmRevisionInfo revInfo; QmGetRevision(p_Qm, &revInfo); if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0)) { QmSetWqScheduling(p_Qm, e_QM_WQ_SW_PORTALS,0,1,1,1,1,1,1); QmSetWqScheduling(p_Qm, e_QM_WQ_POOLS,0,1,1,1,1,1,1); QmSetWqScheduling(p_Qm, e_QM_WQ_DCP0,0,1,1,1,1,1,1); QmSetWqScheduling(p_Qm, e_QM_WQ_DCP1,0,1,1,1,1,1,1); QmSetWqScheduling(p_Qm, e_QM_WQ_DCP2,0,1,1,1,1,1,1); QmSetWqScheduling(p_Qm, e_QM_WQ_DCP3,0,1,1,1,1,1,1); } } #endif /* QMAN_WQ_CS_CFG_ERRATA_QMAN4 */ WRITE_UINT32(p_Qm->p_QmRegs->err_isr, p_Qm->exceptions); WRITE_UINT32(p_Qm->p_QmRegs->err_ier, p_Qm->exceptions); WRITE_UINT32(p_Qm->p_QmRegs->err_isdr, 0x0); if (p_Qm->errIrq != NO_IRQ) { XX_SetIntr(p_Qm->errIrq, QM_ErrorIsr, p_Qm); XX_EnableIntr(p_Qm->errIrq); } if ((err = XX_IpcRegisterMsgHandler(p_Qm->moduleName, QmHandleIpcMsgCB, p_Qm, QM_IPC_MAX_REPLY_SIZE)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); } else /* guest mode */ { char masterModuleName[MODULE_NAME_SIZE]; memset(masterModuleName, 0, MODULE_NAME_SIZE); if(Sprint (masterModuleName, "QM_0_%d", NCSW_MASTER_ID) != (NCSW_MASTER_ID<10 ? 6:7)) { RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); } p_Qm->h_Session = XX_IpcInitSession(masterModuleName, p_Qm->moduleName); if (p_Qm->h_Session) { t_QmIpcMsg msg; uint8_t isMasterAlive = 0; t_QmIpcReply reply; uint32_t replyLength; memset(&msg, 0, sizeof(t_QmIpcMsg)); memset(&reply, 0, sizeof(t_QmIpcReply)); msg.msgId = QM_MASTER_IS_ALIVE; do { blockingFlag = TRUE; replyLength = sizeof(uint32_t) + sizeof(uint8_t); if ((err = XX_IpcSendMessage(p_Qm->h_Session, (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, QmIpcMsgCompletionCB, p_Qm)) != E_OK) REPORT_ERROR(MAJOR, err, NO_MSG); while(blockingFlag) ; if(replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); isMasterAlive = *(uint8_t*)(reply.replyBody); } while (!isMasterAlive); } } p_Qm->lock = XX_InitSpinlock(); XX_Free(p_Qm->p_QmDriverParams); p_Qm->p_QmDriverParams = NULL; return E_OK; } t_Error QM_Free(t_Handle h_Qm) { t_Qm *p_Qm = (t_Qm *)h_Qm; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); if (p_Qm->lock) XX_FreeSpinlock(p_Qm->lock); if (p_Qm->guestId == NCSW_MASTER_ID) { XX_IpcUnregisterMsgHandler(p_Qm->moduleName); if (p_Qm->errIrq != NO_IRQ) { XX_DisableIntr(p_Qm->errIrq); XX_FreeIntr(p_Qm->errIrq); } } FreeInitResources(p_Qm); if (p_Qm->p_QmDriverParams) XX_Free(p_Qm->p_QmDriverParams); XX_Free(p_Qm); return E_OK; } t_Error QM_ConfigRTFramesDepth(t_Handle h_Qm, uint32_t rtFramesDepth) { t_Qm *p_Qm = (t_Qm *)h_Qm; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); p_Qm->p_QmDriverParams->rtFramesDepth = rtFramesDepth; return E_OK; } t_Error QM_ConfigPfdrThreshold(t_Handle h_Qm, uint32_t threshold) { t_Qm *p_Qm = (t_Qm *)h_Qm; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); p_Qm->p_QmDriverParams->pfdrThreshold = threshold; return E_OK; } t_Error QM_ConfigSfdrReservationThreshold(t_Handle h_Qm, uint32_t threshold) { t_Qm *p_Qm = (t_Qm *)h_Qm; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE); p_Qm->p_QmDriverParams->sfdrThreshold = threshold; return E_OK; } t_Error QM_ConfigErrorRejectionNotificationDest(t_Handle h_Qm, e_DpaaDcPortal id, t_QmDcPortalParams *p_Params) { UNUSED(h_Qm); UNUSED(id); UNUSED(p_Params); RETURN_ERROR(INFO, E_NOT_SUPPORTED, ("Only default ERN destination available.")); } t_Error QM_Poll(t_Handle h_Qm, e_QmPortalPollSource source) { t_Qm *p_Qm = (t_Qm *)h_Qm; t_QmPortal *p_QmPortal; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); p_QmPortal = QmGetPortalHandle(p_Qm); SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); return QM_PORTAL_Poll(p_QmPortal, source); } uint32_t QM_GetCounter(t_Handle h_Qm, e_QmCounters counter) { t_Qm *p_Qm = (t_Qm *)h_Qm; SANITY_CHECK_RETURN_VALUE(p_Qm, E_INVALID_HANDLE, 0); SANITY_CHECK_RETURN_VALUE(!p_Qm->p_QmDriverParams, E_INVALID_STATE, 0); switch(counter) { case(e_QM_COUNTERS_SFDR_IN_USE): return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_SFDR_IN_USE); case(e_QM_COUNTERS_PFDR_IN_USE): return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_PFDR_IN_USE); case(e_QM_COUNTERS_PFDR_FREE_POOL): return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_PFDR_FREE_POOL); default: break; } /* should never get here */ ASSERT_COND(FALSE); return 0; } void QM_ErrorIsr(t_Handle h_Qm) { t_Qm *p_Qm = (t_Qm *)h_Qm; uint32_t tmpReg; SANITY_CHECK_RETURN(p_Qm, E_INVALID_HANDLE); if (p_Qm->guestId != NCSW_MASTER_ID) { REPORT_ERROR(WARNING, E_INVALID_OPERATION, ("Master Only")); return; } tmpReg = GET_UINT32(p_Qm->p_QmRegs->err_isr); tmpReg &= GET_UINT32(p_Qm->p_QmRegs->err_ier); WRITE_UINT32(p_Qm->p_QmRegs->err_isr, tmpReg); if (tmpReg & QM_EX_CORENET_INITIATOR_DATA) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_INITIATOR_DATA); if (tmpReg & QM_EX_CORENET_TARGET_DATA) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_TARGET_DATA); if (tmpReg & QM_EX_CORENET_INVALID_TARGET_TRANSACTION) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_INVALID_TARGET_TRANSACTION); if (tmpReg & QM_EX_PFDR_THRESHOLD) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_PFDR_THRESHOLD); if (tmpReg & QM_EX_MULTI_ECC) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_MULTI_ECC); if (tmpReg & QM_EX_SINGLE_ECC) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_SINGLE_ECC); if (tmpReg & QM_EX_PFDR_ENQUEUE_BLOCKED) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_PFDR_ENQUEUE_BLOCKED); if (tmpReg & QM_EX_INVALID_COMMAND) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_INVALID_COMMAND); if (tmpReg & QM_EX_DEQUEUE_DCP) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_DCP); if (tmpReg & QM_EX_DEQUEUE_FQ) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_FQ); if (tmpReg & QM_EX_DEQUEUE_SOURCE) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_SOURCE); if (tmpReg & QM_EX_DEQUEUE_QUEUE) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_QUEUE); if (tmpReg & QM_EX_ENQUEUE_OVERFLOW) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_OVERFLOW); if (tmpReg & QM_EX_ENQUEUE_STATE) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_STATE); if (tmpReg & QM_EX_ENQUEUE_CHANNEL) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_CHANNEL); if (tmpReg & QM_EX_ENQUEUE_QUEUE) p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_QUEUE); } t_Error QM_SetException(t_Handle h_Qm, e_QmExceptions exception, bool enable) { t_Qm *p_Qm = (t_Qm*)h_Qm; t_Error err = E_OK; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE); if ((err = SetException(p_Qm, exception, enable)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); WRITE_UINT32(p_Qm->p_QmRegs->err_ier, p_Qm->exceptions); return E_OK; } t_Error QM_GetRevision(t_Handle h_Qm, t_QmRevisionInfo *p_QmRevisionInfo) { t_Qm *p_Qm = (t_Qm*)h_Qm; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_QmRevisionInfo, E_NULL_POINTER); return QmGetRevision(p_Qm, p_QmRevisionInfo); } t_Error QM_ReserveQueues(t_Handle h_Qm, t_QmRsrvFqrParams *p_QmFqrParams, uint32_t *p_BaseFqid) { t_Qm *p_Qm = (t_Qm*)h_Qm; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE); *p_BaseFqid = ReserveFqids(p_Qm, (uint32_t)((p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ? 1 : p_QmFqrParams->numOfFqids), p_QmFqrParams->qs.nonFrcQs.align, p_QmFqrParams->useForce, p_QmFqrParams->qs.frcQ.fqid); if (*p_BaseFqid == ILLEGAL_BASE) RETURN_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid")); return E_OK; } t_Error QM_GetErrorInformation(t_Handle h_Qm, t_QmErrorInfo *p_errInfo) { uint32_t ecsr, ecir; t_Qm *p_Qm = (t_Qm*)h_Qm; t_Error err = E_OK; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_errInfo, E_NULL_POINTER); ecsr = GET_UINT32(p_Qm->p_QmRegs->ecsr); ecir = GET_UINT32(p_Qm->p_QmRegs->ecir); if ((ecsr & QM_EX_MULTI_ECC) || (ecsr & QM_EX_SINGLE_ECC)) { err = E_NOT_SUPPORTED; REPORT_ERROR(INFO, E_NOT_SUPPORTED, ("single and multi ecc, use QM_DumpRegs")); } if ((ecsr & QM_EX_ENQUEUE_QUEUE) || (ecsr & QM_EX_ENQUEUE_STATE) || (ecsr & QM_EX_ENQUEUE_OVERFLOW) || (ecsr & QM_EX_DEQUEUE_DCP) || (ecsr & QM_EX_DEQUEUE_FQ) || (ecsr & QM_EX_DEQUEUE_QUEUE) || (ecsr & QM_EX_DEQUEUE_SOURCE) || (ecsr & QM_EX_INVALID_COMMAND)) { p_errInfo->portalValid = TRUE; p_errInfo->hwPortal = (bool)(ecir & ECIR_PORTAL_TYPE); if (p_errInfo->hwPortal) p_errInfo->dcpId = (e_DpaaDcPortal)((ecir & ECIR_PORTAL_MASK) >> ECIR_PORTAL_SHIFT); else p_errInfo->swPortalId = (e_DpaaSwPortal)((ecir & ECIR_PORTAL_MASK) >> ECIR_PORTAL_SHIFT); } if ((ecsr & QM_EX_ENQUEUE_QUEUE) || (ecsr & QM_EX_ENQUEUE_STATE) || (ecsr & QM_EX_ENQUEUE_OVERFLOW) || (ecsr & QM_EX_ENQUEUE_CHANNEL) || (ecsr & QM_EX_DEQUEUE_QUEUE) || (ecsr & QM_EX_DEQUEUE_FQ)) { p_errInfo->fqidValid = TRUE; p_errInfo->fqid = ((ecir & ECIR_FQID_MASK) >> ECIR_FQID_SHIFT); } WRITE_UINT32(p_Qm->p_QmRegs->ecsr, ecsr); return ERROR_CODE(err); } #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) t_Error QM_DumpRegs(t_Handle h_Qm) { t_Qm *p_Qm = (t_Qm *)h_Qm; uint8_t i = 0; DECLARE_DUMP; SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_STATE); DUMP_SUBTITLE(("\n")); DUMP_TITLE(p_Qm->p_QmRegs, ("QmRegs Regs")); DUMP_SUBSTRUCT_ARRAY(i, QM_NUM_OF_SWP) { DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], lio_cfg); DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], io_cfg); DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], dd_cfg); } DUMP_VAR(p_Qm->p_QmRegs, qman_dd_cfg); DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_ihrsr); DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_ihrfr); DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_hasr); DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_ihrsr); DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_ihrfr); DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_hasr); DUMP_SUBSTRUCT_ARRAY(i, QM_NUM_OF_DCP) { DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], cfg); DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dd_cfg); DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dlm_cfg); DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dlm_avg); } DUMP_VAR(p_Qm->p_QmRegs, pfdr_fpc); DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_head); DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_tail); DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_lwit); DUMP_VAR(p_Qm->p_QmRegs, pfdr_cfg); DUMP_VAR(p_Qm->p_QmRegs, sfdr_cfg); DUMP_VAR(p_Qm->p_QmRegs, sfdr_in_use); DUMP_ARR(p_Qm->p_QmRegs, wq_cs_cfg); DUMP_VAR(p_Qm->p_QmRegs, wq_def_enq_wqid); DUMP_ARR(p_Qm->p_QmRegs, wq_sc_dd_cfg); DUMP_ARR(p_Qm->p_QmRegs, wq_pc_dd_cs_cfg); DUMP_ARR(p_Qm->p_QmRegs, wq_dc0_dd_cs_cfg); DUMP_ARR(p_Qm->p_QmRegs, wq_dc1_dd_cs_cfg); DUMP_VAR(p_Qm->p_QmRegs, wq_dc2_dd_cs_cfg); DUMP_VAR(p_Qm->p_QmRegs, wq_dc3_dd_cs_cfg); DUMP_VAR(p_Qm->p_QmRegs, cm_cfg); DUMP_VAR(p_Qm->p_QmRegs, ecsr); DUMP_VAR(p_Qm->p_QmRegs, ecir); DUMP_VAR(p_Qm->p_QmRegs, eadr); DUMP_ARR(p_Qm->p_QmRegs, edata); DUMP_VAR(p_Qm->p_QmRegs, sbet); DUMP_ARR(p_Qm->p_QmRegs, sbec); DUMP_VAR(p_Qm->p_QmRegs, mcr); DUMP_VAR(p_Qm->p_QmRegs, mcp0); DUMP_VAR(p_Qm->p_QmRegs, mcp1); DUMP_ARR(p_Qm->p_QmRegs, mr); DUMP_VAR(p_Qm->p_QmRegs, idle_stat); DUMP_VAR(p_Qm->p_QmRegs, ip_rev_1); DUMP_VAR(p_Qm->p_QmRegs, ip_rev_2); DUMP_VAR(p_Qm->p_QmRegs, fqd_bare); DUMP_VAR(p_Qm->p_QmRegs, fqd_bar); DUMP_VAR(p_Qm->p_QmRegs, fqd_ar); DUMP_VAR(p_Qm->p_QmRegs, pfdr_bare); DUMP_VAR(p_Qm->p_QmRegs, pfdr_bar); DUMP_VAR(p_Qm->p_QmRegs, pfdr_ar); DUMP_VAR(p_Qm->p_QmRegs, qcsp_bare); DUMP_VAR(p_Qm->p_QmRegs, qcsp_bar); DUMP_VAR(p_Qm->p_QmRegs, ci_sched_cfg); DUMP_VAR(p_Qm->p_QmRegs, srcidr); DUMP_VAR(p_Qm->p_QmRegs, liodnr); DUMP_VAR(p_Qm->p_QmRegs, ci_rlm_cfg); DUMP_VAR(p_Qm->p_QmRegs, ci_rlm_avg); DUMP_VAR(p_Qm->p_QmRegs, err_isr); DUMP_VAR(p_Qm->p_QmRegs, err_ier); DUMP_VAR(p_Qm->p_QmRegs, err_isdr); DUMP_VAR(p_Qm->p_QmRegs, err_iir); DUMP_VAR(p_Qm->p_QmRegs, err_her); return E_OK; } #endif /* (defined(DEBUG_ERRORS) && ... */