1/******************************************************************************
2
3 � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4 All rights reserved.
5
6 This is proprietary source code of Freescale Semiconductor Inc.,
7 and its use is subject to the NetComm Device Drivers EULA.
8 The copyright notice above does not evidence any actual or intended
9 publication of such source code.
10
11 ALTERNATIVELY, redistribution and use in source and binary forms, with
12 or without modification, are permitted provided that the following
13 conditions are met:
14     * Redistributions of source code must retain the above copyright
15       notice, this list of conditions and the following disclaimer.
16     * Redistributions in binary form must reproduce the above copyright
17       notice, this list of conditions and the following disclaimer in the
18       documentation and/or other materials provided with the distribution.
19     * Neither the name of Freescale Semiconductor nor the
20       names of its contributors may be used to endorse or promote products
21       derived from this software without specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34
35 **************************************************************************/
36/******************************************************************************
37 @File          qm.c
38
39 @Description   QM & Portal implementation
40*//***************************************************************************/
41#include "error_ext.h"
42#include "std_ext.h"
43#include "string_ext.h"
44#include "sprint_ext.h"
45#include "mm_ext.h"
46#include "core_ext.h"
47#include "debug_ext.h"
48
49#include "qm.h"
50
51
52static volatile bool blockingFlag = FALSE;
53static void QmIpcMsgCompletionCB(t_Handle   h_Module,
54                                 uint8_t    *p_Msg,
55                                 uint8_t    *p_Reply,
56                                 uint32_t   replyLength,
57                                 t_Error    status)
58{
59    SANITY_CHECK_RETURN(h_Module, E_INVALID_HANDLE);
60
61    UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);UNUSED(h_Module);
62    blockingFlag = FALSE;
63}
64
65static t_Error QmHandleIpcMsgCB(t_Handle  h_Qm,
66                                uint8_t   *p_Msg,
67                                uint32_t  msgLength,
68                                uint8_t   *p_Reply,
69                                uint32_t  *p_ReplyLength)
70{
71    t_Qm            *p_Qm           = (t_Qm*)h_Qm;
72    t_QmIpcMsg      *p_IpcMsg       = (t_QmIpcMsg*)p_Msg;
73    t_QmIpcReply    *p_IpcReply   = (t_QmIpcReply *)p_Reply;
74
75    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
76    SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE);
77
78#ifdef DISABLE_SANITY_CHECKS
79    UNUSED(msgLength);
80#endif /* DISABLE_SANITY_CHECKS */
81
82    ASSERT_COND(p_IpcMsg);
83
84    memset(p_IpcReply, 0, (sizeof(uint8_t) * QM_IPC_MAX_REPLY_SIZE));
85    *p_ReplyLength = 0;
86
87    switch(p_IpcMsg->msgId)
88    {
89        case (QM_MASTER_IS_ALIVE):
90            *(uint8_t*)p_IpcReply->replyBody = 1;
91            *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
92            break;
93        case (QM_FORCE_FQID):
94        {
95            t_QmIpcFqidParams   ipcFqid;
96            uint32_t            fqid;
97
98            memcpy((uint8_t*)&ipcFqid, p_IpcMsg->msgBody, sizeof(t_QmIpcFqidParams));
99            fqid = QmFqidGet(p_Qm, ipcFqid.size, 1, TRUE, ipcFqid.fqid);
100            memcpy(p_IpcReply->replyBody, (uint8_t*)&fqid, sizeof(uint32_t));
101            *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
102            break;
103        }
104        case (QM_PUT_FQID):
105        {
106            t_Error             err;
107            t_QmIpcFqidParams   ipcFqid;
108
109            memcpy((uint8_t*)&ipcFqid, p_IpcMsg->msgBody, sizeof(t_QmIpcFqidParams));
110            if ((err = QmFqidPut(p_Qm, ipcFqid.fqid)) != E_OK)
111                REPORT_ERROR(MINOR, err, NO_MSG);
112            break;
113        }
114        case (QM_GET_COUNTER):
115        {
116            t_QmIpcGetCounter   ipcCounter;
117            uint32_t            count;
118
119            memcpy((uint8_t*)&ipcCounter, p_IpcMsg->msgBody, sizeof(t_QmIpcGetCounter));
120            count = QmGetCounter(p_Qm, (e_QmInterModuleCounters)ipcCounter.enumId);
121            memcpy(p_IpcReply->replyBody, (uint8_t*)&count, sizeof(uint32_t));
122            *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
123            break;
124        }
125        case (QM_GET_SET_PORTAL_PARAMS):
126        {
127            t_Error                         err;
128            t_QmIpcPortalInitParams         ipcPortalInitParams;
129            t_QmInterModulePortalInitParams portalInitParams;
130
131            memcpy((uint8_t*)&ipcPortalInitParams, p_IpcMsg->msgBody, sizeof(t_QmIpcPortalInitParams));
132            portalInitParams.portalId       = ipcPortalInitParams.portalId;
133            portalInitParams.stashDestQueue = ipcPortalInitParams.stashDestQueue;
134            portalInitParams.liodn          = ipcPortalInitParams.liodn;
135            portalInitParams.dqrrLiodn      = ipcPortalInitParams.dqrrLiodn;
136            portalInitParams.fdFqLiodn      = ipcPortalInitParams.fdFqLiodn;
137            if ((err = QmGetSetPortalParams(p_Qm, &portalInitParams)) != E_OK)
138                REPORT_ERROR(MINOR, err, NO_MSG);
139            break;
140        }
141        case (QM_GET_REVISION):
142        {
143            t_QmRevisionInfo    revInfo;
144            t_QmIpcRevisionInfo ipcRevInfo;
145
146            p_IpcReply->error = (uint32_t)QmGetRevision(h_Qm, &revInfo);
147            ipcRevInfo.majorRev = revInfo.majorRev;
148            ipcRevInfo.minorRev = revInfo.minorRev;
149            memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_QmIpcRevisionInfo));
150            *p_ReplyLength = sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo);
151            break;
152        }
153        default:
154            *p_ReplyLength = 0;
155            RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
156    }
157    return E_OK;
158}
159
160static t_Error CheckQmParameters(t_Qm *p_Qm)
161{
162    if ((p_Qm->p_QmDriverParams->partFqidBase + p_Qm->p_QmDriverParams->partNumOfFqids) > QM_MAX_NUM_OF_FQIDS)
163            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partFqidBase+partNumOfFqids out of range!!!"));
164    if ((p_Qm->partCgsBase + p_Qm->partNumOfCgs) > QM_MAX_NUM_OF_CGS)
165            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partCgsBase+partNumOfCgs out of range!!!"));
166
167    if (p_Qm->guestId == NCSW_MASTER_ID)
168    {
169        uint64_t            phyAddr;
170
171        phyAddr = XX_VirtToPhys(UINT_TO_PTR(p_Qm->p_QmDriverParams->swPortalsBaseAddress));
172
173        if (phyAddr & 0x00000000001fffffLL)
174            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("swPortalsBaseAddress isn't properly aligned"));
175        if (!p_Qm->p_QmDriverParams->rtFramesDepth)
176            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rtFramesDepth must be larger than '0'!!!"));
177        if (p_Qm->p_QmDriverParams->rtFramesDepth > ((16*MEGABYTE)*3))
178            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rtFramesDepth must be equal or smaller than 48MB!!!"));
179        if (!p_Qm->p_QmDriverParams->totalNumOfFqids)
180            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfFqids must be larger than '0'!!!"));
181        if (p_Qm->p_QmDriverParams->totalNumOfFqids > (16*MEGABYTE))
182            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfFqids must be equal or smaller than 16MB!!!"));
183        if(!p_Qm->f_Exception)
184            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided"));
185    }
186
187    return E_OK;
188}
189
190static t_Error QmInitPfdr(t_Qm *p_Qm, uint32_t pfdr_start, uint32_t num)
191{
192    uint8_t     rslt;
193    uint32_t    timeout = 100000;
194
195    ASSERT_COND(p_Qm);
196
197    ASSERT_COND(pfdr_start && !(pfdr_start & 7) && !(num & 7) && num);
198
199    /* Make sure te command interface is 'idle' */
200    rslt = MCR_get_rslt(GET_UINT32(p_Qm->p_QmRegs->mcr));
201    if (!MCR_rslt_idle(rslt))
202        RETURN_ERROR(CRITICAL,E_INVALID_STATE,("QMAN_MCR isn't idle"));
203
204    /* Write the MCR command params then the verb */
205    WRITE_UINT32(p_Qm->p_QmRegs->mcp0, pfdr_start);
206    /* TODO: remove this - it's a workaround for a model bug that is
207     * corrected in more recent versions. We use the workaround until
208     * everyone has upgraded. */
209    WRITE_UINT32(p_Qm->p_QmRegs->mcp1, (pfdr_start + num - 16));
210    WRITE_UINT32(p_Qm->p_QmRegs->mcp1, (pfdr_start + num - 1));
211
212    CORE_MemoryBarrier();
213    WRITE_UINT32(p_Qm->p_QmRegs->mcr, MCR_INIT_PFDR);
214
215    /* Poll for the result */
216    do {
217        XX_UDelay(1);
218        rslt = MCR_get_rslt(GET_UINT32(p_Qm->p_QmRegs->mcr));
219    } while(!MCR_rslt_idle(rslt) && --timeout);
220
221    if (MCR_rslt_ok(rslt))
222        return E_OK;
223    WRITE_UINT32(p_Qm->p_QmRegs->mcr, 0);
224    if (!timeout)
225        RETURN_ERROR(MAJOR, E_TIMEOUT, NO_MSG);
226    if (MCR_rslt_eaccess(rslt))
227        RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
228    if (MCR_rslt_inval(rslt))
229        RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
230    RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unexpected result from MCR_INIT_PFDR: %02x\n", rslt));
231}
232
233static __inline__ void QmSetWqScheduling(t_Qm *p_Qm,
234                                         e_QmWqClass wqClass,
235                                         uint8_t csElev,
236                                         uint8_t csw2,
237                                         uint8_t csw3,
238                                         uint8_t csw4,
239                                         uint8_t csw5,
240                                         uint8_t csw6,
241                                         uint8_t csw7)
242{
243    ASSERT_COND(p_Qm);
244
245    WRITE_UINT32(p_Qm->p_QmRegs->wq_cs_cfg[wqClass],
246                 (uint32_t)(((csElev & 0xff) << 24) |
247                 ((csw2 & 0x7) << 20) |
248                 ((csw3 & 0x7) << 16) |
249                 ((csw4 & 0x7) << 12) |
250                 ((csw5 & 0x7) << 8) |
251                 ((csw6 & 0x7) << 4) |
252                 (csw7 & 0x7)));
253}
254
255static uint32_t ReserveFqids(t_Qm *p_Qm, uint32_t size, uint32_t alignment, bool force, uint32_t base)
256{
257    uint64_t    ans;
258    uint32_t    intFlags;
259
260    intFlags = XX_LockIntrSpinlock(p_Qm->lock);
261    if (force)
262        ans = MM_GetForce(p_Qm->h_FqidMm,
263                          (uint64_t)base,
264                          (uint64_t)size,
265                          "QM FQID MEM");
266    else
267        ans = MM_Get(p_Qm->h_FqidMm,
268                     (uint64_t)size,
269                     alignment,
270                     "QM FQID MEM");
271    if (ans == ILLEGAL_BASE)
272    {
273        XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
274        return (uint32_t)ans;
275    }
276    base = (uint32_t)ans;
277    ans = MM_GetForce(p_Qm->h_RsrvFqidMm,
278                      (uint64_t)base,
279                      (uint64_t)size,
280                      "QM rsrv FQID MEM");
281    if (ans == ILLEGAL_BASE)
282    {
283        MM_Put(p_Qm->h_FqidMm, (uint64_t)base);
284        XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
285        return (uint32_t)ans;
286    }
287    XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
288
289    return (uint32_t)base;
290}
291
292static void FreeInitResources(t_Qm *p_Qm)
293{
294    if (p_Qm->p_FqdBase)
295        XX_FreeSmart(p_Qm->p_FqdBase);
296    if (p_Qm->p_PfdrBase)
297        XX_FreeSmart(p_Qm->p_PfdrBase);
298    if (p_Qm->h_Session)
299        XX_IpcFreeSession(p_Qm->h_Session);
300    if (p_Qm->h_RsrvFqidMm)
301        MM_Free(p_Qm->h_RsrvFqidMm);
302    if (p_Qm->h_FqidMm)
303        MM_Free(p_Qm->h_FqidMm);
304}
305
306
307/****************************************/
308/*       Inter-Module functions         */
309/****************************************/
310
311uint32_t QmGetCounter(t_Handle h_Qm, e_QmInterModuleCounters counter)
312{
313    t_Qm *p_Qm = (t_Qm*)h_Qm;
314
315    SANITY_CHECK_RETURN_VALUE(p_Qm, E_INVALID_HANDLE, 0);
316    SANITY_CHECK_RETURN_VALUE((((p_Qm->guestId == NCSW_MASTER_ID) && p_Qm->p_QmRegs) ||
317                               (p_Qm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE, 0);
318
319    if ((p_Qm->guestId == NCSW_MASTER_ID) ||
320        (!p_Qm->h_Session && p_Qm->p_QmRegs))
321    {
322        switch(counter)
323        {
324            case(e_QM_IM_COUNTERS_SFDR_IN_USE):
325                return GET_UINT32(p_Qm->p_QmRegs->sfdr_in_use);
326            case(e_QM_IM_COUNTERS_PFDR_IN_USE):
327                return (p_Qm->numOfPfdr - GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc));
328            case(e_QM_IM_COUNTERS_PFDR_FREE_POOL):
329                return (GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc) - GET_UINT32(p_Qm->p_QmRegs->pfdr_cfg));
330            default:
331                break;
332        }
333        /* should never get here */
334        ASSERT_COND(FALSE);
335    }
336    else if (p_Qm->h_Session)
337    {
338        t_QmIpcMsg              msg;
339        t_QmIpcReply            reply;
340        t_QmIpcGetCounter       ipcCounter;
341        uint32_t                replyLength, count;
342        t_Error                 errCode = E_OK;
343
344        memset(&msg, 0, sizeof(t_QmIpcMsg));
345        memset(&reply, 0, sizeof(t_QmIpcReply));
346        ipcCounter.enumId       = (uint32_t)counter;
347        msg.msgId               = QM_GET_COUNTER;
348        memcpy(msg.msgBody, &ipcCounter, sizeof(t_QmIpcGetCounter));
349        replyLength = sizeof(uint32_t) + sizeof(uint32_t);
350        if ((errCode = XX_IpcSendMessage(p_Qm->h_Session,
351                                         (uint8_t*)&msg,
352                                         sizeof(msg.msgId) + sizeof(t_QmIpcGetCounter),
353                                         (uint8_t*)&reply,
354                                         &replyLength,
355                                         NULL,
356                                         NULL)) != E_OK)
357            REPORT_ERROR(MAJOR, errCode, NO_MSG);
358        if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
359            REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
360        if ((errCode == E_OK) && (replyLength == (sizeof(uint32_t) + sizeof(uint32_t))))
361        {
362            memcpy((uint8_t*)&count, reply.replyBody, sizeof(uint32_t));
363            return count;
364        }
365    }
366    else
367        REPORT_ERROR(WARNING, E_NOT_SUPPORTED,
368                     ("In 'guest', either IPC or 'baseAddress' is required!"));
369
370    return 0;
371}
372
373t_Error QmGetRevision(t_Handle h_Qm, t_QmRevisionInfo *p_QmRevisionInfo)
374{
375    t_Qm        *p_Qm = (t_Qm *)h_Qm;
376    uint32_t    tmpReg;
377
378    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
379    SANITY_CHECK_RETURN_ERROR(p_QmRevisionInfo, E_NULL_POINTER);
380    SANITY_CHECK_RETURN_ERROR((((p_Qm->guestId == NCSW_MASTER_ID) && p_Qm->p_QmRegs) ||
381                               (p_Qm->guestId != NCSW_MASTER_ID)), E_INVALID_STATE);
382
383    if ((p_Qm->guestId == NCSW_MASTER_ID) ||
384        (!p_Qm->h_Session && p_Qm->p_QmRegs))
385    {
386        /* read revision register 1 */
387        tmpReg = GET_UINT32(p_Qm->p_QmRegs->ip_rev_1);
388        p_QmRevisionInfo->majorRev = (uint8_t)((tmpReg & REV1_MAJOR_MASK) >> REV1_MAJOR_SHIFT);
389        p_QmRevisionInfo->minorRev = (uint8_t)((tmpReg & REV1_MINOR_MASK) >> REV1_MINOR_SHIFT);
390    }
391    else if (p_Qm->h_Session)
392    {
393        t_QmIpcMsg          msg;
394        t_QmIpcReply        reply;
395        t_QmIpcRevisionInfo ipcRevInfo;
396        uint32_t            replyLength;
397        t_Error             errCode = E_OK;
398
399        memset(&msg, 0, sizeof(t_QmIpcMsg));
400        memset(&reply, 0, sizeof(reply));
401        msg.msgId           = QM_GET_REVISION;
402        replyLength = sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo);
403        if ((errCode = XX_IpcSendMessage(p_Qm->h_Session,
404                                         (uint8_t*)&msg,
405                                         sizeof(msg.msgId),
406                                         (uint8_t*)&reply,
407                                         &replyLength,
408                                         NULL,
409                                         NULL)) != E_OK)
410            RETURN_ERROR(MAJOR, errCode, NO_MSG);
411        if (replyLength != (sizeof(uint32_t) + sizeof(t_QmIpcRevisionInfo)))
412            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
413
414        memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_QmIpcRevisionInfo));
415        p_QmRevisionInfo->majorRev = ipcRevInfo.majorRev;
416        p_QmRevisionInfo->minorRev = ipcRevInfo.minorRev;
417
418        return (t_Error)(reply.error);
419    }
420    else
421        RETURN_ERROR(WARNING, E_NOT_SUPPORTED,
422                     ("In 'guest', either IPC or 'baseAddress' is required!"));
423
424    return E_OK;
425}
426
427t_Error QmGetSetPortalParams(t_Handle h_Qm, t_QmInterModulePortalInitParams *p_PortalParams)
428{
429    t_Qm                *p_Qm = (t_Qm *)h_Qm;
430    t_QmRevisionInfo    revInfo;
431    uint32_t            lioReg,ioReg;
432
433    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
434    SANITY_CHECK_RETURN_ERROR(p_PortalParams, E_NULL_POINTER);
435
436    if (p_Qm->guestId == NCSW_MASTER_ID)
437    {
438        QmGetRevision(p_Qm, &revInfo);
439
440        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
441        {
442            lioReg  = (uint32_t)(p_PortalParams->stashDestQueue << 24) |
443                      (p_PortalParams->liodn << 16) |
444                      (p_PortalParams->dqrrLiodn);
445            ioReg   = (p_PortalParams->fdFqLiodn);
446        }
447        else
448        {
449            lioReg  = (uint32_t)(p_PortalParams->liodn << 16) |
450                      (p_PortalParams->dqrrLiodn);
451            ioReg   = (uint32_t)(p_PortalParams->stashDestQueue << 16) |
452                      (p_PortalParams->fdFqLiodn);
453        }
454
455        WRITE_UINT32(p_Qm->p_QmRegs->swpConfRegs[p_PortalParams->portalId].lio_cfg, lioReg);
456        WRITE_UINT32(p_Qm->p_QmRegs->swpConfRegs[p_PortalParams->portalId].io_cfg, ioReg);
457    }
458    else if (p_Qm->h_Session)
459    {
460        t_QmIpcMsg                  msg;
461        t_QmIpcPortalInitParams     portalParams;
462        t_Error                     errCode;
463
464        memset(&msg, 0, sizeof(t_QmIpcMsg));
465        portalParams.portalId       = p_PortalParams->portalId;
466        portalParams.stashDestQueue = p_PortalParams->stashDestQueue;
467        portalParams.liodn          = p_PortalParams->liodn;
468        portalParams.dqrrLiodn      = p_PortalParams->dqrrLiodn;
469        portalParams.fdFqLiodn      = p_PortalParams->fdFqLiodn;
470        msg.msgId           = QM_GET_SET_PORTAL_PARAMS;
471        memcpy(msg.msgBody, &portalParams, sizeof(t_QmIpcPortalInitParams));
472        XX_LockSpinlock(p_Qm->lock);
473        if ((errCode = XX_IpcSendMessage(p_Qm->h_Session,
474                                         (uint8_t*)&msg,
475                                         sizeof(msg.msgId) + sizeof(t_QmIpcPortalInitParams),
476                                         NULL,
477                                         NULL,
478                                         NULL,
479                                         NULL)) != E_OK)
480        {
481            XX_UnlockSpinlock(p_Qm->lock);
482            RETURN_ERROR(MAJOR, errCode, NO_MSG);
483        }
484        XX_UnlockSpinlock(p_Qm->lock);
485    }
486    else
487        DBG(WARNING, ("Can't set portal parameters (e.g. liodns). " \
488                      "probably QM is running in guest-mode with no IPC!"));
489
490    return E_OK;
491}
492
493uint32_t QmFqidGet(t_Qm *p_Qm, uint32_t size, uint32_t alignment, bool force, uint32_t base)
494{
495    uint64_t    ans;
496    uint32_t    intFlags;
497
498    intFlags = XX_LockIntrSpinlock(p_Qm->lock);
499    if (force)
500    {
501        ans = MM_GetForce(p_Qm->h_FqidMm,
502                          (uint64_t)base,
503                          (uint64_t)size,
504                          "QM FQID MEM");
505        if (ans == ILLEGAL_BASE)
506        {
507            ans = MM_GetForce(p_Qm->h_RsrvFqidMm,
508                              (uint64_t)base,
509                              (uint64_t)size,
510                              "QM rsrv FQID MEM");
511            if (ans == ILLEGAL_BASE)
512                ans = base;
513            else if (p_Qm->h_Session)
514            {
515                t_QmIpcMsg              msg;
516                t_QmIpcReply            reply;
517                uint32_t                replyLength;
518                t_QmIpcFqidParams       ipcFqid;
519                t_Error                 errCode = E_OK;
520
521                memset(&msg, 0, sizeof(t_QmIpcMsg));
522                memset(&reply, 0, sizeof(t_QmIpcReply));
523                ipcFqid.fqid        = base;
524                ipcFqid.size        = size;
525                msg.msgId           = QM_FORCE_FQID;
526                memcpy(msg.msgBody, &ipcFqid, sizeof(t_QmIpcFqidParams));
527                replyLength = sizeof(uint32_t) + sizeof(uint32_t);
528                if ((errCode = XX_IpcSendMessage(p_Qm->h_Session,
529                                                 (uint8_t*)&msg,
530                                                 sizeof(msg.msgId) + sizeof(t_QmIpcFqidParams),
531                                                 (uint8_t*)&reply,
532                                                 &replyLength,
533                                                 NULL,
534                                                 NULL)) != E_OK)
535                    REPORT_ERROR(MAJOR, errCode, NO_MSG);
536                if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
537                   REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
538
539                if ((errCode != E_OK) ||
540                    (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))))
541                    ans = ILLEGAL_BASE;
542                else
543                    memcpy((uint8_t*)&ans, reply.replyBody, sizeof(uint32_t));
544            }
545            else
546            {
547                DBG(WARNING, ("No Ipc - can't validate fqid."));
548                ans = base;
549            }
550        }
551    }
552    else
553        ans = MM_Get(p_Qm->h_FqidMm,
554                     size,
555                     alignment,
556                     "QM FQID MEM");
557    XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
558
559    return (uint32_t)ans;
560}
561
562t_Error QmFqidPut(t_Qm *p_Qm, uint32_t base)
563{
564    uint32_t    intFlags;
565
566    intFlags = XX_LockIntrSpinlock(p_Qm->lock);
567    /* Check maybe this fqid was reserved in the past */
568    if (MM_GetForce(p_Qm->h_RsrvFqidMm,
569                    (uint64_t)base,
570                    (uint64_t)1,
571                    "QM rsrv FQID MEM") == ILLEGAL_BASE)
572    {
573        XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
574        return E_OK;
575    }
576    else
577        MM_PutForce(p_Qm->h_RsrvFqidMm,
578                    (uint64_t)base,
579                    (uint64_t)1);
580    if (MM_InRange(p_Qm->h_FqidMm, (uint64_t)base))
581    {
582        if (MM_Put(p_Qm->h_FqidMm, (uint64_t)base) != 0)
583        {
584            XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
585            return E_OK;
586        }
587        else
588        {
589            XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
590            return ERROR_CODE(E_NOT_FOUND);
591        }
592    }
593    else if (p_Qm->h_Session)
594    {
595        t_QmIpcMsg              msg;
596        t_QmIpcFqidParams       ipcFqid;
597        t_Error                 errCode = E_OK;
598
599        memset(&msg, 0, sizeof(t_QmIpcMsg));
600        ipcFqid.fqid        = (uint8_t)base;
601        ipcFqid.size        = 0;
602        msg.msgId           = QM_PUT_FQID;
603        memcpy(msg.msgBody, &ipcFqid, sizeof(t_QmIpcFqidParams));
604        if ((errCode = XX_IpcSendMessage(p_Qm->h_Session,
605                                         (uint8_t*)&msg,
606                                         sizeof(msg.msgId) + sizeof(t_QmIpcFqidParams),
607                                         NULL,
608                                         NULL,
609                                         NULL,
610                                         NULL)) != E_OK)
611        {
612            XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
613            RETURN_ERROR(MAJOR, errCode, NO_MSG);
614        }
615    }
616    else
617        DBG(WARNING, ("No Ipc - can't validate fqid."));
618    XX_UnlockIntrSpinlock(p_Qm->lock, intFlags);
619
620    return E_OK;
621}
622
623t_Error QmGetCgId(t_Handle h_Qm, uint8_t *p_CgId)
624{
625    t_Qm        *p_Qm = (t_Qm *)h_Qm;
626    uint16_t    i;
627
628    for(i = p_Qm->partCgsBase;i<p_Qm->partCgsBase+p_Qm->partNumOfCgs;i++)
629        if (!p_Qm->cgsUsed[i])
630        {
631            p_Qm->cgsUsed[i] = (uint8_t)TRUE;
632            *p_CgId = (uint8_t)i;
633            break;
634        }
635    if(i == (p_Qm->partCgsBase+p_Qm->partNumOfCgs))
636        RETURN_ERROR(MINOR, E_BUSY, ("No available CG"));
637    else
638        return E_OK;
639}
640
641t_Error QmFreeCgId(t_Handle h_Qm, uint8_t cgId)
642{
643    t_Qm        *p_Qm = (t_Qm *)h_Qm;
644
645    if (!p_Qm->cgsUsed[cgId])
646        RETURN_ERROR(MINOR, E_INVALID_STATE, ("CG is not in use"));
647    else
648        p_Qm->cgsUsed[cgId] = (uint8_t)FALSE;
649
650    return E_OK;
651}
652
653
654/****************************************/
655/*       API Init unit functions        */
656/****************************************/
657
658t_Handle QM_Config(t_QmParam *p_QmParam)
659{
660    t_Qm    *p_Qm;
661    uint8_t i;
662
663    SANITY_CHECK_RETURN_VALUE(p_QmParam, E_INVALID_HANDLE, NULL);
664
665    p_Qm = (t_Qm *)XX_Malloc(sizeof(t_Qm));
666    if (!p_Qm)
667    {
668        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM obj!!!"));
669        return NULL;
670    }
671    memset(p_Qm, 0, sizeof(t_Qm));
672    p_Qm->p_QmDriverParams = (t_QmDriverParams *)XX_Malloc(sizeof(t_QmDriverParams));
673    if (!p_Qm->p_QmDriverParams)
674    {
675        XX_Free(p_Qm);
676        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm driver parameters"));
677        return NULL;
678    }
679    memset(p_Qm->p_QmDriverParams, 0, sizeof(t_QmDriverParams));
680
681    p_Qm->guestId                           = p_QmParam->guestId;
682    p_Qm->p_QmDriverParams->partFqidBase    = p_QmParam->partFqidBase;
683    p_Qm->p_QmDriverParams->partNumOfFqids  = p_QmParam->partNumOfFqids;
684    p_Qm->partCgsBase                       = p_QmParam->partCgsBase;
685    p_Qm->partNumOfCgs                      = p_QmParam->partNumOfCgs;
686    p_Qm->p_QmRegs                          = (t_QmRegs *)UINT_TO_PTR(p_QmParam->baseAddress);
687
688    if (p_Qm->guestId == NCSW_MASTER_ID)
689    {
690        p_Qm->exceptions        = DEFAULT_exceptions;
691        p_Qm->f_Exception       = p_QmParam->f_Exception;
692        p_Qm->h_App             = p_QmParam->h_App;
693        p_Qm->errIrq            = p_QmParam->errIrq;
694        p_Qm->p_QmDriverParams->liodn                   = p_QmParam->liodn;
695        p_Qm->p_QmDriverParams->rtFramesDepth           = DEFAULT_rtFramesDepth;
696        p_Qm->p_QmDriverParams->fqdMemPartitionId       = p_QmParam->fqdMemPartitionId;
697        p_Qm->p_QmDriverParams->pfdrMemPartitionId      = p_QmParam->pfdrMemPartitionId;
698        p_Qm->p_QmDriverParams->swPortalsBaseAddress    = p_QmParam->swPortalsBaseAddress;
699        p_Qm->p_QmDriverParams->totalNumOfFqids         = p_QmParam->totalNumOfFqids;
700        p_Qm->p_QmDriverParams->pfdrThreshold           = DEFAULT_pfdrThreshold;
701        p_Qm->p_QmDriverParams->sfdrThreshold           = DEFAULT_sfdrThreshold;
702        p_Qm->p_QmDriverParams->pfdrBaseConstant        = DEFAULT_pfdrBaseConstant;
703        for(i= 0;i<DPAA_MAX_NUM_OF_DC_PORTALS;i++)
704            p_Qm->p_QmDriverParams->dcPortalsParams[i].sendToSw =
705                (bool)((i < e_DPAA_DCPORTAL2) ? FALSE : TRUE);
706
707#ifdef QMAN_SFDR_LEAK_ERRATA_QMAN5
708        {
709#define WORKAROUND_TMP_VAL  0x00000003
710        t_QmRevisionInfo revInfo;
711        QmGetRevision(p_Qm, &revInfo);
712        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
713        {
714            uint32_t *tmp = (uint32_t *)UINT_TO_PTR(p_QmParam->baseAddress + 0xbf0);
715            uint32_t tmpReg = WORKAROUND_TMP_VAL;
716            WRITE_UINT32(*tmp, tmpReg);
717            while ((tmpReg = GET_UINT32(*tmp)) != WORKAROUND_TMP_VAL) ;
718        }
719        }
720#endif /* QMAN_SFDR_LEAK_ERRATA_QMAN5 */
721    }
722
723    /* build the QM partition IPC address */
724    memset(p_Qm->moduleName, 0, MODULE_NAME_SIZE);
725    if(Sprint (p_Qm->moduleName, "QM_0_%d",p_Qm->guestId) != (p_Qm->guestId<10 ? 6:7))
726    {
727        XX_Free(p_Qm->p_QmDriverParams);
728        XX_Free(p_Qm);
729        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
730        return NULL;
731    }
732
733    return p_Qm;
734}
735
736t_Error QM_Init(t_Handle h_Qm)
737{
738    t_Qm                *p_Qm = (t_Qm *)h_Qm;
739    t_QmDriverParams    *p_QmDriverParams;
740    t_Error             err;
741
742    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
743    SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE);
744
745    CHECK_INIT_PARAMETERS(p_Qm, CheckQmParameters);
746
747    p_QmDriverParams        = p_Qm->p_QmDriverParams;
748
749    if (p_QmDriverParams->partNumOfFqids)
750    {
751        if (MM_Init(&p_Qm->h_FqidMm, p_QmDriverParams->partFqidBase, p_QmDriverParams->partNumOfFqids) != E_OK)
752            RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("QM-FQIDS-MEM partition!!!"));
753        if (MM_Init(&p_Qm->h_RsrvFqidMm, p_QmDriverParams->partFqidBase, p_QmDriverParams->partNumOfFqids) != E_OK)
754            RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("QM-Reserve-FQIDS-MEM partition!!!"));
755    }
756
757    if (p_Qm->guestId == NCSW_MASTER_ID)
758    {
759        uint64_t            phyAddr;
760        t_QmRevisionInfo    revInfo;
761        uint32_t            dsSize, exp, i;
762
763        QmGetRevision(p_Qm, &revInfo);
764        DBG(TRACE, ("Qman ver:%02x,%02x", revInfo.majorRev, revInfo.minorRev));
765
766        phyAddr = XX_VirtToPhys(UINT_TO_PTR(p_QmDriverParams->swPortalsBaseAddress));
767        WRITE_UINT32(p_Qm->p_QmRegs->qcsp_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff));
768        WRITE_UINT32(p_Qm->p_QmRegs->qcsp_bar, (uint32_t)phyAddr);
769        WRITE_UINT32(p_Qm->p_QmRegs->liodnr, (uint16_t)p_QmDriverParams->liodn);
770
771        /* FQD memory */
772        dsSize = (uint32_t)(p_QmDriverParams->totalNumOfFqids * FQD_ENTRY_SIZE);
773        LOG2(dsSize, exp);
774        if (!POWER_OF_2(dsSize)) (exp++);
775        dsSize = (uint32_t)(1 << exp);
776        if (dsSize < (4*KILOBYTE))
777        {
778            dsSize = (4*KILOBYTE);
779            LOG2(dsSize, exp);
780        }
781        p_Qm->p_FqdBase = XX_MallocSmart(dsSize, (int)p_QmDriverParams->fqdMemPartitionId, dsSize);
782        if (!p_Qm->p_FqdBase)
783        {
784            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQD obj!!!"));
785        }
786        memset(p_Qm->p_FqdBase, 0, dsSize);
787        CORE_MemoryBarrier();
788        for (i=0; i<dsSize; i+=64)
789            dcbf(PTR_MOVE(p_Qm->p_FqdBase, i));
790        CORE_MemoryBarrier();
791
792        phyAddr = XX_VirtToPhys(p_Qm->p_FqdBase);
793        WRITE_UINT32(p_Qm->p_QmRegs->fqd_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff));
794        WRITE_UINT32(p_Qm->p_QmRegs->fqd_bar, (uint32_t)phyAddr);
795        WRITE_UINT32(p_Qm->p_QmRegs->fqd_ar, AR_ENABLE | (exp - 1));
796
797        /* PFDR memory */
798        dsSize = (uint32_t)(p_QmDriverParams->rtFramesDepth * (PFDR_ENTRY_SIZE/3));
799        LOG2(dsSize, exp);
800        if (!POWER_OF_2(dsSize)) (exp++);
801        dsSize = (uint32_t)(1 << exp);
802        if (dsSize < (4*KILOBYTE))
803        {
804            dsSize = (4*KILOBYTE);
805            LOG2(dsSize, exp);
806        }
807
808        p_Qm->p_PfdrBase = XX_MallocSmart(dsSize, (int)p_QmDriverParams->pfdrMemPartitionId, dsSize);
809        if (!p_Qm->p_PfdrBase)
810            RETURN_ERROR(MAJOR, E_NO_MEMORY, ("PFDR obj!!!"));
811
812        phyAddr = XX_VirtToPhys(p_Qm->p_PfdrBase);
813        WRITE_UINT32(p_Qm->p_QmRegs->pfdr_bare, ((uint32_t)(phyAddr >> 32) & 0x000000ff));
814        WRITE_UINT32(p_Qm->p_QmRegs->pfdr_bar, (uint32_t)phyAddr);
815        WRITE_UINT32(p_Qm->p_QmRegs->pfdr_ar, AR_ENABLE | (exp - 1));
816
817        if (QmInitPfdr(p_Qm, 8, dsSize / 64 - 8) != E_OK)
818            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PFDR init failed!!!"));
819
820        /* thresholds */
821        WRITE_UINT32(p_Qm->p_QmRegs->pfdr_fp_lwit, (p_Qm->p_QmDriverParams->pfdrThreshold & 0xffffff));
822        WRITE_UINT32(p_Qm->p_QmRegs->pfdr_cfg, p_Qm->p_QmDriverParams->pfdrBaseConstant);
823        WRITE_UINT32(p_Qm->p_QmRegs->sfdr_cfg, (p_Qm->p_QmDriverParams->sfdrThreshold & 0x3ff));
824
825        p_Qm->numOfPfdr = GET_UINT32(p_Qm->p_QmRegs->pfdr_fpc);
826
827        /* corenet initiator settings */
828        WRITE_UINT32(p_Qm->p_QmRegs->ci_sched_cfg,
829                     (CI_SCHED_CFG_EN |
830                     (DEFAULT_initiatorSrcciv << CI_SCHED_CFG_SRCCIV_SHIFT) |
831                     (DEFAULT_initiatorSrqW << CI_SCHED_CFG_SRQ_W_SHIFT) |
832                     (DEFAULT_initiatorRwW << CI_SCHED_CFG_RW_W_SHIFT) |
833                     (DEFAULT_initiatorBmanW << CI_SCHED_CFG_BMAN_W_SHIFT)));
834
835        /* HID settings */
836        if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
837            /* offset 0x0bf0 */
838            WRITE_UINT32(p_Qm->p_QmRegs->res23[144], 0x3);
839        else
840            WRITE_UINT32(p_Qm->p_QmRegs->res23[144], 0x0);
841
842        for(i=0;i<DPAA_MAX_NUM_OF_DC_PORTALS;i++)
843        {
844            if(p_Qm->p_QmDriverParams->dcPortalsParams[i].sendToSw)
845                WRITE_UINT32(p_Qm->p_QmRegs->dcpConfRegs[i].cfg,
846                    p_Qm->p_QmDriverParams->dcPortalsParams[i].swPortalId);
847            else
848                WRITE_UINT32(p_Qm->p_QmRegs->dcpConfRegs[i].cfg, QM_DCP_CFG_ED);
849        }
850
851#ifdef QMAN_WQ_CS_CFG_ERRATA_QMAN4
852        {
853            t_QmRevisionInfo revInfo;
854            QmGetRevision(p_Qm, &revInfo);
855            if ((revInfo.majorRev == 1) && (revInfo.minorRev == 0))
856            {
857                QmSetWqScheduling(p_Qm, e_QM_WQ_SW_PORTALS,0,1,1,1,1,1,1);
858                QmSetWqScheduling(p_Qm, e_QM_WQ_POOLS,0,1,1,1,1,1,1);
859                QmSetWqScheduling(p_Qm, e_QM_WQ_DCP0,0,1,1,1,1,1,1);
860                QmSetWqScheduling(p_Qm, e_QM_WQ_DCP1,0,1,1,1,1,1,1);
861                QmSetWqScheduling(p_Qm, e_QM_WQ_DCP2,0,1,1,1,1,1,1);
862                QmSetWqScheduling(p_Qm, e_QM_WQ_DCP3,0,1,1,1,1,1,1);
863            }
864        }
865#endif /* QMAN_WQ_CS_CFG_ERRATA_QMAN4 */
866
867        WRITE_UINT32(p_Qm->p_QmRegs->err_isr, p_Qm->exceptions);
868        WRITE_UINT32(p_Qm->p_QmRegs->err_ier, p_Qm->exceptions);
869        WRITE_UINT32(p_Qm->p_QmRegs->err_isdr, 0x0);
870        if (p_Qm->errIrq != NO_IRQ)
871        {
872            XX_SetIntr(p_Qm->errIrq, QM_ErrorIsr, p_Qm);
873            XX_EnableIntr(p_Qm->errIrq);
874        }
875        if ((err = XX_IpcRegisterMsgHandler(p_Qm->moduleName, QmHandleIpcMsgCB, p_Qm, QM_IPC_MAX_REPLY_SIZE)) != E_OK)
876            RETURN_ERROR(MAJOR, err, NO_MSG);
877    }
878    else /* guest mode */
879    {
880        char                    masterModuleName[MODULE_NAME_SIZE];
881
882        memset(masterModuleName, 0, MODULE_NAME_SIZE);
883        if(Sprint (masterModuleName, "QM_0_%d", NCSW_MASTER_ID) != (NCSW_MASTER_ID<10 ? 6:7))
884        {
885            RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
886        }
887
888        p_Qm->h_Session     = XX_IpcInitSession(masterModuleName, p_Qm->moduleName);
889        if (p_Qm->h_Session)
890        {
891            t_QmIpcMsg              msg;
892            uint8_t                 isMasterAlive = 0;
893            t_QmIpcReply            reply;
894            uint32_t                replyLength;
895
896            memset(&msg, 0, sizeof(t_QmIpcMsg));
897            memset(&reply, 0, sizeof(t_QmIpcReply));
898            msg.msgId   = QM_MASTER_IS_ALIVE;
899            do
900            {
901                blockingFlag = TRUE;
902                replyLength = sizeof(uint32_t) + sizeof(uint8_t);
903                if ((err = XX_IpcSendMessage(p_Qm->h_Session,
904                                             (uint8_t*)&msg,
905                                             sizeof(msg.msgId),
906                                             (uint8_t*)&reply,
907                                             &replyLength,
908                                             QmIpcMsgCompletionCB,
909                                             p_Qm)) != E_OK)
910                    REPORT_ERROR(MAJOR, err, NO_MSG);
911                while(blockingFlag) ;
912                if(replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
913                    REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
914                isMasterAlive = *(uint8_t*)(reply.replyBody);
915            } while (!isMasterAlive);
916        }
917    }
918
919    p_Qm->lock = XX_InitSpinlock();
920    XX_Free(p_Qm->p_QmDriverParams);
921    p_Qm->p_QmDriverParams = NULL;
922
923    return E_OK;
924}
925
926t_Error QM_Free(t_Handle h_Qm)
927{
928    t_Qm        *p_Qm = (t_Qm *)h_Qm;
929
930    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
931
932    if (p_Qm->lock)
933        XX_FreeSpinlock(p_Qm->lock);
934
935    if (p_Qm->guestId == NCSW_MASTER_ID)
936    {
937        XX_IpcUnregisterMsgHandler(p_Qm->moduleName);
938        if (p_Qm->errIrq  != NO_IRQ)
939        {
940            XX_DisableIntr(p_Qm->errIrq);
941            XX_FreeIntr(p_Qm->errIrq);
942        }
943    }
944    FreeInitResources(p_Qm);
945
946    if (p_Qm->p_QmDriverParams)
947        XX_Free(p_Qm->p_QmDriverParams);
948
949    XX_Free(p_Qm);
950
951    return E_OK;
952}
953
954t_Error QM_ConfigRTFramesDepth(t_Handle h_Qm, uint32_t rtFramesDepth)
955{
956    t_Qm        *p_Qm = (t_Qm *)h_Qm;
957
958    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
959    SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE);
960
961    p_Qm->p_QmDriverParams->rtFramesDepth = rtFramesDepth;
962
963    return E_OK;
964}
965
966t_Error QM_ConfigPfdrThreshold(t_Handle h_Qm, uint32_t threshold)
967{
968    t_Qm        *p_Qm = (t_Qm *)h_Qm;
969
970    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
971    SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE);
972
973    p_Qm->p_QmDriverParams->pfdrThreshold = threshold;
974
975    return E_OK;
976}
977
978t_Error QM_ConfigSfdrReservationThreshold(t_Handle h_Qm, uint32_t threshold)
979{
980    t_Qm        *p_Qm = (t_Qm *)h_Qm;
981
982    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
983    SANITY_CHECK_RETURN_ERROR(p_Qm->p_QmDriverParams, E_INVALID_HANDLE);
984
985    p_Qm->p_QmDriverParams->sfdrThreshold = threshold;
986
987    return E_OK;
988}
989
990
991t_Error QM_ConfigErrorRejectionNotificationDest(t_Handle h_Qm, e_DpaaDcPortal id, t_QmDcPortalParams *p_Params)
992{
993    UNUSED(h_Qm); UNUSED(id); UNUSED(p_Params);
994
995    RETURN_ERROR(INFO, E_NOT_SUPPORTED, ("Only default ERN destination available."));
996}
997
998
999t_Error QM_Poll(t_Handle h_Qm, e_QmPortalPollSource source)
1000{
1001    t_Qm        *p_Qm = (t_Qm *)h_Qm;
1002    t_QmPortal  *p_QmPortal;
1003
1004    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
1005    p_QmPortal = QmGetPortalHandle(p_Qm);
1006    SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1007
1008    return QM_PORTAL_Poll(p_QmPortal, source);
1009}
1010
1011uint32_t QM_GetCounter(t_Handle h_Qm, e_QmCounters counter)
1012{
1013    t_Qm    *p_Qm = (t_Qm *)h_Qm;
1014
1015    SANITY_CHECK_RETURN_VALUE(p_Qm, E_INVALID_HANDLE, 0);
1016    SANITY_CHECK_RETURN_VALUE(!p_Qm->p_QmDriverParams, E_INVALID_STATE, 0);
1017
1018    switch(counter)
1019    {
1020        case(e_QM_COUNTERS_SFDR_IN_USE):
1021            return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_SFDR_IN_USE);
1022        case(e_QM_COUNTERS_PFDR_IN_USE):
1023            return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_PFDR_IN_USE);
1024        case(e_QM_COUNTERS_PFDR_FREE_POOL):
1025            return QmGetCounter(p_Qm, e_QM_IM_COUNTERS_PFDR_FREE_POOL);
1026        default:
1027            break;
1028    }
1029    /* should never get here */
1030    ASSERT_COND(FALSE);
1031
1032    return 0;
1033}
1034
1035void QM_ErrorIsr(t_Handle h_Qm)
1036{
1037    t_Qm        *p_Qm = (t_Qm *)h_Qm;
1038    uint32_t    tmpReg;
1039
1040    SANITY_CHECK_RETURN(p_Qm, E_INVALID_HANDLE);
1041
1042    if (p_Qm->guestId != NCSW_MASTER_ID)
1043    {
1044        REPORT_ERROR(WARNING, E_INVALID_OPERATION, ("Master Only"));
1045        return;
1046    }
1047
1048    tmpReg = GET_UINT32(p_Qm->p_QmRegs->err_isr);
1049    tmpReg &= GET_UINT32(p_Qm->p_QmRegs->err_ier);
1050    WRITE_UINT32(p_Qm->p_QmRegs->err_isr, tmpReg);
1051
1052    if (tmpReg & QM_EX_CORENET_INITIATOR_DATA)
1053        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_INITIATOR_DATA);
1054    if (tmpReg & QM_EX_CORENET_TARGET_DATA)
1055        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_TARGET_DATA);
1056    if (tmpReg & QM_EX_CORENET_INVALID_TARGET_TRANSACTION)
1057        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_CORENET_INVALID_TARGET_TRANSACTION);
1058    if (tmpReg & QM_EX_PFDR_THRESHOLD)
1059        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_PFDR_THRESHOLD);
1060    if (tmpReg & QM_EX_MULTI_ECC)
1061        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_MULTI_ECC);
1062    if (tmpReg & QM_EX_SINGLE_ECC)
1063        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_SINGLE_ECC);
1064    if (tmpReg & QM_EX_PFDR_ENQUEUE_BLOCKED)
1065        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_PFDR_ENQUEUE_BLOCKED);
1066    if (tmpReg & QM_EX_INVALID_COMMAND)
1067        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_INVALID_COMMAND);
1068    if (tmpReg & QM_EX_DEQUEUE_DCP)
1069        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_DCP);
1070    if (tmpReg & QM_EX_DEQUEUE_FQ)
1071        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_FQ);
1072    if (tmpReg & QM_EX_DEQUEUE_SOURCE)
1073        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_SOURCE);
1074    if (tmpReg & QM_EX_DEQUEUE_QUEUE)
1075        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_DEQUEUE_QUEUE);
1076    if (tmpReg & QM_EX_ENQUEUE_OVERFLOW)
1077        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_OVERFLOW);
1078    if (tmpReg & QM_EX_ENQUEUE_STATE)
1079        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_STATE);
1080    if (tmpReg & QM_EX_ENQUEUE_CHANNEL)
1081        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_CHANNEL);
1082    if (tmpReg & QM_EX_ENQUEUE_QUEUE)
1083        p_Qm->f_Exception(p_Qm->h_App, e_QM_EX_ENQUEUE_QUEUE);
1084}
1085
1086t_Error QM_SetException(t_Handle h_Qm, e_QmExceptions exception, bool enable)
1087{
1088    t_Qm                *p_Qm = (t_Qm*)h_Qm;
1089    t_Error             err = E_OK;
1090
1091    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
1092    SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE);
1093
1094    if ((err = SetException(p_Qm, exception, enable)) != E_OK)
1095        RETURN_ERROR(MINOR, err, NO_MSG);
1096
1097    WRITE_UINT32(p_Qm->p_QmRegs->err_ier, p_Qm->exceptions);
1098
1099    return E_OK;
1100}
1101
1102t_Error QM_GetRevision(t_Handle h_Qm, t_QmRevisionInfo *p_QmRevisionInfo)
1103{
1104    t_Qm        *p_Qm = (t_Qm*)h_Qm;
1105
1106    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
1107    SANITY_CHECK_RETURN_ERROR(p_QmRevisionInfo, E_NULL_POINTER);
1108
1109    return QmGetRevision(p_Qm, p_QmRevisionInfo);
1110}
1111
1112t_Error QM_ReserveQueues(t_Handle h_Qm, t_QmRsrvFqrParams *p_QmFqrParams, uint32_t  *p_BaseFqid)
1113{
1114    t_Qm                *p_Qm = (t_Qm*)h_Qm;
1115
1116    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
1117    SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE);
1118
1119    *p_BaseFqid = ReserveFqids(p_Qm,
1120                               (uint32_t)((p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ?
1121                                          1 : p_QmFqrParams->numOfFqids),
1122                               p_QmFqrParams->qs.nonFrcQs.align,
1123                               p_QmFqrParams->useForce,
1124                               p_QmFqrParams->qs.frcQ.fqid);
1125    if (*p_BaseFqid == ILLEGAL_BASE)
1126        RETURN_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid"));
1127
1128    return E_OK;
1129}
1130
1131t_Error QM_GetErrorInformation(t_Handle h_Qm, t_QmErrorInfo *p_errInfo)
1132{
1133    uint32_t            ecsr, ecir;
1134    t_Qm                *p_Qm = (t_Qm*)h_Qm;
1135    t_Error             err = E_OK;
1136
1137    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
1138    SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_HANDLE);
1139    SANITY_CHECK_RETURN_ERROR(p_errInfo, E_NULL_POINTER);
1140
1141    ecsr = GET_UINT32(p_Qm->p_QmRegs->ecsr);
1142    ecir = GET_UINT32(p_Qm->p_QmRegs->ecir);
1143    if ((ecsr & QM_EX_MULTI_ECC) ||
1144        (ecsr & QM_EX_SINGLE_ECC))
1145    {
1146        err = E_NOT_SUPPORTED;
1147        REPORT_ERROR(INFO, E_NOT_SUPPORTED, ("single and multi ecc, use QM_DumpRegs"));
1148    }
1149    if ((ecsr & QM_EX_ENQUEUE_QUEUE)    ||
1150        (ecsr & QM_EX_ENQUEUE_STATE)    ||
1151        (ecsr & QM_EX_ENQUEUE_OVERFLOW) ||
1152        (ecsr & QM_EX_DEQUEUE_DCP)      ||
1153        (ecsr & QM_EX_DEQUEUE_FQ)       ||
1154        (ecsr & QM_EX_DEQUEUE_QUEUE)    ||
1155        (ecsr & QM_EX_DEQUEUE_SOURCE)   ||
1156        (ecsr & QM_EX_INVALID_COMMAND))
1157    {
1158        p_errInfo->portalValid = TRUE;
1159        p_errInfo->hwPortal = (bool)(ecir & ECIR_PORTAL_TYPE);
1160        if (p_errInfo->hwPortal)
1161            p_errInfo->dcpId = (e_DpaaDcPortal)((ecir & ECIR_PORTAL_MASK) >> ECIR_PORTAL_SHIFT);
1162        else
1163            p_errInfo->swPortalId = (e_DpaaSwPortal)((ecir & ECIR_PORTAL_MASK) >> ECIR_PORTAL_SHIFT);
1164    }
1165
1166    if ((ecsr & QM_EX_ENQUEUE_QUEUE)    ||
1167        (ecsr & QM_EX_ENQUEUE_STATE)    ||
1168        (ecsr & QM_EX_ENQUEUE_OVERFLOW) ||
1169        (ecsr & QM_EX_ENQUEUE_CHANNEL)  ||
1170        (ecsr & QM_EX_DEQUEUE_QUEUE)    ||
1171        (ecsr & QM_EX_DEQUEUE_FQ))
1172    {
1173        p_errInfo->fqidValid = TRUE;
1174        p_errInfo->fqid = ((ecir & ECIR_FQID_MASK) >> ECIR_FQID_SHIFT);
1175    }
1176
1177    WRITE_UINT32(p_Qm->p_QmRegs->ecsr, ecsr);
1178
1179    return ERROR_CODE(err);
1180}
1181
1182#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
1183t_Error QM_DumpRegs(t_Handle h_Qm)
1184{
1185    t_Qm        *p_Qm = (t_Qm *)h_Qm;
1186    uint8_t     i = 0;
1187
1188    DECLARE_DUMP;
1189
1190    SANITY_CHECK_RETURN_ERROR(p_Qm, E_INVALID_HANDLE);
1191    SANITY_CHECK_RETURN_ERROR(!p_Qm->p_QmDriverParams, E_INVALID_STATE);
1192
1193    DUMP_SUBTITLE(("\n"));
1194    DUMP_TITLE(p_Qm->p_QmRegs, ("QmRegs Regs"));
1195
1196    DUMP_SUBSTRUCT_ARRAY(i, QM_NUM_OF_SWP)
1197    {
1198        DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], lio_cfg);
1199        DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], io_cfg);
1200        DUMP_VAR(&p_Qm->p_QmRegs->swpConfRegs[i], dd_cfg);
1201    }
1202    DUMP_VAR(p_Qm->p_QmRegs, qman_dd_cfg);
1203    DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_ihrsr);
1204    DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_ihrfr);
1205    DUMP_VAR(p_Qm->p_QmRegs, qcsp_dd_hasr);
1206    DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_ihrsr);
1207    DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_ihrfr);
1208    DUMP_VAR(p_Qm->p_QmRegs, dcp_dd_hasr);
1209    DUMP_SUBSTRUCT_ARRAY(i, QM_NUM_OF_DCP)
1210    {
1211        DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], cfg);
1212        DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dd_cfg);
1213        DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dlm_cfg);
1214        DUMP_VAR(&p_Qm->p_QmRegs->dcpConfRegs[i], dlm_avg);
1215    }
1216    DUMP_VAR(p_Qm->p_QmRegs, pfdr_fpc);
1217    DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_head);
1218    DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_tail);
1219    DUMP_VAR(p_Qm->p_QmRegs, pfdr_fp_lwit);
1220    DUMP_VAR(p_Qm->p_QmRegs, pfdr_cfg);
1221    DUMP_VAR(p_Qm->p_QmRegs, sfdr_cfg);
1222    DUMP_VAR(p_Qm->p_QmRegs, sfdr_in_use);
1223    DUMP_ARR(p_Qm->p_QmRegs, wq_cs_cfg);
1224    DUMP_VAR(p_Qm->p_QmRegs, wq_def_enq_wqid);
1225    DUMP_ARR(p_Qm->p_QmRegs, wq_sc_dd_cfg);
1226    DUMP_ARR(p_Qm->p_QmRegs, wq_pc_dd_cs_cfg);
1227    DUMP_ARR(p_Qm->p_QmRegs, wq_dc0_dd_cs_cfg);
1228    DUMP_ARR(p_Qm->p_QmRegs, wq_dc1_dd_cs_cfg);
1229    DUMP_VAR(p_Qm->p_QmRegs, wq_dc2_dd_cs_cfg);
1230    DUMP_VAR(p_Qm->p_QmRegs, wq_dc3_dd_cs_cfg);
1231    DUMP_VAR(p_Qm->p_QmRegs, cm_cfg);
1232    DUMP_VAR(p_Qm->p_QmRegs, ecsr);
1233    DUMP_VAR(p_Qm->p_QmRegs, ecir);
1234    DUMP_VAR(p_Qm->p_QmRegs, eadr);
1235    DUMP_ARR(p_Qm->p_QmRegs, edata);
1236    DUMP_VAR(p_Qm->p_QmRegs, sbet);
1237    DUMP_ARR(p_Qm->p_QmRegs, sbec);
1238    DUMP_VAR(p_Qm->p_QmRegs, mcr);
1239    DUMP_VAR(p_Qm->p_QmRegs, mcp0);
1240    DUMP_VAR(p_Qm->p_QmRegs, mcp1);
1241    DUMP_ARR(p_Qm->p_QmRegs, mr);
1242    DUMP_VAR(p_Qm->p_QmRegs, idle_stat);
1243    DUMP_VAR(p_Qm->p_QmRegs, ip_rev_1);
1244    DUMP_VAR(p_Qm->p_QmRegs, ip_rev_2);
1245    DUMP_VAR(p_Qm->p_QmRegs, fqd_bare);
1246    DUMP_VAR(p_Qm->p_QmRegs, fqd_bar);
1247    DUMP_VAR(p_Qm->p_QmRegs, fqd_ar);
1248    DUMP_VAR(p_Qm->p_QmRegs, pfdr_bare);
1249    DUMP_VAR(p_Qm->p_QmRegs, pfdr_bar);
1250    DUMP_VAR(p_Qm->p_QmRegs, pfdr_ar);
1251    DUMP_VAR(p_Qm->p_QmRegs, qcsp_bare);
1252    DUMP_VAR(p_Qm->p_QmRegs, qcsp_bar);
1253    DUMP_VAR(p_Qm->p_QmRegs, ci_sched_cfg);
1254    DUMP_VAR(p_Qm->p_QmRegs, srcidr);
1255    DUMP_VAR(p_Qm->p_QmRegs, liodnr);
1256    DUMP_VAR(p_Qm->p_QmRegs, ci_rlm_cfg);
1257    DUMP_VAR(p_Qm->p_QmRegs, ci_rlm_avg);
1258    DUMP_VAR(p_Qm->p_QmRegs, err_isr);
1259    DUMP_VAR(p_Qm->p_QmRegs, err_ier);
1260    DUMP_VAR(p_Qm->p_QmRegs, err_isdr);
1261    DUMP_VAR(p_Qm->p_QmRegs, err_iir);
1262    DUMP_VAR(p_Qm->p_QmRegs, err_her);
1263
1264    return E_OK;
1265}
1266#endif /* (defined(DEBUG_ERRORS) && ... */
1267