diff options
Diffstat (limited to 'sys/contrib/ncsw/Peripherals/QM/qm.c')
-rw-r--r-- | sys/contrib/ncsw/Peripherals/QM/qm.c | 1266 |
1 files changed, 1266 insertions, 0 deletions
diff --git a/sys/contrib/ncsw/Peripherals/QM/qm.c b/sys/contrib/ncsw/Peripherals/QM/qm.c new file mode 100644 index 0000000..d1d7032 --- /dev/null +++ b/sys/contrib/ncsw/Peripherals/QM/qm.c @@ -0,0 +1,1266 @@ +/****************************************************************************** + + © 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 "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)); + + CORE_MemoryBarrier(); + 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); + + 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;i<p_Qm->partCgsBase+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;i<DPAA_MAX_NUM_OF_DC_PORTALS;i++) + p_Qm->p_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); + CORE_MemoryBarrier(); + for (i=0; i<dsSize; i+=64) + dcbf(PTR_MOVE(p_Qm->p_FqdBase, i)); + CORE_MemoryBarrier(); + + 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;i<DPAA_MAX_NUM_OF_DC_PORTALS;i++) + { + if(p_Qm->p_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) && ... */ |