xref: /freebsd/sys/contrib/ncsw/Peripherals/QM/qm.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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 
56 static volatile bool blockingFlag = FALSE;
57 static 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 
69 static 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 
164 static 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 
194 static 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 
237 static __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 
259 static 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 
296 static 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 
315 uint32_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 
377 t_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 
431 t_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 
497 uint32_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, %jx > UINT32_MAX!\n", (uintmax_t)ans));
564     return (uint32_t)ans;
565 }
566 
567 t_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 
628 t_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 
646 t_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 
663 t_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 
741 t_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 
931 t_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 
959 t_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 
971 t_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 
983 t_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 
996 t_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 
1004 t_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 
1016 uint32_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 
1040 void 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 
1091 t_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 
1107 t_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 
1117 t_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 
1136 t_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))
1188 t_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