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