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