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 <sys/cdefs.h>
42 #include <sys/types.h>
43 #include <machine/atomic.h>
44 
45 #include "error_ext.h"
46 #include "std_ext.h"
47 #include "string_ext.h"
48 #include "mm_ext.h"
49 #include "qm.h"
50 #include "qman_low.h"
51 
52 #include <machine/vmparam.h>
53 
54 /****************************************/
55 /*       static functions               */
56 /****************************************/
57 
58 #define SLOW_POLL_IDLE   1000
59 #define SLOW_POLL_BUSY   10
60 
61 /*
62  * Context entries are 32-bit.  The qman driver uses the pointer to the queue as
63  * its context, and the pointer is 64-byte aligned, per the XX_MallocSmart()
64  * call.  Take advantage of this fact to shove a 64-bit kernel pointer into a
65  * 32-bit context integer, and back.
66  *
67  * XXX: This depends on the fact that VM_MAX_KERNEL_ADDRESS is less than 38-bit
68  * count from VM_MIN_KERNEL_ADDRESS.  If this ever changes, this needs to be
69  * updated.
70  */
71 CTASSERT((VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) < (1ULL << 35));
72 static inline uint32_t
73 aligned_int_from_ptr(const void *p)
74 {
75 	uintptr_t ctx;
76 
77 	ctx = (uintptr_t)p;
78 	KASSERT(ctx >= VM_MIN_KERNEL_ADDRESS, ("%p is too low!\n", p));
79 	ctx -= VM_MIN_KERNEL_ADDRESS;
80 	KASSERT((ctx & 0x07) == 0, ("Pointer %p is not 8-byte aligned!\n", p));
81 
82 	return (ctx >> 3);
83 }
84 
85 static inline void *
86 ptr_from_aligned_int(uint32_t ctx)
87 {
88 	uintptr_t p;
89 
90 	p = ctx;
91 	p = VM_MIN_KERNEL_ADDRESS + (p << 3);
92 
93 	return ((void *)p);
94 }
95 
96 static t_Error qman_volatile_dequeue(t_QmPortal     *p_QmPortal,
97                                      struct qman_fq *p_Fq,
98                                      uint32_t       vdqcr)
99 {
100     ASSERT_COND((p_Fq->state == qman_fq_state_parked) ||
101                 (p_Fq->state == qman_fq_state_retired));
102     ASSERT_COND(!(vdqcr & QM_VDQCR_FQID_MASK));
103     ASSERT_COND(!(p_Fq->flags & QMAN_FQ_STATE_VDQCR));
104 
105     vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | p_Fq->fqid;
106     NCSW_PLOCK(p_QmPortal);
107     FQLOCK(p_Fq);
108     p_Fq->flags |= QMAN_FQ_STATE_VDQCR;
109     qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, vdqcr);
110     FQUNLOCK(p_Fq);
111     PUNLOCK(p_QmPortal);
112 
113     return E_OK;
114 }
115 
116 static const char *mcr_result_str(uint8_t result)
117 {
118     switch (result) {
119     case QM_MCR_RESULT_NULL:
120         return "QM_MCR_RESULT_NULL";
121     case QM_MCR_RESULT_OK:
122         return "QM_MCR_RESULT_OK";
123     case QM_MCR_RESULT_ERR_FQID:
124         return "QM_MCR_RESULT_ERR_FQID";
125     case QM_MCR_RESULT_ERR_FQSTATE:
126         return "QM_MCR_RESULT_ERR_FQSTATE";
127     case QM_MCR_RESULT_ERR_NOTEMPTY:
128         return "QM_MCR_RESULT_ERR_NOTEMPTY";
129     case QM_MCR_RESULT_PENDING:
130         return "QM_MCR_RESULT_PENDING";
131     }
132     return "<unknown MCR result>";
133 }
134 
135 static t_Error qman_create_fq(t_QmPortal        *p_QmPortal,
136                               uint32_t          fqid,
137                               uint32_t          flags,
138                               struct qman_fq    *p_Fq)
139 {
140     struct qm_fqd fqd;
141     struct qm_mcr_queryfq_np np;
142     struct qm_mc_command *p_Mcc;
143     struct qm_mc_result *p_Mcr;
144 
145     p_Fq->fqid = fqid;
146     p_Fq->flags = flags;
147     p_Fq->state = qman_fq_state_oos;
148     p_Fq->cgr_groupid = 0;
149     if (!(flags & QMAN_FQ_FLAG_RECOVER) ||
150             (flags & QMAN_FQ_FLAG_NO_MODIFY))
151         return E_OK;
152     /* Everything else is RECOVER support */
153     NCSW_PLOCK(p_QmPortal);
154     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
155     p_Mcc->queryfq.fqid = fqid;
156     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ);
157     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
158     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ);
159     if (p_Mcr->result != QM_MCR_RESULT_OK) {
160         PUNLOCK(p_QmPortal);
161         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QUERYFQ failed: %s", mcr_result_str(p_Mcr->result)));
162     }
163     fqd = p_Mcr->queryfq.fqd;
164     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
165     p_Mcc->queryfq_np.fqid = fqid;
166     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP);
167     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
168     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ_NP);
169     if (p_Mcr->result != QM_MCR_RESULT_OK) {
170         PUNLOCK(p_QmPortal);
171         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("UERYFQ_NP failed: %s", mcr_result_str(p_Mcr->result)));
172     }
173     np = p_Mcr->queryfq_np;
174     /* Phew, have queryfq and queryfq_np results, stitch together
175      * the FQ object from those. */
176     p_Fq->cgr_groupid = fqd.cgid;
177     switch (np.state & QM_MCR_NP_STATE_MASK) {
178     case QM_MCR_NP_STATE_OOS:
179         break;
180     case QM_MCR_NP_STATE_RETIRED:
181         p_Fq->state = qman_fq_state_retired;
182         if (np.frm_cnt)
183             p_Fq->flags |= QMAN_FQ_STATE_NE;
184         break;
185     case QM_MCR_NP_STATE_TEN_SCHED:
186     case QM_MCR_NP_STATE_TRU_SCHED:
187     case QM_MCR_NP_STATE_ACTIVE:
188         p_Fq->state = qman_fq_state_sched;
189         if (np.state & QM_MCR_NP_STATE_R)
190             p_Fq->flags |= QMAN_FQ_STATE_CHANGING;
191         break;
192     case QM_MCR_NP_STATE_PARKED:
193         p_Fq->state = qman_fq_state_parked;
194         break;
195     default:
196         ASSERT_COND(FALSE);
197     }
198     if (fqd.fq_ctrl & QM_FQCTRL_CGE)
199         p_Fq->state |= QMAN_FQ_STATE_CGR_EN;
200     PUNLOCK(p_QmPortal);
201 
202     return E_OK;
203 }
204 
205 static void qman_destroy_fq(struct qman_fq *p_Fq, uint32_t flags)
206 {
207     /* We don't need to lock the FQ as it is a pre-condition that the FQ be
208      * quiesced. Instead, run some checks. */
209     UNUSED(flags);
210     switch (p_Fq->state) {
211     case qman_fq_state_parked:
212         ASSERT_COND(flags & QMAN_FQ_DESTROY_PARKED);
213     case qman_fq_state_oos:
214         return;
215     default:
216         break;
217     }
218     ASSERT_COND(FALSE);
219 }
220 
221 static t_Error qman_init_fq(t_QmPortal          *p_QmPortal,
222                             struct qman_fq      *p_Fq,
223                             uint32_t            flags,
224                             struct qm_mcc_initfq *p_Opts)
225 {
226     struct qm_mc_command    *p_Mcc;
227     struct qm_mc_result     *p_Mcr;
228     uint8_t res, myverb = (uint8_t)((flags & QMAN_INITFQ_FLAG_SCHED) ?
229         QM_MCC_VERB_INITFQ_SCHED : QM_MCC_VERB_INITFQ_PARKED);
230 
231     SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_oos) ||
232                               (p_Fq->state == qman_fq_state_parked),
233                               E_INVALID_STATE);
234 
235     if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
236         return ERROR_CODE(E_INVALID_VALUE);
237     /* Issue an INITFQ_[PARKED|SCHED] management command */
238     NCSW_PLOCK(p_QmPortal);
239     FQLOCK(p_Fq);
240     if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||
241             ((p_Fq->state != qman_fq_state_oos) &&
242                 (p_Fq->state != qman_fq_state_parked))) {
243         FQUNLOCK(p_Fq);
244         PUNLOCK(p_QmPortal);
245         return ERROR_CODE(E_BUSY);
246     }
247     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
248     Mem2IOCpy32((void*)&p_Mcc->initfq, p_Opts, sizeof(struct qm_mcc_initfq));
249     qm_mc_commit(p_QmPortal->p_LowQmPortal, myverb);
250     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
251     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == myverb);
252     res = p_Mcr->result;
253     if (res != QM_MCR_RESULT_OK) {
254         FQUNLOCK(p_Fq);
255         PUNLOCK(p_QmPortal);
256         RETURN_ERROR(MINOR, E_INVALID_STATE,("INITFQ failed: %s", mcr_result_str(res)));
257     }
258 
259     if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_FQCTRL) {
260         if (p_Mcc->initfq.fqd.fq_ctrl & QM_FQCTRL_CGE)
261             p_Fq->flags |= QMAN_FQ_STATE_CGR_EN;
262         else
263             p_Fq->flags &= ~QMAN_FQ_STATE_CGR_EN;
264     }
265     if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_CGID)
266         p_Fq->cgr_groupid = p_Mcc->initfq.fqd.cgid;
267     p_Fq->state = (flags & QMAN_INITFQ_FLAG_SCHED) ?
268             qman_fq_state_sched : qman_fq_state_parked;
269     FQUNLOCK(p_Fq);
270     PUNLOCK(p_QmPortal);
271     return E_OK;
272 }
273 
274 static t_Error qman_retire_fq(t_QmPortal        *p_QmPortal,
275                               struct qman_fq    *p_Fq,
276                               uint32_t          *p_Flags,
277                               bool              drain)
278 {
279     struct qm_mc_command    *p_Mcc;
280     struct qm_mc_result     *p_Mcr;
281     t_Error                 err = E_OK;
282     uint8_t                 res;
283 
284     SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_parked) ||
285                               (p_Fq->state == qman_fq_state_sched),
286                               E_INVALID_STATE);
287 
288     if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
289         return E_INVALID_VALUE;
290     NCSW_PLOCK(p_QmPortal);
291     FQLOCK(p_Fq);
292     if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||
293             (p_Fq->state == qman_fq_state_retired) ||
294                 (p_Fq->state == qman_fq_state_oos)) {
295         err = E_BUSY;
296         goto out;
297     }
298     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
299     p_Mcc->alterfq.fqid = p_Fq->fqid;
300     if (drain)
301         p_Mcc->alterfq.context_b = aligned_int_from_ptr(p_Fq);
302     qm_mc_commit(p_QmPortal->p_LowQmPortal,
303                  (uint8_t)((drain)?QM_MCC_VERB_ALTER_RETIRE_CTXB:QM_MCC_VERB_ALTER_RETIRE));
304     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
305     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) ==
306                 (drain)?QM_MCR_VERB_ALTER_RETIRE_CTXB:QM_MCR_VERB_ALTER_RETIRE);
307     res = p_Mcr->result;
308     if (res == QM_MCR_RESULT_OK)
309     {
310         /* Process 'fq' right away, we'll ignore FQRNI */
311         if (p_Mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY)
312             p_Fq->flags |= QMAN_FQ_STATE_NE;
313         if (p_Mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT)
314             p_Fq->flags |= QMAN_FQ_STATE_ORL;
315         p_Fq->state = qman_fq_state_retired;
316     }
317     else if (res == QM_MCR_RESULT_PENDING)
318         p_Fq->flags |= QMAN_FQ_STATE_CHANGING;
319     else {
320         XX_Print("ALTER_RETIRE failed: %s\n",
321                 mcr_result_str(res));
322         err = E_INVALID_STATE;
323     }
324     if (p_Flags)
325         *p_Flags = p_Fq->flags;
326 out:
327     FQUNLOCK(p_Fq);
328     PUNLOCK(p_QmPortal);
329     return err;
330 }
331 
332 static t_Error qman_oos_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)
333 {
334     struct qm_mc_command    *p_Mcc;
335     struct qm_mc_result     *p_Mcr;
336     uint8_t                 res;
337 
338     ASSERT_COND(p_Fq->state == qman_fq_state_retired);
339     if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
340         return ERROR_CODE(E_INVALID_VALUE);
341     NCSW_PLOCK(p_QmPortal);
342     FQLOCK(p_Fq);
343     if ((p_Fq->flags & QMAN_FQ_STATE_BLOCKOOS) ||
344             (p_Fq->state != qman_fq_state_retired)) {
345         FQUNLOCK(p_Fq);
346         PUNLOCK(p_QmPortal);
347         return ERROR_CODE(E_BUSY);
348     }
349     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
350     p_Mcc->alterfq.fqid = p_Fq->fqid;
351     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_OOS);
352     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
353     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS);
354     res = p_Mcr->result;
355     if (res != QM_MCR_RESULT_OK) {
356         FQUNLOCK(p_Fq);
357         PUNLOCK(p_QmPortal);
358         RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_OOS failed: %s\n", mcr_result_str(res)));
359     }
360     p_Fq->state = qman_fq_state_oos;
361 
362     FQUNLOCK(p_Fq);
363     PUNLOCK(p_QmPortal);
364     return E_OK;
365 }
366 
367 static t_Error qman_schedule_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)
368 {
369     struct qm_mc_command    *p_Mcc;
370     struct qm_mc_result     *p_Mcr;
371     uint8_t                 res;
372 
373     ASSERT_COND(p_Fq->state == qman_fq_state_parked);
374     if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)
375         return ERROR_CODE(E_INVALID_VALUE);
376     /* Issue a ALTERFQ_SCHED management command */
377     NCSW_PLOCK(p_QmPortal);
378     FQLOCK(p_Fq);
379     if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) ||
380             (p_Fq->state != qman_fq_state_parked)) {
381         FQUNLOCK(p_Fq);
382         PUNLOCK(p_QmPortal);
383         return ERROR_CODE(E_BUSY);
384     }
385     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
386     p_Mcc->alterfq.fqid = p_Fq->fqid;
387     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_SCHED);
388     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
389     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_SCHED);
390     res = p_Mcr->result;
391     if (res != QM_MCR_RESULT_OK) {
392         FQUNLOCK(p_Fq);
393         PUNLOCK(p_QmPortal);
394         RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_SCHED failed: %s\n", mcr_result_str(res)));
395     }
396     p_Fq->state = qman_fq_state_sched;
397 
398     FQUNLOCK(p_Fq);
399     PUNLOCK(p_QmPortal);
400     return E_OK;
401 }
402 
403 /* Inline helper to reduce nesting in LoopMessageRing() */
404 static __inline__ void fq_state_change(struct qman_fq *p_Fq,
405                                        struct qm_mr_entry *p_Msg,
406                                        uint8_t verb)
407 {
408     FQLOCK(p_Fq);
409     switch(verb) {
410         case QM_MR_VERB_FQRL:
411             ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_ORL);
412             p_Fq->flags &= ~QMAN_FQ_STATE_ORL;
413             break;
414         case QM_MR_VERB_FQRN:
415             ASSERT_COND((p_Fq->state == qman_fq_state_parked) ||
416                 (p_Fq->state == qman_fq_state_sched));
417             ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING);
418             p_Fq->flags &= ~QMAN_FQ_STATE_CHANGING;
419             if (p_Msg->fq.fqs & QM_MR_FQS_NOTEMPTY)
420                 p_Fq->flags |= QMAN_FQ_STATE_NE;
421             if (p_Msg->fq.fqs & QM_MR_FQS_ORLPRESENT)
422                 p_Fq->flags |= QMAN_FQ_STATE_ORL;
423             p_Fq->state = qman_fq_state_retired;
424             break;
425         case QM_MR_VERB_FQPN:
426             ASSERT_COND(p_Fq->state == qman_fq_state_sched);
427             ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING);
428             p_Fq->state = qman_fq_state_parked;
429     }
430     FQUNLOCK(p_Fq);
431 }
432 
433 static t_Error freeDrainedFq(struct qman_fq *p_Fq)
434 {
435     t_QmFqr     *p_QmFqr;
436     uint32_t    i;
437 
438     ASSERT_COND(p_Fq);
439     p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr;
440     ASSERT_COND(p_QmFqr);
441 
442     ASSERT_COND(!p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset]);
443     p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset] = TRUE;
444     p_QmFqr->numOfDrainedFqids++;
445     if (p_QmFqr->numOfDrainedFqids == p_QmFqr->numOfFqids)
446     {
447         for (i=0;i<p_QmFqr->numOfFqids;i++)
448         {
449             if ((p_QmFqr->p_Fqs[i]->state == qman_fq_state_retired) &&
450                     (qman_oos_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]) != E_OK))
451                 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!"));
452             qman_destroy_fq(p_QmFqr->p_Fqs[i], 0);
453             XX_FreeSmart(p_QmFqr->p_Fqs[i]);
454         }
455         XX_Free(p_QmFqr->p_DrainedFqs);
456         p_QmFqr->p_DrainedFqs = NULL;
457 
458         if (p_QmFqr->f_CompletionCB)
459         {
460             p_QmFqr->f_CompletionCB(p_QmFqr->h_App, p_QmFqr);
461             XX_Free(p_QmFqr->p_Fqs);
462             if (p_QmFqr->fqidBase)
463                 QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
464             XX_Free(p_QmFqr);
465         }
466     }
467 
468     return E_OK;
469 }
470 
471 static t_Error drainRetiredFq(struct qman_fq *p_Fq)
472 {
473     t_QmFqr     *p_QmFqr;
474 
475     ASSERT_COND(p_Fq);
476     p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr;
477     ASSERT_COND(p_QmFqr);
478 
479     if (p_Fq->flags & QMAN_FQ_STATE_NE)
480     {
481         if (qman_volatile_dequeue(p_QmFqr->h_QmPortal, p_Fq,
482                                 (QM_VDQCR_PRECEDENCE_VDQCR | QM_VDQCR_NUMFRAMES_TILLEMPTY)) != E_OK)
483 
484             RETURN_ERROR(MAJOR, E_INVALID_STATE, ("drain with volatile failed"));
485         return E_OK;
486     }
487     else
488         return freeDrainedFq(p_Fq);
489 }
490 
491 static e_RxStoreResponse drainCB(t_Handle h_App,
492                                  t_Handle h_QmFqr,
493                                  t_Handle h_QmPortal,
494                                  uint32_t fqidOffset,
495                                  t_DpaaFD *p_Frame)
496 {
497     UNUSED(h_App);
498     UNUSED(h_QmFqr);
499     UNUSED(h_QmPortal);
500     UNUSED(fqidOffset);
501     UNUSED(p_Frame);
502 
503     DBG(TRACE,("got fd for fqid %d", ((t_QmFqr *)h_QmFqr)->fqidBase + fqidOffset));
504     return e_RX_STORE_RESPONSE_CONTINUE;
505 }
506 
507 static void cb_ern_dcErn(t_Handle                   h_App,
508                          t_Handle                   h_QmPortal,
509                          struct qman_fq             *p_Fq,
510                          const struct qm_mr_entry   *p_Msg)
511 {
512     static int cnt = 0;
513     UNUSED(p_Fq);
514     UNUSED(p_Msg);
515     UNUSED(h_App);
516     UNUSED(h_QmPortal);
517 
518     XX_Print("cb_ern_dcErn_fqs() unimplemented %d\n", ++cnt);
519 }
520 
521 static void cb_fqs(t_Handle                   h_App,
522                    t_Handle                   h_QmPortal,
523                    struct qman_fq             *p_Fq,
524                    const struct qm_mr_entry   *p_Msg)
525 {
526     UNUSED(p_Msg);
527     UNUSED(h_App);
528     UNUSED(h_QmPortal);
529 
530     if (p_Fq->state == qman_fq_state_retired &&
531         !(p_Fq->flags & QMAN_FQ_STATE_ORL))
532         drainRetiredFq(p_Fq);
533 }
534 
535 static void null_cb_mr(t_Handle                   h_App,
536                        t_Handle                   h_QmPortal,
537                        struct qman_fq             *p_Fq,
538                        const struct qm_mr_entry   *p_Msg)
539 {
540     t_QmPortal      *p_QmPortal = (t_QmPortal *)h_QmPortal;
541 
542     UNUSED(p_Fq);UNUSED(h_App);
543 
544     if ((p_Msg->verb & QM_MR_VERB_DC_ERN) == QM_MR_VERB_DC_ERN)
545         XX_Print("Ignoring unowned MR frame on cpu %d, dc-portal 0x%02x.\n",
546                  p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->dcern.portal);
547     else
548         XX_Print("Ignoring unowned MR frame on cpu %d, verb 0x%02x.\n",
549                  p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->verb);
550 }
551 
552 static uint32_t LoopMessageRing(t_QmPortal *p_QmPortal, uint32_t is)
553 {
554     struct qm_mr_entry          *p_Msg;
555 
556     if (is & QM_PIRQ_CSCI) {
557         struct qm_mc_result *p_Mcr;
558         struct qman_cgrs    tmp;
559         uint32_t            mask;
560         unsigned int        i, j;
561 
562         NCSW_PLOCK(p_QmPortal);
563         qm_mc_start(p_QmPortal->p_LowQmPortal);
564         qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCONGESTION);
565         while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
566 
567         /* cgrs[0] is the portal mask for its cg's, cgrs[1] is the
568            previous state of cg's */
569         for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++)
570         {
571             /* get curent state */
572             tmp.q.__state[i] = p_Mcr->querycongestion.state.__state[i];
573             /* keep only cg's that are registered for this portal */
574             tmp.q.__state[i] &= p_QmPortal->cgrs[0].q.__state[i];
575             /* handle only cg's that changed their state from previous exception */
576             tmp.q.__state[i] ^= p_QmPortal->cgrs[1].q.__state[i];
577             /* update previous */
578             p_QmPortal->cgrs[1].q.__state[i] = p_Mcr->querycongestion.state.__state[i];
579         }
580         PUNLOCK(p_QmPortal);
581 
582         /* if in interrupt */
583         /* call the callback routines for any CG with a changed state */
584         for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++)
585             for(j=0, mask = 0x80000000; j<32 ; j++, mask>>=1)
586             {
587                 if(tmp.q.__state[i] & mask)
588                 {
589                     t_QmCg *p_QmCg = (t_QmCg *)(p_QmPortal->cgsHandles[i*32 + j]);
590                     if(p_QmCg->f_Exception)
591                         p_QmCg->f_Exception(p_QmCg->h_App, e_QM_EX_CG_STATE_CHANGE);
592                 }
593             }
594 
595     }
596 
597 
598     if (is & QM_PIRQ_EQRI) {
599         NCSW_PLOCK(p_QmPortal);
600         qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);
601         qm_eqcr_set_ithresh(p_QmPortal->p_LowQmPortal, 0);
602         PUNLOCK(p_QmPortal);
603     }
604 
605     if (is & QM_PIRQ_MRI) {
606 mr_loop:
607         qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal);
608         p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal);
609         if (p_Msg) {
610             struct qman_fq  *p_FqFqs  = ptr_from_aligned_int(p_Msg->fq.contextB);
611             struct qman_fq  *p_FqErn  = ptr_from_aligned_int(p_Msg->ern.tag);
612             uint8_t         verb    =(uint8_t)(p_Msg->verb & QM_MR_VERB_TYPE_MASK);
613             t_QmRejectedFrameInfo   rejectedFrameInfo;
614 
615             memset(&rejectedFrameInfo, 0, sizeof(t_QmRejectedFrameInfo));
616             if (!(verb & QM_MR_VERB_DC_ERN))
617             {
618                 switch(p_Msg->ern.rc)
619                 {
620                     case(QM_MR_RC_CGR_TAILDROP):
621                         rejectedFrameInfo.rejectionCode = e_QM_RC_CG_TAILDROP;
622                         rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;
623                         break;
624                     case(QM_MR_RC_WRED):
625                         rejectedFrameInfo.rejectionCode = e_QM_RC_CG_WRED;
626                         rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;
627                         break;
628                     case(QM_MR_RC_FQ_TAILDROP):
629                         rejectedFrameInfo.rejectionCode = e_QM_RC_FQ_TAILDROP;
630                         rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid;
631                         break;
632                     case(QM_MR_RC_ERROR):
633                         break;
634                     default:
635                         REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("Unknown rejection code"));
636                 }
637                 if (!p_FqErn)
638                     p_QmPortal->p_NullCB->ern(p_QmPortal->h_App, NULL, p_QmPortal, 0, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo);
639                 else
640                     p_FqErn->cb.ern(p_FqErn->h_App, p_FqErn->h_QmFqr, p_QmPortal, p_FqErn->fqidOffset, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo);
641             } else if (verb == QM_MR_VERB_DC_ERN)
642             {
643                 if (!p_FqErn)
644                     p_QmPortal->p_NullCB->dc_ern(NULL, p_QmPortal, NULL, p_Msg);
645                 else
646                     p_FqErn->cb.dc_ern(p_FqErn->h_App, p_QmPortal, p_FqErn, p_Msg);
647             } else
648             {
649                 if (verb == QM_MR_VERB_FQRNI)
650                     ; /* we drop FQRNIs on the floor */
651                 else if (!p_FqFqs)
652                             p_QmPortal->p_NullCB->fqs(NULL, p_QmPortal, NULL, p_Msg);
653                 else if ((verb == QM_MR_VERB_FQRN) ||
654                          (verb == QM_MR_VERB_FQRL) ||
655                          (verb == QM_MR_VERB_FQPN))
656                 {
657                     fq_state_change(p_FqFqs, p_Msg, verb);
658                     p_FqFqs->cb.fqs(p_FqFqs->h_App, p_QmPortal, p_FqFqs, p_Msg);
659                 }
660             }
661             qm_mr_next(p_QmPortal->p_LowQmPortal);
662             qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1);
663 
664             goto mr_loop;
665         }
666     }
667 
668     return is & (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI);
669 }
670 
671 static void LoopDequeueRing(t_Handle h_QmPortal)
672 {
673     struct qm_dqrr_entry        *p_Dq;
674     struct qman_fq              *p_Fq;
675     enum qman_cb_dqrr_result    res = qman_cb_dqrr_consume;
676     e_RxStoreResponse           tmpRes;
677     t_QmPortal                  *p_QmPortal = (t_QmPortal *)h_QmPortal;
678     int                         prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
679 
680     while (res != qman_cb_dqrr_pause)
681     {
682         if (prefetch)
683             qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
684         qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
685         p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
686         if (!p_Dq)
687             break;
688 	p_Fq = ptr_from_aligned_int(p_Dq->contextB);
689         if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {
690             /* We only set QMAN_FQ_STATE_NE when retiring, so we only need
691              * to check for clearing it when doing volatile dequeues. It's
692              * one less thing to check in the critical path (SDQCR). */
693             tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);
694             if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
695                 res = qman_cb_dqrr_pause;
696             /* Check for VDQCR completion */
697             if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)
698                 p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;
699             if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)
700             {
701                 p_Fq->flags &= ~QMAN_FQ_STATE_NE;
702                 freeDrainedFq(p_Fq);
703             }
704         }
705         else
706         {
707             /* Interpret 'dq' from the owner's perspective. */
708             /* use portal default handlers */
709             ASSERT_COND(p_Dq->fqid);
710             if (p_Fq)
711             {
712                 tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,
713                                        p_Fq->h_QmFqr,
714                                        p_QmPortal,
715                                        p_Fq->fqidOffset,
716                                        (t_DpaaFD*)&p_Dq->fd);
717                 if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
718                     res = qman_cb_dqrr_pause;
719                 else if (p_Fq->state == qman_fq_state_waiting_parked)
720                     res = qman_cb_dqrr_park;
721             }
722             else
723             {
724                 tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,
725                                                     NULL,
726                                                     p_QmPortal,
727                                                     p_Dq->fqid,
728                                                     (t_DpaaFD*)&p_Dq->fd);
729                 if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
730                     res = qman_cb_dqrr_pause;
731             }
732         }
733 
734         /* Parking isn't possible unless HELDACTIVE was set. NB,
735          * FORCEELIGIBLE implies HELDACTIVE, so we only need to
736          * check for HELDACTIVE to cover both. */
737         ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||
738                     (res != qman_cb_dqrr_park));
739         if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) {
740             /* Defer just means "skip it, I'll consume it myself later on" */
741             if (res != qman_cb_dqrr_defer)
742                 qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
743                                            p_Dq,
744                                            (res == qman_cb_dqrr_park));
745             qm_dqrr_next(p_QmPortal->p_LowQmPortal);
746         } else {
747             if (res == qman_cb_dqrr_park)
748                 /* The only thing to do for non-DCA is the park-request */
749                 qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal);
750             qm_dqrr_next(p_QmPortal->p_LowQmPortal);
751             qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
752         }
753     }
754 }
755 
756 static void LoopDequeueRingDcaOptimized(t_Handle h_QmPortal)
757 {
758     struct qm_dqrr_entry        *p_Dq;
759     struct qman_fq              *p_Fq;
760     enum qman_cb_dqrr_result    res = qman_cb_dqrr_consume;
761     e_RxStoreResponse           tmpRes;
762     t_QmPortal                  *p_QmPortal = (t_QmPortal *)h_QmPortal;
763 
764     while (res != qman_cb_dqrr_pause)
765     {
766         qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
767         p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
768         if (!p_Dq)
769             break;
770 	p_Fq = ptr_from_aligned_int(p_Dq->contextB);
771         if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {
772             /* We only set QMAN_FQ_STATE_NE when retiring, so we only need
773              * to check for clearing it when doing volatile dequeues. It's
774              * one less thing to check in the critical path (SDQCR). */
775             tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);
776             if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
777                 res = qman_cb_dqrr_pause;
778             /* Check for VDQCR completion */
779             if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)
780                 p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;
781             if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)
782             {
783                 p_Fq->flags &= ~QMAN_FQ_STATE_NE;
784                 freeDrainedFq(p_Fq);
785             }
786         }
787         else
788         {
789             /* Interpret 'dq' from the owner's perspective. */
790             /* use portal default handlers */
791             ASSERT_COND(p_Dq->fqid);
792             if (p_Fq)
793             {
794                 tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,
795                                        p_Fq->h_QmFqr,
796                                        p_QmPortal,
797                                        p_Fq->fqidOffset,
798                                        (t_DpaaFD*)&p_Dq->fd);
799                 if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
800                     res = qman_cb_dqrr_pause;
801                 else if (p_Fq->state == qman_fq_state_waiting_parked)
802                     res = qman_cb_dqrr_park;
803             }
804             else
805             {
806                 tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,
807                                                     NULL,
808                                                     p_QmPortal,
809                                                     p_Dq->fqid,
810                                                     (t_DpaaFD*)&p_Dq->fd);
811                 if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
812                     res = qman_cb_dqrr_pause;
813             }
814         }
815 
816         /* Parking isn't possible unless HELDACTIVE was set. NB,
817          * FORCEELIGIBLE implies HELDACTIVE, so we only need to
818          * check for HELDACTIVE to cover both. */
819         ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||
820                 (res != qman_cb_dqrr_park));
821         /* Defer just means "skip it, I'll consume it myself later on" */
822         if (res != qman_cb_dqrr_defer)
823             qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
824                                        p_Dq,
825                                        (res == qman_cb_dqrr_park));
826         qm_dqrr_next(p_QmPortal->p_LowQmPortal);
827     }
828 }
829 
830 static void LoopDequeueRingOptimized(t_Handle h_QmPortal)
831 {
832     struct qm_dqrr_entry        *p_Dq;
833     struct qman_fq              *p_Fq;
834     enum qman_cb_dqrr_result    res = qman_cb_dqrr_consume;
835     e_RxStoreResponse           tmpRes;
836     t_QmPortal                  *p_QmPortal = (t_QmPortal *)h_QmPortal;
837 
838     while (res != qman_cb_dqrr_pause)
839     {
840         qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
841         p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
842         if (!p_Dq)
843             break;
844 	p_Fq = ptr_from_aligned_int(p_Dq->contextB);
845         if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) {
846             /* We only set QMAN_FQ_STATE_NE when retiring, so we only need
847              * to check for clearing it when doing volatile dequeues. It's
848              * one less thing to check in the critical path (SDQCR). */
849             tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd);
850             if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
851                 res = qman_cb_dqrr_pause;
852             /* Check for VDQCR completion */
853             if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)
854                 p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR;
855             if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY)
856             {
857                 p_Fq->flags &= ~QMAN_FQ_STATE_NE;
858                 freeDrainedFq(p_Fq);
859             }
860         }
861         else
862         {
863             /* Interpret 'dq' from the owner's perspective. */
864             /* use portal default handlers */
865             ASSERT_COND(p_Dq->fqid);
866             if (p_Fq)
867             {
868                 tmpRes = p_Fq->cb.dqrr(p_Fq->h_App,
869                                        p_Fq->h_QmFqr,
870                                        p_QmPortal,
871                                        p_Fq->fqidOffset,
872                                        (t_DpaaFD*)&p_Dq->fd);
873                 if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
874                     res = qman_cb_dqrr_pause;
875                 else if (p_Fq->state == qman_fq_state_waiting_parked)
876                     res = qman_cb_dqrr_park;
877             }
878             else
879             {
880                 tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App,
881                                                     NULL,
882                                                     p_QmPortal,
883                                                     p_Dq->fqid,
884                                                     (t_DpaaFD*)&p_Dq->fd);
885                 if (tmpRes == e_RX_STORE_RESPONSE_PAUSE)
886                     res = qman_cb_dqrr_pause;
887             }
888         }
889 
890         /* Parking isn't possible unless HELDACTIVE was set. NB,
891          * FORCEELIGIBLE implies HELDACTIVE, so we only need to
892          * check for HELDACTIVE to cover both. */
893         ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||
894                 (res != qman_cb_dqrr_park));
895         if (res == qman_cb_dqrr_park)
896             /* The only thing to do for non-DCA is the park-request */
897             qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal);
898         qm_dqrr_next(p_QmPortal->p_LowQmPortal);
899         qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
900     }
901 }
902 
903 /* Portal interrupt handler */
904 static void portal_isr(void *ptr)
905 {
906     t_QmPortal  *p_QmPortal = ptr;
907     uint32_t    event = 0;
908     uint32_t    enableEvents = qm_isr_enable_read(p_QmPortal->p_LowQmPortal);
909 
910     DBG(TRACE, ("software-portal %d got interrupt", p_QmPortal->p_LowQmPortal->config.cpu));
911 
912     event |= (qm_isr_status_read(p_QmPortal->p_LowQmPortal) &
913             enableEvents);
914 
915     qm_isr_status_clear(p_QmPortal->p_LowQmPortal, event);
916     /* Only do fast-path handling if it's required */
917     if (/*(event & QM_PIRQ_DQRI) &&*/
918         (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_FAST))
919         p_QmPortal->f_LoopDequeueRingCB(p_QmPortal);
920     if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_SLOW)
921         LoopMessageRing(p_QmPortal, event);
922 }
923 
924 
925 static t_Error qman_query_fq_np(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq, struct qm_mcr_queryfq_np *p_Np)
926 {
927     struct qm_mc_command    *p_Mcc;
928     struct qm_mc_result     *p_Mcr;
929     uint8_t                 res;
930 
931     NCSW_PLOCK(p_QmPortal);
932     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
933     p_Mcc->queryfq_np.fqid = p_Fq->fqid;
934     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP);
935     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
936     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP);
937     res = p_Mcr->result;
938     if (res == QM_MCR_RESULT_OK)
939         *p_Np = p_Mcr->queryfq_np;
940     PUNLOCK(p_QmPortal);
941     if (res != QM_MCR_RESULT_OK)
942         RETURN_ERROR(MINOR, E_INVALID_STATE, ("QUERYFQ_NP failed: %s\n", mcr_result_str(res)));
943     return E_OK;
944 }
945 
946 static uint8_t QmCgGetCgId(t_Handle h_QmCg)
947 {
948    t_QmCg *p_QmCg = (t_QmCg *)h_QmCg;
949 
950    return p_QmCg->id;
951 
952 }
953 
954 static t_Error qm_new_fq(t_QmPortal                         *p_QmPortal,
955                          uint32_t                           fqid,
956                          uint32_t                           fqidOffset,
957                          uint32_t                           channel,
958                          uint32_t                           wqid,
959                          uint16_t                           count,
960                          uint32_t                           flags,
961                          t_QmFqrCongestionAvoidanceParams   *p_CgParams,
962                          t_QmContextA                       *p_ContextA,
963                          t_QmContextB                       *p_ContextB,
964                          bool                               initParked,
965                          t_Handle                           h_QmFqr,
966                          struct qman_fq                     **p_Fqs)
967 {
968     struct qman_fq          *p_Fq = NULL;
969     struct qm_mcc_initfq    fq_opts;
970     uint32_t                i;
971     t_Error                 err = E_OK;
972     int         gap, tmp;
973     uint32_t    tmpA, tmpN, ta=0, tn=0, initFqFlag;
974 
975     ASSERT_COND(p_QmPortal);
976     ASSERT_COND(count);
977 
978     for(i=0;i<count;i++)
979     {
980         p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64);
981         if (!p_Fq)
982             RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));
983         memset(p_Fq, 0, sizeof(struct qman_fq));
984         p_Fq->cb.dqrr     = p_QmPortal->f_DfltFrame;
985         p_Fq->cb.ern      = p_QmPortal->f_RejectedFrame;
986         p_Fq->cb.dc_ern   = cb_ern_dcErn;
987         p_Fq->cb.fqs      = cb_fqs;
988         p_Fq->h_App       = p_QmPortal->h_App;
989         p_Fq->h_QmFqr     = h_QmFqr;
990         p_Fq->fqidOffset  = fqidOffset;
991         p_Fqs[i] = p_Fq;
992         if ((err = qman_create_fq(p_QmPortal,(uint32_t)(fqid + i), 0, p_Fqs[i])) != E_OK)
993             break;
994     }
995 
996     if (err != E_OK)
997     {
998         for(i=0;i<count;i++)
999             if (p_Fqs[i])
1000             {
1001                 XX_FreeSmart(p_Fqs[i]);
1002                 p_Fqs[i] = NULL;
1003             }
1004         RETURN_ERROR(MINOR, err, ("Failed to create Fqs"));
1005     }
1006 
1007     memset(&fq_opts,0,sizeof(fq_opts));
1008     fq_opts.fqid = fqid;
1009     fq_opts.count = (uint16_t)(count-1);
1010     fq_opts.we_mask |= QM_INITFQ_WE_DESTWQ;
1011     fq_opts.fqd.dest.channel = channel;
1012     fq_opts.fqd.dest.wq = wqid;
1013     fq_opts.we_mask |= QM_INITFQ_WE_FQCTRL;
1014     fq_opts.fqd.fq_ctrl = (uint16_t)flags;
1015 
1016     if ((flags & QM_FQCTRL_CGE) || (flags & QM_FQCTRL_TDE))
1017         ASSERT_COND(p_CgParams);
1018 
1019     if(flags & QM_FQCTRL_CGE)
1020     {
1021         ASSERT_COND(p_CgParams->h_QmCg);
1022 
1023         /* CG OAC and FQ TD may not be configured at the same time. if both are required,
1024            than we configure CG first, and the FQ TD later - see below. */
1025         fq_opts.fqd.cgid = QmCgGetCgId(p_CgParams->h_QmCg);
1026         fq_opts.we_mask |= QM_INITFQ_WE_CGID;
1027         if(p_CgParams->overheadAccountingLength)
1028         {
1029             fq_opts.we_mask |= QM_INITFQ_WE_OAC;
1030             fq_opts.we_mask &= ~QM_INITFQ_WE_TDTHRESH;
1031             fq_opts.fqd.td_thresh = (uint16_t)(QM_FQD_TD_THRESH_OAC_EN | p_CgParams->overheadAccountingLength);
1032         }
1033     }
1034     if((flags & QM_FQCTRL_TDE) && (!p_CgParams->overheadAccountingLength))
1035     {
1036         ASSERT_COND(p_CgParams->fqTailDropThreshold);
1037 
1038         fq_opts.we_mask |= QM_INITFQ_WE_TDTHRESH;
1039 
1040             /* express thresh as ta*2^tn */
1041             gap = (int)p_CgParams->fqTailDropThreshold;
1042             for (tmpA=0 ; tmpA<256; tmpA++ )
1043                 for (tmpN=0 ; tmpN<32; tmpN++ )
1044                 {
1045                     tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<<tmpN)));
1046                     if (tmp < gap)
1047                     {
1048                        ta = tmpA;
1049                        tn = tmpN;
1050                        gap = tmp;
1051                     }
1052                 }
1053             fq_opts.fqd.td.exp = tn;
1054             fq_opts.fqd.td.mant = ta;
1055     }
1056 
1057     if (p_ContextA)
1058     {
1059         fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTA;
1060         memcpy((void*)&fq_opts.fqd.context_a, p_ContextA, sizeof(t_QmContextA));
1061     }
1062     /* If this FQ will not be used for tx, we can use contextB field */
1063     if (fq_opts.fqd.dest.channel < e_QM_FQ_CHANNEL_FMAN0_SP0)
1064     {
1065             fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTB;
1066             fq_opts.fqd.context_b = aligned_int_from_ptr(p_Fqs[0]);
1067     }
1068     else if (p_ContextB) /* Tx-Queue */
1069     {
1070         fq_opts.we_mask |= QM_INITFQ_WE_CONTEXTB;
1071         memcpy((void*)&fq_opts.fqd.context_b, p_ContextB, sizeof(t_QmContextB));
1072     }
1073 
1074     if((flags & QM_FQCTRL_TDE) && (p_CgParams->overheadAccountingLength))
1075         initFqFlag = 0;
1076     else
1077         initFqFlag = (uint32_t)(initParked?0:QMAN_INITFQ_FLAG_SCHED);
1078 
1079     if ((err = qman_init_fq(p_QmPortal, p_Fqs[0], initFqFlag, &fq_opts)) != E_OK)
1080     {
1081         for(i=0;i<count;i++)
1082             if (p_Fqs[i])
1083             {
1084                 XX_FreeSmart(p_Fqs[i]);
1085                 p_Fqs[i] = NULL;
1086             }
1087         RETURN_ERROR(MINOR, err, ("Failed to init Fqs [%d-%d]", fqid, fqid+count-1));
1088     }
1089 
1090     /* if both CG OAC and FQ TD are needed, we call qman_init_fq again, this time for the FQ TD only */
1091     if((flags & QM_FQCTRL_TDE) && (p_CgParams->overheadAccountingLength))
1092     {
1093         ASSERT_COND(p_CgParams->fqTailDropThreshold);
1094 
1095         fq_opts.we_mask = QM_INITFQ_WE_TDTHRESH;
1096 
1097         /* express thresh as ta*2^tn */
1098         gap = (int)p_CgParams->fqTailDropThreshold;
1099         for (tmpA=0 ; tmpA<256; tmpA++ )
1100             for (tmpN=0 ; tmpN<32; tmpN++ )
1101             {
1102                 tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<<tmpN)));
1103                 if (tmp < gap)
1104                 {
1105                    ta = tmpA;
1106                    tn = tmpN;
1107                    gap = tmp;
1108                 }
1109             }
1110         fq_opts.fqd.td.exp = tn;
1111         fq_opts.fqd.td.mant = ta;
1112         if ((err = qman_init_fq(p_QmPortal, p_Fqs[0], (uint32_t)(initParked?0:QMAN_INITFQ_FLAG_SCHED), &fq_opts)) != E_OK)
1113         {
1114             for(i=0;i<count;i++)
1115                 if (p_Fqs[i])
1116                 {
1117                     XX_FreeSmart(p_Fqs[i]);
1118                     p_Fqs[i] = NULL;
1119                 }
1120             RETURN_ERROR(MINOR, err, ("Failed to init Fqs"));
1121         }
1122     }
1123 
1124 
1125     for(i=1;i<count;i++)
1126     {
1127         memcpy(p_Fqs[i], p_Fqs[0], sizeof(struct qman_fq));
1128         p_Fqs[i]->fqid += i;
1129     }
1130 
1131     return err;
1132 }
1133 
1134 
1135 static t_Error qm_free_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq)
1136 {
1137     uint32_t flags=0;
1138 
1139     if (qman_retire_fq(p_QmPortal, p_Fq, &flags, false) != E_OK)
1140         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!"));
1141 
1142     if (flags & QMAN_FQ_STATE_CHANGING)
1143         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("fq %d currently in use, will be retired", p_Fq->fqid));
1144 
1145     if (flags & QMAN_FQ_STATE_NE)
1146         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed;" \
1147                                           "Frame Queue Not Empty, Need to dequeue"));
1148 
1149     if (qman_oos_fq(p_QmPortal, p_Fq) != E_OK)
1150         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!"));
1151 
1152     qman_destroy_fq(p_Fq,0);
1153 
1154     return E_OK;
1155 }
1156 
1157 static void qman_disable_portal(t_QmPortal *p_QmPortal)
1158 {
1159     NCSW_PLOCK(p_QmPortal);
1160     if (!(p_QmPortal->disable_count++))
1161         qm_dqrr_set_maxfill(p_QmPortal->p_LowQmPortal, 0);
1162     PUNLOCK(p_QmPortal);
1163 }
1164 
1165 
1166 /* quiesce SDQCR/VDQCR, then drain till h/w wraps up anything it
1167  * was doing (5ms is more than enough to ensure it's done). */
1168 static void clean_dqrr_mr(t_QmPortal *p_QmPortal)
1169 {
1170     struct qm_dqrr_entry    *p_Dq;
1171     struct qm_mr_entry      *p_Msg;
1172     int                     idle = 0;
1173 
1174     qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, 0);
1175     qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, 0);
1176 drain_loop:
1177     qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1178     qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1179     qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal);
1180     p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1181     p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal);
1182     if (p_Dq) {
1183         qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1184         qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1185     }
1186     if (p_Msg) {
1187     qm_mr_next(p_QmPortal->p_LowQmPortal);
1188         qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1189     }
1190     if (!p_Dq && !p_Msg) {
1191     if (++idle < 5) {
1192     XX_UDelay(1000);
1193     goto drain_loop;
1194     }
1195     } else {
1196     idle = 0;
1197     goto drain_loop;
1198     }
1199 }
1200 
1201 static t_Error qman_create_portal(t_QmPortal *p_QmPortal,
1202                                    uint32_t flags,
1203                                    uint32_t sdqcrFlags,
1204                                    uint8_t  dqrrSize)
1205 {
1206     const struct qm_portal_config   *p_Config = &(p_QmPortal->p_LowQmPortal->config);
1207     int                             ret = 0;
1208     t_Error                         err;
1209     uint32_t                        isdr;
1210 
1211     if ((err = qm_eqcr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalEqcrCCE)) != E_OK)
1212         RETURN_ERROR(MINOR, err, ("Qman EQCR initialization failed\n"));
1213 
1214     if (qm_dqrr_init(p_QmPortal->p_LowQmPortal,
1215                      sdqcrFlags ? e_QmPortalDequeuePushMode : e_QmPortalDequeuePullMode,
1216                      e_QmPortalPVB,
1217                      (flags & QMAN_PORTAL_FLAG_DCA) ? e_QmPortalDqrrDCA : e_QmPortalDqrrCCI,
1218                      dqrrSize,
1219                      (flags & QMAN_PORTAL_FLAG_RSTASH) ? 1 : 0,
1220                      (flags & QMAN_PORTAL_FLAG_DSTASH) ? 1 : 0)) {
1221         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR initialization failed"));
1222         goto fail_dqrr;
1223     }
1224 
1225     if (qm_mr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalMrCCI)) {
1226         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR initialization failed"));
1227         goto fail_mr;
1228     }
1229     if (qm_mc_init(p_QmPortal->p_LowQmPortal)) {
1230         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MC initialization failed"));
1231         goto fail_mc;
1232     }
1233     if (qm_isr_init(p_QmPortal->p_LowQmPortal)) {
1234         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("ISR initialization failed"));
1235         goto fail_isr;
1236     }
1237     /* static interrupt-gating controls */
1238     qm_dqrr_set_ithresh(p_QmPortal->p_LowQmPortal, 12);
1239     qm_mr_set_ithresh(p_QmPortal->p_LowQmPortal, 4);
1240     qm_isr_set_iperiod(p_QmPortal->p_LowQmPortal, 100);
1241     p_QmPortal->options = flags;
1242     isdr = 0xffffffff;
1243     qm_isr_status_clear(p_QmPortal->p_LowQmPortal, 0xffffffff);
1244     qm_isr_enable_write(p_QmPortal->p_LowQmPortal, DEFAULT_portalExceptions);
1245     qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);
1246     if (flags & QMAN_PORTAL_FLAG_IRQ)
1247     {
1248         XX_SetIntr(p_Config->irq, portal_isr, p_QmPortal);
1249         XX_EnableIntr(p_Config->irq);
1250         qm_isr_uninhibit(p_QmPortal->p_LowQmPortal);
1251     } else
1252         /* without IRQ, we can't block */
1253         flags &= ~QMAN_PORTAL_FLAG_WAIT;
1254     /* Need EQCR to be empty before continuing */
1255     isdr ^= QM_PIRQ_EQCI;
1256     qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);
1257     ret = qm_eqcr_get_fill(p_QmPortal->p_LowQmPortal);
1258     if (ret) {
1259         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("EQCR unclean"));
1260         goto fail_eqcr_empty;
1261     }
1262     isdr ^= (QM_PIRQ_DQRI | QM_PIRQ_MRI);
1263     qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr);
1264     if (qm_dqrr_current(p_QmPortal->p_LowQmPortal) != NULL)
1265     {
1266         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR unclean"));
1267 goto fail_dqrr_mr_empty;
1268     }
1269     if (qm_mr_current(p_QmPortal->p_LowQmPortal) != NULL)
1270     {
1271         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR unclean"));
1272 goto fail_dqrr_mr_empty;
1273     }
1274     qm_isr_disable_write(p_QmPortal->p_LowQmPortal, 0);
1275     qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags);
1276     return E_OK;
1277 fail_dqrr_mr_empty:
1278 fail_eqcr_empty:
1279     qm_isr_finish(p_QmPortal->p_LowQmPortal);
1280 fail_isr:
1281     qm_mc_finish(p_QmPortal->p_LowQmPortal);
1282 fail_mc:
1283     qm_mr_finish(p_QmPortal->p_LowQmPortal);
1284 fail_mr:
1285     qm_dqrr_finish(p_QmPortal->p_LowQmPortal);
1286 fail_dqrr:
1287     qm_eqcr_finish(p_QmPortal->p_LowQmPortal);
1288     return ERROR_CODE(E_INVALID_STATE);
1289 }
1290 
1291 static void qman_destroy_portal(t_QmPortal *p_QmPortal)
1292 {
1293     /* NB we do this to "quiesce" EQCR. If we add enqueue-completions or
1294      * something related to QM_PIRQ_EQCI, this may need fixing. */
1295     qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);
1296     if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ)
1297     {
1298         XX_DisableIntr(p_QmPortal->p_LowQmPortal->config.irq);
1299         XX_FreeIntr(p_QmPortal->p_LowQmPortal->config.irq);
1300     }
1301     qm_isr_finish(p_QmPortal->p_LowQmPortal);
1302     qm_mc_finish(p_QmPortal->p_LowQmPortal);
1303     qm_mr_finish(p_QmPortal->p_LowQmPortal);
1304     qm_dqrr_finish(p_QmPortal->p_LowQmPortal);
1305     qm_eqcr_finish(p_QmPortal->p_LowQmPortal);
1306 }
1307 
1308 static inline struct qm_eqcr_entry *try_eq_start(t_QmPortal *p_QmPortal)
1309 {
1310     struct qm_eqcr_entry    *p_Eq;
1311     uint8_t                 avail;
1312 
1313     avail = qm_eqcr_get_avail(p_QmPortal->p_LowQmPortal);
1314     if (avail == EQCR_THRESH)
1315         qmPortalEqcrCcePrefetch(p_QmPortal->p_LowQmPortal);
1316     else if (avail < EQCR_THRESH)
1317             qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal);
1318     p_Eq = qm_eqcr_start(p_QmPortal->p_LowQmPortal);
1319 
1320     return p_Eq;
1321 }
1322 
1323 
1324 static t_Error qman_orp_update(t_QmPortal   *p_QmPortal,
1325                                uint32_t     orpId,
1326                                uint16_t     orpSeqnum,
1327                                uint32_t     flags)
1328 {
1329     struct qm_eqcr_entry *p_Eq;
1330 
1331     NCSW_PLOCK(p_QmPortal);
1332     p_Eq = try_eq_start(p_QmPortal);
1333     if (!p_Eq)
1334     {
1335         PUNLOCK(p_QmPortal);
1336         return ERROR_CODE(E_BUSY);
1337     }
1338 
1339     if (flags & QMAN_ENQUEUE_FLAG_NESN)
1340         orpSeqnum |= QM_EQCR_SEQNUM_NESN;
1341     else
1342         /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */
1343         orpSeqnum &= ~QM_EQCR_SEQNUM_NESN;
1344     p_Eq->seqnum  = orpSeqnum;
1345     p_Eq->orp     = orpId;
1346 qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal, (uint8_t)QM_EQCR_VERB_ORP);
1347 
1348     PUNLOCK(p_QmPortal);
1349     return E_OK;
1350 }
1351 
1352 static __inline__ t_Error CheckStashParams(t_QmFqrParams *p_QmFqrParams)
1353 {
1354     ASSERT_COND(p_QmFqrParams);
1355 
1356     if (p_QmFqrParams->stashingParams.frameAnnotationSize > QM_CONTEXTA_MAX_STASH_SIZE)
1357         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Annotation Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));
1358     if (p_QmFqrParams->stashingParams.frameDataSize > QM_CONTEXTA_MAX_STASH_SIZE)
1359         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Data Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));
1360     if (p_QmFqrParams->stashingParams.fqContextSize > QM_CONTEXTA_MAX_STASH_SIZE)
1361         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Context Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE));
1362     if (p_QmFqrParams->stashingParams.fqContextSize)
1363     {
1364         if (!p_QmFqrParams->stashingParams.fqContextAddr)
1365             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be givven"));
1366         if (!IS_ALIGNED(p_QmFqrParams->stashingParams.fqContextAddr, CACHELINE_SIZE))
1367             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be aligned to %d", CACHELINE_SIZE));
1368         if (p_QmFqrParams->stashingParams.fqContextAddr & 0xffffff0000000000LL)
1369             RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address May be up to 40 bit"));
1370     }
1371 
1372     return E_OK;
1373 }
1374 
1375 static t_Error QmPortalRegisterCg(t_Handle h_QmPortal, t_Handle h_QmCg, uint8_t  cgId)
1376 {
1377     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1378 
1379     /* cgrs[0] is the mask of registered CG's*/
1380     if(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32)))
1381         RETURN_ERROR(MINOR, E_BUSY, ("CG already used"));
1382 
1383     p_QmPortal->cgrs[0].q.__state[cgId/32] |=  0x80000000 >> (cgId % 32);
1384     p_QmPortal->cgsHandles[cgId] = h_QmCg;
1385 
1386     return E_OK;
1387 }
1388 
1389 static t_Error QmPortalUnregisterCg(t_Handle h_QmPortal, uint8_t  cgId)
1390 {
1391     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1392 
1393     /* cgrs[0] is the mask of registered CG's*/
1394     if(!(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32))))
1395         RETURN_ERROR(MINOR, E_BUSY, ("CG is not in use"));
1396 
1397     p_QmPortal->cgrs[0].q.__state[cgId/32] &=  ~0x80000000 >> (cgId % 32);
1398     p_QmPortal->cgsHandles[cgId] = NULL;
1399 
1400     return E_OK;
1401 }
1402 
1403 static e_DpaaSwPortal QmPortalGetSwPortalId(t_Handle h_QmPortal)
1404 {
1405     t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal;
1406 
1407     return (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu;
1408 }
1409 
1410 static t_Error CalcWredCurve(t_QmCgWredCurve *p_WredCurve, uint32_t  *p_CurveWord)
1411 {
1412     uint32_t    maxP, roundDown, roundUp, tmpA, tmpN;
1413     uint32_t    ma=0, mn=0, slope, sa=0, sn=0, pn;
1414     int         pres = 1000;
1415     int         gap, tmp;
1416 
1417 /*  TODO - change maxTh to uint64_t?
1418    if(p_WredCurve->maxTh > (1<<39))
1419         RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh is not in range"));*/
1420 
1421     /* express maxTh as ma*2^mn */
1422      gap = (int)p_WredCurve->maxTh;
1423      for (tmpA=0 ; tmpA<256; tmpA++ )
1424          for (tmpN=0 ; tmpN<32; tmpN++ )
1425          {
1426              tmp = ABS((int)(p_WredCurve->maxTh - tmpA*(1<<tmpN)));
1427              if (tmp < gap)
1428              {
1429                 ma = tmpA;
1430                 mn = tmpN;
1431                 gap = tmp;
1432              }
1433          }
1434      ASSERT_COND(ma <256);
1435      ASSERT_COND(mn <32);
1436      p_WredCurve->maxTh = ma*(1<<mn);
1437 
1438      if(p_WredCurve->maxTh <= p_WredCurve->minTh)
1439         RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh must be larger than minTh"));
1440      if(p_WredCurve->probabilityDenominator > 64)
1441         RETURN_ERROR(MINOR, E_INVALID_VALUE, ("probabilityDenominator mustn't be 1-64"));
1442 
1443     /* first we translate from Cisco probabilityDenominator
1444        to 256 fixed denominator, result must be divisible by 4. */
1445     /* we multiply by a fixed value to get better accuracy (without
1446        using floating point) */
1447     maxP = (uint32_t)(256*1000/p_WredCurve->probabilityDenominator);
1448     if (maxP % 4*pres)
1449     {
1450         roundDown  = maxP + (maxP % (4*pres));
1451         roundUp = roundDown + 4*pres;
1452         if((roundUp - maxP) > (maxP - roundDown))
1453             maxP = roundDown;
1454         else
1455             maxP = roundUp;
1456     }
1457     maxP = maxP/pres;
1458     ASSERT_COND(maxP <= 256);
1459     pn = (uint8_t)(maxP/4 - 1);
1460 
1461     if(maxP >= (p_WredCurve->maxTh - p_WredCurve->minTh))
1462         RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Due to probabilityDenominator selected, maxTh-minTh must be larger than %d", maxP));
1463 
1464     pres = 1000000;
1465     slope = maxP*pres/(p_WredCurve->maxTh - p_WredCurve->minTh);
1466     /* express slope as sa/2^sn */
1467     gap = (int)slope;
1468     for (tmpA=(uint32_t)(64*pres) ; tmpA<128*pres; tmpA += pres )
1469         for (tmpN=7 ; tmpN<64; tmpN++ )
1470         {
1471             tmp = ABS((int)(slope - tmpA/(1UL<<(tmpN%32))));
1472             if (tmp < gap)
1473             {
1474                sa = tmpA;
1475                sn = tmpN;
1476                gap = tmp;
1477             }
1478         }
1479     sa = sa/pres;
1480     ASSERT_COND(sa<128 && sa>=64);
1481     ASSERT_COND(sn<64 && sn>=7);
1482 
1483     *p_CurveWord = ((ma << 24) |
1484                     (mn << 19) |
1485                     (sa << 12) |
1486                     (sn << 6) |
1487                     pn);
1488 
1489     return E_OK;
1490 }
1491 
1492 static t_Error QmPortalPullFrame(t_Handle h_QmPortal, uint32_t pdqcr, t_DpaaFD *p_Frame)
1493 {
1494     t_QmPortal              *p_QmPortal = (t_QmPortal *)h_QmPortal;
1495     struct qm_dqrr_entry    *p_Dq;
1496     struct qman_fq          *p_Fq;
1497     int                     prefetch;
1498     uint32_t                *p_Dst, *p_Src;
1499 
1500     ASSERT_COND(p_QmPortal);
1501     ASSERT_COND(p_Frame);
1502     SANITY_CHECK_RETURN_ERROR(p_QmPortal->pullMode, E_INVALID_STATE);
1503 
1504     NCSW_PLOCK(p_QmPortal);
1505 
1506     qm_dqrr_pdqcr_set(p_QmPortal->p_LowQmPortal, pdqcr);
1507     mb();
1508     while (qm_dqrr_pdqcr_get(p_QmPortal->p_LowQmPortal)) ;
1509 
1510     prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
1511     while(TRUE)
1512     {
1513         if (prefetch)
1514             qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1515         qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1516         p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1517         if (!p_Dq)
1518             continue;
1519         p_Fq = ptr_from_aligned_int(p_Dq->contextB);
1520         ASSERT_COND(p_Dq->fqid);
1521         p_Dst = (uint32_t *)p_Frame;
1522         p_Src = (uint32_t *)&p_Dq->fd;
1523         p_Dst[0] = p_Src[0];
1524         p_Dst[1] = p_Src[1];
1525         p_Dst[2] = p_Src[2];
1526         p_Dst[3] = p_Src[3];
1527         if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA)
1528         {
1529             qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
1530                                        p_Dq,
1531                                        false);
1532             qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1533         }
1534         else
1535         {
1536             qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1537             qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1538         }
1539         break;
1540     }
1541 
1542     PUNLOCK(p_QmPortal);
1543 
1544     if (!(p_Dq->stat & QM_DQRR_STAT_FD_VALID))
1545         return ERROR_CODE(E_EMPTY);
1546 
1547     return E_OK;
1548 }
1549 
1550 
1551 /****************************************/
1552 /*       API Init unit functions        */
1553 /****************************************/
1554 t_Handle QM_PORTAL_Config(t_QmPortalParam *p_QmPortalParam)
1555 {
1556     t_QmPortal          *p_QmPortal;
1557     uint32_t            i;
1558 
1559     SANITY_CHECK_RETURN_VALUE(p_QmPortalParam, E_INVALID_HANDLE, NULL);
1560     SANITY_CHECK_RETURN_VALUE(p_QmPortalParam->swPortalId < DPAA_MAX_NUM_OF_SW_PORTALS, E_INVALID_VALUE, 0);
1561 
1562     p_QmPortal = (t_QmPortal *)XX_Malloc(sizeof(t_QmPortal));
1563     if (!p_QmPortal)
1564     {
1565         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal obj!!!"));
1566         return NULL;
1567     }
1568     memset(p_QmPortal, 0, sizeof(t_QmPortal));
1569 
1570     p_QmPortal->p_LowQmPortal = (struct qm_portal *)XX_Malloc(sizeof(struct qm_portal));
1571     if (!p_QmPortal->p_LowQmPortal)
1572     {
1573         XX_Free(p_QmPortal);
1574         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Low qm p_QmPortal obj!!!"));
1575         return NULL;
1576     }
1577     memset(p_QmPortal->p_LowQmPortal, 0, sizeof(struct qm_portal));
1578 
1579     p_QmPortal->p_QmPortalDriverParams = (t_QmPortalDriverParams *)XX_Malloc(sizeof(t_QmPortalDriverParams));
1580     if (!p_QmPortal->p_QmPortalDriverParams)
1581     {
1582         XX_Free(p_QmPortal->p_LowQmPortal);
1583         XX_Free(p_QmPortal);
1584         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal driver parameters"));
1585         return NULL;
1586     }
1587     memset(p_QmPortal->p_QmPortalDriverParams, 0, sizeof(t_QmPortalDriverParams));
1588 
1589     p_QmPortal->p_LowQmPortal->addr.addr_ce = UINT_TO_PTR(p_QmPortalParam->ceBaseAddress);
1590     p_QmPortal->p_LowQmPortal->addr.addr_ci = UINT_TO_PTR(p_QmPortalParam->ciBaseAddress);
1591     p_QmPortal->p_LowQmPortal->config.irq = p_QmPortalParam->irq;
1592     p_QmPortal->p_LowQmPortal->config.bound = 0;
1593     p_QmPortal->p_LowQmPortal->config.cpu = (int)p_QmPortalParam->swPortalId;
1594     p_QmPortal->p_LowQmPortal->config.channel = (e_QmFQChannel)(e_QM_FQ_CHANNEL_SWPORTAL0 + p_QmPortalParam->swPortalId);
1595     p_QmPortal->p_LowQmPortal->bind_lock = XX_InitSpinlock();
1596 
1597     p_QmPortal->h_Qm                = p_QmPortalParam->h_Qm;
1598     p_QmPortal->f_DfltFrame         = p_QmPortalParam->f_DfltFrame;
1599     p_QmPortal->f_RejectedFrame     = p_QmPortalParam->f_RejectedFrame;
1600     p_QmPortal->h_App               = p_QmPortalParam->h_App;
1601 
1602     p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset           = p_QmPortalParam->fdLiodnOffset;
1603     p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode          = DEFAULT_dequeueDcaMode;
1604     p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames  = DEFAULT_dequeueUpToThreeFrames;
1605     p_QmPortal->p_QmPortalDriverParams->commandType             = DEFAULT_dequeueCommandType;
1606     p_QmPortal->p_QmPortalDriverParams->userToken               = DEFAULT_dequeueUserToken;
1607     p_QmPortal->p_QmPortalDriverParams->specifiedWq             = DEFAULT_dequeueSpecifiedWq;
1608     p_QmPortal->p_QmPortalDriverParams->dedicatedChannel        = DEFAULT_dequeueDedicatedChannel;
1609     p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels =
1610         DEFAULT_dequeueDedicatedChannelHasPrecedenceOverPoolChannels;
1611     p_QmPortal->p_QmPortalDriverParams->poolChannelId           = DEFAULT_dequeuePoolChannelId;
1612     p_QmPortal->p_QmPortalDriverParams->wqId                    = DEFAULT_dequeueWqId;
1613     for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)
1614         p_QmPortal->p_QmPortalDriverParams->poolChannels[i] = FALSE;
1615     p_QmPortal->p_QmPortalDriverParams->dqrrSize                = DEFAULT_dqrrSize;
1616     p_QmPortal->p_QmPortalDriverParams->pullMode                = DEFAULT_pullMode;
1617 
1618     return p_QmPortal;
1619 }
1620 
1621 t_Error QM_PORTAL_Init(t_Handle h_QmPortal)
1622 {
1623     t_QmPortal                          *p_QmPortal = (t_QmPortal *)h_QmPortal;
1624     uint32_t                            i, flags=0, sdqcrFlags=0;
1625     t_Error                             err;
1626     t_QmInterModulePortalInitParams     qmParams;
1627 
1628     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1629     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);
1630 
1631     memset(&qmParams, 0, sizeof(qmParams));
1632     qmParams.portalId       = (uint8_t)p_QmPortal->p_LowQmPortal->config.cpu;
1633     qmParams.liodn          = p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset;
1634     qmParams.dqrrLiodn      = p_QmPortal->p_QmPortalDriverParams->dqrrLiodn;
1635     qmParams.fdFqLiodn      = p_QmPortal->p_QmPortalDriverParams->fdFqLiodn;
1636     qmParams.stashDestQueue = p_QmPortal->p_QmPortalDriverParams->stashDestQueue;
1637     if ((err = QmGetSetPortalParams(p_QmPortal->h_Qm, &qmParams)) != E_OK)
1638         RETURN_ERROR(MAJOR, err, NO_MSG);
1639 
1640     flags = (uint32_t)(((p_QmPortal->p_LowQmPortal->config.irq == NO_IRQ) ?
1641             0 :
1642             (QMAN_PORTAL_FLAG_IRQ |
1643              QMAN_PORTAL_FLAG_IRQ_FAST |
1644              QMAN_PORTAL_FLAG_IRQ_SLOW)));
1645     flags |= ((p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode) ? QMAN_PORTAL_FLAG_DCA : 0);
1646     flags |= (p_QmPortal->p_QmPortalDriverParams->dqrr)?QMAN_PORTAL_FLAG_RSTASH:0;
1647     flags |= (p_QmPortal->p_QmPortalDriverParams->fdFq)?QMAN_PORTAL_FLAG_DSTASH:0;
1648 
1649     p_QmPortal->pullMode = p_QmPortal->p_QmPortalDriverParams->pullMode;
1650     if (!p_QmPortal->pullMode)
1651     {
1652         sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames) ? QM_SDQCR_COUNT_UPTO3 : QM_SDQCR_COUNT_EXACT1;
1653         sdqcrFlags |= QM_SDQCR_TOKEN_SET(p_QmPortal->p_QmPortalDriverParams->userToken);
1654         sdqcrFlags |= QM_SDQCR_TYPE_SET(p_QmPortal->p_QmPortalDriverParams->commandType);
1655         if (!p_QmPortal->p_QmPortalDriverParams->specifiedWq)
1656         {
1657             /* sdqcrFlags |= QM_SDQCR_SOURCE_CHANNELS;*/ /* removed as the macro is '0' */
1658             sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels) ? QM_SDQCR_DEDICATED_PRECEDENCE : 0;
1659             sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ? QM_SDQCR_CHANNELS_DEDICATED : 0;
1660             for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)
1661                 sdqcrFlags |= ((p_QmPortal->p_QmPortalDriverParams->poolChannels[i]) ?
1662                      QM_SDQCR_CHANNELS_POOL(i+1) : 0);
1663         }
1664         else
1665         {
1666             sdqcrFlags |= QM_SDQCR_SOURCE_SPECIFICWQ;
1667             sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ?
1668                             QM_SDQCR_SPECIFICWQ_DEDICATED : QM_SDQCR_SPECIFICWQ_POOL(p_QmPortal->p_QmPortalDriverParams->poolChannelId);
1669             sdqcrFlags |= QM_SDQCR_SPECIFICWQ_WQ(p_QmPortal->p_QmPortalDriverParams->wqId);
1670         }
1671     }
1672     if ((flags & QMAN_PORTAL_FLAG_RSTASH) && (flags & QMAN_PORTAL_FLAG_DCA))
1673         p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingDcaOptimized;
1674     else if ((flags & QMAN_PORTAL_FLAG_RSTASH) && !(flags & QMAN_PORTAL_FLAG_DCA))
1675         p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingOptimized;
1676     else
1677         p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRing;
1678 
1679     if ((!p_QmPortal->f_RejectedFrame) || (!p_QmPortal->f_DfltFrame))
1680         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_RejectedFrame or f_DfltFrame callback not provided"));
1681 
1682     p_QmPortal->p_NullCB = (struct qman_fq_cb *)XX_Malloc(sizeof(struct qman_fq_cb));
1683     if (!p_QmPortal->p_NullCB)
1684         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ Null CB obj!!!"));
1685     memset(p_QmPortal->p_NullCB, 0, sizeof(struct qman_fq_cb));
1686 
1687     p_QmPortal->p_NullCB->dqrr      = p_QmPortal->f_DfltFrame;
1688     p_QmPortal->p_NullCB->ern       = p_QmPortal->f_RejectedFrame;
1689     p_QmPortal->p_NullCB->dc_ern    = p_QmPortal->p_NullCB->fqs = null_cb_mr;
1690 
1691     if (qman_create_portal(p_QmPortal, flags, sdqcrFlags, p_QmPortal->p_QmPortalDriverParams->dqrrSize) != E_OK)
1692     {
1693         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("create portal failed"));
1694     }
1695 
1696     QmSetPortalHandle(p_QmPortal->h_Qm, (t_Handle)p_QmPortal, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);
1697     XX_Free(p_QmPortal->p_QmPortalDriverParams);
1698     p_QmPortal->p_QmPortalDriverParams = NULL;
1699 
1700     DBG(TRACE, ("Qman-Portal %d @ %p:%p",
1701                 p_QmPortal->p_LowQmPortal->config.cpu,
1702                 p_QmPortal->p_LowQmPortal->addr.addr_ce,
1703                 p_QmPortal->p_LowQmPortal->addr.addr_ci
1704                 ));
1705 
1706     DBG(TRACE, ("Qman-Portal %d phys @ 0x%016llx:0x%016llx",
1707                 p_QmPortal->p_LowQmPortal->config.cpu,
1708                 (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ce),
1709                 (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ci)
1710                 ));
1711 
1712     return E_OK;
1713 }
1714 
1715 t_Error QM_PORTAL_Free(t_Handle h_QmPortal)
1716 {
1717     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1718 
1719     if (!p_QmPortal)
1720        return ERROR_CODE(E_INVALID_HANDLE);
1721 
1722     ASSERT_COND(p_QmPortal->p_LowQmPortal);
1723     QmSetPortalHandle(p_QmPortal->h_Qm, NULL, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);
1724     qman_destroy_portal(p_QmPortal);
1725     if (p_QmPortal->p_NullCB)
1726         XX_Free(p_QmPortal->p_NullCB);
1727 
1728     if (p_QmPortal->p_LowQmPortal->bind_lock)
1729         XX_FreeSpinlock(p_QmPortal->p_LowQmPortal->bind_lock);
1730     if(p_QmPortal->p_QmPortalDriverParams)
1731         XX_Free(p_QmPortal->p_QmPortalDriverParams);
1732     XX_Free(p_QmPortal->p_LowQmPortal);
1733     XX_Free(p_QmPortal);
1734 
1735     return E_OK;
1736 }
1737 
1738 t_Error QM_PORTAL_ConfigDcaMode(t_Handle h_QmPortal, bool enable)
1739 {
1740     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1741 
1742     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1743     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);
1744 
1745     p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode = enable;
1746 
1747     return E_OK;
1748 }
1749 
1750 t_Error QM_PORTAL_ConfigStash(t_Handle h_QmPortal, t_QmPortalStashParam *p_StashParams)
1751 {
1752     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1753 
1754     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1755     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);
1756     SANITY_CHECK_RETURN_ERROR(p_StashParams, E_NULL_POINTER);
1757 
1758     p_QmPortal->p_QmPortalDriverParams->stashDestQueue  = p_StashParams->stashDestQueue;
1759     p_QmPortal->p_QmPortalDriverParams->dqrrLiodn       = p_StashParams->dqrrLiodn;
1760     p_QmPortal->p_QmPortalDriverParams->fdFqLiodn       = p_StashParams->fdFqLiodn;
1761     p_QmPortal->p_QmPortalDriverParams->eqcr            = p_StashParams->eqcr;
1762     p_QmPortal->p_QmPortalDriverParams->eqcrHighPri     = p_StashParams->eqcrHighPri;
1763     p_QmPortal->p_QmPortalDriverParams->dqrr            = p_StashParams->dqrr;
1764     p_QmPortal->p_QmPortalDriverParams->dqrrHighPri     = p_StashParams->dqrrHighPri;
1765     p_QmPortal->p_QmPortalDriverParams->fdFq            = p_StashParams->fdFq;
1766     p_QmPortal->p_QmPortalDriverParams->fdFqHighPri     = p_StashParams->fdFqHighPri;
1767     p_QmPortal->p_QmPortalDriverParams->fdFqDrop        = p_StashParams->fdFqDrop;
1768 
1769     return E_OK;
1770 }
1771 
1772 
1773 t_Error QM_PORTAL_ConfigPullMode(t_Handle h_QmPortal, bool pullMode)
1774 {
1775     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1776 
1777     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1778     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);
1779 
1780     p_QmPortal->p_QmPortalDriverParams->pullMode  = pullMode;
1781 
1782     return E_OK;
1783 }
1784 
1785 t_Error QM_PORTAL_AddPoolChannel(t_Handle h_QmPortal, uint8_t poolChannelId)
1786 {
1787     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1788     uint32_t    sdqcrFlags;
1789 
1790     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1791     SANITY_CHECK_RETURN_ERROR((poolChannelId < QM_MAX_NUM_OF_POOL_CHANNELS), E_INVALID_VALUE);
1792 
1793     sdqcrFlags = qm_dqrr_sdqcr_get(p_QmPortal->p_LowQmPortal);
1794     sdqcrFlags |= QM_SDQCR_CHANNELS_POOL(poolChannelId+1);
1795     qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags);
1796 
1797     return E_OK;
1798 }
1799 
1800 t_Error QM_PORTAL_Poll(t_Handle h_QmPortal, e_QmPortalPollSource source)
1801 {
1802     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1803 
1804     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1805 
1806     NCSW_PLOCK(p_QmPortal);
1807 
1808     if ((source == e_QM_PORTAL_POLL_SOURCE_CONTROL_FRAMES) ||
1809         (source == e_QM_PORTAL_POLL_SOURCE_BOTH))
1810     {
1811         uint32_t is = qm_isr_status_read(p_QmPortal->p_LowQmPortal);
1812         uint32_t active = LoopMessageRing(p_QmPortal, is);
1813         if (active)
1814             qm_isr_status_clear(p_QmPortal->p_LowQmPortal, active);
1815     }
1816     if ((source == e_QM_PORTAL_POLL_SOURCE_DATA_FRAMES) ||
1817         (source == e_QM_PORTAL_POLL_SOURCE_BOTH))
1818         p_QmPortal->f_LoopDequeueRingCB((t_Handle)p_QmPortal);
1819 
1820     PUNLOCK(p_QmPortal);
1821 
1822     return E_OK;
1823 }
1824 
1825 t_Error QM_PORTAL_PollFrame(t_Handle h_QmPortal, t_QmPortalFrameInfo *p_frameInfo)
1826 {
1827     t_QmPortal              *p_QmPortal     = (t_QmPortal *)h_QmPortal;
1828     struct qm_dqrr_entry    *p_Dq;
1829     struct qman_fq          *p_Fq;
1830     int                     prefetch;
1831 
1832     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1833     SANITY_CHECK_RETURN_ERROR(p_frameInfo, E_NULL_POINTER);
1834 
1835     NCSW_PLOCK(p_QmPortal);
1836 
1837     prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
1838     if (prefetch)
1839         qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1840     qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1841     p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1842     if (!p_Dq)
1843     {
1844         PUNLOCK(p_QmPortal);
1845         return ERROR_CODE(E_EMPTY);
1846     }
1847     p_Fq = ptr_from_aligned_int(p_Dq->contextB);
1848     ASSERT_COND(p_Dq->fqid);
1849     if (p_Fq)
1850     {
1851         p_frameInfo->h_App = p_Fq->h_App;
1852         p_frameInfo->h_QmFqr = p_Fq->h_QmFqr;
1853         p_frameInfo->fqidOffset = p_Fq->fqidOffset;
1854         memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));
1855     }
1856     else
1857     {
1858         p_frameInfo->h_App = p_QmPortal->h_App;
1859         p_frameInfo->h_QmFqr = NULL;
1860         p_frameInfo->fqidOffset = p_Dq->fqid;
1861         memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));
1862     }
1863     if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) {
1864         qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
1865                                    p_Dq,
1866                                    false);
1867         qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1868     } else {
1869         qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1870         qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1871     }
1872 
1873     PUNLOCK(p_QmPortal);
1874 
1875     return E_OK;
1876 }
1877 
1878 
1879 t_Handle QM_FQR_Create(t_QmFqrParams *p_QmFqrParams)
1880 {
1881     t_QmFqr             *p_QmFqr;
1882     uint32_t            i, flags = 0;
1883     u_QmFqdContextA     cnxtA;
1884 
1885     SANITY_CHECK_RETURN_VALUE(p_QmFqrParams, E_INVALID_HANDLE, NULL);
1886     SANITY_CHECK_RETURN_VALUE(p_QmFqrParams->h_Qm, E_INVALID_HANDLE, NULL);
1887 
1888     if (p_QmFqrParams->shadowMode &&
1889         (!p_QmFqrParams->useForce || p_QmFqrParams->numOfFqids != 1))
1890     {
1891         REPORT_ERROR(MAJOR, E_CONFLICT, ("shadowMode must be use with useForce and numOfFqids==1!!!"));
1892         return NULL;
1893     }
1894 
1895     p_QmFqr = (t_QmFqr *)XX_MallocSmart(sizeof(t_QmFqr), 0, 64);
1896     if (!p_QmFqr)
1897     {
1898         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQR obj!!!"));
1899         return NULL;
1900     }
1901     memset(p_QmFqr, 0, sizeof(t_QmFqr));
1902 
1903     p_QmFqr->h_Qm       = p_QmFqrParams->h_Qm;
1904     p_QmFqr->h_QmPortal = p_QmFqrParams->h_QmPortal;
1905     p_QmFqr->shadowMode = p_QmFqrParams->shadowMode;
1906     p_QmFqr->numOfFqids = (p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ?
1907                               1 : p_QmFqrParams->numOfFqids;
1908 
1909     if (!p_QmFqr->h_QmPortal)
1910     {
1911         p_QmFqr->h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
1912         SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_QmPortal, E_INVALID_HANDLE, NULL);
1913     }
1914 
1915     p_QmFqr->p_Fqs = (struct qman_fq **)XX_Malloc(sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);
1916     if (!p_QmFqr->p_Fqs)
1917     {
1918         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQs obj!!!"));
1919         QM_FQR_Free(p_QmFqr);
1920         return NULL;
1921     }
1922     memset(p_QmFqr->p_Fqs, 0, sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);
1923 
1924     if (p_QmFqr->shadowMode)
1925     {
1926         struct qman_fq          *p_Fq = NULL;
1927 
1928         p_QmFqr->fqidBase = p_QmFqrParams->qs.frcQ.fqid;
1929         p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64);
1930         if (!p_Fq)
1931         {
1932             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));
1933             QM_FQR_Free(p_QmFqr);
1934             return NULL;
1935         }
1936         memset(p_Fq, 0, sizeof(struct qman_fq));
1937         p_Fq->cb.dqrr     = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_DfltFrame;
1938         p_Fq->cb.ern      = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_RejectedFrame;
1939         p_Fq->cb.dc_ern   = cb_ern_dcErn;
1940         p_Fq->cb.fqs      = cb_fqs;
1941         p_Fq->h_App       = ((t_QmPortal*)p_QmFqr->h_QmPortal)->h_App;
1942         p_Fq->h_QmFqr     = p_QmFqr;
1943         p_Fq->state       = qman_fq_state_sched;
1944         p_Fq->fqid        = p_QmFqr->fqidBase;
1945         p_QmFqr->p_Fqs[0] = p_Fq;
1946     }
1947     else
1948     {
1949         p_QmFqr->channel    = p_QmFqrParams->channel;
1950         p_QmFqr->workQueue  = p_QmFqrParams->wq;
1951 
1952         p_QmFqr->fqidBase = QmFqidGet(p_QmFqr->h_Qm,
1953                                       p_QmFqr->numOfFqids,
1954                                       p_QmFqrParams->qs.nonFrcQs.align,
1955                                       p_QmFqrParams->useForce,
1956                                       p_QmFqrParams->qs.frcQ.fqid);
1957         if (p_QmFqr->fqidBase == (uint32_t)ILLEGAL_BASE)
1958         {
1959             REPORT_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid"));
1960             QM_FQR_Free(p_QmFqr);
1961             return NULL;
1962         }
1963 
1964         if(p_QmFqrParams->congestionAvoidanceEnable &&
1965             (p_QmFqrParams->congestionAvoidanceParams.h_QmCg == NULL) &&
1966             (p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold == 0))
1967         {
1968             REPORT_ERROR(CRITICAL,E_INVALID_STATE,("NULL congestion group handle and no FQ Threshold"));
1969             QM_FQR_Free(p_QmFqr);
1970             return NULL;
1971         }
1972         if(p_QmFqrParams->congestionAvoidanceEnable)
1973         {
1974             if(p_QmFqrParams->congestionAvoidanceParams.h_QmCg)
1975                 flags |= QM_FQCTRL_CGE;
1976             if(p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold)
1977                 flags |= QM_FQCTRL_TDE;
1978         }
1979 
1980     /*
1981         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_ORP : 0;
1982         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_CPCSTASH : 0;
1983         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_FORCESFDR : 0;
1984         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_AVOIDBLOCK : 0;
1985     */
1986         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_HOLDACTIVE : 0;
1987         flags |= (p_QmFqrParams->preferInCache) ? QM_FQCTRL_LOCKINCACHE : 0;
1988 
1989         if (p_QmFqrParams->useContextAForStash)
1990         {
1991             if (CheckStashParams(p_QmFqrParams) != E_OK)
1992             {
1993                 REPORT_ERROR(CRITICAL,E_INVALID_STATE,NO_MSG);
1994                 QM_FQR_Free(p_QmFqr);
1995                 return NULL;
1996             }
1997 
1998             memset(&cnxtA, 0, sizeof(cnxtA));
1999             cnxtA.stashing.annotation_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameAnnotationSize, CACHELINE_SIZE);
2000             cnxtA.stashing.data_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameDataSize, CACHELINE_SIZE);
2001             cnxtA.stashing.context_cl = DIV_CEIL(p_QmFqrParams->stashingParams.fqContextSize, CACHELINE_SIZE);
2002             cnxtA.context_hi = (uint8_t)((p_QmFqrParams->stashingParams.fqContextAddr >> 32) & 0xff);
2003             cnxtA.context_lo = (uint32_t)(p_QmFqrParams->stashingParams.fqContextAddr);
2004             flags |= QM_FQCTRL_CTXASTASHING;
2005         }
2006 
2007         for(i=0;i<p_QmFqr->numOfFqids;i++)
2008             if (qm_new_fq(p_QmFqr->h_QmPortal,
2009                           p_QmFqr->fqidBase+i,
2010                           i,
2011                           p_QmFqr->channel,
2012                           p_QmFqr->workQueue,
2013                           1/*p_QmFqr->numOfFqids*/,
2014                           flags,
2015                           (p_QmFqrParams->congestionAvoidanceEnable ?
2016                               &p_QmFqrParams->congestionAvoidanceParams : NULL),
2017                           p_QmFqrParams->useContextAForStash ?
2018                               (t_QmContextA *)&cnxtA : p_QmFqrParams->p_ContextA,
2019                           p_QmFqrParams->p_ContextB,
2020                           p_QmFqrParams->initParked,
2021                           p_QmFqr,
2022                           &p_QmFqr->p_Fqs[i]) != E_OK)
2023             {
2024                 QM_FQR_Free(p_QmFqr);
2025                 return NULL;
2026             }
2027     }
2028     return p_QmFqr;
2029 }
2030 
2031 t_Error  QM_FQR_Free(t_Handle h_QmFqr)
2032 {
2033     t_QmFqr     *p_QmFqr    = (t_QmFqr *)h_QmFqr;
2034     uint32_t    i;
2035 
2036     if (!p_QmFqr)
2037         return ERROR_CODE(E_INVALID_HANDLE);
2038 
2039     if (p_QmFqr->p_Fqs)
2040     {
2041         for (i=0;i<p_QmFqr->numOfFqids;i++)
2042             if (p_QmFqr->p_Fqs[i])
2043             {
2044                 if (!p_QmFqr->shadowMode)
2045                     qm_free_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]);
2046                 XX_FreeSmart(p_QmFqr->p_Fqs[i]);
2047             }
2048         XX_Free(p_QmFqr->p_Fqs);
2049     }
2050 
2051     if (!p_QmFqr->shadowMode && p_QmFqr->fqidBase)
2052         QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
2053 
2054     XX_FreeSmart(p_QmFqr);
2055 
2056     return E_OK;
2057 }
2058 
2059 t_Error  QM_FQR_FreeWDrain(t_Handle                     h_QmFqr,
2060                            t_QmFqrDrainedCompletionCB   *f_CompletionCB,
2061                            bool                         deliverFrame,
2062                            t_QmReceivedFrameCallback    *f_CallBack,
2063                            t_Handle                     h_App)
2064 {
2065     t_QmFqr     *p_QmFqr    = (t_QmFqr *)h_QmFqr;
2066     uint32_t    i;
2067 
2068     if (!p_QmFqr)
2069         return ERROR_CODE(E_INVALID_HANDLE);
2070 
2071     if (p_QmFqr->shadowMode)
2072         RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("QM_FQR_FreeWDrain can't be called to shadow FQR!!!. call QM_FQR_Free"));
2073 
2074     p_QmFqr->p_DrainedFqs = (bool *)XX_Malloc(sizeof(bool) * p_QmFqr->numOfFqids);
2075     if (!p_QmFqr->p_DrainedFqs)
2076         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("QM Drained-FQs obj!!!. Try to Free without draining"));
2077     memset(p_QmFqr->p_DrainedFqs, 0, sizeof(bool) * p_QmFqr->numOfFqids);
2078 
2079     if (f_CompletionCB)
2080     {
2081         p_QmFqr->f_CompletionCB = f_CompletionCB;
2082         p_QmFqr->h_App          = h_App;
2083     }
2084 
2085     if (deliverFrame)
2086     {
2087         if (!f_CallBack)
2088         {
2089             REPORT_ERROR(MAJOR, E_NULL_POINTER, ("f_CallBack must be given."));
2090             XX_Free(p_QmFqr->p_DrainedFqs);
2091             return ERROR_CODE(E_NULL_POINTER);
2092         }
2093         QM_FQR_RegisterCB(p_QmFqr, f_CallBack, h_App);
2094     }
2095     else
2096         QM_FQR_RegisterCB(p_QmFqr, drainCB, h_App);
2097 
2098     for (i=0;i<p_QmFqr->numOfFqids;i++)
2099     {
2100         if (qman_retire_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i], 0, true) != E_OK)
2101             RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!"));
2102 
2103         if (p_QmFqr->p_Fqs[i]->flags & QMAN_FQ_STATE_CHANGING)
2104             DBG(INFO, ("fq %d currently in use, will be retired", p_QmFqr->p_Fqs[i]->fqid));
2105         else
2106             drainRetiredFq(p_QmFqr->p_Fqs[i]);
2107     }
2108 
2109     if (!p_QmFqr->f_CompletionCB)
2110     {
2111         while(p_QmFqr->p_DrainedFqs) ;
2112         DBG(TRACE, ("QM-FQR with base %d completed", p_QmFqr->fqidBase));
2113         XX_FreeSmart(p_QmFqr->p_Fqs);
2114         if (p_QmFqr->fqidBase)
2115             QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
2116         XX_FreeSmart(p_QmFqr);
2117     }
2118 
2119     return E_OK;
2120 }
2121 
2122 t_Error QM_FQR_RegisterCB(t_Handle h_QmFqr, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App)
2123 {
2124     t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2125     int         i;
2126 
2127     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2128 
2129     for (i=0;i<p_QmFqr->numOfFqids;i++)
2130     {
2131         p_QmFqr->p_Fqs[i]->cb.dqrr = f_CallBack;
2132         p_QmFqr->p_Fqs[i]->h_App   = h_App;
2133     }
2134 
2135     return E_OK;
2136 }
2137 
2138 t_Error QM_FQR_Enqueue(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)
2139 {
2140     t_QmFqr                 *p_QmFqr = (t_QmFqr *)h_QmFqr;
2141     t_QmPortal              *p_QmPortal;
2142     struct qm_eqcr_entry    *p_Eq;
2143     uint32_t                *p_Dst, *p_Src;
2144     const struct qman_fq    *p_Fq;
2145 
2146     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2147     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2148 
2149     if (!h_QmPortal)
2150     {
2151         SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2152         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2153         SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2154     }
2155     p_QmPortal = (t_QmPortal *)h_QmPortal;
2156 
2157     p_Fq = p_QmFqr->p_Fqs[fqidOffset];
2158 
2159 #ifdef QM_CHECKING
2160     if (p_Fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE)
2161         RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
2162     if ((!(p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)) &&
2163         ((p_Fq->state == qman_fq_state_retired) ||
2164          (p_Fq->state == qman_fq_state_oos)))
2165         return ERROR_CODE(E_BUSY);
2166 #endif /* QM_CHECKING */
2167 
2168     NCSW_PLOCK(p_QmPortal);
2169     p_Eq = try_eq_start(p_QmPortal);
2170     if (!p_Eq)
2171     {
2172         PUNLOCK(p_QmPortal);
2173         return ERROR_CODE(E_BUSY);
2174     }
2175 
2176     p_Eq->fqid = p_Fq->fqid;
2177     p_Eq->tag = aligned_int_from_ptr(p_Fq);
2178     /* gcc does a dreadful job of the following;
2179      *  eq->fd = *fd;
2180      * It causes the entire function to save/restore a wider range of
2181      * registers, and comes up with instruction-waste galore. This will do
2182      * until we can rework the function for better code-generation. */
2183     p_Dst = (uint32_t *)&p_Eq->fd;
2184     p_Src = (uint32_t *)p_Frame;
2185     p_Dst[0] = p_Src[0];
2186     p_Dst[1] = p_Src[1];
2187     p_Dst[2] = p_Src[2];
2188     p_Dst[3] = p_Src[3];
2189 
2190     qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal,
2191                           (uint8_t)(QM_EQCR_VERB_CMD_ENQUEUE/* |
2192                           (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))*/));
2193     PUNLOCK(p_QmPortal);
2194 
2195     return E_OK;
2196 }
2197 
2198 
2199 t_Error QM_FQR_PullFrame(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)
2200 {
2201     t_QmFqr                 *p_QmFqr = (t_QmFqr *)h_QmFqr;
2202     uint32_t                pdqcr = 0;
2203 
2204     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2205     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2206     SANITY_CHECK_RETURN_ERROR(p_Frame, E_NULL_POINTER);
2207     SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_oos) ||
2208                               (p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_parked),
2209                               E_INVALID_STATE);
2210     if (!h_QmPortal)
2211     {
2212         SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2213         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2214         SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2215     }
2216 
2217     pdqcr |= QM_PDQCR_MODE_UNSCHEDULED;
2218     pdqcr |= QM_PDQCR_FQID(p_QmFqr->p_Fqs[fqidOffset]->fqid);
2219     return QmPortalPullFrame(h_QmPortal, pdqcr, p_Frame);
2220 }
2221 
2222 t_Error QM_FQR_Resume(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)
2223 {
2224     t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2225 
2226     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2227     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2228 
2229     if (!h_QmPortal)
2230     {
2231         SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2232         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2233         SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2234     }
2235     return qman_schedule_fq(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset]);
2236 }
2237 
2238 t_Error  QM_FQR_Suspend(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)
2239 {
2240     t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2241 
2242     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2243     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2244     SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->flags & QM_FQCTRL_HOLDACTIVE), E_INVALID_STATE);
2245 
2246     UNUSED(h_QmPortal);
2247     p_QmFqr->p_Fqs[fqidOffset]->state = qman_fq_state_waiting_parked;
2248 
2249     return E_OK;
2250 }
2251 
2252 uint32_t QM_FQR_GetFqid(t_Handle h_QmFqr)
2253 {
2254     t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;
2255 
2256     SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);
2257 
2258     return p_QmFqr->fqidBase;
2259 }
2260 
2261 uint32_t QM_FQR_GetCounter(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, e_QmFqrCounters counter)
2262 {
2263     t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;
2264     struct qm_mcr_queryfq_np    queryfq_np;
2265 
2266     SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);
2267     SANITY_CHECK_RETURN_VALUE((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE, 0);
2268 
2269     if (!h_QmPortal)
2270     {
2271         SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_Qm, E_INVALID_HANDLE, 0);
2272         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2273         SANITY_CHECK_RETURN_VALUE(h_QmPortal, E_INVALID_HANDLE, 0);
2274     }
2275     if (qman_query_fq_np(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset], &queryfq_np) != E_OK)
2276         return 0;
2277     switch (counter)
2278     {
2279         case e_QM_FQR_COUNTERS_FRAME :
2280             return queryfq_np.frm_cnt;
2281         case e_QM_FQR_COUNTERS_BYTE :
2282             return queryfq_np.byte_cnt;
2283         default :
2284             break;
2285     }
2286     /* should never get here */
2287     ASSERT_COND(FALSE);
2288 
2289     return 0;
2290 }
2291 
2292 
2293 t_Handle QM_CG_Create(t_QmCgParams *p_CgParams)
2294 {
2295     t_QmCg                          *p_QmCg;
2296     t_QmPortal                      *p_QmPortal;
2297     t_Error                         err;
2298     uint32_t                        wredParams;
2299     uint32_t                        tmpA, tmpN, ta=0, tn=0;
2300     int                             gap, tmp;
2301     struct qm_mc_command            *p_Mcc;
2302     struct qm_mc_result             *p_Mcr;
2303 
2304     SANITY_CHECK_RETURN_VALUE(p_CgParams, E_INVALID_HANDLE, NULL);
2305     SANITY_CHECK_RETURN_VALUE(p_CgParams->h_Qm, E_INVALID_HANDLE, NULL);
2306 
2307     if(p_CgParams->notifyDcPortal &&
2308        ((p_CgParams->dcPortalId == e_DPAA_DCPORTAL2) || (p_CgParams->dcPortalId == e_DPAA_DCPORTAL3)))
2309     {
2310         REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("notifyDcPortal is invalid for this DC Portal"));
2311         return NULL;
2312     }
2313 
2314     if (!p_CgParams->h_QmPortal)
2315     {
2316         p_QmPortal = QmGetPortalHandle(p_CgParams->h_Qm);
2317         SANITY_CHECK_RETURN_VALUE(p_QmPortal, E_INVALID_STATE, NULL);
2318     }
2319     else
2320         p_QmPortal = p_CgParams->h_QmPortal;
2321 
2322     p_QmCg = (t_QmCg *)XX_Malloc(sizeof(t_QmCg));
2323     if (!p_QmCg)
2324     {
2325         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM CG obj!!!"));
2326         return NULL;
2327     }
2328     memset(p_QmCg, 0, sizeof(t_QmCg));
2329 
2330     /* build CG struct */
2331     p_QmCg->h_Qm        = p_CgParams->h_Qm;
2332     p_QmCg->h_QmPortal  = p_QmPortal;
2333     p_QmCg->h_App       = p_CgParams->h_App;
2334     err = QmGetCgId(p_CgParams->h_Qm, &p_QmCg->id);
2335     if (err)
2336     {
2337         XX_Free(p_QmCg);
2338         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmGetCgId failed"));
2339         return NULL;
2340     }
2341 
2342     NCSW_PLOCK(p_QmPortal);
2343     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2344     p_Mcc->initcgr.cgid = p_QmCg->id;
2345 
2346     err = QmPortalRegisterCg(p_QmPortal, p_QmCg, p_QmCg->id);
2347     if (err)
2348     {
2349         XX_Free(p_QmCg);
2350         PUNLOCK(p_QmPortal);
2351         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalRegisterCg failed"));
2352         return NULL;
2353     }
2354 
2355     /*  Build CGR command */
2356     {
2357 #ifdef QM_CGS_NO_FRAME_MODE
2358     t_QmRevisionInfo    revInfo;
2359 
2360     QmGetRevision(p_QmCg->h_Qm, &revInfo);
2361 
2362     if (!((revInfo.majorRev == 1) && (revInfo.minorRev == 0)))
2363 #endif /* QM_CGS_NO_FRAME_MODE */
2364         if (p_CgParams->frameCount)
2365         {
2366             p_Mcc->initcgr.we_mask |= QM_CGR_WE_MODE;
2367             p_Mcc->initcgr.cgr.frame_mode = QM_CGR_EN;
2368         }
2369     }
2370 
2371     if (p_CgParams->wredEnable)
2372     {
2373         if (p_CgParams->wredParams.enableGreen)
2374         {
2375             err = CalcWredCurve(&p_CgParams->wredParams.greenCurve, &wredParams);
2376             if(err)
2377             {
2378                 XX_Free(p_QmCg);
2379                 PUNLOCK(p_QmPortal);
2380                 REPORT_ERROR(MAJOR, err, NO_MSG);
2381                 return NULL;
2382             }
2383             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;
2384             p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;
2385             p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;
2386         }
2387         if (p_CgParams->wredParams.enableYellow)
2388         {
2389             err = CalcWredCurve(&p_CgParams->wredParams.yellowCurve, &wredParams);
2390             if(err)
2391             {
2392                 XX_Free(p_QmCg);
2393                 PUNLOCK(p_QmPortal);
2394                 REPORT_ERROR(MAJOR, err, NO_MSG);
2395                 return NULL;
2396             }
2397             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;
2398             p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;
2399             p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;
2400         }
2401         if (p_CgParams->wredParams.enableRed)
2402         {
2403             err = CalcWredCurve(&p_CgParams->wredParams.redCurve, &wredParams);
2404             if(err)
2405             {
2406                 XX_Free(p_QmCg);
2407                 PUNLOCK(p_QmPortal);
2408                 REPORT_ERROR(MAJOR, err, NO_MSG);
2409                 return NULL;
2410             }
2411             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;
2412             p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;
2413             p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;
2414         }
2415     }
2416 
2417     if (p_CgParams->tailDropEnable)
2418     {
2419         if (!p_CgParams->threshold)
2420         {
2421             XX_Free(p_QmCg);
2422             PUNLOCK(p_QmPortal);
2423             REPORT_ERROR(MINOR, E_INVALID_STATE, ("tailDropThreshold must be configured if tailDropEnable "));
2424             return NULL;
2425         }
2426         p_Mcc->initcgr.cgr.cstd_en = QM_CGR_EN;
2427         p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSTD_EN;
2428     }
2429 
2430     if (p_CgParams->threshold)
2431     {
2432         p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;
2433         p_QmCg->f_Exception = p_CgParams->f_Exception;
2434         if (p_QmCg->f_Exception || p_CgParams->notifyDcPortal)
2435         {
2436             p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;
2437             p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSCN_EN | QM_CGR_WE_CSCN_TARG;
2438             /* if SW - set target, if HW - if FM, set HW target, otherwize, set SW target */
2439             p_Mcc->initcgr.cgr.cscn_targ = 0;
2440             if (p_QmCg->f_Exception)
2441                 p_Mcc->initcgr.cgr.cscn_targ = (uint32_t)QM_CGR_TARGET_SWP(QmPortalGetSwPortalId(p_QmCg->h_QmPortal));
2442             if (p_CgParams->notifyDcPortal)
2443                 p_Mcc->initcgr.cgr.cscn_targ |= (uint32_t)QM_CGR_TARGET_DCP(p_CgParams->dcPortalId);
2444         }
2445 
2446         /* express thresh as ta*2^tn */
2447         gap = (int)p_CgParams->threshold;
2448         for (tmpA=0 ; tmpA<256; tmpA++ )
2449             for (tmpN=0 ; tmpN<32; tmpN++ )
2450             {
2451                 tmp = ABS((int)(p_CgParams->threshold - tmpA*(1<<tmpN)));
2452                 if (tmp < gap)
2453                 {
2454                    ta = tmpA;
2455                    tn = tmpN;
2456                    gap = tmp;
2457                 }
2458             }
2459         p_Mcc->initcgr.cgr.cs_thres.TA = ta;
2460         p_Mcc->initcgr.cgr.cs_thres.Tn = tn;
2461     }
2462     else if(p_CgParams->f_Exception)
2463     {
2464         XX_Free(p_QmCg);
2465         PUNLOCK(p_QmPortal);
2466         REPORT_ERROR(MINOR, E_INVALID_STATE, ("No threshold configured, but f_Exception defined"));
2467         return NULL;
2468     }
2469 
2470     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_INITCGR);
2471     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2472     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_INITCGR);
2473     if (p_Mcr->result != QM_MCR_RESULT_OK)
2474     {
2475         XX_Free(p_QmCg);
2476         PUNLOCK(p_QmPortal);
2477         REPORT_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2478         return NULL;
2479     }
2480     PUNLOCK(p_QmPortal);
2481 
2482     return p_QmCg;
2483 }
2484 
2485 t_Error QM_CG_Free(t_Handle h_QmCg)
2486 {
2487 
2488     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2489     t_Error                 err;
2490     struct qm_mc_command    *p_Mcc;
2491     struct qm_mc_result     *p_Mcr;
2492     t_QmPortal              *p_QmPortal;
2493 
2494     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2495 
2496     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2497 
2498     NCSW_PLOCK(p_QmPortal);
2499     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2500     p_Mcc->initcgr.cgid = p_QmCg->id;
2501     p_Mcc->initcgr.we_mask = QM_CGR_WE_MASK;
2502 
2503     err = QmFreeCgId(p_QmCg->h_Qm, p_QmCg->id);
2504     if(err)
2505     {
2506         XX_Free(p_QmCg);
2507         PUNLOCK(p_QmPortal);
2508         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmFreeCgId failed"));
2509     }
2510 
2511     err = QmPortalUnregisterCg(p_QmCg->h_QmPortal, p_QmCg->id);
2512     if(err)
2513     {
2514         XX_Free(p_QmCg);
2515         PUNLOCK(p_QmPortal);
2516         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalUnregisterCg failed"));
2517     }
2518 
2519     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2520     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2521     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2522     if (p_Mcr->result != QM_MCR_RESULT_OK)
2523     {
2524         PUNLOCK(p_QmPortal);
2525         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2526     }
2527     PUNLOCK(p_QmPortal);
2528 
2529     XX_Free(p_QmCg);
2530 
2531     return E_OK;
2532 }
2533 
2534 t_Error QM_CG_SetException(t_Handle h_QmCg, e_QmExceptions exception, bool enable)
2535 {
2536     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2537     struct qm_mc_command    *p_Mcc;
2538     struct qm_mc_result     *p_Mcr;
2539     t_QmPortal              *p_QmPortal;
2540 
2541     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2542 
2543     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2544     if (!p_QmCg->f_Exception)
2545         RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Either threshold or exception callback was not configured."));
2546 
2547     NCSW_PLOCK(p_QmPortal);
2548     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2549     p_Mcc->initcgr.cgid = p_QmCg->id;
2550     p_Mcc->initcgr.we_mask = QM_CGR_WE_CSCN_EN;
2551 
2552     if(exception == e_QM_EX_CG_STATE_CHANGE)
2553     {
2554         if(enable)
2555             p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;
2556     }
2557     else
2558     {
2559         PUNLOCK(p_QmPortal);
2560         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal exception"));
2561     }
2562 
2563     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2564     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2565     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2566     if (p_Mcr->result != QM_MCR_RESULT_OK)
2567     {
2568         PUNLOCK(p_QmPortal);
2569         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2570     }
2571     PUNLOCK(p_QmPortal);
2572 
2573     return E_OK;
2574 }
2575 
2576 t_Error QM_CG_ModifyWredCurve(t_Handle h_QmCg, t_QmCgModifyWredParams *p_QmCgModifyParams)
2577 {
2578     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2579     uint32_t                wredParams;
2580     struct qm_mc_command    *p_Mcc;
2581     struct qm_mc_result     *p_Mcr;
2582     t_QmPortal              *p_QmPortal;
2583     t_Error                 err = E_OK;
2584 
2585     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2586 
2587     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2588 
2589     NCSW_PLOCK(p_QmPortal);
2590     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2591     p_Mcc->initcgr.cgid = p_QmCg->id;
2592 
2593     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);
2594     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2595     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);
2596     if (p_Mcr->result != QM_MCR_RESULT_OK)
2597     {
2598         PUNLOCK(p_QmPortal);
2599         RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));
2600     }
2601 
2602     switch(p_QmCgModifyParams->color)
2603     {
2604         case(e_QM_CG_COLOR_GREEN):
2605             if(!p_Mcr->querycgr.cgr.wr_en_g)
2606             {
2607                 PUNLOCK(p_QmPortal);
2608                 RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for green"));
2609             }
2610             break;
2611         case(e_QM_CG_COLOR_YELLOW):
2612             if(!p_Mcr->querycgr.cgr.wr_en_y)
2613             {
2614                 PUNLOCK(p_QmPortal);
2615                 RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for yellow"));
2616             }
2617             break;
2618         case(e_QM_CG_COLOR_RED):
2619             if(!p_Mcr->querycgr.cgr.wr_en_r)
2620             {
2621                 PUNLOCK(p_QmPortal);
2622                 RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for red"));
2623             }
2624             break;
2625     }
2626 
2627     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2628     p_Mcc->initcgr.cgid = p_QmCg->id;
2629 
2630     switch(p_QmCgModifyParams->color)
2631     {
2632         case(e_QM_CG_COLOR_GREEN):
2633             err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2634             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;
2635             p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;
2636             p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;
2637             break;
2638         case(e_QM_CG_COLOR_YELLOW):
2639             err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2640             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;
2641             p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;
2642             p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;
2643             break;
2644         case(e_QM_CG_COLOR_RED):
2645             err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2646             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;
2647             p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;
2648             p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;
2649             break;
2650     }
2651     if (err)
2652     {
2653         PUNLOCK(p_QmPortal);
2654         RETURN_ERROR(MINOR, err, NO_MSG);
2655     }
2656 
2657     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2658     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2659     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2660     if (p_Mcr->result != QM_MCR_RESULT_OK)
2661     {
2662         PUNLOCK(p_QmPortal);
2663         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2664     }
2665     PUNLOCK(p_QmPortal);
2666 
2667     return E_OK;
2668 }
2669 
2670 t_Error QM_CG_ModifyTailDropThreshold(t_Handle h_QmCg, uint32_t threshold)
2671 {
2672     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2673     struct qm_mc_command    *p_Mcc;
2674     struct qm_mc_result     *p_Mcr;
2675     t_QmPortal              *p_QmPortal;
2676     uint32_t                tmpA, tmpN, ta=0, tn=0;
2677     int                     gap, tmp;
2678 
2679     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2680 
2681     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2682 
2683     NCSW_PLOCK(p_QmPortal);
2684     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2685     p_Mcc->initcgr.cgid = p_QmCg->id;
2686 
2687     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);
2688     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2689     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);
2690     if (p_Mcr->result != QM_MCR_RESULT_OK)
2691     {
2692         PUNLOCK(p_QmPortal);
2693         RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));
2694     }
2695 
2696     if(!p_Mcr->querycgr.cgr.cstd_en)
2697     {
2698         PUNLOCK(p_QmPortal);
2699         RETURN_ERROR(MINOR, E_INVALID_STATE, ("Tail Drop is not enabled!"));
2700     }
2701 
2702     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2703     p_Mcc->initcgr.cgid = p_QmCg->id;
2704     p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;
2705 
2706     /* express thresh as ta*2^tn */
2707     gap = (int)threshold;
2708     for (tmpA=0 ; tmpA<256; tmpA++ )
2709         for (tmpN=0 ; tmpN<32; tmpN++ )
2710         {
2711             tmp = ABS((int)(threshold - tmpA*(1<<tmpN)));
2712             if (tmp < gap)
2713             {
2714                ta = tmpA;
2715                tn = tmpN;
2716                gap = tmp;
2717             }
2718         }
2719     p_Mcc->initcgr.cgr.cs_thres.TA = ta;
2720     p_Mcc->initcgr.cgr.cs_thres.Tn = tn;
2721 
2722     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2723     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2724     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2725     if (p_Mcr->result != QM_MCR_RESULT_OK)
2726     {
2727         PUNLOCK(p_QmPortal);
2728         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2729     }
2730     PUNLOCK(p_QmPortal);
2731 
2732     return E_OK;
2733 }
2734 
2735