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 	if ((ctx & (0x7)) != 0)
82 		return (0);
83 	return (ctx >> 3);
84 }
85 
86 static inline void *
87 ptr_from_aligned_int(uint32_t ctx)
88 {
89 	uintptr_t p;
90 
91 	p = VM_MIN_KERNEL_ADDRESS + (ctx << 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/(1<<tmpN)));
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     sn = sn;
1482     ASSERT_COND(sn<64 && sn>=7);
1483 
1484     *p_CurveWord = ((ma << 24) |
1485                     (mn << 19) |
1486                     (sa << 12) |
1487                     (sn << 6) |
1488                     pn);
1489 
1490     return E_OK;
1491 }
1492 
1493 static t_Error QmPortalPullFrame(t_Handle h_QmPortal, uint32_t pdqcr, t_DpaaFD *p_Frame)
1494 {
1495     t_QmPortal              *p_QmPortal = (t_QmPortal *)h_QmPortal;
1496     struct qm_dqrr_entry    *p_Dq;
1497     struct qman_fq          *p_Fq;
1498     int                     prefetch;
1499     uint32_t                *p_Dst, *p_Src;
1500 
1501     ASSERT_COND(p_QmPortal);
1502     ASSERT_COND(p_Frame);
1503     SANITY_CHECK_RETURN_ERROR(p_QmPortal->pullMode, E_INVALID_STATE);
1504 
1505     NCSW_PLOCK(p_QmPortal);
1506 
1507     qm_dqrr_pdqcr_set(p_QmPortal->p_LowQmPortal, pdqcr);
1508     mb();
1509     while (qm_dqrr_pdqcr_get(p_QmPortal->p_LowQmPortal)) ;
1510 
1511     prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
1512     while(TRUE)
1513     {
1514         if (prefetch)
1515             qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1516         qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1517         p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1518         if (!p_Dq)
1519             continue;
1520         p_Fq = ptr_from_aligned_int(p_Dq->contextB);
1521         ASSERT_COND(p_Dq->fqid);
1522         p_Dst = (uint32_t *)p_Frame;
1523         p_Src = (uint32_t *)&p_Dq->fd;
1524         p_Dst[0] = p_Src[0];
1525         p_Dst[1] = p_Src[1];
1526         p_Dst[2] = p_Src[2];
1527         p_Dst[3] = p_Src[3];
1528         if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA)
1529         {
1530             qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
1531                                        p_Dq,
1532                                        false);
1533             qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1534         }
1535         else
1536         {
1537             qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1538             qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1539         }
1540         break;
1541     }
1542 
1543     PUNLOCK(p_QmPortal);
1544 
1545     if (!(p_Dq->stat & QM_DQRR_STAT_FD_VALID))
1546         return ERROR_CODE(E_EMPTY);
1547 
1548     return E_OK;
1549 }
1550 
1551 
1552 /****************************************/
1553 /*       API Init unit functions        */
1554 /****************************************/
1555 t_Handle QM_PORTAL_Config(t_QmPortalParam *p_QmPortalParam)
1556 {
1557     t_QmPortal          *p_QmPortal;
1558     uint32_t            i;
1559 
1560     SANITY_CHECK_RETURN_VALUE(p_QmPortalParam, E_INVALID_HANDLE, NULL);
1561     SANITY_CHECK_RETURN_VALUE(p_QmPortalParam->swPortalId < DPAA_MAX_NUM_OF_SW_PORTALS, E_INVALID_VALUE, 0);
1562 
1563     p_QmPortal = (t_QmPortal *)XX_Malloc(sizeof(t_QmPortal));
1564     if (!p_QmPortal)
1565     {
1566         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal obj!!!"));
1567         return NULL;
1568     }
1569     memset(p_QmPortal, 0, sizeof(t_QmPortal));
1570 
1571     p_QmPortal->p_LowQmPortal = (struct qm_portal *)XX_Malloc(sizeof(struct qm_portal));
1572     if (!p_QmPortal->p_LowQmPortal)
1573     {
1574         XX_Free(p_QmPortal);
1575         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Low qm p_QmPortal obj!!!"));
1576         return NULL;
1577     }
1578     memset(p_QmPortal->p_LowQmPortal, 0, sizeof(struct qm_portal));
1579 
1580     p_QmPortal->p_QmPortalDriverParams = (t_QmPortalDriverParams *)XX_Malloc(sizeof(t_QmPortalDriverParams));
1581     if (!p_QmPortal->p_QmPortalDriverParams)
1582     {
1583         XX_Free(p_QmPortal->p_LowQmPortal);
1584         XX_Free(p_QmPortal);
1585         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal driver parameters"));
1586         return NULL;
1587     }
1588     memset(p_QmPortal->p_QmPortalDriverParams, 0, sizeof(t_QmPortalDriverParams));
1589 
1590     p_QmPortal->p_LowQmPortal->addr.addr_ce = UINT_TO_PTR(p_QmPortalParam->ceBaseAddress);
1591     p_QmPortal->p_LowQmPortal->addr.addr_ci = UINT_TO_PTR(p_QmPortalParam->ciBaseAddress);
1592     p_QmPortal->p_LowQmPortal->config.irq = p_QmPortalParam->irq;
1593     p_QmPortal->p_LowQmPortal->config.bound = 0;
1594     p_QmPortal->p_LowQmPortal->config.cpu = (int)p_QmPortalParam->swPortalId;
1595     p_QmPortal->p_LowQmPortal->config.channel = (e_QmFQChannel)(e_QM_FQ_CHANNEL_SWPORTAL0 + p_QmPortalParam->swPortalId);
1596     p_QmPortal->p_LowQmPortal->bind_lock = XX_InitSpinlock();
1597 
1598     p_QmPortal->h_Qm                = p_QmPortalParam->h_Qm;
1599     p_QmPortal->f_DfltFrame         = p_QmPortalParam->f_DfltFrame;
1600     p_QmPortal->f_RejectedFrame     = p_QmPortalParam->f_RejectedFrame;
1601     p_QmPortal->h_App               = p_QmPortalParam->h_App;
1602 
1603     p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset           = p_QmPortalParam->fdLiodnOffset;
1604     p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode          = DEFAULT_dequeueDcaMode;
1605     p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames  = DEFAULT_dequeueUpToThreeFrames;
1606     p_QmPortal->p_QmPortalDriverParams->commandType             = DEFAULT_dequeueCommandType;
1607     p_QmPortal->p_QmPortalDriverParams->userToken               = DEFAULT_dequeueUserToken;
1608     p_QmPortal->p_QmPortalDriverParams->specifiedWq             = DEFAULT_dequeueSpecifiedWq;
1609     p_QmPortal->p_QmPortalDriverParams->dedicatedChannel        = DEFAULT_dequeueDedicatedChannel;
1610     p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels =
1611         DEFAULT_dequeueDedicatedChannelHasPrecedenceOverPoolChannels;
1612     p_QmPortal->p_QmPortalDriverParams->poolChannelId           = DEFAULT_dequeuePoolChannelId;
1613     p_QmPortal->p_QmPortalDriverParams->wqId                    = DEFAULT_dequeueWqId;
1614     for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)
1615         p_QmPortal->p_QmPortalDriverParams->poolChannels[i] = FALSE;
1616     p_QmPortal->p_QmPortalDriverParams->dqrrSize                = DEFAULT_dqrrSize;
1617     p_QmPortal->p_QmPortalDriverParams->pullMode                = DEFAULT_pullMode;
1618 
1619     return p_QmPortal;
1620 }
1621 
1622 t_Error QM_PORTAL_Init(t_Handle h_QmPortal)
1623 {
1624     t_QmPortal                          *p_QmPortal = (t_QmPortal *)h_QmPortal;
1625     uint32_t                            i, flags=0, sdqcrFlags=0;
1626     t_Error                             err;
1627     t_QmInterModulePortalInitParams     qmParams;
1628 
1629     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1630     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);
1631 
1632     memset(&qmParams, 0, sizeof(qmParams));
1633     qmParams.portalId       = (uint8_t)p_QmPortal->p_LowQmPortal->config.cpu;
1634     qmParams.liodn          = p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset;
1635     qmParams.dqrrLiodn      = p_QmPortal->p_QmPortalDriverParams->dqrrLiodn;
1636     qmParams.fdFqLiodn      = p_QmPortal->p_QmPortalDriverParams->fdFqLiodn;
1637     qmParams.stashDestQueue = p_QmPortal->p_QmPortalDriverParams->stashDestQueue;
1638     if ((err = QmGetSetPortalParams(p_QmPortal->h_Qm, &qmParams)) != E_OK)
1639         RETURN_ERROR(MAJOR, err, NO_MSG);
1640 
1641     flags = (uint32_t)(((p_QmPortal->p_LowQmPortal->config.irq == NO_IRQ) ?
1642             0 :
1643             (QMAN_PORTAL_FLAG_IRQ |
1644              QMAN_PORTAL_FLAG_IRQ_FAST |
1645              QMAN_PORTAL_FLAG_IRQ_SLOW)));
1646     flags |= ((p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode) ? QMAN_PORTAL_FLAG_DCA : 0);
1647     flags |= (p_QmPortal->p_QmPortalDriverParams->dqrr)?QMAN_PORTAL_FLAG_RSTASH:0;
1648     flags |= (p_QmPortal->p_QmPortalDriverParams->fdFq)?QMAN_PORTAL_FLAG_DSTASH:0;
1649 
1650     p_QmPortal->pullMode = p_QmPortal->p_QmPortalDriverParams->pullMode;
1651     if (!p_QmPortal->pullMode)
1652     {
1653         sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames) ? QM_SDQCR_COUNT_UPTO3 : QM_SDQCR_COUNT_EXACT1;
1654         sdqcrFlags |= QM_SDQCR_TOKEN_SET(p_QmPortal->p_QmPortalDriverParams->userToken);
1655         sdqcrFlags |= QM_SDQCR_TYPE_SET(p_QmPortal->p_QmPortalDriverParams->commandType);
1656         if (!p_QmPortal->p_QmPortalDriverParams->specifiedWq)
1657         {
1658             /* sdqcrFlags |= QM_SDQCR_SOURCE_CHANNELS;*/ /* removed as the macro is '0' */
1659             sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels) ? QM_SDQCR_DEDICATED_PRECEDENCE : 0;
1660             sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ? QM_SDQCR_CHANNELS_DEDICATED : 0;
1661             for (i=0;i<QM_MAX_NUM_OF_POOL_CHANNELS;i++)
1662                 sdqcrFlags |= ((p_QmPortal->p_QmPortalDriverParams->poolChannels[i]) ?
1663                      QM_SDQCR_CHANNELS_POOL(i+1) : 0);
1664         }
1665         else
1666         {
1667             sdqcrFlags |= QM_SDQCR_SOURCE_SPECIFICWQ;
1668             sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ?
1669                             QM_SDQCR_SPECIFICWQ_DEDICATED : QM_SDQCR_SPECIFICWQ_POOL(p_QmPortal->p_QmPortalDriverParams->poolChannelId);
1670             sdqcrFlags |= QM_SDQCR_SPECIFICWQ_WQ(p_QmPortal->p_QmPortalDriverParams->wqId);
1671         }
1672     }
1673     if ((flags & QMAN_PORTAL_FLAG_RSTASH) && (flags & QMAN_PORTAL_FLAG_DCA))
1674         p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingDcaOptimized;
1675     else if ((flags & QMAN_PORTAL_FLAG_RSTASH) && !(flags & QMAN_PORTAL_FLAG_DCA))
1676         p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingOptimized;
1677     else
1678         p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRing;
1679 
1680     if ((!p_QmPortal->f_RejectedFrame) || (!p_QmPortal->f_DfltFrame))
1681         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_RejectedFrame or f_DfltFrame callback not provided"));
1682 
1683     p_QmPortal->p_NullCB = (struct qman_fq_cb *)XX_Malloc(sizeof(struct qman_fq_cb));
1684     if (!p_QmPortal->p_NullCB)
1685         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ Null CB obj!!!"));
1686     memset(p_QmPortal->p_NullCB, 0, sizeof(struct qman_fq_cb));
1687 
1688     p_QmPortal->p_NullCB->dqrr      = p_QmPortal->f_DfltFrame;
1689     p_QmPortal->p_NullCB->ern       = p_QmPortal->f_RejectedFrame;
1690     p_QmPortal->p_NullCB->dc_ern    = p_QmPortal->p_NullCB->fqs = null_cb_mr;
1691 
1692     if (qman_create_portal(p_QmPortal, flags, sdqcrFlags, p_QmPortal->p_QmPortalDriverParams->dqrrSize) != E_OK)
1693     {
1694         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("create portal failed"));
1695     }
1696 
1697     QmSetPortalHandle(p_QmPortal->h_Qm, (t_Handle)p_QmPortal, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);
1698     XX_Free(p_QmPortal->p_QmPortalDriverParams);
1699     p_QmPortal->p_QmPortalDriverParams = NULL;
1700 
1701     DBG(TRACE, ("Qman-Portal %d @ %p:%p",
1702                 p_QmPortal->p_LowQmPortal->config.cpu,
1703                 p_QmPortal->p_LowQmPortal->addr.addr_ce,
1704                 p_QmPortal->p_LowQmPortal->addr.addr_ci
1705                 ));
1706 
1707     DBG(TRACE, ("Qman-Portal %d phys @ 0x%016llx:0x%016llx",
1708                 p_QmPortal->p_LowQmPortal->config.cpu,
1709                 (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ce),
1710                 (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ci)
1711                 ));
1712 
1713     return E_OK;
1714 }
1715 
1716 t_Error QM_PORTAL_Free(t_Handle h_QmPortal)
1717 {
1718     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1719 
1720     if (!p_QmPortal)
1721        return ERROR_CODE(E_INVALID_HANDLE);
1722 
1723     ASSERT_COND(p_QmPortal->p_LowQmPortal);
1724     QmSetPortalHandle(p_QmPortal->h_Qm, NULL, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu);
1725     qman_destroy_portal(p_QmPortal);
1726     if (p_QmPortal->p_NullCB)
1727         XX_Free(p_QmPortal->p_NullCB);
1728 
1729     if (p_QmPortal->p_LowQmPortal->bind_lock)
1730         XX_FreeSpinlock(p_QmPortal->p_LowQmPortal->bind_lock);
1731     if(p_QmPortal->p_QmPortalDriverParams)
1732         XX_Free(p_QmPortal->p_QmPortalDriverParams);
1733     XX_Free(p_QmPortal->p_LowQmPortal);
1734     XX_Free(p_QmPortal);
1735 
1736     return E_OK;
1737 }
1738 
1739 t_Error QM_PORTAL_ConfigDcaMode(t_Handle h_QmPortal, bool enable)
1740 {
1741     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1742 
1743     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1744     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE);
1745 
1746     p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode = enable;
1747 
1748     return E_OK;
1749 }
1750 
1751 t_Error QM_PORTAL_ConfigStash(t_Handle h_QmPortal, t_QmPortalStashParam *p_StashParams)
1752 {
1753     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1754 
1755     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1756     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);
1757     SANITY_CHECK_RETURN_ERROR(p_StashParams, E_NULL_POINTER);
1758 
1759     p_QmPortal->p_QmPortalDriverParams->stashDestQueue  = p_StashParams->stashDestQueue;
1760     p_QmPortal->p_QmPortalDriverParams->dqrrLiodn       = p_StashParams->dqrrLiodn;
1761     p_QmPortal->p_QmPortalDriverParams->fdFqLiodn       = p_StashParams->fdFqLiodn;
1762     p_QmPortal->p_QmPortalDriverParams->eqcr            = p_StashParams->eqcr;
1763     p_QmPortal->p_QmPortalDriverParams->eqcrHighPri     = p_StashParams->eqcrHighPri;
1764     p_QmPortal->p_QmPortalDriverParams->dqrr            = p_StashParams->dqrr;
1765     p_QmPortal->p_QmPortalDriverParams->dqrrHighPri     = p_StashParams->dqrrHighPri;
1766     p_QmPortal->p_QmPortalDriverParams->fdFq            = p_StashParams->fdFq;
1767     p_QmPortal->p_QmPortalDriverParams->fdFqHighPri     = p_StashParams->fdFqHighPri;
1768     p_QmPortal->p_QmPortalDriverParams->fdFqDrop        = p_StashParams->fdFqDrop;
1769 
1770     return E_OK;
1771 }
1772 
1773 
1774 t_Error QM_PORTAL_ConfigPullMode(t_Handle h_QmPortal, bool pullMode)
1775 {
1776     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1777 
1778     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1779     SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER);
1780 
1781     p_QmPortal->p_QmPortalDriverParams->pullMode  = pullMode;
1782 
1783     return E_OK;
1784 }
1785 
1786 t_Error QM_PORTAL_AddPoolChannel(t_Handle h_QmPortal, uint8_t poolChannelId)
1787 {
1788     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1789     uint32_t    sdqcrFlags;
1790 
1791     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1792     SANITY_CHECK_RETURN_ERROR((poolChannelId < QM_MAX_NUM_OF_POOL_CHANNELS), E_INVALID_VALUE);
1793 
1794     sdqcrFlags = qm_dqrr_sdqcr_get(p_QmPortal->p_LowQmPortal);
1795     sdqcrFlags |= QM_SDQCR_CHANNELS_POOL(poolChannelId+1);
1796     qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags);
1797 
1798     return E_OK;
1799 }
1800 
1801 t_Error QM_PORTAL_Poll(t_Handle h_QmPortal, e_QmPortalPollSource source)
1802 {
1803     t_QmPortal  *p_QmPortal = (t_QmPortal *)h_QmPortal;
1804 
1805     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1806 
1807     NCSW_PLOCK(p_QmPortal);
1808 
1809     if ((source == e_QM_PORTAL_POLL_SOURCE_CONTROL_FRAMES) ||
1810         (source == e_QM_PORTAL_POLL_SOURCE_BOTH))
1811     {
1812         uint32_t is = qm_isr_status_read(p_QmPortal->p_LowQmPortal);
1813         uint32_t active = LoopMessageRing(p_QmPortal, is);
1814         if (active)
1815             qm_isr_status_clear(p_QmPortal->p_LowQmPortal, active);
1816     }
1817     if ((source == e_QM_PORTAL_POLL_SOURCE_DATA_FRAMES) ||
1818         (source == e_QM_PORTAL_POLL_SOURCE_BOTH))
1819         p_QmPortal->f_LoopDequeueRingCB((t_Handle)p_QmPortal);
1820 
1821     PUNLOCK(p_QmPortal);
1822 
1823     return E_OK;
1824 }
1825 
1826 t_Error QM_PORTAL_PollFrame(t_Handle h_QmPortal, t_QmPortalFrameInfo *p_frameInfo)
1827 {
1828     t_QmPortal              *p_QmPortal     = (t_QmPortal *)h_QmPortal;
1829     struct qm_dqrr_entry    *p_Dq;
1830     struct qman_fq          *p_Fq;
1831     int                     prefetch;
1832 
1833     SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE);
1834     SANITY_CHECK_RETURN_ERROR(p_frameInfo, E_NULL_POINTER);
1835 
1836     NCSW_PLOCK(p_QmPortal);
1837 
1838     prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH);
1839     if (prefetch)
1840         qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal);
1841     qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal);
1842     p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal);
1843     if (!p_Dq)
1844     {
1845         PUNLOCK(p_QmPortal);
1846         return ERROR_CODE(E_EMPTY);
1847     }
1848     p_Fq = ptr_from_aligned_int(p_Dq->contextB);
1849     ASSERT_COND(p_Dq->fqid);
1850     if (p_Fq)
1851     {
1852         p_frameInfo->h_App = p_Fq->h_App;
1853         p_frameInfo->h_QmFqr = p_Fq->h_QmFqr;
1854         p_frameInfo->fqidOffset = p_Fq->fqidOffset;
1855         memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));
1856     }
1857     else
1858     {
1859         p_frameInfo->h_App = p_QmPortal->h_App;
1860         p_frameInfo->h_QmFqr = NULL;
1861         p_frameInfo->fqidOffset = p_Dq->fqid;
1862         memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD));
1863     }
1864     if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) {
1865         qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal,
1866                                    p_Dq,
1867                                    false);
1868         qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1869     } else {
1870         qm_dqrr_next(p_QmPortal->p_LowQmPortal);
1871         qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1);
1872     }
1873 
1874     PUNLOCK(p_QmPortal);
1875 
1876     return E_OK;
1877 }
1878 
1879 
1880 t_Handle QM_FQR_Create(t_QmFqrParams *p_QmFqrParams)
1881 {
1882     t_QmFqr             *p_QmFqr;
1883     uint32_t            i, flags = 0;
1884     u_QmFqdContextA     cnxtA;
1885 
1886     SANITY_CHECK_RETURN_VALUE(p_QmFqrParams, E_INVALID_HANDLE, NULL);
1887     SANITY_CHECK_RETURN_VALUE(p_QmFqrParams->h_Qm, E_INVALID_HANDLE, NULL);
1888 
1889     if (p_QmFqrParams->shadowMode &&
1890         (!p_QmFqrParams->useForce || p_QmFqrParams->numOfFqids != 1))
1891     {
1892         REPORT_ERROR(MAJOR, E_CONFLICT, ("shadowMode must be use with useForce and numOfFqids==1!!!"));
1893         return NULL;
1894     }
1895 
1896     p_QmFqr = (t_QmFqr *)XX_MallocSmart(sizeof(t_QmFqr), 0, 64);
1897     if (!p_QmFqr)
1898     {
1899         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQR obj!!!"));
1900         return NULL;
1901     }
1902     memset(p_QmFqr, 0, sizeof(t_QmFqr));
1903 
1904     p_QmFqr->h_Qm       = p_QmFqrParams->h_Qm;
1905     p_QmFqr->h_QmPortal = p_QmFqrParams->h_QmPortal;
1906     p_QmFqr->shadowMode = p_QmFqrParams->shadowMode;
1907     p_QmFqr->numOfFqids = (p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ?
1908                               1 : p_QmFqrParams->numOfFqids;
1909 
1910     if (!p_QmFqr->h_QmPortal)
1911     {
1912         p_QmFqr->h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
1913         SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_QmPortal, E_INVALID_HANDLE, NULL);
1914     }
1915 
1916     p_QmFqr->p_Fqs = (struct qman_fq **)XX_Malloc(sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);
1917     if (!p_QmFqr->p_Fqs)
1918     {
1919         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQs obj!!!"));
1920         QM_FQR_Free(p_QmFqr);
1921         return NULL;
1922     }
1923     memset(p_QmFqr->p_Fqs, 0, sizeof(struct qman_fq *) * p_QmFqr->numOfFqids);
1924 
1925     if (p_QmFqr->shadowMode)
1926     {
1927         struct qman_fq          *p_Fq = NULL;
1928 
1929         p_QmFqr->fqidBase = p_QmFqrParams->qs.frcQ.fqid;
1930         p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64);
1931         if (!p_Fq)
1932         {
1933             REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));
1934             QM_FQR_Free(p_QmFqr);
1935             return NULL;
1936         }
1937         memset(p_Fq, 0, sizeof(struct qman_fq));
1938         p_Fq->cb.dqrr     = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_DfltFrame;
1939         p_Fq->cb.ern      = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_RejectedFrame;
1940         p_Fq->cb.dc_ern   = cb_ern_dcErn;
1941         p_Fq->cb.fqs      = cb_fqs;
1942         p_Fq->h_App       = ((t_QmPortal*)p_QmFqr->h_QmPortal)->h_App;
1943         p_Fq->h_QmFqr     = p_QmFqr;
1944         p_Fq->state       = qman_fq_state_sched;
1945         p_Fq->fqid        = p_QmFqr->fqidBase;
1946         p_QmFqr->p_Fqs[0] = p_Fq;
1947     }
1948     else
1949     {
1950         p_QmFqr->channel    = p_QmFqrParams->channel;
1951         p_QmFqr->workQueue  = p_QmFqrParams->wq;
1952 
1953         p_QmFqr->fqidBase = QmFqidGet(p_QmFqr->h_Qm,
1954                                       p_QmFqr->numOfFqids,
1955                                       p_QmFqrParams->qs.nonFrcQs.align,
1956                                       p_QmFqrParams->useForce,
1957                                       p_QmFqrParams->qs.frcQ.fqid);
1958         if (p_QmFqr->fqidBase == (uint32_t)ILLEGAL_BASE)
1959         {
1960             REPORT_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid"));
1961             QM_FQR_Free(p_QmFqr);
1962             return NULL;
1963         }
1964 
1965         if(p_QmFqrParams->congestionAvoidanceEnable &&
1966             (p_QmFqrParams->congestionAvoidanceParams.h_QmCg == NULL) &&
1967             (p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold == 0))
1968         {
1969             REPORT_ERROR(CRITICAL,E_INVALID_STATE,("NULL congestion group handle and no FQ Threshold"));
1970             QM_FQR_Free(p_QmFqr);
1971             return NULL;
1972         }
1973         if(p_QmFqrParams->congestionAvoidanceEnable)
1974         {
1975             if(p_QmFqrParams->congestionAvoidanceParams.h_QmCg)
1976                 flags |= QM_FQCTRL_CGE;
1977             if(p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold)
1978                 flags |= QM_FQCTRL_TDE;
1979         }
1980 
1981     /*
1982         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_ORP : 0;
1983         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_CPCSTASH : 0;
1984         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_FORCESFDR : 0;
1985         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_AVOIDBLOCK : 0;
1986     */
1987         flags |= (p_QmFqrParams->holdActive)    ? QM_FQCTRL_HOLDACTIVE : 0;
1988         flags |= (p_QmFqrParams->preferInCache) ? QM_FQCTRL_LOCKINCACHE : 0;
1989 
1990         if (p_QmFqrParams->useContextAForStash)
1991         {
1992             if (CheckStashParams(p_QmFqrParams) != E_OK)
1993             {
1994                 REPORT_ERROR(CRITICAL,E_INVALID_STATE,NO_MSG);
1995                 QM_FQR_Free(p_QmFqr);
1996                 return NULL;
1997             }
1998 
1999             memset(&cnxtA, 0, sizeof(cnxtA));
2000             cnxtA.stashing.annotation_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameAnnotationSize, CACHELINE_SIZE);
2001             cnxtA.stashing.data_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameDataSize, CACHELINE_SIZE);
2002             cnxtA.stashing.context_cl = DIV_CEIL(p_QmFqrParams->stashingParams.fqContextSize, CACHELINE_SIZE);
2003             cnxtA.context_hi = (uint8_t)((p_QmFqrParams->stashingParams.fqContextAddr >> 32) & 0xff);
2004             cnxtA.context_lo = (uint32_t)(p_QmFqrParams->stashingParams.fqContextAddr);
2005             flags |= QM_FQCTRL_CTXASTASHING;
2006         }
2007 
2008         for(i=0;i<p_QmFqr->numOfFqids;i++)
2009             if (qm_new_fq(p_QmFqr->h_QmPortal,
2010                           p_QmFqr->fqidBase+i,
2011                           i,
2012                           p_QmFqr->channel,
2013                           p_QmFqr->workQueue,
2014                           1/*p_QmFqr->numOfFqids*/,
2015                           flags,
2016                           (p_QmFqrParams->congestionAvoidanceEnable ?
2017                               &p_QmFqrParams->congestionAvoidanceParams : NULL),
2018                           p_QmFqrParams->useContextAForStash ?
2019                               (t_QmContextA *)&cnxtA : p_QmFqrParams->p_ContextA,
2020                           p_QmFqrParams->p_ContextB,
2021                           p_QmFqrParams->initParked,
2022                           p_QmFqr,
2023                           &p_QmFqr->p_Fqs[i]) != E_OK)
2024             {
2025                 QM_FQR_Free(p_QmFqr);
2026                 return NULL;
2027             }
2028     }
2029     return p_QmFqr;
2030 }
2031 
2032 t_Error  QM_FQR_Free(t_Handle h_QmFqr)
2033 {
2034     t_QmFqr     *p_QmFqr    = (t_QmFqr *)h_QmFqr;
2035     uint32_t    i;
2036 
2037     if (!p_QmFqr)
2038         return ERROR_CODE(E_INVALID_HANDLE);
2039 
2040     if (p_QmFqr->p_Fqs)
2041     {
2042         for (i=0;i<p_QmFqr->numOfFqids;i++)
2043             if (p_QmFqr->p_Fqs[i])
2044             {
2045                 if (!p_QmFqr->shadowMode)
2046                     qm_free_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]);
2047                 XX_FreeSmart(p_QmFqr->p_Fqs[i]);
2048             }
2049         XX_Free(p_QmFqr->p_Fqs);
2050     }
2051 
2052     if (!p_QmFqr->shadowMode && p_QmFqr->fqidBase)
2053         QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
2054 
2055     XX_FreeSmart(p_QmFqr);
2056 
2057     return E_OK;
2058 }
2059 
2060 t_Error  QM_FQR_FreeWDrain(t_Handle                     h_QmFqr,
2061                            t_QmFqrDrainedCompletionCB   *f_CompletionCB,
2062                            bool                         deliverFrame,
2063                            t_QmReceivedFrameCallback    *f_CallBack,
2064                            t_Handle                     h_App)
2065 {
2066     t_QmFqr     *p_QmFqr    = (t_QmFqr *)h_QmFqr;
2067     uint32_t    i;
2068 
2069     if (!p_QmFqr)
2070         return ERROR_CODE(E_INVALID_HANDLE);
2071 
2072     if (p_QmFqr->shadowMode)
2073         RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("QM_FQR_FreeWDrain can't be called to shadow FQR!!!. call QM_FQR_Free"));
2074 
2075     p_QmFqr->p_DrainedFqs = (bool *)XX_Malloc(sizeof(bool) * p_QmFqr->numOfFqids);
2076     if (!p_QmFqr->p_DrainedFqs)
2077         RETURN_ERROR(MAJOR, E_NO_MEMORY, ("QM Drained-FQs obj!!!. Try to Free without draining"));
2078     memset(p_QmFqr->p_DrainedFqs, 0, sizeof(bool) * p_QmFqr->numOfFqids);
2079 
2080     if (f_CompletionCB)
2081     {
2082         p_QmFqr->f_CompletionCB = f_CompletionCB;
2083         p_QmFqr->h_App          = h_App;
2084     }
2085 
2086     if (deliverFrame)
2087     {
2088         if (!f_CallBack)
2089         {
2090             REPORT_ERROR(MAJOR, E_NULL_POINTER, ("f_CallBack must be given."));
2091             XX_Free(p_QmFqr->p_DrainedFqs);
2092             return ERROR_CODE(E_NULL_POINTER);
2093         }
2094         QM_FQR_RegisterCB(p_QmFqr, f_CallBack, h_App);
2095     }
2096     else
2097         QM_FQR_RegisterCB(p_QmFqr, drainCB, h_App);
2098 
2099     for (i=0;i<p_QmFqr->numOfFqids;i++)
2100     {
2101         if (qman_retire_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i], 0, true) != E_OK)
2102             RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!"));
2103 
2104         if (p_QmFqr->p_Fqs[i]->flags & QMAN_FQ_STATE_CHANGING)
2105             DBG(INFO, ("fq %d currently in use, will be retired", p_QmFqr->p_Fqs[i]->fqid));
2106         else
2107             drainRetiredFq(p_QmFqr->p_Fqs[i]);
2108     }
2109 
2110     if (!p_QmFqr->f_CompletionCB)
2111     {
2112         while(p_QmFqr->p_DrainedFqs) ;
2113         DBG(TRACE, ("QM-FQR with base %d completed", p_QmFqr->fqidBase));
2114         XX_FreeSmart(p_QmFqr->p_Fqs);
2115         if (p_QmFqr->fqidBase)
2116             QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase);
2117         XX_FreeSmart(p_QmFqr);
2118     }
2119 
2120     return E_OK;
2121 }
2122 
2123 t_Error QM_FQR_RegisterCB(t_Handle h_QmFqr, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App)
2124 {
2125     t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2126     int         i;
2127 
2128     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2129 
2130     for (i=0;i<p_QmFqr->numOfFqids;i++)
2131     {
2132         p_QmFqr->p_Fqs[i]->cb.dqrr = f_CallBack;
2133         p_QmFqr->p_Fqs[i]->h_App   = h_App;
2134     }
2135 
2136     return E_OK;
2137 }
2138 
2139 t_Error QM_FQR_Enqueue(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)
2140 {
2141     t_QmFqr                 *p_QmFqr = (t_QmFqr *)h_QmFqr;
2142     t_QmPortal              *p_QmPortal;
2143     struct qm_eqcr_entry    *p_Eq;
2144     uint32_t                *p_Dst, *p_Src;
2145     const struct qman_fq    *p_Fq;
2146 
2147     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2148     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2149 
2150     if (!h_QmPortal)
2151     {
2152         SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2153         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2154         SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2155     }
2156     p_QmPortal = (t_QmPortal *)h_QmPortal;
2157 
2158     p_Fq = p_QmFqr->p_Fqs[fqidOffset];
2159 
2160 #ifdef QM_CHECKING
2161     if (p_Fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE)
2162         RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
2163     if ((!(p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)) &&
2164         ((p_Fq->state == qman_fq_state_retired) ||
2165          (p_Fq->state == qman_fq_state_oos)))
2166         return ERROR_CODE(E_BUSY);
2167 #endif /* QM_CHECKING */
2168 
2169     NCSW_PLOCK(p_QmPortal);
2170     p_Eq = try_eq_start(p_QmPortal);
2171     if (!p_Eq)
2172     {
2173         PUNLOCK(p_QmPortal);
2174         return ERROR_CODE(E_BUSY);
2175     }
2176 
2177     p_Eq->fqid = p_Fq->fqid;
2178     p_Eq->tag = aligned_int_from_ptr(p_Fq);
2179     /* gcc does a dreadful job of the following;
2180      *  eq->fd = *fd;
2181      * It causes the entire function to save/restore a wider range of
2182      * registers, and comes up with instruction-waste galore. This will do
2183      * until we can rework the function for better code-generation. */
2184     p_Dst = (uint32_t *)&p_Eq->fd;
2185     p_Src = (uint32_t *)p_Frame;
2186     p_Dst[0] = p_Src[0];
2187     p_Dst[1] = p_Src[1];
2188     p_Dst[2] = p_Src[2];
2189     p_Dst[3] = p_Src[3];
2190 
2191     qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal,
2192                           (uint8_t)(QM_EQCR_VERB_CMD_ENQUEUE/* |
2193                           (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))*/));
2194     PUNLOCK(p_QmPortal);
2195 
2196     return E_OK;
2197 }
2198 
2199 
2200 t_Error QM_FQR_PullFrame(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame)
2201 {
2202     t_QmFqr                 *p_QmFqr = (t_QmFqr *)h_QmFqr;
2203     uint32_t                pdqcr = 0;
2204 
2205     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2206     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2207     SANITY_CHECK_RETURN_ERROR(p_Frame, E_NULL_POINTER);
2208     SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_oos) ||
2209                               (p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_parked),
2210                               E_INVALID_STATE);
2211     if (!h_QmPortal)
2212     {
2213         SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2214         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2215         SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2216     }
2217 
2218     pdqcr |= QM_PDQCR_MODE_UNSCHEDULED;
2219     pdqcr |= QM_PDQCR_FQID(p_QmFqr->p_Fqs[fqidOffset]->fqid);
2220     return QmPortalPullFrame(h_QmPortal, pdqcr, p_Frame);
2221 }
2222 
2223 t_Error QM_FQR_Resume(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)
2224 {
2225     t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2226 
2227     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2228     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2229 
2230     if (!h_QmPortal)
2231     {
2232         SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE);
2233         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2234         SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE);
2235     }
2236     return qman_schedule_fq(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset]);
2237 }
2238 
2239 t_Error  QM_FQR_Suspend(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset)
2240 {
2241     t_QmFqr     *p_QmFqr = (t_QmFqr *)h_QmFqr;
2242 
2243     SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE);
2244     SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE);
2245     SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->flags & QM_FQCTRL_HOLDACTIVE), E_INVALID_STATE);
2246 
2247     UNUSED(h_QmPortal);
2248     p_QmFqr->p_Fqs[fqidOffset]->state = qman_fq_state_waiting_parked;
2249 
2250     return E_OK;
2251 }
2252 
2253 uint32_t QM_FQR_GetFqid(t_Handle h_QmFqr)
2254 {
2255     t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;
2256 
2257     SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);
2258 
2259     return p_QmFqr->fqidBase;
2260 }
2261 
2262 uint32_t QM_FQR_GetCounter(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, e_QmFqrCounters counter)
2263 {
2264     t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr;
2265     struct qm_mcr_queryfq_np    queryfq_np;
2266 
2267     SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0);
2268     SANITY_CHECK_RETURN_VALUE((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE, 0);
2269 
2270     if (!h_QmPortal)
2271     {
2272         SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_Qm, E_INVALID_HANDLE, 0);
2273         h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm);
2274         SANITY_CHECK_RETURN_VALUE(h_QmPortal, E_INVALID_HANDLE, 0);
2275     }
2276     if (qman_query_fq_np(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset], &queryfq_np) != E_OK)
2277         return 0;
2278     switch (counter)
2279     {
2280         case e_QM_FQR_COUNTERS_FRAME :
2281             return queryfq_np.frm_cnt;
2282         case e_QM_FQR_COUNTERS_BYTE :
2283             return queryfq_np.byte_cnt;
2284         default :
2285             break;
2286     }
2287     /* should never get here */
2288     ASSERT_COND(FALSE);
2289 
2290     return 0;
2291 }
2292 
2293 
2294 t_Handle QM_CG_Create(t_QmCgParams *p_CgParams)
2295 {
2296     t_QmCg                          *p_QmCg;
2297     t_QmPortal                      *p_QmPortal;
2298     t_Error                         err;
2299     uint32_t                        wredParams;
2300     uint32_t                        tmpA, tmpN, ta=0, tn=0;
2301     int                             gap, tmp;
2302     struct qm_mc_command            *p_Mcc;
2303     struct qm_mc_result             *p_Mcr;
2304 
2305     SANITY_CHECK_RETURN_VALUE(p_CgParams, E_INVALID_HANDLE, NULL);
2306     SANITY_CHECK_RETURN_VALUE(p_CgParams->h_Qm, E_INVALID_HANDLE, NULL);
2307 
2308     if(p_CgParams->notifyDcPortal &&
2309        ((p_CgParams->dcPortalId == e_DPAA_DCPORTAL2) || (p_CgParams->dcPortalId == e_DPAA_DCPORTAL3)))
2310     {
2311         REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("notifyDcPortal is invalid for this DC Portal"));
2312         return NULL;
2313     }
2314 
2315     if (!p_CgParams->h_QmPortal)
2316     {
2317         p_QmPortal = QmGetPortalHandle(p_CgParams->h_Qm);
2318         SANITY_CHECK_RETURN_VALUE(p_QmPortal, E_INVALID_STATE, NULL);
2319     }
2320     else
2321         p_QmPortal = p_CgParams->h_QmPortal;
2322 
2323     p_QmCg = (t_QmCg *)XX_Malloc(sizeof(t_QmCg));
2324     if (!p_QmCg)
2325     {
2326         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM CG obj!!!"));
2327         return NULL;
2328     }
2329     memset(p_QmCg, 0, sizeof(t_QmCg));
2330 
2331     /* build CG struct */
2332     p_QmCg->h_Qm        = p_CgParams->h_Qm;
2333     p_QmCg->h_QmPortal  = p_QmPortal;
2334     p_QmCg->h_App       = p_CgParams->h_App;
2335     err = QmGetCgId(p_CgParams->h_Qm, &p_QmCg->id);
2336     if (err)
2337     {
2338         XX_Free(p_QmCg);
2339         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmGetCgId failed"));
2340         return NULL;
2341     }
2342 
2343     NCSW_PLOCK(p_QmPortal);
2344     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2345     p_Mcc->initcgr.cgid = p_QmCg->id;
2346 
2347     err = QmPortalRegisterCg(p_QmPortal, p_QmCg, p_QmCg->id);
2348     if (err)
2349     {
2350         XX_Free(p_QmCg);
2351         PUNLOCK(p_QmPortal);
2352         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalRegisterCg failed"));
2353         return NULL;
2354     }
2355 
2356     /*  Build CGR command */
2357     {
2358 #ifdef QM_CGS_NO_FRAME_MODE
2359     t_QmRevisionInfo    revInfo;
2360 
2361     QmGetRevision(p_QmCg->h_Qm, &revInfo);
2362 
2363     if (!((revInfo.majorRev == 1) && (revInfo.minorRev == 0)))
2364 #endif /* QM_CGS_NO_FRAME_MODE */
2365         if (p_CgParams->frameCount)
2366         {
2367             p_Mcc->initcgr.we_mask |= QM_CGR_WE_MODE;
2368             p_Mcc->initcgr.cgr.frame_mode = QM_CGR_EN;
2369         }
2370     }
2371 
2372     if (p_CgParams->wredEnable)
2373     {
2374         if (p_CgParams->wredParams.enableGreen)
2375         {
2376             err = CalcWredCurve(&p_CgParams->wredParams.greenCurve, &wredParams);
2377             if(err)
2378             {
2379                 XX_Free(p_QmCg);
2380                 PUNLOCK(p_QmPortal);
2381                 REPORT_ERROR(MAJOR, err, NO_MSG);
2382                 return NULL;
2383             }
2384             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;
2385             p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;
2386             p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;
2387         }
2388         if (p_CgParams->wredParams.enableYellow)
2389         {
2390             err = CalcWredCurve(&p_CgParams->wredParams.yellowCurve, &wredParams);
2391             if(err)
2392             {
2393                 XX_Free(p_QmCg);
2394                 PUNLOCK(p_QmPortal);
2395                 REPORT_ERROR(MAJOR, err, NO_MSG);
2396                 return NULL;
2397             }
2398             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;
2399             p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;
2400             p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;
2401         }
2402         if (p_CgParams->wredParams.enableRed)
2403         {
2404             err = CalcWredCurve(&p_CgParams->wredParams.redCurve, &wredParams);
2405             if(err)
2406             {
2407                 XX_Free(p_QmCg);
2408                 PUNLOCK(p_QmPortal);
2409                 REPORT_ERROR(MAJOR, err, NO_MSG);
2410                 return NULL;
2411             }
2412             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;
2413             p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;
2414             p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;
2415         }
2416     }
2417 
2418     if (p_CgParams->tailDropEnable)
2419     {
2420         if (!p_CgParams->threshold)
2421         {
2422             XX_Free(p_QmCg);
2423             PUNLOCK(p_QmPortal);
2424             REPORT_ERROR(MINOR, E_INVALID_STATE, ("tailDropThreshold must be configured if tailDropEnable "));
2425             return NULL;
2426         }
2427         p_Mcc->initcgr.cgr.cstd_en = QM_CGR_EN;
2428         p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSTD_EN;
2429     }
2430 
2431     if (p_CgParams->threshold)
2432     {
2433         p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;
2434         p_QmCg->f_Exception = p_CgParams->f_Exception;
2435         if (p_QmCg->f_Exception || p_CgParams->notifyDcPortal)
2436         {
2437             p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;
2438             p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSCN_EN | QM_CGR_WE_CSCN_TARG;
2439             /* if SW - set target, if HW - if FM, set HW target, otherwize, set SW target */
2440             p_Mcc->initcgr.cgr.cscn_targ = 0;
2441             if (p_QmCg->f_Exception)
2442                 p_Mcc->initcgr.cgr.cscn_targ = (uint32_t)QM_CGR_TARGET_SWP(QmPortalGetSwPortalId(p_QmCg->h_QmPortal));
2443             if (p_CgParams->notifyDcPortal)
2444                 p_Mcc->initcgr.cgr.cscn_targ |= (uint32_t)QM_CGR_TARGET_DCP(p_CgParams->dcPortalId);
2445         }
2446 
2447         /* express thresh as ta*2^tn */
2448         gap = (int)p_CgParams->threshold;
2449         for (tmpA=0 ; tmpA<256; tmpA++ )
2450             for (tmpN=0 ; tmpN<32; tmpN++ )
2451             {
2452                 tmp = ABS((int)(p_CgParams->threshold - tmpA*(1<<tmpN)));
2453                 if (tmp < gap)
2454                 {
2455                    ta = tmpA;
2456                    tn = tmpN;
2457                    gap = tmp;
2458                 }
2459             }
2460         p_Mcc->initcgr.cgr.cs_thres.TA = ta;
2461         p_Mcc->initcgr.cgr.cs_thres.Tn = tn;
2462     }
2463     else if(p_CgParams->f_Exception)
2464     {
2465         XX_Free(p_QmCg);
2466         PUNLOCK(p_QmPortal);
2467         REPORT_ERROR(MINOR, E_INVALID_STATE, ("No threshold configured, but f_Exception defined"));
2468         return NULL;
2469     }
2470 
2471     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_INITCGR);
2472     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2473     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_INITCGR);
2474     if (p_Mcr->result != QM_MCR_RESULT_OK)
2475     {
2476         XX_Free(p_QmCg);
2477         PUNLOCK(p_QmPortal);
2478         REPORT_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2479         return NULL;
2480     }
2481     PUNLOCK(p_QmPortal);
2482 
2483     return p_QmCg;
2484 }
2485 
2486 t_Error QM_CG_Free(t_Handle h_QmCg)
2487 {
2488 
2489     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2490     t_Error                 err;
2491     struct qm_mc_command    *p_Mcc;
2492     struct qm_mc_result     *p_Mcr;
2493     t_QmPortal              *p_QmPortal;
2494 
2495     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2496 
2497     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2498 
2499     NCSW_PLOCK(p_QmPortal);
2500     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2501     p_Mcc->initcgr.cgid = p_QmCg->id;
2502     p_Mcc->initcgr.we_mask = QM_CGR_WE_MASK;
2503 
2504     err = QmFreeCgId(p_QmCg->h_Qm, p_QmCg->id);
2505     if(err)
2506     {
2507         XX_Free(p_QmCg);
2508         PUNLOCK(p_QmPortal);
2509         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmFreeCgId failed"));
2510     }
2511 
2512     err = QmPortalUnregisterCg(p_QmCg->h_QmPortal, p_QmCg->id);
2513     if(err)
2514     {
2515         XX_Free(p_QmCg);
2516         PUNLOCK(p_QmPortal);
2517         RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalUnregisterCg failed"));
2518     }
2519 
2520     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2521     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2522     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2523     if (p_Mcr->result != QM_MCR_RESULT_OK)
2524     {
2525         PUNLOCK(p_QmPortal);
2526         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2527     }
2528     PUNLOCK(p_QmPortal);
2529 
2530     XX_Free(p_QmCg);
2531 
2532     return E_OK;
2533 }
2534 
2535 t_Error QM_CG_SetException(t_Handle h_QmCg, e_QmExceptions exception, bool enable)
2536 {
2537     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2538     struct qm_mc_command    *p_Mcc;
2539     struct qm_mc_result     *p_Mcr;
2540     t_QmPortal              *p_QmPortal;
2541 
2542     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2543 
2544     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2545     if (!p_QmCg->f_Exception)
2546         RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Either threshold or exception callback was not configured."));
2547 
2548     NCSW_PLOCK(p_QmPortal);
2549     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2550     p_Mcc->initcgr.cgid = p_QmCg->id;
2551     p_Mcc->initcgr.we_mask = QM_CGR_WE_CSCN_EN;
2552 
2553     if(exception == e_QM_EX_CG_STATE_CHANGE)
2554     {
2555         if(enable)
2556             p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN;
2557     }
2558     else
2559     {
2560         PUNLOCK(p_QmPortal);
2561         RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal exception"));
2562     }
2563 
2564     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2565     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2566     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2567     if (p_Mcr->result != QM_MCR_RESULT_OK)
2568     {
2569         PUNLOCK(p_QmPortal);
2570         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2571     }
2572     PUNLOCK(p_QmPortal);
2573 
2574     return E_OK;
2575 }
2576 
2577 t_Error QM_CG_ModifyWredCurve(t_Handle h_QmCg, t_QmCgModifyWredParams *p_QmCgModifyParams)
2578 {
2579     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2580     uint32_t                wredParams;
2581     struct qm_mc_command    *p_Mcc;
2582     struct qm_mc_result     *p_Mcr;
2583     t_QmPortal              *p_QmPortal;
2584     t_Error                 err = E_OK;
2585 
2586     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2587 
2588     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2589 
2590     NCSW_PLOCK(p_QmPortal);
2591     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2592     p_Mcc->initcgr.cgid = p_QmCg->id;
2593 
2594     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);
2595     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2596     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);
2597     if (p_Mcr->result != QM_MCR_RESULT_OK)
2598     {
2599         PUNLOCK(p_QmPortal);
2600         RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));
2601     }
2602 
2603     switch(p_QmCgModifyParams->color)
2604     {
2605         case(e_QM_CG_COLOR_GREEN):
2606             if(!p_Mcr->querycgr.cgr.wr_en_g)
2607             {
2608                 PUNLOCK(p_QmPortal);
2609                 RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for green"));
2610             }
2611             break;
2612         case(e_QM_CG_COLOR_YELLOW):
2613             if(!p_Mcr->querycgr.cgr.wr_en_y)
2614             {
2615                 PUNLOCK(p_QmPortal);
2616                 RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for yellow"));
2617             }
2618             break;
2619         case(e_QM_CG_COLOR_RED):
2620             if(!p_Mcr->querycgr.cgr.wr_en_r)
2621             {
2622                 PUNLOCK(p_QmPortal);
2623                 RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for red"));
2624             }
2625             break;
2626     }
2627 
2628     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2629     p_Mcc->initcgr.cgid = p_QmCg->id;
2630 
2631     switch(p_QmCgModifyParams->color)
2632     {
2633         case(e_QM_CG_COLOR_GREEN):
2634             err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2635             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G;
2636             p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN;
2637             p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams;
2638             break;
2639         case(e_QM_CG_COLOR_YELLOW):
2640             err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2641             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y;
2642             p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN;
2643             p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams;
2644             break;
2645         case(e_QM_CG_COLOR_RED):
2646             err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams);
2647             p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R;
2648             p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN;
2649             p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams;
2650             break;
2651     }
2652     if (err)
2653     {
2654         PUNLOCK(p_QmPortal);
2655         RETURN_ERROR(MINOR, err, NO_MSG);
2656     }
2657 
2658     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2659     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2660     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2661     if (p_Mcr->result != QM_MCR_RESULT_OK)
2662     {
2663         PUNLOCK(p_QmPortal);
2664         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2665     }
2666     PUNLOCK(p_QmPortal);
2667 
2668     return E_OK;
2669 }
2670 
2671 t_Error QM_CG_ModifyTailDropThreshold(t_Handle h_QmCg, uint32_t threshold)
2672 {
2673     t_QmCg                  *p_QmCg = (t_QmCg *)h_QmCg;
2674     struct qm_mc_command    *p_Mcc;
2675     struct qm_mc_result     *p_Mcr;
2676     t_QmPortal              *p_QmPortal;
2677     uint32_t                tmpA, tmpN, ta=0, tn=0;
2678     int                     gap, tmp;
2679 
2680     SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE);
2681 
2682     p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal;
2683 
2684     NCSW_PLOCK(p_QmPortal);
2685     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2686     p_Mcc->initcgr.cgid = p_QmCg->id;
2687 
2688     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR);
2689     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2690     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);
2691     if (p_Mcr->result != QM_MCR_RESULT_OK)
2692     {
2693         PUNLOCK(p_QmPortal);
2694         RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result)));
2695     }
2696 
2697     if(!p_Mcr->querycgr.cgr.cstd_en)
2698     {
2699         PUNLOCK(p_QmPortal);
2700         RETURN_ERROR(MINOR, E_INVALID_STATE, ("Tail Drop is not enabled!"));
2701     }
2702 
2703     p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal);
2704     p_Mcc->initcgr.cgid = p_QmCg->id;
2705     p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES;
2706 
2707     /* express thresh as ta*2^tn */
2708     gap = (int)threshold;
2709     for (tmpA=0 ; tmpA<256; tmpA++ )
2710         for (tmpN=0 ; tmpN<32; tmpN++ )
2711         {
2712             tmp = ABS((int)(threshold - tmpA*(1<<tmpN)));
2713             if (tmp < gap)
2714             {
2715                ta = tmpA;
2716                tn = tmpN;
2717                gap = tmp;
2718             }
2719         }
2720     p_Mcc->initcgr.cgr.cs_thres.TA = ta;
2721     p_Mcc->initcgr.cgr.cs_thres.Tn = tn;
2722 
2723     qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR);
2724     while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ;
2725     ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR);
2726     if (p_Mcr->result != QM_MCR_RESULT_OK)
2727     {
2728         PUNLOCK(p_QmPortal);
2729         RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result)));
2730     }
2731     PUNLOCK(p_QmPortal);
2732 
2733     return E_OK;
2734 }
2735 
2736