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